Skip to content
Snippets Groups Projects
Commit ad2cee68 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Add support for ctrl/text.ini, used for sysop-override of text.dat strings

The syntax of text.ini is:
<id>: "string"
<id>: "string"

Where <id> is the named identifier of a text.dat string as seen ctrl/text.dat
and string is a literal string value (optionally, in double-quotes). Line
continuations (for long strings) are not supported: you'll just need to put
your string all on one long line (up to 1024 char string).
C-escape characters for control chars and hex-encoded chars are supported.

This should address feature request issue #644
parent 31baaede
No related branches found
No related tags found
1 merge request!455Update branch with changes from master
......@@ -25,6 +25,7 @@
#include "nopen.h"
#include "datewrap.h"
#include "text.h" /* TOTAL_TEXT */
#include "ini_file.h"
#ifdef USE_CRYPTLIB
#include "cryptlib.h"
#endif
......@@ -37,6 +38,15 @@ int lprintf(int level, const char *fmt, ...); /* log output */
/* readtext.c */
char * readtext(long *line, FILE *stream, long dflt);
int get_text_num(const char* id)
{
int i;
for (i = 0; i < TOTAL_TEXT; ++i)
if (strcmp(text_id[i], id) == 0)
break;
return i;
}
/****************************************************************************/
/* Initializes system and node configuration information and data variables */
/****************************************************************************/
......@@ -44,7 +54,7 @@ BOOL load_cfg(scfg_t* cfg, char* text[], BOOL prep, BOOL req_cfg, char* error, s
{
int i;
long line=0L;
FILE *instream;
FILE* fp;
char str[256];
if(cfg->size!=sizeof(scfg_t)) {
......@@ -90,16 +100,16 @@ BOOL load_cfg(scfg_t* cfg, char* text[], BOOL prep, BOOL req_cfg, char* error, s
free_text(text);
SAFEPRINTF(str,"%stext.dat",cfg->ctrl_dir);
if((instream=fnopen(NULL,str,O_RDONLY))==NULL) {
if((fp=fnopen(NULL,str,O_RDONLY))==NULL) {
safe_snprintf(error, maxerrlen,"%d opening %s",errno,str);
return(FALSE);
}
for(i=0;i<TOTAL_TEXT;i++)
if((text[i]=readtext(&line,instream,i))==NULL) {
if((text[i]=readtext(&line,fp,i))==NULL) {
i--;
break;
}
fclose(instream);
fclose(fp);
if(i<TOTAL_TEXT) {
safe_snprintf(error, maxerrlen,"line %d: Less than TOTAL_TEXT (%u) strings defined in %s."
......@@ -107,6 +117,31 @@ BOOL load_cfg(scfg_t* cfg, char* text[], BOOL prep, BOOL req_cfg, char* error, s
,TOTAL_TEXT,str);
return(FALSE);
}
SAFEPRINTF(str, "%stext.ini", cfg->ctrl_dir);
if ((fp = fnopen(NULL, str, O_RDONLY)) != NULL) {
BOOL success = TRUE;
str_list_t ini = iniReadFile(fp);
fclose(fp);
named_string_t** list = iniGetNamedStringList(ini, ROOT_SECTION);
for (i = 0; list != NULL && list[i] != NULL; ++i) {
int n = get_text_num(list[i]->name);
if (n >= TOTAL_TEXT) {
safe_snprintf(error, maxerrlen, "%s text ID (%s) not recognized"
,str
,list[i]->name);
success = FALSE;
break;
}
free(text[n]);
text[n] = strdup(list[i]->value);
}
iniFreeNamedStringList(list);
iniFreeStringList(ini);
if (!success)
return FALSE;
}
cfg->text = text;
}
......
......@@ -34,6 +34,7 @@ extern "C" {
DLLEXPORT BOOL load_cfg(scfg_t* cfg, char* text[], BOOL prep, BOOL req_node, char* error, size_t);
DLLEXPORT void free_cfg(scfg_t* cfg);
DLLEXPORT void free_text(char* text[]);
DLLEXPORT int get_text_num(const char* id);
DLLEXPORT ushort sys_timezone(scfg_t* cfg);
DLLEXPORT char * prep_dir(const char* base, char* dir, size_t buflen);
DLLEXPORT char * prep_code(char *str, const char* prefix);
......
......@@ -728,6 +728,7 @@ public:
bool gettimeleft_inside = false;
/* str.cpp */
const char* gettext(const char* id);
char* server_host_name(void);
char* timestr(time_t);
char* datestr(time_t);
......
......@@ -719,6 +719,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="text_id.c" />
<ClCompile Include="text_sec.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
......
......@@ -22,6 +22,15 @@
#include "sbbs.h"
#include "dat_rec.h"
const char* sbbs_t::gettext(const char* id)
{
// TODO: hash/cache results
int i = get_text_num(id);
if(i >= 0 && i < TOTAL_TEXT)
return text[i];
return NULL;
}
/****************************************************************************/
/* Lists all users who have access to the current sub. */
/****************************************************************************/
......
......@@ -10,6 +10,12 @@
#ifndef _TEXT_H
#define _TEXT_H
extern
#ifdef __cplusplus
"C"
#endif
const char* const text_id[];
enum {
MsgSubj
,MsgAttr
......@@ -422,12 +428,12 @@ enum {
,PasswordNotChanged
,PasswordInvalid
,PasswordObvious
,ComputerTypeMenu
,ComputerTypePrompt
,ComputerTypeB
,ComputerTypeC
,ComputerTypeD
,ComputerTypeE
,Unused412
,Unused413
,Unused414
,Unused415
,Unused416
,Unused417
,NoUserData
,Deleted
,Inactive
......
......@@ -680,14 +680,12 @@ const char * const text_defaults[TOTAL_TEXT]={
"\x6e" // 410 PasswordInvalid
,"\x01\x72\x01\x68\x01\x69\x54\x68\x61\x74\x20\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x69\x73\x20\x74\x6f\x6f\x20\x6f\x62\x76\x69\x6f"
"\x75\x73\x21\x01\x6e" // 411 PasswordObvious
,"\x0d\x0a\x01\x6e\x41\x29\x20\x49\x42\x4d\x20\x28\x6f\x72\x20\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x29\x0d\x0a\x42\x29\x20\x41"
"\x70\x70\x6c\x65\x0d\x0a\x43\x29\x20\x4d\x61\x63\x69\x6e\x74\x6f\x73\x68\x0d\x0a\x44\x29\x20\x41\x6d\x69\x67\x61\x0d\x0a\x45\x29"
"\x20\x4f\x74\x68\x65\x72\x0d\x0a\x0d\x0a" // 412 ComputerTypeMenu
,"\x01\x5f\x01\x79\x01\x68\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x3a\x20\x01\x6e" // 413 ComputerTypePrompt
,"\x41\x70\x70\x6c\x65" // 414 ComputerTypeB
,"\x4d\x61\x63\x69\x6e\x74\x6f\x73\x68" // 415 ComputerTypeC
,"\x41\x6d\x69\x67\x61" // 416 ComputerTypeD
,"\x4f\x74\x68\x65\x72" // 417 ComputerTypeE
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x32" // 412 Unused412
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x33" // 413 Unused413
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x34" // 414 Unused414
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x35" // 415 Unused415
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x36" // 416 Unused416
,"\x55\x4e\x55\x53\x45\x44\x34\x31\x37" // 417 Unused417
,"\x07\x0d\x0a\x4e\x6f\x20\x75\x73\x65\x72\x20\x64\x61\x74\x61\x20\x64\x65\x66\x69\x6e\x65\x64\x2e\x0d\x0a" // 418 NoUserData
,"\x01\x72\x01\x68\xae\xae\xae\x20\x01\x69\x44\x45\x4c\x45\x54\x45\x44\x01\x6e\x01\x72\x01\x68\x20\xaf\xaf\xaf\x0d\x0a" // 419 Deleted
,"\x01\x62\x01\x68\xae\xae\xae\x20\x01\x69\x49\x4e\x41\x43\x54\x49\x56\x45\x01\x6e\x01\x62\x01\x68\x20\xaf\xaf\xaf\x0d\x0a" // 420 Inactive
......
......@@ -165,6 +165,7 @@ int main(int argc, char **argv)
int i=0;
FILE *text_h;
FILE *text_js;
FILE *text_id;
FILE *text_defaults_c;
if(argc > 1)
......@@ -186,12 +187,17 @@ int main(int argc, char **argv)
fputs("\n",text_h);
fputs("/****************************************************************************/\n",text_h);
fputs("/* Macros for elements of the array of pointers (text[]) to static text */\n",text_h);
fputs("/* Auto-generated from CTRL\\TEXT.DAT */\n",text_h);
fputs("/* Auto-generated from ctrl/text.dat */\n",text_h);
fputs("/****************************************************************************/\n",text_h);
fputs("\n",text_h);
fputs("#ifndef _TEXT_H\n",text_h);
fputs("#define _TEXT_H\n",text_h);
fputs("\n",text_h);
fputs("extern\n", text_h);
fputs("#ifdef __cplusplus\n", text_h);
fputs("\"C\"\n", text_h);
fputs("#endif\n", text_h);
fputs("const char* const text_id[];\n\n", text_h);
fputs("enum {\n",text_h);
if(argc > 2)
......@@ -225,6 +231,12 @@ int main(int argc, char **argv)
fputs("#include \"text_defaults.h\"\n",text_defaults_c);
fputs("\n",text_defaults_c);
fputs("const char * const text_defaults[TOTAL_TEXT]={\n",text_defaults_c);
if ((text_id = fopen("text_id.c", "w")) == NULL) {
fprintf(stderr, "Can't open text_id.c!\n");
return __LINE__;
}
fprintf(text_id, "// Synchronet text.dat string identifiers\n\n");
fprintf(text_id, "const char* const text_id[]={\n");
do {
i++;
p=readtext(text_dat, &comment);
......@@ -241,6 +253,7 @@ int main(int argc, char **argv)
}
fprintf(text_h, "\t%c%s\n", i==1?' ':',', macro);
fprintf(text_js, "var %s=%d;\n", macro, i);
fprintf(text_id, "\t%c\"%s\"\n", i == 1 ? ' ' : ',', macro);
fprintf(text_defaults_c, "\t%c%s // %s\n", i==1?' ':',', cstr, comment);
}
} while(p != NULL);
......@@ -258,6 +271,8 @@ int main(int argc, char **argv)
fclose(text_js);
fputs("};\n",text_defaults_c);
fclose(text_defaults_c);
fputs("};\n", text_id);
fclose(text_id);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment