diff --git a/src/sbbs3/echocfg.vcxproj b/src/sbbs3/echocfg.vcxproj index d8f6fbb481da19a780cec9783549a11b389f1f16..155aa4f52ba72bf471cf45adddf907ce55bbf201 100644 --- a/src/sbbs3/echocfg.vcxproj +++ b/src/sbbs3/echocfg.vcxproj @@ -153,6 +153,7 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> + <ClCompile Include="getctrl.c" /> <ClCompile Include="nopen.c"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/sbbs3/findstr.c b/src/sbbs3/findstr.c new file mode 100644 index 0000000000000000000000000000000000000000..1cfd0d9dff08b591fca74d8699c81e40aaa71b52 --- /dev/null +++ b/src/sbbs3/findstr.c @@ -0,0 +1,215 @@ +/* Synchronet find string routines */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#include "genwrap.h" +#include "findstr.h" + +/****************************************************************************/ +/* Pattern matching string search of 'insearchof' in 'pattern'. */ +/* pattern matching is case-insensitive */ +/* patterns beginning with ';' are comments (never match) */ +/* patterns beginning with '!' are reverse-matched (returns FALSE if match) */ +/* patterns ending in '~' will match string anywhere (sub-string search) */ +/* patterns ending in '^' will match left string fragment only */ +/* patterns including '*' must match both left and right string fragments */ +/* all other patterns are exact-match checking */ +/****************************************************************************/ +BOOL findstr_in_string(const char* search, const char* pattern) +{ + char buf[256]; + char* p; + char* last; + const char* splat; + size_t len; + BOOL found = FALSE; + + if(pattern == NULL || search == NULL) + return FALSE; + + SAFECOPY(buf, pattern); + p = buf; + + if(*p == ';') /* comment */ + return FALSE; + + if(*p == '!') { /* reverse-match */ + found = TRUE; + p++; + } + + truncsp(p); + len = strlen(p); + if(len > 0) { + last = p + len - 1; + if(*last == '~') { + *last = '\0'; + if(strcasestr(search, p) != NULL) + found = !found; + } + + else if(*last == '^') { + if(strnicmp(p, search, len - 1) == 0) + found = !found; + } + + else if((splat = strchr(p, '*')) != NULL) { + int left = splat - p; + int right = len - (left + 1); + int slen = strlen(search); + if(slen < left + right) + return found; + if(strnicmp(search, p, left) == 0 + && strnicmp(p + left + 1, search + (slen - right), right) == 0) + found = !found; + } + + else if(stricmp(p, search) == 0) + found = !found; + } + return found; +} + +static uint32_t encode_ipv4_address(unsigned int byte[]) +{ + if(byte[0] > 0xff || byte[1] > 0xff || byte[2] > 0xff || byte[3] > 0xff) + return 0; + return (byte[0]<<24) | (byte[1]<<16) | (byte[2]<<8) | byte[3]; +} + +static uint32_t parse_ipv4_address(const char* str) +{ + unsigned int byte[4]; + + if(sscanf(str, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]) != 4) + return 0; + return encode_ipv4_address(byte); +} + +static uint32_t parse_cidr(const char* p, unsigned* subnet) +{ + unsigned int byte[4]; + + if(*p == '!') + p++; + + *subnet = 0; + if(sscanf(p, "%u.%u.%u.%u/%u", &byte[0], &byte[1], &byte[2], &byte[3], subnet) != 5 || *subnet > 32) + return 0; + return encode_ipv4_address(byte); +} + +static BOOL is_cidr_match(const char *p, uint32_t ip_addr, uint32_t cidr, unsigned subnet) +{ + BOOL match = FALSE; + + if(*p == '!') + match = TRUE; + + if(((ip_addr ^ cidr) >> (32-subnet)) == 0) + match = !match; + + return match; +} + +/****************************************************************************/ +/* Pattern matching string search of 'insearchof' in 'list'. */ +/****************************************************************************/ +BOOL findstr_in_list(const char* insearchof, str_list_t list) +{ + size_t index; + BOOL found=FALSE; + char* p; + uint32_t ip_addr, cidr; + unsigned subnet; + + if(list==NULL || insearchof==NULL) + return FALSE; + ip_addr = parse_ipv4_address(insearchof); + for(index=0; list[index]!=NULL; index++) { + p=list[index]; +// SKIP_WHITESPACE(p); + if(ip_addr != 0 && (cidr = parse_cidr(p, &subnet)) != 0) + found = is_cidr_match(p, ip_addr, cidr, subnet); + else + found = findstr_in_string(insearchof,p); + if(found != (*p=='!')) + break; + } + return found; +} + +/****************************************************************************/ +/* Pattern matching string search of 'insearchof' in 'fname'. */ +/****************************************************************************/ +BOOL findstr(const char* insearchof, const char* fname) +{ + char str[256]; + BOOL found=FALSE; + FILE* fp; + uint32_t ip_addr, cidr; + unsigned subnet; + + if(insearchof==NULL || fname==NULL || *fname == '\0') + return FALSE; + + if((fp=fopen(fname,"r"))==NULL) + return FALSE; + + ip_addr = parse_ipv4_address(insearchof); + while(!feof(fp) && !ferror(fp) && !found) { + if(!fgets(str,sizeof(str),fp)) + break; + char* p = str; + SKIP_WHITESPACE(p); + c_unescape_str(p); + if(ip_addr !=0 && (cidr = parse_cidr(p, &subnet)) != 0) + found = is_cidr_match(p, ip_addr, cidr, subnet); + else + found = findstr_in_string(insearchof, p); + } + + fclose(fp); + return found; +} + +static char* process_findstr_item(size_t index, char *str, void* cbdata) +{ + SKIP_WHITESPACE(str); + return c_unescape_str(str); +} + +/****************************************************************************/ +str_list_t findstr_list(const char* fname) +{ + FILE* fp; + str_list_t list; + + if((fp=fopen(fname,"r"))==NULL) + return NULL; + + list=strListReadFile(fp, NULL, /* Max line length: */255); + strListModifyEach(list, process_findstr_item, /* cbdata: */NULL); + + fclose(fp); + + return list; +} + diff --git a/src/sbbs3/findstr.h b/src/sbbs3/findstr.h new file mode 100644 index 0000000000000000000000000000000000000000..0a5c2814bd4c2b0938925b2c39f77dcf2ae24fab --- /dev/null +++ b/src/sbbs3/findstr.h @@ -0,0 +1,40 @@ +/* Synchronet find string functions */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _FINDSTR_H_ +#define _FINDSTR_H_ + +#include "str_list.h" +#include "dllexport.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DLLEXPORT BOOL findstr(const char *insearch, const char *fname); +DLLEXPORT BOOL findstr_in_string(const char* insearchof, const char* pattern); +DLLEXPORT BOOL findstr_in_list(const char* insearchof, str_list_t list); +DLLEXPORT str_list_t findstr_list(const char* fname); + +#ifdef __cplusplus +} +#endif +#endif /* Don't add anything after this line */ diff --git a/src/sbbs3/getctrl.c b/src/sbbs3/getctrl.c index 3f6e1f809134122de24ddb19fda34c58c9f4df2b..c3ffbcfbed49e8e03bc173b6b73b72d265357926 100644 --- a/src/sbbs3/getctrl.c +++ b/src/sbbs3/getctrl.c @@ -1,37 +1,35 @@ -#include <gen_defs.h> -#include <dirwrap.h> +/* Synchronet get "control" directory function */ -char *get_ctrl_dir(char *path, size_t pathsz) -{ -#ifdef PREFIX - char ini_file[MAX_PATH]; -#endif - char *p; - - p=getenv("SBBSCTRL"); - if(p!=NULL) { - strncpy(path, p, pathsz); - if(pathsz > 0) - path[pathsz-1]=0; - return path; - } +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ -#ifdef PREFIX - strncpy(path, PREFIX"/etc", pathsz); - if(pathsz > 0) - path[pathsz-1]=0; - iniFileName(ini_file, sizeof(ini_file)-1, PREFIX"/etc", "sbbs.ini"); - if(fexistcase(ini_file)) { - FILE* fini; - char* str; +#include <stdio.h> +#include "getctrl.h" +#include "sbbsdefs.h" - fini=iniOpenFile(ini_file, FALSE); - if(fini==NULL) - return NULL; - str = iniReadExistingString(fini, "Global", "CtrlDirectory", NULL, ini_file); - iniCloseFile(fini); - return str; +const char* get_ctrl_dir(BOOL warn) +{ + char* p = getenv("SBBSCTRL"); + if(p == NULL || *p == '\0') { + if(warn) + fprintf(stderr, "!SBBSCTRL environment variable not set, using default value: " SBBSCTRL_DEFAULT "\n\n"); + p = SBBSCTRL_DEFAULT; } -#endif - return NULL; + return p; } diff --git a/src/sbbs3/getctrl.h b/src/sbbs3/getctrl.h index 20713e9221becf013d5b504e3a3a3f3fe467a7d0..5a26f64665001038d25f7e2fff038bcec559ea84 100644 --- a/src/sbbs3/getctrl.h +++ b/src/sbbs3/getctrl.h @@ -1,9 +1,32 @@ -#ifndef GETCTRL_H -#define GETCTRL_H +/* Synchronet get "control" directory function */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef GETCTRL_H_ +#define GETCTRL_H_ + +#include "gen_defs.h" #if defined(__cplusplus) - extern "C" +extern "C" #endif -char *get_ctrl_dir(char *path, size_t pathsz) +const char* get_ctrl_dir(BOOL warn); #endif diff --git a/src/sbbs3/jsexec.vcxproj b/src/sbbs3/jsexec.vcxproj index 0bd5f22da99aefbfff95f91154129aaacc690e9d..fc16d40e6fb80e7d0f9dada63685535e719a9d01 100644 --- a/src/sbbs3/jsexec.vcxproj +++ b/src/sbbs3/jsexec.vcxproj @@ -157,6 +157,7 @@ </ProjectReference> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="getctrl.c" /> <ClCompile Include="jsdebug.c" /> <ClCompile Include="js_conio.c"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> diff --git a/src/sbbs3/load_cfg.vcxproj b/src/sbbs3/load_cfg.vcxproj index 6a164bb296fc83665a2716e1b86bfc2ac0ef67b5..3464a21fbde7bc0327ca557b026d29a1cae84f3f 100644 --- a/src/sbbs3/load_cfg.vcxproj +++ b/src/sbbs3/load_cfg.vcxproj @@ -101,6 +101,8 @@ <ItemGroup> <ClCompile Include="..\encode\utf8.c" /> <ClCompile Include="ars.c" /> + <ClCompile Include="findstr.c" /> + <ClCompile Include="getctrl.c" /> <ClCompile Include="load_cfg.c" /> <ClCompile Include="nopen.c" /> <ClCompile Include="readtext.c" /> diff --git a/src/sbbs3/ntsvcs.vcxproj b/src/sbbs3/ntsvcs.vcxproj index 20557eebb0504aa1800f428eb44bf72d447c0691..dd7180f6e7ab044ae8fe5c74dc588141aa82af52 100644 --- a/src/sbbs3/ntsvcs.vcxproj +++ b/src/sbbs3/ntsvcs.vcxproj @@ -148,6 +148,7 @@ </Bscmake> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="getctrl.c" /> <ClCompile Include="ntsvcs.c"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index ef00b376105744de4c578d04c30f40b74337b68e..61cc7b49bebe8e649ab5bcc66e401f19f5caa595 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -289,6 +289,7 @@ extern int thread_suid_broken; /* NPTL is no longer broken */ #include "nopen.h" #include "text.h" #include "str_util.h" +#include "findstr.h" #include "date_str.h" #include "load_cfg.h" #include "getstats.h" diff --git a/src/sbbs3/sbbs.vcxproj b/src/sbbs3/sbbs.vcxproj index 7d16015d0f5054032e140c842e77fa2d468cfff5..640e73a482c99b8a844e1253e24c0224cee90523 100644 --- a/src/sbbs3/sbbs.vcxproj +++ b/src/sbbs3/sbbs.vcxproj @@ -328,6 +328,7 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> + <ClCompile Include="findstr.c" /> <ClCompile Include="getkey.cpp"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/sbbs3/sbbscon.vcxproj b/src/sbbs3/sbbscon.vcxproj index 62e836144e096536cc18f31cdfae8e45574b6dce..8e96a5491b1dc180674ca689584a1634edceff3c 100644 --- a/src/sbbs3/sbbscon.vcxproj +++ b/src/sbbs3/sbbscon.vcxproj @@ -147,6 +147,7 @@ </Bscmake> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="getctrl.c" /> <ClCompile Include="sbbs_ini.c"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c index 45e693fd71553ea0ab2bda277c70023b2559d1fd..9020bb1e2f44b92a7e79e7a250a1b34e9d775f50 100644 --- a/src/sbbs3/sbbsecho.c +++ b/src/sbbs3/sbbsecho.c @@ -46,6 +46,7 @@ #include "link_list.h" #include "str_list.h" #include "str_util.h" +#include "findstr.h" #include "datewrap.h" #include "nopen.h" #include "crc32.h" diff --git a/src/sbbs3/scfglib.h b/src/sbbs3/scfglib.h index 9aae1d3781f540e1f611b5dc95abf806d0d367df..1c70181c1dc46395a764f189095fb527c5c3ea7c 100644 --- a/src/sbbs3/scfglib.h +++ b/src/sbbs3/scfglib.h @@ -72,6 +72,14 @@ DLLEXPORT BOOL is_valid_libnum(scfg_t*, int); DLLEXPORT BOOL is_valid_subnum(scfg_t*, int); DLLEXPORT BOOL is_valid_grpnum(scfg_t*, int); +DLLEXPORT BOOL trashcan(scfg_t* cfg, const char *insearch, const char *name); +DLLEXPORT char * trashcan_fname(scfg_t* cfg, const char *name, char* fname, size_t); +DLLEXPORT str_list_t trashcan_list(scfg_t* cfg, const char* name); + +DLLEXPORT char * sub_newsgroup_name(scfg_t*, sub_t*, char*, size_t); +DLLEXPORT char * sub_area_tag(scfg_t*, sub_t*, char*, size_t); +DLLEXPORT char * dir_area_tag(scfg_t*, dir_t*, char*, size_t); + faddr_t* nearest_sysfaddr(scfg_t*, faddr_t*); #ifdef __cplusplus diff --git a/src/sbbs3/scfglib1.c b/src/sbbs3/scfglib1.c index 0809b7e1631a920285b26831d84947b11994a767..1a7a8c4fc1d077724e9551a832e3802937ce4e88 100644 --- a/src/sbbs3/scfglib1.c +++ b/src/sbbs3/scfglib1.c @@ -23,6 +23,7 @@ #include "load_cfg.h" #include "nopen.h" #include "ars_defs.h" +#include "findstr.h" BOOL allocerr(FILE* fp, char* error, size_t maxerrlen, long offset, const char *fname, size_t size) { @@ -874,3 +875,96 @@ faddr_t* nearest_sysfaddr(scfg_t* cfg, faddr_t* addr) return &cfg->faddr[i]; return &cfg->faddr[0]; } + +/****************************************************************************/ +/* Searches the file <name>.can in the TEXT directory for matches */ +/* Returns TRUE if found in list, FALSE if not. */ +/****************************************************************************/ +BOOL trashcan(scfg_t* cfg, const char* insearchof, const char* name) +{ + char fname[MAX_PATH+1]; + + return(findstr(insearchof,trashcan_fname(cfg,name,fname,sizeof(fname)))); +} + +/****************************************************************************/ +char* trashcan_fname(scfg_t* cfg, const char* name, char* fname, size_t maxlen) +{ + safe_snprintf(fname,maxlen,"%s%s.can",cfg->text_dir,name); + return fname; +} + +/****************************************************************************/ +str_list_t trashcan_list(scfg_t* cfg, const char* name) +{ + char fname[MAX_PATH+1]; + + return findstr_list(trashcan_fname(cfg, name, fname, sizeof(fname))); +} + +char* sub_newsgroup_name(scfg_t* cfg, sub_t* sub, char* str, size_t size) +{ + memset(str, 0, size); + if(sub->newsgroup[0]) + strncpy(str, sub->newsgroup, size - 1); + else { + snprintf(str, size - 1, "%s.%s", cfg->grp[sub->grp]->sname, sub->sname); + /* + * From RFC5536: + * newsgroup-name = component *( "." component ) + * component = 1*component-char + * component-char = ALPHA / DIGIT / "+" / "-" / "_" + */ + if (str[0] == '.') + str[0] = '_'; + size_t c; + for(c = 0; str[c] != 0; c++) { + /* Legal characters */ + if ((str[c] >= 'A' && str[c] <= 'Z') + || (str[c] >= 'a' && str[c] <= 'z') + || (str[c] >= '0' && str[c] <= '9') + || str[c] == '+' + || str[c] == '-' + || str[c] == '_' + || str[c] == '.') + continue; + str[c] = '_'; + } + c--; + if (str[c] == '.') + str[c] = '_'; + } + return str; +} + +char* sub_area_tag(scfg_t* cfg, sub_t* sub, char* str, size_t size) +{ + char* p; + + memset(str, 0, size); + if(sub->area_tag[0]) + strncpy(str, sub->area_tag, size - 1); + else if(sub->newsgroup[0]) + strncpy(str, sub->newsgroup, size - 1); + else { + strncpy(str, sub->sname, size - 1); + REPLACE_CHARS(str, ' ', '_', p); + } + strupr(str); + return str; +} + +char* dir_area_tag(scfg_t* cfg, dir_t* dir, char* str, size_t size) +{ + char* p; + + memset(str, 0, size); + if(dir->area_tag[0]) + strncpy(str, dir->area_tag, size - 1); + else { + strncpy(str, dir->sname, size - 1); + REPLACE_CHARS(str, ' ', '_', p); + } + strupr(str); + return str; +} diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c index 9991892fbd22fe2b413d993b62f8f600feb526e3..ae91f70c47ec3b3df24f7d5271be64d4209ecc2f 100644 --- a/src/sbbs3/str_util.c +++ b/src/sbbs3/str_util.c @@ -19,6 +19,8 @@ * Note: If this box doesn't appear square, then you need to fix your tabs. * ****************************************************************************/ +#include "genwrap.h" +#include "dirwrap.h" #include "str_util.h" #include "utf8.h" #include "unicode.h" @@ -257,223 +259,6 @@ char* strip_char(const char* str, char* dest, char ch) return retval; } -/****************************************************************************/ -/* Pattern matching string search of 'insearchof' in 'pattern'. */ -/* pattern matching is case-insensitive */ -/* patterns beginning with ';' are comments (never match) */ -/* patterns beginning with '!' are reverse-matched (returns FALSE if match) */ -/* patterns ending in '~' will match string anywhere (sub-string search) */ -/* patterns ending in '^' will match left string fragment only */ -/* patterns including '*' must match both left and right string fragments */ -/* all other patterns are exact-match checking */ -/****************************************************************************/ -BOOL findstr_in_string(const char* search, const char* pattern) -{ - char buf[256]; - char* p; - char* last; - const char* splat; - size_t len; - BOOL found = FALSE; - - if(pattern == NULL || search == NULL) - return FALSE; - - SAFECOPY(buf, pattern); - p = buf; - - if(*p == ';') /* comment */ - return FALSE; - - if(*p == '!') { /* reverse-match */ - found = TRUE; - p++; - } - - truncsp(p); - len = strlen(p); - if(len > 0) { - last = p + len - 1; - if(*last == '~') { - *last = '\0'; - if(strcasestr(search, p) != NULL) - found = !found; - } - - else if(*last == '^') { - if(strnicmp(p, search, len - 1) == 0) - found = !found; - } - - else if((splat = strchr(p, '*')) != NULL) { - int left = splat - p; - int right = len - (left + 1); - int slen = strlen(search); - if(slen < left + right) - return found; - if(strnicmp(search, p, left) == 0 - && strnicmp(p + left + 1, search + (slen - right), right) == 0) - found = !found; - } - - else if(stricmp(p, search) == 0) - found = !found; - } - return found; -} - -static uint32_t encode_ipv4_address(unsigned int byte[]) -{ - if(byte[0] > 0xff || byte[1] > 0xff || byte[2] > 0xff || byte[3] > 0xff) - return 0; - return (byte[0]<<24) | (byte[1]<<16) | (byte[2]<<8) | byte[3]; -} - -static uint32_t parse_ipv4_address(const char* str) -{ - unsigned int byte[4]; - - if(sscanf(str, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]) != 4) - return 0; - return encode_ipv4_address(byte); -} - -static uint32_t parse_cidr(const char* p, unsigned* subnet) -{ - unsigned int byte[4]; - - if(*p == '!') - p++; - - *subnet = 0; - if(sscanf(p, "%u.%u.%u.%u/%u", &byte[0], &byte[1], &byte[2], &byte[3], subnet) != 5 || *subnet > 32) - return 0; - return encode_ipv4_address(byte); -} - -static BOOL is_cidr_match(const char *p, uint32_t ip_addr, uint32_t cidr, unsigned subnet) -{ - BOOL match = FALSE; - - if(*p == '!') - match = TRUE; - - if(((ip_addr ^ cidr) >> (32-subnet)) == 0) - match = !match; - - return match; -} - -/****************************************************************************/ -/* Pattern matching string search of 'insearchof' in 'list'. */ -/****************************************************************************/ -BOOL findstr_in_list(const char* insearchof, str_list_t list) -{ - size_t index; - BOOL found=FALSE; - char* p; - uint32_t ip_addr, cidr; - unsigned subnet; - - if(list==NULL || insearchof==NULL) - return FALSE; - ip_addr = parse_ipv4_address(insearchof); - for(index=0; list[index]!=NULL; index++) { - p=list[index]; -// SKIP_WHITESPACE(p); - if(ip_addr != 0 && (cidr = parse_cidr(p, &subnet)) != 0) - found = is_cidr_match(p, ip_addr, cidr, subnet); - else - found = findstr_in_string(insearchof,p); - if(found != (*p=='!')) - break; - } - return found; -} - -/****************************************************************************/ -/* Pattern matching string search of 'insearchof' in 'fname'. */ -/****************************************************************************/ -BOOL findstr(const char* insearchof, const char* fname) -{ - char str[256]; - BOOL found=FALSE; - FILE* fp; - uint32_t ip_addr, cidr; - unsigned subnet; - - if(insearchof==NULL || fname==NULL) - return FALSE; - - if((fp=fopen(fname,"r"))==NULL) - return FALSE; - - ip_addr = parse_ipv4_address(insearchof); - while(!feof(fp) && !ferror(fp) && !found) { - if(!fgets(str,sizeof(str),fp)) - break; - char* p = str; - SKIP_WHITESPACE(p); - c_unescape_str(p); - if(ip_addr !=0 && (cidr = parse_cidr(p, &subnet)) != 0) - found = is_cidr_match(p, ip_addr, cidr, subnet); - else - found = findstr_in_string(insearchof, p); - } - - fclose(fp); - return found; -} - -/****************************************************************************/ -/* Searches the file <name>.can in the TEXT directory for matches */ -/* Returns TRUE if found in list, FALSE if not. */ -/****************************************************************************/ -BOOL trashcan(scfg_t* cfg, const char* insearchof, const char* name) -{ - char fname[MAX_PATH+1]; - - return(findstr(insearchof,trashcan_fname(cfg,name,fname,sizeof(fname)))); -} - -/****************************************************************************/ -char* trashcan_fname(scfg_t* cfg, const char* name, char* fname, size_t maxlen) -{ - safe_snprintf(fname,maxlen,"%s%s.can",cfg->text_dir,name); - return fname; -} - -static char* process_findstr_item(size_t index, char *str, void* cbdata) -{ - SKIP_WHITESPACE(str); - return c_unescape_str(str); -} - -/****************************************************************************/ -str_list_t findstr_list(const char* fname) -{ - FILE* fp; - str_list_t list; - - if((fp=fopen(fname,"r"))==NULL) - return NULL; - - list=strListReadFile(fp, NULL, /* Max line length: */255); - strListModifyEach(list, process_findstr_item, /* cbdata: */NULL); - - fclose(fp); - - return list; -} - -/****************************************************************************/ -str_list_t trashcan_list(scfg_t* cfg, const char* name) -{ - char fname[MAX_PATH+1]; - - return findstr_list(trashcan_fname(cfg, name, fname, sizeof(fname))); -} - /****************************************************************************/ /* Returns in 'string' a character representation of the number in l with */ /* thousands separators (e.g. commas). */ @@ -910,81 +695,3 @@ char* utf8_to_cp437_inplace(char* str) ,/* decode error char: */CP437_INVERTED_EXCLAMATION_MARK); } -char* sub_newsgroup_name(scfg_t* cfg, sub_t* sub, char* str, size_t size) -{ - memset(str, 0, size); - if(sub->newsgroup[0]) - strncpy(str, sub->newsgroup, size - 1); - else { - snprintf(str, size - 1, "%s.%s", cfg->grp[sub->grp]->sname, sub->sname); - /* - * From RFC5536: - * newsgroup-name = component *( "." component ) - * component = 1*component-char - * component-char = ALPHA / DIGIT / "+" / "-" / "_" - */ - if (str[0] == '.') - str[0] = '_'; - size_t c; - for(c = 0; str[c] != 0; c++) { - /* Legal characters */ - if ((str[c] >= 'A' && str[c] <= 'Z') - || (str[c] >= 'a' && str[c] <= 'z') - || (str[c] >= '0' && str[c] <= '9') - || str[c] == '+' - || str[c] == '-' - || str[c] == '_' - || str[c] == '.') - continue; - str[c] = '_'; - } - c--; - if (str[c] == '.') - str[c] = '_'; - } - return str; -} - -char* sub_area_tag(scfg_t* cfg, sub_t* sub, char* str, size_t size) -{ - char* p; - - memset(str, 0, size); - if(sub->area_tag[0]) - strncpy(str, sub->area_tag, size - 1); - else if(sub->newsgroup[0]) - strncpy(str, sub->newsgroup, size - 1); - else { - strncpy(str, sub->sname, size - 1); - REPLACE_CHARS(str, ' ', '_', p); - } - strupr(str); - return str; -} - -char* dir_area_tag(scfg_t* cfg, dir_t* dir, char* str, size_t size) -{ - char* p; - - memset(str, 0, size); - if(dir->area_tag[0]) - strncpy(str, dir->area_tag, size - 1); - else { - strncpy(str, dir->sname, size - 1); - REPLACE_CHARS(str, ' ', '_', p); - } - strupr(str); - return str; -} - -char* get_ctrl_dir(BOOL warn) -{ - char* p = getenv("SBBSCTRL"); - if(p == NULL || *p == '\0') { - if(warn) - fprintf(stderr, "!SBBSCTRL environment variable not set, using default value: " SBBSCTRL_DEFAULT "\n\n"); - p = SBBSCTRL_DEFAULT; - } - return p; -} - diff --git a/src/sbbs3/str_util.h b/src/sbbs3/str_util.h index 5b9e4b44a4325213c2e707ebf23f910c2d83ae58..8acc11918f5beb7cd095a7465adcfd209dda8ddd 100644 --- a/src/sbbs3/str_util.h +++ b/src/sbbs3/str_util.h @@ -22,7 +22,7 @@ #ifndef _STR_UTIL_H_ #define _STR_UTIL_H_ -#include "scfgdefs.h" // scfg_t +#include "gen_defs.h" #include "dllexport.h" #ifdef __cplusplus @@ -45,13 +45,6 @@ DLLEXPORT char * replace_named_values(const char* src ,char* buf, size_t bufl named_int_t* int_list, BOOL case_sensitive); DLLEXPORT char * condense_whitespace(char* str); DLLEXPORT char exascii_to_ascii_char(uchar ch); -DLLEXPORT BOOL findstr(const char *insearch, const char *fname); -DLLEXPORT BOOL findstr_in_string(const char* insearchof, const char* pattern); -DLLEXPORT BOOL findstr_in_list(const char* insearchof, str_list_t list); -DLLEXPORT str_list_t findstr_list(const char* fname); -DLLEXPORT BOOL trashcan(scfg_t* cfg, const char *insearch, const char *name); -DLLEXPORT char * trashcan_fname(scfg_t* cfg, const char *name, char* fname, size_t); -DLLEXPORT str_list_t trashcan_list(scfg_t* cfg, const char* name); DLLEXPORT char * convert_ansi(const char* src, char* dest, size_t, int width, BOOL ice_color); DLLEXPORT char * strip_ansi(char* str); DLLEXPORT char * strip_exascii(const char *str, char* dest); @@ -59,7 +52,6 @@ DLLEXPORT char * strip_cp437_graphics(const char *str, char* dest); DLLEXPORT char * strip_space(const char *str, char* dest); DLLEXPORT char * strip_ctrl(const char *str, char* dest); DLLEXPORT char * strip_char(const char* str, char* dest, char); -DLLEXPORT char * net_addr(net_t* net); DLLEXPORT BOOL valid_ctrl_a_attr(char a); DLLEXPORT BOOL valid_ctrl_a_code(char a); DLLEXPORT size_t strip_invalid_attr(char *str); @@ -70,10 +62,6 @@ DLLEXPORT uint32_t str_to_bits(uint32_t currval, const char *str); DLLEXPORT BOOL str_has_ctrl(const char*); DLLEXPORT BOOL str_is_ascii(const char*); DLLEXPORT char * utf8_to_cp437_inplace(char* str); -DLLEXPORT char * sub_newsgroup_name(scfg_t*, sub_t*, char*, size_t); -DLLEXPORT char * sub_area_tag(scfg_t*, sub_t*, char*, size_t); -DLLEXPORT char * dir_area_tag(scfg_t*, dir_t*, char*, size_t); -DLLEXPORT char * get_ctrl_dir(BOOL warn); #ifdef __cplusplus } diff --git a/src/sbbs3/textgen.vcxproj b/src/sbbs3/textgen.vcxproj index ca934051992391d8e7534f6afb9e8eb9cb40bb41..29a6f3c99867cd91e710eb9e7cfb2ba43fbc61fe 100644 --- a/src/sbbs3/textgen.vcxproj +++ b/src/sbbs3/textgen.vcxproj @@ -156,6 +156,7 @@ </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="..\encode\utf8.c" /> + <ClCompile Include="getctrl.c" /> <ClCompile Include="str_util.c" /> <ClCompile Include="textgen.c"> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index 88d62e8cfb0b01eae5e3b9a2c4655a3ada1ffe95..b800fe26c3b096242fcbf8fc100bdfa5de27b0fa 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -20,6 +20,7 @@ ****************************************************************************/ #include "str_util.h" +#include "findstr.h" #include "cmdshell.h" #include "userdat.h" #include "filedat.h"