Commits (3)
  • Rob Swindell's avatar
    Increase maximum file extension length from 3 to 15 characters · ffc8d5db
    Rob Swindell authored
    For Viewable, Testable, Compressible file types and download events,
    the file extension is no longer limited to 3 characters. 15 characters
    seemed like "enough".
    
    Similarly, a user's temp/QWK file type preference is also extended from
    3 to 15 characters.
    
    This fixes issue #486, but file types such as *.tar.gz (2 dots in the extension)
    are still an issue and will be addressed next.
    ffc8d5db
  • Rob Swindell's avatar
    Fix possible crash when no extractable file types are configured in SCFG · 4e1ca83a
    Rob Swindell authored
    If libarchive couldn't extract a QWK or REP packet, we'd fallback to searching
    for a match among the configured extractable file types and if no extension/type
    match was found, default to the first configured extractable file type
    (even if there wasn't one) which would result in a NULL pointer dereference
    and most likely a crash. Instead, if no matching configured extractable
    file type is found, just log a warning message and don't continue with the
    extraction attempt. With SBBS v3.19+, it's totally valid/legit to have no
    extractable file types configured in SCFG and things "just work" (using
    libarchive).
    4e1ca83a
  • Rob Swindell's avatar
    Create/use file_type_match() for viewing, testing, and download-events · e8944f5b
    Rob Swindell authored
    Allows for more/better wildcard matching in viewable and testable
    file types and download-events (e.g. "tar.gz" or "tar.*").
    
    This solves the "double-dot" problem in some file types/extensions.
    An implicit "*." is prepended before the configured file type/extension.
    e8944f5b
......@@ -798,6 +798,13 @@ int archive_type(const char* archive, char* str, size_t size)
return result;
}
bool file_type_match(const char* filename, const char* type)
{
char filespec[MAX_PATH + 1];
SAFEPRINTF(filespec, "*.%s", type);
return wildmatch(filename, filespec, /* path: */false, /* case-sensitive: */false);
}
str_list_t directory(const char* path)
{
int flags = GLOB_MARK;
......@@ -1058,13 +1065,8 @@ bool extract_diz(scfg_t* cfg, file_t* f, str_list_t diz_fnames, char* path, size
}
}
char* fext = getfext(f->name);
if(fext == NULL)
return false;
for(i = 0; i < cfg->total_fextrs; i++)
if(stricmp(cfg->fextr[i]->ext, fext + 1) == 0 && chk_ar(cfg, cfg->fextr[i]->ar, /* user: */NULL, /* client: */NULL))
if(file_type_match(f->name, cfg->fextr[i]->ext) && chk_ar(cfg, cfg->fextr[i]->ar, /* user: */NULL, /* client: */NULL))
break;
if(i >= cfg->total_fextrs)
return false;
......
......@@ -77,6 +77,7 @@ DLLEXPORT long extract_files_from_archive(const char* archive, const char* out
,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[];
DLLEXPORT bool file_type_match(const char* filename, const char* type);
/* Batch file transfer queues */
DLLEXPORT char* batch_list_name(scfg_t* , uint usernumber, enum XFER_TYPE, char* fname, size_t);
......
......@@ -1019,16 +1019,13 @@ int sbbs_t::listfileinfo(uint dirnum, const char *filespec, long mode)
}
CRLF;
}
const char* file_ext = getfext(f->name);
if(file_ext != NULL) {
for(j=0; j<cfg.total_dlevents; j++) {
if(!stricmp(cfg.dlevent[j]->ext, file_ext + 1)
&& chk_ar(cfg.dlevent[j]->ar,&useron,&client)) {
bputs(cfg.dlevent[j]->workstr);
external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL)
,EX_OUTL);
clearline();
}
for(j=0; j<cfg.total_dlevents; j++) {
if(file_type_match(f->name, cfg.dlevent[j]->ext)
&& chk_ar(cfg.dlevent[j]->ar,&useron,&client)) {
bputs(cfg.dlevent[j]->workstr);
external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL)
,EX_OUTL);
clearline();
}
}
action = NODE_DLNG;
......
......@@ -87,8 +87,10 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
if(!stricmp(cfg.fextr[k]->ext,useron.tmpext)
&& chk_ar(cfg.fextr[k]->ar,&useron,&client))
break;
if(k>=cfg.total_fextrs)
k=0;
if(k>=cfg.total_fextrs) {
lprintf(LOG_WARNING, "No extractable file type matching user's QWK packet type: %s", useron.tmpext);
return false;
}
p=cmdstr(cfg.fextr[k]->cmd,str,ALLFILES,NULL);
if((i=external(p,ex))==0)
preqwk=1;
......
......@@ -50,6 +50,7 @@
#define FNOPEN_BUF_SIZE (2*1024)
#define MAX_FILENAME_LEN 64
#define MAX_FILEEXT_LEN 15
#define ILLEGAL_FILENAME_CHARS "\\/|<>:\";,%?*"
#define SAFEST_FILENAME_CHARS "-._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
......@@ -925,7 +926,7 @@ typedef struct { /* Users information */
phone[LEN_PHONE+1], /* Phone number xxx-xxx-xxxx format */
modem[LEN_MODEM+1], /* Modem type - 8 chars max */
netmail[LEN_NETMAIL+1], /* NetMail forwarding address */
tmpext[4], /* QWK Packet extension */
tmpext[MAX_FILEEXT_LEN+1], /* QWK Packet / Temp file type */
comment[LEN_COMMENT+1], /* Private comment about user */
cursub[LEN_EXTCODE+1], /* Current sub-board internal code */
curdir[LEN_EXTCODE+1], /* Current directory internal code */
......
......@@ -329,7 +329,7 @@ void xfer_opts()
case __COUNTER__: /* Viewable file types */
while(1) {
for(i=0;i<cfg.total_fviews && i<MAX_OPTS;i++)
sprintf(opt[i],"%-3.3s %-40s",cfg.fview[i]->ext,cfg.fview[i]->cmd);
sprintf(opt[i],"%-*s %-40s", MAX_FILEEXT_LEN, cfg.fview[i]->ext, cfg.fview[i]->cmd);
opt[i][0]=0;
i=WIN_RHT|WIN_ACT|WIN_SAV; /* save cause size can change */
if(cfg.total_fviews<MAX_OPTS)
......@@ -465,7 +465,7 @@ void xfer_opts()
case __COUNTER__: /* Testable file types */
while(1) {
for(i=0;i<cfg.total_ftests && i<MAX_OPTS;i++)
sprintf(opt[i],"%-3.3s %-40s",cfg.ftest[i]->ext,cfg.ftest[i]->cmd);
sprintf(opt[i],"%-*s %-40s", MAX_FILEEXT_LEN, cfg.ftest[i]->ext, cfg.ftest[i]->cmd);
opt[i][0]=0;
i=WIN_RHT|WIN_ACT|WIN_SAV; /* save cause size can change */
if(cfg.total_ftests<MAX_OPTS)
......@@ -599,7 +599,7 @@ void xfer_opts()
case __COUNTER__: /* Download Events */
while(1) {
for(i=0;i<cfg.total_dlevents && i<MAX_OPTS;i++)
sprintf(opt[i],"%-3.3s %-40s",cfg.dlevent[i]->ext,cfg.dlevent[i]->cmd);
sprintf(opt[i],"%-*s %-40s", MAX_FILEEXT_LEN, cfg.dlevent[i]->ext, cfg.dlevent[i]->cmd);
opt[i][0]=0;
i=WIN_RHT|WIN_ACT|WIN_SAV; /* save cause size can change */
if(cfg.total_dlevents<MAX_OPTS)
......@@ -747,8 +747,8 @@ void xfer_opts()
case __COUNTER__: /* Extractable file types */
while(1) {
for(i=0;i<cfg.total_fextrs && i<MAX_OPTS;i++)
sprintf(opt[i],"%-3.3s %-40s"
,cfg.fextr[i]->ext,cfg.fextr[i]->cmd);
sprintf(opt[i],"%-*s %-40s"
,MAX_FILEEXT_LEN, cfg.fextr[i]->ext, cfg.fextr[i]->cmd);
opt[i][0]=0;
i=WIN_RHT|WIN_ACT|WIN_SAV; /* save cause size can change */
if(cfg.total_fextrs<MAX_OPTS)
......@@ -882,7 +882,7 @@ void xfer_opts()
case __COUNTER__: /* Compressible file types */
while(1) {
for(i=0;i<cfg.total_fcomps && i<MAX_OPTS;i++)
sprintf(opt[i],"%-3.3s %-40s",cfg.fcomp[i]->ext,cfg.fcomp[i]->cmd);
sprintf(opt[i],"%-*s %-40s",MAX_FILEEXT_LEN, cfg.fcomp[i]->ext, cfg.fcomp[i]->cmd);
opt[i][0]=0;
i=WIN_RHT|WIN_ACT|WIN_SAV; /* save cause size can change */
if(cfg.total_fcomps<MAX_OPTS)
......
......@@ -239,7 +239,7 @@ typedef struct { /* Transfer Protocol information */
} prot_t;
typedef struct { /* Extractable file types */
char ext[4]; /* Extension */
char ext[MAX_FILEEXT_LEN+1]; /* Extension */
char arstr[LEN_ARSTR+1], /* Access Requirements */
cmd[LEN_CMD+1]; /* Command line */
uchar ar[LEN_ARSTR+1];
......@@ -247,7 +247,7 @@ typedef struct { /* Extractable file types */
} fextr_t;
typedef struct { /* Compressable file types */
char ext[4]; /* Extension */
char ext[MAX_FILEEXT_LEN+1]; /* Extension */
char arstr[LEN_ARSTR+1], /* Access Requirements */
cmd[LEN_CMD+1]; /* Command line */
uchar ar[LEN_ARSTR+1];
......@@ -255,7 +255,7 @@ typedef struct { /* Compressable file types */
} fcomp_t;
typedef struct { /* Viewable file types */
char ext[4]; /* Extension */
char ext[MAX_FILEEXT_LEN+1]; /* Extension */
char arstr[LEN_ARSTR+1], /* Access Requirements */
cmd[LEN_CMD+1]; /* Command line */
uchar ar[LEN_ARSTR+1];
......@@ -263,7 +263,7 @@ typedef struct { /* Viewable file types */
} fview_t;
typedef struct { /* Testable file types */
char ext[4]; /* Extension */
char ext[MAX_FILEEXT_LEN+1]; /* Extension */
char arstr[LEN_ARSTR+1], /* Access requirement */
cmd[LEN_CMD+1], /* Command line */
workstr[41]; /* String to display while working */
......@@ -272,7 +272,7 @@ typedef struct { /* Testable file types */
} ftest_t;
typedef struct { /* Download events */
char ext[4];
char ext[MAX_FILEEXT_LEN+1]; /* Extension */
char arstr[LEN_ARSTR+1], /* Access requirement */
cmd[LEN_CMD+1], /* Command line */
workstr[41]; /* String to display while working */
......@@ -325,7 +325,7 @@ typedef struct { /* QWK Network Hub */
call[LEN_CMD+1], /* Call-out command line to execute */
pack[LEN_CMD+1], /* Packing command line */
unpack[LEN_CMD+1]; /* Unpacking command line */
char fmt[4]; /* Archive format */
char fmt[MAX_FILEEXT_LEN+1]; /* Archive format */
uint16_t time, /* Time to call-out */
node, /* Node to do the call-out */
freq, /* Frequency of call-outs */
......
......@@ -85,8 +85,10 @@ bool sbbs_t::unpack_rep(char* repfile)
for(k=0;k<cfg.total_fextrs;k++)
if(!stricmp(cfg.fextr[k]->ext,useron.tmpext) && chk_ar(cfg.fextr[k]->ar,&useron,&client))
break;
if(k>=cfg.total_fextrs)
k=0;
if(k>=cfg.total_fextrs) {
lprintf(LOG_WARNING, "No extractable file type matching user's REP packet type: %s", useron.tmpext);
return false;
}
ex=EX_STDOUT;
if(online!=ON_REMOTE)
ex|=EX_OFFLINE;
......
......@@ -53,9 +53,8 @@ bool sbbs_t::uploadfile(file_t* f)
return false;
}
f->hdr.when_written.time = (uint32_t)fdate(path);
char* fext = getfext(f->name);
for(i=0;i<cfg.total_ftests;i++)
if(cfg.ftest[i]->ext[0]=='*' || (fext != NULL && stricmp(fext + 1, cfg.ftest[i]->ext) == 0)) {
if(file_type_match(f->name, cfg.ftest[i]->ext)) {
if(!chk_ar(cfg.ftest[i]->ar,&useron,&client))
continue;
attr(LIGHTGRAY);
......
......@@ -97,18 +97,13 @@ bool sbbs_t::viewfile(const char* inpath)
bputs(text[FileNotFound]);
return false;
}
char* file_ext = getfext(path);
if(file_ext == NULL) {
bprintf(text[NonviewableFile], getfname(path));
return false;
}
for(i=0;i<cfg.total_fviews;i++)
if(wildmatchi(file_ext + 1, cfg.fview[i]->ext, /* path: */false) && chk_ar(cfg.fview[i]->ar,&useron,&client)) {
if(file_type_match(path, cfg.fview[i]->ext) && chk_ar(cfg.fview[i]->ar,&useron,&client)) {
SAFECOPY(viewcmd,cfg.fview[i]->cmd);
break;
}
if(i >= cfg.total_fviews) {
bprintf(text[NonviewableFile], file_ext);
bprintf(text[NonviewableFile], getfname(path));
return false;
}
if((i=external(cmdstr(viewcmd, path, path, NULL), EX_STDIO|EX_SH))!=0) {
......