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

Add optional/configurable feedback module

Most sysops didn't know it, but if exec/feedback.* existed, it would be
executed just before any user sent an email to the sysop (user #1),
excluding new user validation requests:
- make this module name configurable and loadable from mods
- support JS module here (exit(1) to abort the feedback)
- invoke for email being sent to *any* sysop (not just user #1)
- don't invoke the module when sending *from* a sysop account

This fixes issue #16
parent 67c1b25d
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #3864 passed
...@@ -38,12 +38,12 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode, ...@@ -38,12 +38,12 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
uint16_t msgattr=0; uint16_t msgattr=0;
uint16_t xlat=XLAT_NONE; uint16_t xlat=XLAT_NONE;
int i,j,x,file; int i,j,x,file;
int l;
int length; int length;
off_t offset; off_t offset;
uint32_t crc=0xffffffffUL; uint32_t crc=0xffffffffUL;
FILE* instream; FILE* instream;
node_t node; node_t node;
user_t user{};
smbmsg_t msg; smbmsg_t msg;
if(subj != NULL) if(subj != NULL)
...@@ -55,35 +55,29 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode, ...@@ -55,35 +55,29 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
bputs(text[TooManyEmailsToday]); bputs(text[TooManyEmailsToday]);
return(false); return(false);
} }
if(usernumber==1 && useron.rest&FLAG('S') user.number = usernumber;
&& (cfg.valuser!=1 || useron.fbacks || useron.emails)) { /* ! val fback */ if(getuserdat(&cfg, &user) != 0 || (user.misc & (DELETED | INACTIVE))) {
bputs(text[UnknownUser]);
return(false);
}
bool to_sysop = is_user_sysop(&user);
if(to_sysop && useron.rest&FLAG('S')
&& (cfg.valuser!=usernumber || useron.fbacks || useron.emails)) { /* ! val fback */
bprintf(text[R_Feedback],cfg.sys_op); bprintf(text[R_Feedback],cfg.sys_op);
return(false); return(false);
} }
if(usernumber!=1 && useron.rest&FLAG('E') if(!to_sysop && useron.rest&FLAG('E')
&& (cfg.valuser!=usernumber || useron.fbacks || useron.emails)) { && (cfg.valuser!=usernumber || useron.fbacks || useron.emails)) {
bputs(text[R_Email]); bputs(text[R_Email]);
return(false); return(false);
} }
if(!usernumber) { if((user.misc&NETMAIL) && (cfg.sys_misc&SM_FWDTONET) && !(mode & WM_NOFWD) && !(useron.rest&FLAG('M'))) {
bputs(text[UnknownUser]); if(is_supported_netmail_addr(&cfg, user.netmail)) {
return(false); bprintf(text[UserNetMail], user.netmail);
}
str[0] = '\0';
l = getusermisc(&cfg, usernumber);
if(l&(DELETED|INACTIVE)) { /* Deleted or Inactive User */
bputs(text[UnknownUser]);
return(false);
}
if((l&NETMAIL) && (cfg.sys_misc&SM_FWDTONET) && !(mode & WM_NOFWD) && !(useron.rest&FLAG('M'))) {
str[0] = '\0';
if(getuserstr(&cfg, usernumber, USER_NETMAIL, str, sizeof(str)) != NULL
&& is_supported_netmail_addr(&cfg, str)) {
bprintf(text[UserNetMail],str);
if((mode & WM_FORCEFWD) || yesno(text[ForwardMailQ])) /* Forward to netmail address */ if((mode & WM_FORCEFWD) || yesno(text[ForwardMailQ])) /* Forward to netmail address */
return(netmail(str, subj, mode, resmb, remsg)); return(netmail(user.netmail, subj, mode, resmb, remsg));
} else { } else {
bprintf(text[InvalidNetMailAddr], str); bprintf(text[InvalidNetMailAddr], user.netmail);
} }
} }
if(sys_status&SS_ABORT) { if(sys_status&SS_ABORT) {
...@@ -94,10 +88,10 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode, ...@@ -94,10 +88,10 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
action=NODE_SMAL; action=NODE_SMAL;
nodesync(); nodesync();
SAFEPRINTF(str,"%sfeedback.*", cfg.exec_dir); if(cfg.feedback_mod[0] && to_sysop && !SYSOP
if(usernumber==cfg.valuser && useron.fbacks && fexist(str)) { && (useron.fbacks || usernumber != cfg.valuser)) {
exec_bin("feedback",&main_csi); main_csi.logic = LOGIC_TRUE;
if(main_csi.logic!=LOGIC_TRUE) if(exec_bin(cfg.feedback_mod, &main_csi) != 0 || main_csi.logic != LOGIC_TRUE)
return(false); return(false);
} }
...@@ -164,7 +158,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode, ...@@ -164,7 +158,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
safe_snprintf(tmp,sizeof(tmp),"%s%s",cfg.temp_dir,title); safe_snprintf(tmp,sizeof(tmp),"%s%s",cfg.temp_dir,title);
if(!fexistcase(str2) && fexistcase(tmp)) if(!fexistcase(str2) && fexistcase(tmp))
mv(tmp,str2,0); mv(tmp,str2,0);
l=(int)flength(str2); off_t l=flength(str2);
if(l>0) if(l>0)
bprintf(text[FileNBytesReceived],title,ultoac(l,tmp)); bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
else { else {
......
...@@ -2602,6 +2602,7 @@ void sys_cfg(void) ...@@ -2602,6 +2602,7 @@ void sys_cfg(void)
sprintf(opt[i++],"%-16.16s%s","New User",cfg.newuser_mod); sprintf(opt[i++],"%-16.16s%s","New User",cfg.newuser_mod);
sprintf(opt[i++],"%-16.16s%s","Expired User",cfg.expire_mod); sprintf(opt[i++],"%-16.16s%s","Expired User",cfg.expire_mod);
sprintf(opt[i++],"%-16.16s%s","Auto Message",cfg.automsg_mod); sprintf(opt[i++],"%-16.16s%s","Auto Message",cfg.automsg_mod);
sprintf(opt[i++],"%-16.16s%s","Send Feedback",cfg.feedback_mod);
sprintf(opt[i++],"%-16.16s%s","Text Section",cfg.textsec_mod); sprintf(opt[i++],"%-16.16s%s","Text Section",cfg.textsec_mod);
sprintf(opt[i++],"%-16.16s%s","Xtrn Section",cfg.xtrnsec_mod); sprintf(opt[i++],"%-16.16s%s","Xtrn Section",cfg.xtrnsec_mod);
sprintf(opt[i++],"%-16.16s%s","Pre Xtrn",cfg.prextrn_mod); sprintf(opt[i++],"%-16.16s%s","Pre Xtrn",cfg.prextrn_mod);
...@@ -2636,6 +2637,7 @@ void sys_cfg(void) ...@@ -2636,6 +2637,7 @@ void sys_cfg(void)
"`New User` End of new terminal user creation process\n" "`New User` End of new terminal user creation process\n"
"`Expired User` User account expires (offline)\n" "`Expired User` User account expires (offline)\n"
"`Auto Message` User chooses to re-read or edit the auto-message\n" "`Auto Message` User chooses to re-read or edit the auto-message\n"
"`Send Feedback` User sending email to a sysop (return error to cancel)\n"
"`Text Section` Handle general text file (viewing) section\n" "`Text Section` Handle general text file (viewing) section\n"
"`Xtrn Section` Handle external programs (doors) section\n" "`Xtrn Section` Handle external programs (doors) section\n"
"`Pre Xtrn` Executed before external programs (doors) run\n" "`Pre Xtrn` Executed before external programs (doors) run\n"
...@@ -2698,74 +2700,78 @@ void sys_cfg(void) ...@@ -2698,74 +2700,78 @@ void sys_cfg(void)
,cfg.automsg_mod,sizeof(cfg.automsg_mod)-1,K_EDIT); ,cfg.automsg_mod,sizeof(cfg.automsg_mod)-1,K_EDIT);
break; break;
case 8: case 8:
uifc.input(WIN_MID|WIN_SAV,0,0,"Send Feedback Module"
,cfg.feedback_mod,sizeof(cfg.feedback_mod)-1,K_EDIT);
break;
case 9:
uifc.input(WIN_MID|WIN_SAV,0,0,"Text File Section Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Text File Section Module"
,cfg.textsec_mod,sizeof(cfg.textsec_mod)-1,K_EDIT); ,cfg.textsec_mod,sizeof(cfg.textsec_mod)-1,K_EDIT);
break; break;
case 9: case 10:
uifc.input(WIN_MID|WIN_SAV,0,0,"External Program Section Module" uifc.input(WIN_MID|WIN_SAV,0,0,"External Program Section Module"
,cfg.xtrnsec_mod,sizeof(cfg.xtrnsec_mod)-1,K_EDIT); ,cfg.xtrnsec_mod,sizeof(cfg.xtrnsec_mod)-1,K_EDIT);
break; break;
case 10: case 11:
uifc.input(WIN_MID|WIN_SAV,0,0,"Pre External Program Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Pre External Program Module"
,cfg.prextrn_mod,sizeof(cfg.prextrn_mod)-1,K_EDIT); ,cfg.prextrn_mod,sizeof(cfg.prextrn_mod)-1,K_EDIT);
break; break;
case 11: case 12:
uifc.input(WIN_MID|WIN_SAV,0,0,"Post External Program Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Post External Program Module"
,cfg.postxtrn_mod,sizeof(cfg.postxtrn_mod)-1,K_EDIT); ,cfg.postxtrn_mod,sizeof(cfg.postxtrn_mod)-1,K_EDIT);
break; break;
case 12: case 13:
uifc.input(WIN_MID|WIN_SAV,0,0,"Read Mail Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Read Mail Module"
,cfg.readmail_mod,sizeof(cfg.readmail_mod)-1,K_EDIT); ,cfg.readmail_mod,sizeof(cfg.readmail_mod)-1,K_EDIT);
break; break;
case 13: case 14:
uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Msgs Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Msgs Module"
,cfg.scanposts_mod,sizeof(cfg.scanposts_mod)-1,K_EDIT); ,cfg.scanposts_mod,sizeof(cfg.scanposts_mod)-1,K_EDIT);
break; break;
case 14: case 15:
uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Subs Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Subs Module"
,cfg.scansubs_mod,sizeof(cfg.scansubs_mod)-1,K_EDIT); ,cfg.scansubs_mod,sizeof(cfg.scansubs_mod)-1,K_EDIT);
break; break;
case 15: case 16:
uifc.input(WIN_MID|WIN_SAV,0,0,"List Msgs Module" uifc.input(WIN_MID|WIN_SAV,0,0,"List Msgs Module"
,cfg.listmsgs_mod,sizeof(cfg.listmsgs_mod)-1,K_EDIT); ,cfg.listmsgs_mod,sizeof(cfg.listmsgs_mod)-1,K_EDIT);
break; break;
case 16: case 17:
uifc.input(WIN_MID|WIN_SAV,0,0,"List Logons Module" uifc.input(WIN_MID|WIN_SAV,0,0,"List Logons Module"
,cfg.logonlist_mod,sizeof(cfg.logonlist_mod)-1,K_EDIT); ,cfg.logonlist_mod,sizeof(cfg.logonlist_mod)-1,K_EDIT);
break; break;
case 17: case 18:
uifc.input(WIN_MID|WIN_SAV,0,0,"List Users" uifc.input(WIN_MID|WIN_SAV,0,0,"List Users"
,cfg.userlist_mod,sizeof(cfg.userlist_mod)-1,K_EDIT); ,cfg.userlist_mod,sizeof(cfg.userlist_mod)-1,K_EDIT);
break; break;
case 18: case 19:
uifc.input(WIN_MID|WIN_SAV,0,0,"List Nodes Module" uifc.input(WIN_MID|WIN_SAV,0,0,"List Nodes Module"
,cfg.nodelist_mod,sizeof(cfg.nodelist_mod)-1,K_EDIT); ,cfg.nodelist_mod,sizeof(cfg.nodelist_mod)-1,K_EDIT);
break; break;
case 19: case 20:
uifc.input(WIN_MID|WIN_SAV,0,0,"Who's Online Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Who's Online Module"
,cfg.whosonline_mod,sizeof(cfg.whosonline_mod)-1,K_EDIT); ,cfg.whosonline_mod,sizeof(cfg.whosonline_mod)-1,K_EDIT);
break; break;
case 20: case 21:
uifc.input(WIN_MID|WIN_SAV,0,0,"Private Message Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Private Message Module"
,cfg.privatemsg_mod,sizeof(cfg.privatemsg_mod)-1,K_EDIT); ,cfg.privatemsg_mod,sizeof(cfg.privatemsg_mod)-1,K_EDIT);
break; break;
case 21: case 22:
uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Dirs Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Scan Dirs Module"
,cfg.scandirs_mod,sizeof(cfg.scandirs_mod)-1,K_EDIT); ,cfg.scandirs_mod,sizeof(cfg.scandirs_mod)-1,K_EDIT);
break; break;
case 22: case 23:
uifc.input(WIN_MID|WIN_SAV,0,0,"List Files Module" uifc.input(WIN_MID|WIN_SAV,0,0,"List Files Module"
,cfg.listfiles_mod,sizeof(cfg.listfiles_mod)-1,K_EDIT); ,cfg.listfiles_mod,sizeof(cfg.listfiles_mod)-1,K_EDIT);
break; break;
case 23: case 24:
uifc.input(WIN_MID|WIN_SAV,0,0,"View File Information Module" uifc.input(WIN_MID|WIN_SAV,0,0,"View File Information Module"
,cfg.fileinfo_mod,sizeof(cfg.fileinfo_mod)-1,K_EDIT); ,cfg.fileinfo_mod,sizeof(cfg.fileinfo_mod)-1,K_EDIT);
break; break;
case 24: case 25:
uifc.input(WIN_MID|WIN_SAV,0,0,"Batch File Transfer Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Batch File Transfer Module"
,cfg.batxfer_mod, sizeof(cfg.batxfer_mod)-1, K_EDIT); ,cfg.batxfer_mod, sizeof(cfg.batxfer_mod)-1, K_EDIT);
break; break;
case 25: case 26:
uifc.input(WIN_MID|WIN_SAV,0,0,"Temporary File Transfer Module" uifc.input(WIN_MID|WIN_SAV,0,0,"Temporary File Transfer Module"
,cfg.tempxfer_mod, sizeof(cfg.tempxfer_mod)-1, K_EDIT); ,cfg.tempxfer_mod, sizeof(cfg.tempxfer_mod)-1, K_EDIT);
break; break;
......
...@@ -604,6 +604,7 @@ typedef struct ...@@ -604,6 +604,7 @@ typedef struct
char textsec_mod[LEN_CMD+1]; /* Text section module */ char textsec_mod[LEN_CMD+1]; /* Text section module */
char xtrnsec_mod[LEN_CMD+1]; /* External Program section module */ char xtrnsec_mod[LEN_CMD+1]; /* External Program section module */
char automsg_mod[LEN_CMD+1]; /* Auto-message module */ char automsg_mod[LEN_CMD+1]; /* Auto-message module */
char feedback_mod[LEN_CMD+1]; /* Send feedback to sysop module */
char readmail_mod[LEN_CMD+1]; /* Reading mail module */ char readmail_mod[LEN_CMD+1]; /* Reading mail module */
char scanposts_mod[LEN_CMD+1]; /* Scanning posts (in a single sub) module */ char scanposts_mod[LEN_CMD+1]; /* Scanning posts (in a single sub) module */
char scansubs_mod[LEN_CMD+1]; /* Scanning sub-boards module */ char scansubs_mod[LEN_CMD+1]; /* Scanning sub-boards module */
......
...@@ -241,6 +241,7 @@ BOOL read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen) ...@@ -241,6 +241,7 @@ BOOL read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen)
SAFECOPY(cfg->listmsgs_mod, iniGetString(section, NULL, "listmsgs", "", value)); SAFECOPY(cfg->listmsgs_mod, iniGetString(section, NULL, "listmsgs", "", value));
SAFECOPY(cfg->textsec_mod, iniGetString(section, NULL, "textsec", "text_sec", value)); SAFECOPY(cfg->textsec_mod, iniGetString(section, NULL, "textsec", "text_sec", value));
SAFECOPY(cfg->automsg_mod, iniGetString(section, NULL, "automsg", "automsg", value)); SAFECOPY(cfg->automsg_mod, iniGetString(section, NULL, "automsg", "automsg", value));
SAFECOPY(cfg->feedback_mod, iniGetString(section, NULL, "feedback", "", value));
SAFECOPY(cfg->xtrnsec_mod, iniGetString(section, NULL, "xtrnsec", "xtrn_sec", value)); SAFECOPY(cfg->xtrnsec_mod, iniGetString(section, NULL, "xtrnsec", "xtrn_sec", value));
SAFECOPY(cfg->nodelist_mod, iniGetString(section, NULL, "nodelist", "nodelist", value)); SAFECOPY(cfg->nodelist_mod, iniGetString(section, NULL, "nodelist", "nodelist", value));
SAFECOPY(cfg->userlist_mod, iniGetString(section, NULL, "userlist", "", value)); SAFECOPY(cfg->userlist_mod, iniGetString(section, NULL, "userlist", "", value));
......
...@@ -247,6 +247,7 @@ BOOL write_main_cfg(scfg_t* cfg, int backup_level) ...@@ -247,6 +247,7 @@ BOOL write_main_cfg(scfg_t* cfg, int backup_level)
iniSetString(&ini, name, "listmsgs", cfg->listmsgs_mod, NULL); iniSetString(&ini, name, "listmsgs", cfg->listmsgs_mod, NULL);
iniSetString(&ini, name, "textsec", cfg->textsec_mod, NULL); iniSetString(&ini, name, "textsec", cfg->textsec_mod, NULL);
iniSetString(&ini, name, "automsg", cfg->automsg_mod, NULL); iniSetString(&ini, name, "automsg", cfg->automsg_mod, NULL);
iniSetString(&ini, name, "feedback", cfg->feedback_mod, NULL);
iniSetString(&ini, name, "userlist", cfg->userlist_mod, NULL); iniSetString(&ini, name, "userlist", cfg->userlist_mod, NULL);
iniSetString(&ini, name, "nodelist", cfg->nodelist_mod, NULL); iniSetString(&ini, name, "nodelist", cfg->nodelist_mod, NULL);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment