-
Rob Swindell authored
Although we've added (in SBBS v3.20) configurable numeric date input/display formats for the system, the output was still ambiguous for users (e.g. NN/NN/NN which could be interpretted a number of ways), so I've added an option to choose "verbal" short date formats to be displayed where possible instead. The same value separate from the numeric format (whatever the sysop chose) is used in the verbal date output, but since month name abbreviations are 3 characters, only one separator is used (to keep the output length fixed at 8 characters). The new "Verbal" short date display format is choosable in the SCFG wizard and via SCFG->System->Short Date Format.
Rob Swindell authoredAlthough we've added (in SBBS v3.20) configurable numeric date input/display formats for the system, the output was still ambiguous for users (e.g. NN/NN/NN which could be interpretted a number of ways), so I've added an option to choose "verbal" short date formats to be displayed where possible instead. The same value separate from the numeric format (whatever the sysop chose) is used in the verbal date output, but since month name abbreviations are 3 characters, only one separator is used (to keep the output length fixed at 8 characters). The new "Verbal" short date display format is choosable in the SCFG wizard and via SCFG->System->Short Date Format.
atcodes.cpp 59.60 KiB
/* Synchronet "@code" 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. *
****************************************************************************/
#include "sbbs.h"
#include "cmdshell.h"
#include "utf8.h"
#include "unicode.h"
#include "cp437defs.h"
#include "ver.h"
#include "petdefs.h"
#if defined(_WINSOCKAPI_)
extern WSADATA WSAData;
#define SOCKLIB_DESC WSAData.szDescription
#else
#define SOCKLIB_DESC NULL
#endif
struct atcode_format {
int disp_len;
enum {
none,
left,
right,
center
} align = none;
bool zero_padded=false;
bool truncated = true;
bool doubled = false;
bool thousep = false; // thousands-separated
bool uppercase = false;
bool width_specified = false;
char* parse(char* sp) {
char* p;
disp_len=strlen(sp) + 2;
if((p = strchr(sp, '|')) != NULL) {
if(strchr(p, 'T') != NULL)
thousep = true;
if(strchr(p, 'U') != NULL)
uppercase = true;
if(strchr(p, 'L') != NULL)
align = left;
else if(strchr(p, 'R') != NULL)
align = right;
else if(strchr(p, 'C') != NULL)
align = center;
else if(strchr(p, 'W') != NULL)
doubled = true;
else if(strchr(p, 'Z') != NULL)
zero_padded = true;
else if(strchr(p, '>') != NULL)
truncated = false;
}
else if(strchr(sp, ':') != NULL)
p = NULL;
else if((p=strstr(sp,"-L"))!=NULL)
align = left;
else if((p=strstr(sp,"-R"))!=NULL)
align = right;
else if((p=strstr(sp,"-C"))!=NULL)
align = center;
else if((p=strstr(sp,"-W"))!=NULL) /* wide */
doubled=true;
else if((p=strstr(sp,"-Z"))!=NULL)
zero_padded=true;
else if((p=strstr(sp,"-T"))!=NULL)
thousep=true;
else if((p=strstr(sp,"-U"))!=NULL)
uppercase=true;
else if((p=strstr(sp,"->"))!=NULL) /* wrap */
truncated = false;
if(p!=NULL) {
char* lp = p;
lp++; // skip the '|' or '-'
while(*lp == '>'|| IS_ALPHA(*lp))
lp++;
if(*lp)
width_specified = true;
while(*lp && !IS_DIGIT(*lp))
lp++;
if(*lp && IS_DIGIT(*lp)) {
disp_len=atoi(lp);
width_specified = true;
}
*p=0;
}
return p;
}
};
/****************************************************************************/
/* Returns 0 if invalid @ code. Returns length of @ code if valid. */
/****************************************************************************/
int sbbs_t::show_atcode(const char *instr, JSObject* obj)
{
char str[128],str2[128],*tp,*sp,*p;
int len;
atcode_format fmt;
int pmode = 0;
const char *cp;
if(*instr != '@')
return 0;
SAFECOPY(str,instr);
tp=strchr(str+1,'@');
if(!tp) /* no terminating @ */
return(0);
sp=strchr(str+1,' ');
if(sp && sp<tp) /* space before terminating @ */
return(0);
len=(tp-str)+1;
(*tp)=0;
sp=(str+1);
if(*sp == '~' && *(sp + 1)) { // Mouse hot-spot (hungry)
sp++;
tp = strchr(sp + 1, '~');
if(tp == NULL)
tp = sp;
else {
*tp = 0;
tp++;
}
c_unescape_str(tp);
add_hotspot(tp, /* hungry: */true, column, column + strlen(sp) - 1, row);
bputs(sp);
return len;
}
if(*sp == '`' && *(sp + 1)) { // Mouse hot-spot (strict)
sp++;
tp = strchr(sp + 1, '`');
if(tp == NULL)
tp = sp;
else {
*tp = 0;
tp++;
}
c_unescape_str(tp);
add_hotspot(tp, /* hungry: */false, column, column + strlen(sp) - 1, row);
bputs(sp);
return len;
}
// @!x@ for Ctrl-A x equivalent(s) */
if(*sp == '!') {
for(p = sp + 1; *p != '\0' && *p != '@'; p++)
ctrl_a(*p);
return len;
}
p = fmt.parse(sp);
cp = atcode(sp, str2, sizeof(str2), &pmode, fmt.align == fmt.center, obj);
if(cp==NULL)
return(0);
char separated[128];
if(fmt.thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
char upper[128];
if(fmt.uppercase) {
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}
if(p==NULL || fmt.truncated == false || (fmt.width_specified == false && fmt.align == fmt.none))
fmt.disp_len = strlen(cp);
if(fmt.uppercase && fmt.align == fmt.none)
fmt.align = fmt.left;
if(fmt.truncated && strchr(cp, '\n') == NULL) {
if(column + fmt.disp_len > cols - 1) {
if(column >= cols - 1)
fmt.disp_len = 0;
else
fmt.disp_len = (cols - 1) - column;
}
}
if(pmode & P_UTF8) {
if(term_supports(UTF8))
fmt.disp_len += strlen(cp) - utf8_str_total_width(cp, unicode_zerowidth);
else
fmt.disp_len += strlen(cp) - utf8_str_count_width(cp, /* min: */1, /* max: */2, unicode_zerowidth);
}
if(fmt.align == fmt.left)
bprintf(pmode, "%-*.*s",fmt.disp_len,fmt.disp_len,cp);
else if(fmt.align == fmt.right)
bprintf(pmode, "%*.*s",fmt.disp_len,fmt.disp_len,cp);
else if(fmt.align == fmt.center) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len) {
int left = (fmt.disp_len - vlen) / 2;
bprintf(pmode, "%*s%-*s", left, "", fmt.disp_len - left, cp);
} else
bprintf(pmode, "%.*s", fmt.disp_len, cp);
} else if(fmt.doubled) {
wide(cp);
} else if(fmt.zero_padded) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len)
bprintf(pmode, "%-.*s%s", (int)(fmt.disp_len - strlen(cp)), "0000000000", cp);
else
bprintf(pmode, "%.*s", fmt.disp_len, cp);
} else
bprintf(pmode, "%.*s", fmt.disp_len, cp);
return(len);
}
static const char* getpath(scfg_t* cfg, const char* path)
{
for(int i = 0; i < cfg->total_dirs; i++) {
if(stricmp(cfg->dir[i]->code, path) == 0)
return cfg->dir[i]->path;
}
return path;
}
const char* sbbs_t::formatted_atcode(const char* sp, char* str, size_t maxlen)
{
char tmp[128];
char buf[256];
atcode_format fmt;
SAFECOPY(tmp, sp);
char* p = fmt.parse(tmp);
const char* cp = atcode(tmp, buf, sizeof buf);
if(cp == nullptr)
return nullptr;
char separated[128];
if(fmt.thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
char upper[128];
if(fmt.uppercase) {
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}
if(p==NULL || fmt.truncated == false || (fmt.width_specified == false && fmt.align == fmt.none))
fmt.disp_len = strlen(cp);
if(fmt.align == fmt.left)
snprintf(str, maxlen, "%-*.*s", fmt.disp_len, fmt.disp_len, cp);
else if(fmt.align == fmt.right)
snprintf(str, maxlen, "%*.*s", fmt.disp_len, fmt.disp_len, cp);
else if(fmt.align == fmt.center) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len) {
int left = (fmt.disp_len - vlen) / 2;
snprintf(str, maxlen, "%*s%-*s", left, "", fmt.disp_len - left, cp);
} else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
// } else if(fmt.doubled) { // Unsupported in this context
// wide(cp);
} else if(fmt.zero_padded) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len)
snprintf(str, maxlen, "%-.*s%s", (int)(fmt.disp_len - strlen(cp)), "0000000000", cp);
else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
} else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
return str;
}
const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode, bool centered, JSObject* obj)
{
char tmp[128];
char* tp = NULL;
int i;
uint ugrp;
uint usub;
long l;
stats_t stats;
node_t node;
struct tm tm;
str[0]=0;
if(strcmp(sp, "SHOW") == 0) {
console &= ~CON_ECHO_OFF;
return nulstr;
}
if(strncmp(sp, "SHOW:", 5) == 0) {
uchar* ar = arstr(NULL, sp + 5, &cfg, NULL);
if(ar != NULL) {
if(!chk_ar(ar, &useron, &client))
console |= CON_ECHO_OFF;
else
console &= ~CON_ECHO_OFF;
free(ar);
}
return nulstr;
}
if(strcmp(sp, "HOT") == 0) { // Auto-mouse hot-spot attribute
hot_attr = curatr;
return nulstr;
}
if(strncmp(sp, "HOT:", 4) == 0) { // Auto-mouse hot-spot attribute
sp += 4;
if(stricmp(sp, "hungry") == 0) {
hungry_hotspots = true;
hot_attr = curatr;
}
else if(stricmp(sp, "strict") == 0) {
hungry_hotspots = false;
hot_attr = curatr;
}
else if(stricmp(sp, "off") == 0)
hot_attr = 0;
else
hot_attr = strtoattr(sp, /* endptr: */NULL);
return nulstr;
}
if(strcmp(sp, "CLEAR_HOT") == 0) {
clear_hotspots();
return nulstr;
}
if(strncmp(sp, "MNE:", 4) == 0) { // Mnemonic attribute control
sp += 4;
mneattr_low = strtoattr(sp, &tp);
mneattr_high = mneattr_low ^ HIGH;
if(tp != NULL && *tp != '\0')
mneattr_high = strtoattr(tp + 1, &tp);
if(tp != NULL && *tp != '\0')
mneattr_cmd = strtoattr(tp + 1, NULL);
return nulstr;
}
if(strncmp(sp, "RAINBOW:", 8) == 0) {
memset(rainbow, 0, sizeof rainbow);
parse_attr_str_list(rainbow, LEN_RAINBOW, sp + 8);
return nulstr;
}
if(strncmp(sp, "U+", 2) == 0) { // UNICODE
enum unicode_codepoint codepoint = (enum unicode_codepoint)strtoul(sp + 2, &tp, 16);
if(tp == NULL || *tp == 0)
outchar(codepoint, unicode_to_cp437(codepoint));
else if(*tp == ':')
outchar(codepoint, tp + 1);
else {
char fallback = (char)strtoul(tp + 1, NULL, 16);
if(*tp == ',')
outchar(codepoint, fallback);
else if(*tp == '!') {
char ch = unicode_to_cp437(codepoint);
if(ch != 0)
fallback = ch;
outchar(codepoint, fallback);
}
else return NULL; // Invalid @-code
}
return nulstr;
}
if(strcmp(sp, "CHECKMARK") == 0) {
outchar(UNICODE_CHECK_MARK, CP437_CHECK_MARK);
return nulstr;
}
if(strcmp(sp, "ELLIPSIS") == 0) {
outchar(UNICODE_HORIZONTAL_ELLIPSIS, "...");
return nulstr;
}
if(strcmp(sp, "COPY") == 0) {
outchar(UNICODE_COPYRIGHT_SIGN, "(C)");
return nulstr;
}
if(strcmp(sp, "SOUNDCOPY") == 0) {
outchar(UNICODE_SOUND_RECORDING_COPYRIGHT, "(P)");
return nulstr;
}
if(strcmp(sp, "REGISTERED") == 0) {
outchar(UNICODE_REGISTERED_SIGN, "(R)");
return nulstr;
}
if(strcmp(sp, "TRADEMARK") == 0) {
outchar(UNICODE_TRADE_MARK_SIGN, "(TM)");
return nulstr;
}
if(strcmp(sp, "DEGREE_C") == 0) {
outchar(UNICODE_DEGREE_CELSIUS, "\xF8""C");
return nulstr;
}
if(strcmp(sp, "DEGREE_F") == 0) {
outchar(UNICODE_DEGREE_FAHRENHEIT, "\xF8""F");
return nulstr;
}
if(strncmp(sp, "WIDE:", 5) == 0) {
wide(sp + 5);
return(nulstr);
}
if(!strcmp(sp,"VER"))
return(VERSION);
if(!strcmp(sp,"REV")) {
safe_snprintf(str,maxlen,"%c",REVISION);
return(str);
}
if(!strcmp(sp,"FULL_VER")) {
safe_snprintf(str,maxlen,"%s%c%s",VERSION,REVISION,beta_version);
truncsp(str);
#if defined(_DEBUG)
strcat(str," Debug");
#endif
return(str);
}
if(!strcmp(sp,"VER_NOTICE"))
return(VERSION_NOTICE);
if(!strcmp(sp,"OS_VER"))
return(os_version(str, maxlen));
if(strcmp(sp,"OS_CPU") == 0)
return(os_cpuarch(str, maxlen));
#ifdef JAVASCRIPT
if(!strcmp(sp,"JS_VER"))
return((char *)JS_GetImplementationVersion());
#endif
if(!strcmp(sp,"PLATFORM"))
return(PLATFORM_DESC);
if(!strcmp(sp,"COPYRIGHT"))
return(COPYRIGHT_NOTICE);
if(!strcmp(sp,"COMPILER")) {
char compiler[32];
DESCRIBE_COMPILER(compiler);
strncpy(str, compiler, maxlen);
return(str);
}
if(strcmp(sp, "GIT_HASH") == 0)
return git_hash;
if(strcmp(sp, "GIT_BRANCH") == 0)
return git_branch;
if(strcmp(sp, "GIT_DATE") == 0)
return git_date;
if(strcmp(sp, "BUILD_DATE") == 0)
return __DATE__;
if(strcmp(sp, "BUILD_TIME") == 0)
return __TIME__;
if(!strcmp(sp,"UPTIME")) {
extern volatile time_t uptime;
time_t up=0;
now = time(NULL);
if (uptime != 0 && now >= uptime)
up = now-uptime;
char days[64]="";
if((up/(24*60*60))>=2) {
sprintf(days,"%u days ",(uint)(up/(24L*60L*60L)));
up%=(24*60*60);
}
safe_snprintf(str,maxlen,"%s%u:%02u"
,days
,(uint)(up/(60L*60L))
,(uint)((up/60L)%60L)
);
return(str);
}
if(!strcmp(sp,"SERVED")) {
extern volatile uint served;
safe_snprintf(str,maxlen,"%u",served);
return(str);
}
if(!strcmp(sp,"SOCKET_LIB"))
return(socklib_version(str,SOCKLIB_DESC));
if(!strcmp(sp,"MSG_LIB")) {
safe_snprintf(str,maxlen,"SMBLIB %s",smb_lib_ver());
return(str);
}
if(!strcmp(sp,"BBS") || !strcmp(sp,"BOARDNAME"))
return(cfg.sys_name);
if(!strcmp(sp,"BAUD") || !strcmp(sp,"BPS")) {
safe_snprintf(str,maxlen,"%u",cur_output_rate ? cur_output_rate : cur_rate);
return(str);
}
if(!strcmp(sp,"CPS")) {
safe_snprintf(str,maxlen,"%u",cur_cps);
return(str);
}
if(!strcmp(sp,"COLS")) {
safe_snprintf(str,maxlen,"%u",cols);
return(str);
}
if(!strcmp(sp,"ROWS")) {
safe_snprintf(str,maxlen,"%u",rows);
return(str);
}
if(strcmp(sp,"TERM") == 0)
return term_type();
if(strcmp(sp,"CHARSET") == 0)
return term_charset();
if(!strcmp(sp,"CONN"))
return(connection);
if(!strcmp(sp,"SYSOP"))
return(cfg.sys_op);
if(strcmp(sp, "SYSAVAIL") == 0)
return text[sysop_available(&cfg) ? LiSysopAvailable : LiSysopNotAvailable];
if(strcmp(sp, "SYSAVAILYN") == 0)
return text[sysop_available(&cfg) ? Yes : No];
if(!strcmp(sp,"LOCATION"))
return(cfg.sys_location);
if(strcmp(sp,"NODE") == 0 || strcmp(sp,"NN") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.node_num);
return(str);
}
if(strcmp(sp, "TNODES") == 0 || strcmp(sp, "TNODE") == 0 || strcmp(sp, "TN") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.sys_nodes);
return(str);
}
if(strcmp(sp, "ANODES") == 0 || strcmp(sp, "ANODE") == 0 || strcmp(sp, "AN") == 0) {
safe_snprintf(str, maxlen, "%u", count_nodes(/* self: */true));
return str;
}
if(strcmp(sp, "ONODES") == 0 || strcmp(sp, "ONODE") == 0 || strcmp(sp, "ON") == 0) {
safe_snprintf(str, maxlen, "%u", count_nodes(/* self: */false));
return str;
}
if(strcmp(sp, "PWDAYS") == 0) {
if(cfg.sys_pwdays) {
safe_snprintf(str, maxlen, "%u", cfg.sys_pwdays);
return str;
}
return text[Unlimited];
}
if(strcmp(sp, "AUTODEL") == 0) {
if(cfg.sys_autodel) {
safe_snprintf(str, maxlen, "%u", cfg.sys_autodel);
return str;
}
return text[Unlimited];
}
if(strcmp(sp, "PAGER") == 0)
return (thisnode.misc&NODE_POFF) ? text[Off] : text[On];
if(strcmp(sp, "ALERTS") == 0)
return (thisnode.misc&NODE_AOFF) ? text[Off] : text[On];
if(strcmp(sp, "SPLITP") == 0)
return (useron.chat&CHAT_SPLITP) ? text[On] : text[Off];
if(!strcmp(sp,"INETADDR"))
return(cfg.sys_inetaddr);
if(!strcmp(sp,"HOSTNAME"))
return server_host_name();
if(!strcmp(sp,"FIDOADDR")) {
if(cfg.total_faddrs)
return(smb_faddrtoa(&cfg.faddr[0],str));
return(nulstr);
}
if(!strcmp(sp,"EMAILADDR"))
return(usermailaddr(&cfg, str
,(cfg.inetmail_misc&NMAIL_ALIAS) || (useron.rest&FLAG('O')) ? useron.alias : useron.name));
if(strcmp(sp, "NETMAIL") == 0)
return useron.netmail;
if(strcmp(sp, "TERMTYPE") == 0)
return term_type(&useron, term_supports(), str, maxlen);
if(strcmp(sp, "TERMROWS") == 0)
return term_rows(&useron, str, maxlen);
if(strcmp(sp, "TERMCOLS") == 0)
return term_cols(&useron, str, maxlen);
if(strcmp(sp, "AUTOTERM") == 0)
return (useron.misc & AUTOTERM) ? text[On] : text[Off];
if(strcmp(sp, "ANSI") == 0)
return (useron.misc & ANSI) ? text[On] : text[Off];
if(strcmp(sp, "ASCII") == 0)
return (useron.misc & NO_EXASCII) ? text[On] : text[Off];
if(strcmp(sp, "COLOR") == 0)
return (useron.misc & COLOR) ? text[On] : text[Off];
if(strcmp(sp, "ICE") == 0)
return (useron.misc & ICE_COLOR) ? text[On] : text[Off];
if(strcmp(sp, "RIP") == 0)
return (useron.misc & RIP) ? text[On] : text[Off];
if(strcmp(sp, "PETSCII") == 0)
return (useron.misc & PETSCII) ? text[On] : text[Off];
if(strcmp(sp, "PETGRFX") == 0) {
if(term_supports(PETSCII))
outcom(PETSCII_UPPERGRFX);
return nulstr;
}
if(strcmp(sp, "SWAPDEL") == 0)
return (useron.misc & SWAP_DELETE) ? text[On] : text[Off];
if(strcmp(sp, "UTF8") == 0)
return (useron.misc & UTF8) ? text[On] : text[Off];
if(strcmp(sp, "MOUSE") == 0)
return (useron.misc & MOUSE) ? text[On] : text[Off];
if(strcmp(sp, "UPAUSE") == 0)
return (useron.misc & UPAUSE) ? text[On] : text[Off];
if(strcmp(sp, "SPIN") == 0)
return (useron.misc & SPIN) ? text[On] : text[Off];
if(strcmp(sp, "PAUSESPIN") == 0)
return (useron.misc & NOPAUSESPIN) ? text[Off] : text[On];
if(strcmp(sp, "EXPERT") == 0)
return (useron.misc & EXPERT) ? text[On] : text[Off];
if(strcmp(sp, "HOTKEYS") == 0)
return (useron.misc & COLDKEYS) ? text[Off] : text[On];
if(strcmp(sp, "MSGCLS") == 0)
return (useron.misc & CLRSCRN) ? text[On] : text[Off];
if(strcmp(sp, "FWD") == 0)
return (useron.misc & NETMAIL) ? text[On] : text[Off];
if(strcmp(sp, "REMSUBS") == 0)
return (useron.misc & CURSUB) ? text[On] : text[Off];
if(strcmp(sp, "FILEDESC") == 0)
return (useron.misc & EXTDESC) ? text[On] : text[Off];
if(strcmp(sp, "FILEFLAG") == 0)
return (useron.misc & BATCHFLAG) ? text[On] : text[Off];
if(strcmp(sp, "AUTOHANG") == 0)
return (useron.misc & AUTOHANG) ? text[On] : text[Off];
if(strcmp(sp, "AUTOLOGON") == 0)
return (useron.misc & AUTOLOGON) ? text[On] : text[Off];
if(strcmp(sp, "QUIET") == 0)
return (useron.misc & QUIET) ? text[On] : text[Off];
if(strcmp(sp, "ASKNSCAN") == 0)
return (useron.misc & ASK_NSCAN) ? text[On] : text[Off];
if(strcmp(sp, "ASKSSCAN") == 0)
return (useron.misc & ASK_SSCAN) ? text[On] : text[Off];
if(strcmp(sp, "ANFSCAN") == 0)
return (useron.misc & ANFSCAN) ? text[On] : text[Off];
if(strcmp(sp, "EDITOR") == 0)
return (useron.xedit < 1 || useron.xedit >= cfg.total_xedits) ? text[None] : cfg.xedit[useron.xedit - 1]->name;
if(strcmp(sp, "SHELL") == 0)
return cfg.shell[useron.shell]->name;
if(strcmp(sp, "TMP") == 0)
return useron.tmpext;
if(strcmp(sp, "PROT") == 0) {
safe_snprintf(str, maxlen, "%c", useron.prot);
return str;
}
if(strcmp(sp, "PROTNAME") == 0)
return protname(useron.prot);
if(strcmp(sp, "SEX") == 0) {
safe_snprintf(str, maxlen, "%c", useron.sex);
return str;
}
if(strcmp(sp, "GENDERS") == 0) {
return cfg.new_genders;
}
if(!strcmp(sp,"QWKID"))
return(cfg.sys_id);
if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
now=time(NULL);
memset(&tm,0,sizeof(tm));
localtime_r(&now,&tm);
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour,tm.tm_min,tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
return(str);
}
if(!strcmp(sp,"TIMEZONE"))
return(smb_zonestr(sys_timezone(&cfg),str));
if(!strcmp(sp,"DATE") || !strcmp(sp,"SYSDATE")) {
return datestr(time(NULL));
}
if(strncmp(sp, "DATE:", 5) == 0 || strncmp(sp, "TIME:", 5) == 0) {
SAFECOPY(tmp, sp + 5);
c_unescape_str(tmp);
now = time(NULL);
memset(&tm, 0, sizeof(tm));
localtime_r(&now, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"DATETIME"))
return(timestr(time(NULL)));
if(!strcmp(sp,"DATETIMEZONE")) {
char zone[32];
safe_snprintf(str, maxlen, "%s %s", timestr(time(NULL)), smb_zonestr(sys_timezone(&cfg),zone));
return str;
}
if(strcmp(sp, "DATEFMT") == 0) {
return date_format(&cfg, str, maxlen);
}
if(strcmp(sp, "BDATEFMT") == 0 || strcmp(sp, "BIRTHFMT") == 0) {
return birthdate_format(&cfg, str, maxlen);
}
if(strcmp(sp, "GENDERS") == 0)
return cfg.new_genders;
if(!strcmp(sp,"TMSG")) {
l=0;
for(i=0;i<cfg.total_subs;i++)
l+=getposts(&cfg,i); /* l=total posts */
safe_snprintf(str,maxlen,"%lu",l);
return(str);
}
if(!strcmp(sp,"TUSER")) {
safe_snprintf(str,maxlen,"%u",total_users(&cfg));
return(str);
}
if(!strcmp(sp,"TFILE")) {
l=0;
for(i=0;i<cfg.total_dirs;i++)
l+=getfiles(&cfg,i);
safe_snprintf(str,maxlen,"%lu",l);
return(str);
}
if(strncmp(sp, "FILES:", 6) == 0) { // Number of files in specified directory
const char* path = getpath(&cfg, sp + 6);
safe_snprintf(str, maxlen, "%u", getfilecount(path));
return str;
}
if(strcmp(sp, "FILES") == 0) { // Number of files in current directory
safe_snprintf(str, maxlen, "%u", getfiles(&cfg, usrdir[curlib][curdir[curlib]]));
return str;
}
if(strncmp(sp, "FILESIZE:", 9) == 0) {
const char* path = getpath(&cfg, sp + 9);
byte_estimate_to_str(getfilesizetotal(path), str, maxlen, /* unit: */1, /* precision: */1);
return str;
}
if(strcmp(sp, "FILESIZE") == 0) {
byte_estimate_to_str(getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path)
,str, maxlen, /* unit: */1, /* precision: */1);
return str;
}
if(strncmp(sp, "FILEBYTES:", 10) == 0) { // Number of bytes in current file directory
const char* path = getpath(&cfg, sp + 10);
safe_snprintf(str, maxlen, "%" PRIu64, getfilesizetotal(path));
return str;
}
if(strcmp(sp, "FILEBYTES") == 0) { // Number of bytes in current file directory
safe_snprintf(str, maxlen, "%" PRIu64
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path));
return str;
}
if(strncmp(sp, "FILEKB:", 7) == 0) { // Number of kibibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / 1024.0);
return str;
}
if(strcmp(sp, "FILEKB") == 0) { // Number of kibibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / 1024.0);
return str;
}
if(strncmp(sp, "FILEMB:", 7) == 0) { // Number of mebibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / (1024.0 * 1024.0));
return str;
}
if(strcmp(sp, "FILEMB") == 0) { // Number of mebibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / (1024.0 * 1024.0));
return str;
}
if(strncmp(sp, "FILEGB:", 7) == 0) { // Number of gibibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / (1024.0 * 1024.0 * 1024.0));
return str;
}
if(strcmp(sp, "FILEGB") == 0) { // Number of gibibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / (1024.0 * 1024.0 * 1024.0));
return str;
}
if(!strcmp(sp,"TCALLS") || !strcmp(sp,"NUMCALLS")) {
getstats(&cfg,0,&stats);
safe_snprintf(str,maxlen,"%u", stats.logons);
return(str);
}
if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
|| !strcmp(sp,"LASTCALLERSYSTEM"))
return(lastuseron);
if(!strcmp(sp,"CLS") || !strcmp(sp,"CLEAR")) {
CLS;
return(nulstr);
}
if(strcmp(sp, "GETDIM") == 0) {
getdimensions();
return nulstr;
}
if(strcmp(sp, "GETKEY") == 0) {
getkey();
return(nulstr);
}
if(strcmp(sp, "CONTINUE") == 0) {
char ch = getkey(K_UPPER);
if(ch == no_key() || ch == quit_key())
sys_status|=SS_ABORT;
return(nulstr);
}
if(strncmp(sp, "WAIT:", 5) == 0) {
inkey(K_NONE, atoi(sp + 5) * 100);
return(nulstr);
}
if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE")) {
pause();
return(nulstr);
}
if(!strcmp(sp,"RESETPAUSE")) {
lncntr=0;
return(nulstr);
}
if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF")) {
sys_status^=SS_PAUSEOFF;
return(nulstr);
}
if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE")) {
sys_status^=SS_PAUSEON;
return(nulstr);
}
if(strncmp(sp, "FILL:", 5) == 0) {
SAFECOPY(tmp, sp + 5);
int margin = centered ? column : 1;
if(margin < 1) margin = 1;
c_unescape_str(tmp);
while(*tmp && online && column < cols - margin)
bputs(tmp, P_TRUNCATE);
return nulstr;
}
if(strncmp(sp, "POS:", 4) == 0) { // PCBoard (nn is 1 based)
i = atoi(sp + 4);
if(i >= 1) // Convert to 0-based
i--;
for(l = i - column; l > 0; l--)
outchar(' ');
return nulstr;
}
if(strncmp(sp, "DELAY:", 6) == 0) { // PCBoard
mswait(atoi(sp + 6) * 100);
return nulstr;
}
if(strcmp(sp, "YESCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", yes_key());
return str;
}
if(strcmp(sp, "NOCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", no_key());
return str;
}
if(strcmp(sp, "QUITCHAR") == 0) {
safe_snprintf(str, maxlen, "%c", quit_key());
return str;
}
if(strncmp(sp, "BPS:", 4) == 0) {
set_output_rate((enum output_rate)atoi(sp + 4));
return nulstr;
}
if(strncmp(sp, "TEXT:", 5) == 0) {
i = atoi(sp + 5);
if(i >= 1 && i <= TOTAL_TEXT)
return text[i - 1];
else
return get_text(sp + 5);
}
/* NOSTOP */
/* STOP */
if(!strcmp(sp,"BELL") || !strcmp(sp,"BEEP"))
return("\a");
if(!strcmp(sp,"EVENT")) {
if(event_time==0)
return("<none>");
return(timestr(event_time));
}
/* LASTCALL */
if(strcmp(sp, "NODE_USER") == 0)
return thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias;
if(!strncmp(sp,"NODE",4) && IS_DIGIT(sp[4])) {
i=atoi(sp+4);
if(i && i<=cfg.sys_nodes) {
getnodedat(i,&node,0);
printnodedat(i,&node);
}
return(nulstr);
}
if(!strcmp(sp,"WHO")) {
whos_online(true);
return(nulstr);
}
/* User Codes */
if(!strcmp(sp,"USER") || !strcmp(sp,"ALIAS") || !strcmp(sp,"NAME"))
return(useron.alias);
if(!strcmp(sp,"FIRST")) {
safe_snprintf(str,maxlen,"%s",useron.alias);
tp=strchr(str,' ');
if(tp) *tp=0;
return(str);
}
if(!strcmp(sp,"USERNUM")) {
safe_snprintf(str,maxlen,"%u",useron.number);
return(str);
}
if(!strcmp(sp,"PHONE") || !strcmp(sp,"HOMEPHONE")
|| !strcmp(sp,"DATAPHONE") || !strcmp(sp,"DATA"))
return(useron.phone);
if(!strcmp(sp,"ADDR1"))
return(useron.address);
if(!strcmp(sp,"FROM"))
return(useron.location);
if(!strcmp(sp,"CITY")) {
safe_snprintf(str,maxlen,"%s",useron.location);
char* p=strchr(str,',');
if(p) {
*p=0;
return(str);
}
return(nulstr);
}
if(!strcmp(sp,"STATE")) {
char* p=strchr(useron.location,',');
if(p) {
p++;
if(*p==' ')
p++;
return(p);
}
return(nulstr);
}
if(!strcmp(sp,"CPU"))
return(useron.comp);
if(!strcmp(sp,"HOST"))
return(client_name);
if(!strcmp(sp,"BDATE"))
return getbirthdstr(&cfg, useron.birth, str, maxlen);
if(strcmp(sp, "BIRTH") == 0)
return format_birthdate(&cfg, useron.birth, str, maxlen);
if(strncmp(sp, "BDATE:", 6) == 0 || strncmp(sp, "BIRTH:", 6) == 0) {
SAFECOPY(tmp, sp + 6);
c_unescape_str(tmp);
memset(&tm,0,sizeof(tm));
tm.tm_year = getbirthyear(useron.birth) - 1900;
tm.tm_mon = getbirthmonth(&cfg, useron.birth) - 1;
tm.tm_mday = getbirthday(&cfg, useron.birth);
mktime(&tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"AGE")) {
safe_snprintf(str,maxlen,"%u",getage(&cfg,useron.birth));
return(str);
}
if(!strcmp(sp,"CALLS") || !strcmp(sp,"NUMTIMESON")) {
safe_snprintf(str,maxlen,"%u",useron.logons);
return(str);
}
if(strcmp(sp, "PWAGE") == 0) {
time_t age = time(NULL) - useron.pwmod;
safe_snprintf(str, maxlen, "%d", (uint)(age/(24*60*60)));
return str;
}
if(strcmp(sp, "PWDATE") == 0 || strcmp(sp, "MEMO") == 0)
return datestr(useron.pwmod);
if(strncmp(sp, "PWDATE:", 7) == 0) {
SAFECOPY(tmp, sp + 7);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.pwmod;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY")) {
safe_snprintf(str,maxlen,"%u",useron.level);
return(str);
}
if(!strcmp(sp,"SINCE"))
return datestr(useron.firston);
if(strncmp(sp, "SINCE:", 6) == 0) {
SAFECOPY(tmp, sp + 6);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.firston;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
now=time(NULL);
safe_snprintf(str,maxlen,"%u",(uint)(now-logontime)/60);
return(str);
}
if(!strcmp(sp,"TUSED")) { /* Synchronet only */
now=time(NULL);
return(sectostr((uint)(now-logontime),str)+1);
}
if(!strcmp(sp,"TLEFT")) { /* Synchronet only */
gettimeleft();
return(sectostr(timeleft,str)+1);
}
if(!strcmp(sp,"TPERD")) /* Synchronet only */
return(sectostr(cfg.level_timeperday[useron.level],str)+4);
if(!strcmp(sp,"TPERC")) /* Synchronet only */
return(sectostr(cfg.level_timepercall[useron.level],str)+4);
if(strcmp(sp, "MPERC") == 0 || strcmp(sp, "TIMELIMIT") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_timepercall[useron.level]);
return(str);
}
if(strcmp(sp, "MPERD") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_timeperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXCALLS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_callsperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXPOSTS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_postsperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXMAILS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_emailperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXLINES") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_linespermsg[useron.level]);
return str;
}
if(!strcmp(sp,"MINLEFT") || !strcmp(sp,"LEFT") || !strcmp(sp,"TIMELEFT")) {
gettimeleft();
safe_snprintf(str,maxlen,"%u",timeleft/60);
return(str);
}
if(!strcmp(sp,"LASTON"))
return(timestr(useron.laston));
if(!strcmp(sp,"LASTDATEON"))
return datestr(useron.laston);
if(strncmp(sp, "LASTON:", 7) == 0) {
SAFECOPY(tmp, sp + 7);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.laston;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"LASTTIMEON")) {
memset(&tm,0,sizeof(tm));
localtime32(&useron.laston,&tm);
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour, tm.tm_min, tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
return(str);
}
if(!strcmp(sp,"FIRSTON"))
return(timestr(useron.firston));
if(!strcmp(sp,"FIRSTDATEON"))
return datestr(useron.firston);
if(strncmp(sp, "FIRSTON:", 8) == 0) {
SAFECOPY(tmp, sp + 8);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.firston;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"FIRSTTIMEON")) {
memset(&tm,0,sizeof(tm));
localtime32(&useron.firston,&tm);
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour, tm.tm_min, tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
return(str);
}
if(strcmp(sp, "EMAILS") == 0) {
safe_snprintf(str, maxlen, "%u", useron.emails);
return str;
}
if(strcmp(sp, "FBACKS") == 0) {
safe_snprintf(str, maxlen, "%u", useron.fbacks);
return str;
}
if(strcmp(sp, "ETODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.etoday);
return str;
}
if(strcmp(sp, "PTODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.ptoday);
return str;
}
if(strcmp(sp, "LTODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.ltoday);
return str;
}
if(strcmp(sp, "MTODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.ttoday);
return str;
}
if(strcmp(sp, "MTOTAL") == 0) {
safe_snprintf(str, maxlen, "%u", useron.timeon);
return str;
}
if(strcmp(sp, "TTODAY") == 0)
return sectostr(useron.ttoday, str) + 3;
if(strcmp(sp, "TTOTAL") == 0)
return sectostr(useron.timeon, str) + 3;
if(strcmp(sp, "TLAST") == 0) {
safe_snprintf(str, maxlen, "%u", useron.tlast);
return str;
}
if(strcmp(sp, "MEXTRA") == 0) {
safe_snprintf(str, maxlen, "%u", useron.textra);
return str;
}
if(strcmp(sp, "TEXTRA") == 0)
return sectostr(useron.textra, str) + 3;
if(strcmp(sp, "MBANKED") == 0) {
safe_snprintf(str, maxlen, "%" PRIu32, useron.min);
return str;
}
if(strcmp(sp, "TBANKED") == 0)
return sectostr(useron.min, str) + 3;
if(!strcmp(sp,"MSGLEFT") || !strcmp(sp,"MSGSLEFT")) {
safe_snprintf(str,maxlen,"%u",useron.posts);
return(str);
}
if(!strcmp(sp,"MSGREAD")) {
safe_snprintf(str,maxlen,"%u",posts_read);
return(str);
}
if(!strcmp(sp,"FREESPACE")) {
safe_snprintf(str,maxlen,"%" PRIu64,getfreediskspace(cfg.temp_dir,0));
return(str);
}
if(!strcmp(sp,"FREESPACEK")) {
safe_snprintf(str,maxlen,"%" PRIu64,getfreediskspace(cfg.temp_dir,1024));
return(str);
}
if(strcmp(sp,"FREESPACEM") == 0) {
safe_snprintf(str,maxlen,"%" PRIu64,getfreediskspace(cfg.temp_dir, 1024 * 1024));
return(str);
}
if(strcmp(sp,"FREESPACEG") == 0) {
safe_snprintf(str,maxlen,"%" PRIu64,getfreediskspace(cfg.temp_dir, 1024 * 1024 * 1024));
return(str);
}
if(strcmp(sp,"FREESPACET") == 0) {
safe_snprintf(str,maxlen,"%" PRIu64,getfreediskspace(cfg.temp_dir, 1024 * 1024 * 1024) / 1024);
return(str);
}
if(!strcmp(sp,"UPBYTES")) {
safe_snprintf(str,maxlen,"%" PRIu64,useron.ulb);
return(str);
}
if(!strcmp(sp,"UPK")) {
safe_snprintf(str,maxlen,"%" PRIu64,useron.ulb/1024L);
return(str);
}
if(!strcmp(sp,"UPS") || !strcmp(sp,"UPFILES")) {
safe_snprintf(str,maxlen,"%u",useron.uls);
return(str);
}
if(!strcmp(sp,"DLBYTES")) {
safe_snprintf(str,maxlen,"%" PRIu64,useron.dlb);
return(str);
}
if(!strcmp(sp,"DOWNK")) {
safe_snprintf(str,maxlen,"%" PRIu64,useron.dlb/1024L);
return(str);
}
if(!strcmp(sp,"DOWNS") || !strcmp(sp,"DLFILES")) {
safe_snprintf(str,maxlen,"%u",useron.dls);
return(str);
}
if(strcmp(sp, "PCR") == 0) {
float f = 0;
if(useron.posts)
f = (float)useron.logons / useron.posts;
safe_snprintf(str, maxlen, "%u", f ? (uint)(100 / f) : 0);
return str;
}
if(strcmp(sp, "UDR") == 0) {
float f = 0;
if(useron.ulb)
f = (float)useron.dlb / useron.ulb;
safe_snprintf(str, maxlen, "%u", f ? (uint)(100 / f) : 0);
return str;
}
if(strcmp(sp, "UDFR") == 0) {
float f = 0;
if(useron.uls)
f = (float)useron.dls / useron.uls;
safe_snprintf(str, maxlen, "%u", f ? (uint)(100 / f) : 0);
return str;
}
if(!strcmp(sp,"LASTNEW"))
return datestr(ns_time);
if(strncmp(sp, "LASTNEW:", 8) == 0) {
SAFECOPY(tmp, sp + 8);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = ns_time;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"NEWFILETIME"))
return(timestr(ns_time));
/* MAXDL */
if(!strcmp(sp,"MAXDK") || !strcmp(sp,"DLKLIMIT") || !strcmp(sp,"KBLIMIT")) {
safe_snprintf(str,maxlen,"%" PRIu64,cfg.level_freecdtperday[useron.level]/1024L);
return(str);
}
if(!strcmp(sp,"DAYBYTES")) { /* amt of free cdts used today */
safe_snprintf(str,maxlen,"%" PRIu64,cfg.level_freecdtperday[useron.level]-useron.freecdt);
return(str);
}
if(!strcmp(sp,"BYTELIMIT")) {
safe_snprintf(str,maxlen,"%" PRIu64, cfg.level_freecdtperday[useron.level]);
return(str);
}
if(!strcmp(sp,"KBLEFT")) {
safe_snprintf(str,maxlen,"%" PRIu64,user_available_credits(&useron)/1024UL);
return(str);
}
if(!strcmp(sp,"BYTESLEFT")) {
safe_snprintf(str,maxlen,"%" PRIu64,user_available_credits(&useron));
return(str);
}
if(strcmp(sp, "CREDITS") == 0) {
safe_snprintf(str, maxlen, "%" PRIu64, useron.cdt);
return str;
}
if(strcmp(sp, "FREECDT") == 0) {
safe_snprintf(str, maxlen, "%" PRIu64, useron.freecdt);
return str;
}
if(!strcmp(sp,"CONF")) {
safe_snprintf(str,maxlen,"%s %s"
,usrgrps ? cfg.grp[usrgrp[curgrp]]->sname :nulstr
,usrgrps ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
return(str);
}
if(!strcmp(sp,"CONFNUM")) {
safe_snprintf(str,maxlen,"%u %u",curgrp+1,cursub[curgrp]+1);
return(str);
}
if(!strcmp(sp,"NUMDIR")) {
safe_snprintf(str,maxlen,"%u %u",usrlibs ? curlib+1 : 0,usrlibs ? curdir[curlib]+1 : 0);
return(str);
}
if(!strcmp(sp,"EXDATE") || !strcmp(sp,"EXPDATE"))
return datestr(useron.expire);
if(strncmp(sp, "EXPDATE:", 8) == 0) {
if(!useron.expire)
return nulstr;
SAFECOPY(tmp, sp + 8);
c_unescape_str(tmp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.expire;
localtime_r(&date, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"EXPDAYS")) {
now=time(NULL);
l=(uint)(useron.expire-now);
if(l<0)
l=0;
safe_snprintf(str,maxlen,"%lu",l/(1440L*60L));
return(str);
}
if(strcmp(sp, "NOTE") == 0 || strcmp(sp, "MEMO1") == 0)
return useron.note;
if(strcmp(sp,"REALNAME") == 0 || !strcmp(sp,"MEMO2") || !strcmp(sp,"COMPANY"))
return(useron.name);
if(!strcmp(sp,"ZIP"))
return(useron.zipcode);
if(!strcmp(sp,"HANGUP")) {
hangup();
return(nulstr);
}
/* Synchronet Specific */
if(!strncmp(sp,"SETSTR:",7)) {
strcpy(main_csi.str,sp+7);
return(nulstr);
}
if(strcmp(sp,"STR") == 0) {
return main_csi.str;
}
if(strncmp(sp, "STRVAR:", 7) == 0) {
uint32_t crc = crc32(sp + 7, 0);
if(main_csi.str_var && main_csi.str_var_name) {
for(i=0;i<main_csi.str_vars;i++)
if(main_csi.str_var_name[i] == crc)
return main_csi.str_var[i];
}
return nulstr;
}
if(strncmp(sp, "JS:", 3) == 0) {
jsval val;
if(JS_GetProperty(js_cx, obj == NULL ? js_glob : obj, sp + 3, &val))
JSVALUE_TO_STRBUF(js_cx, val, str, maxlen, NULL);
return str;
}
if(!strncmp(sp,"EXEC:",5)) {
exec_bin(sp+5,&main_csi);
return(nulstr);
}
if(!strncmp(sp,"EXEC_XTRN:",10)) {
for(i=0;i<cfg.total_xtrns;i++)
if(!stricmp(cfg.xtrn[i]->code,sp+10))
break;
if(i<cfg.total_xtrns)
exec_xtrn(i);
return(nulstr);
}
if(!strncmp(sp,"MENU:",5)) {
menu(sp+5);
return(nulstr);
}
if(!strncmp(sp,"CONDMENU:",9)) {
menu(sp+9, P_NOERROR);
return(nulstr);
}
if(!strncmp(sp,"TYPE:",5)) {
printfile(cmdstr(sp+5,nulstr,nulstr,str),0);
return(nulstr);
}
if(!strncmp(sp,"INCLUDE:",8)) {
printfile(cmdstr(sp+8,nulstr,nulstr,str),P_NOCRLF|P_SAVEATR);
return(nulstr);
}
if(!strcmp(sp,"QUESTION"))
return(question);
if(!strcmp(sp,"HANDLE"))
return(useron.handle);
if(strcmp(sp, "LASTIP") == 0)
return useron.ipaddr;
if(!strcmp(sp,"CID") || !strcmp(sp,"IP"))
return(cid);
if(!strcmp(sp,"LOCAL-IP"))
return(local_addr);
if(!strcmp(sp,"CRLF"))
return("\r\n");
if(!strcmp(sp,"PUSHXY")) {
ansi_save();
return(nulstr);
}
if(!strcmp(sp,"POPXY")) {
ansi_restore();
return(nulstr);
}
if(!strcmp(sp,"HOME")) {
cursor_home();
return(nulstr);
}
if(!strcmp(sp,"CLRLINE")) {
clearline();
return(nulstr);
}
if(!strcmp(sp,"CLR2EOL") || !strcmp(sp,"CLREOL")) {
cleartoeol();
return(nulstr);
}
if(!strcmp(sp,"CLR2EOS")) {
cleartoeos();
return(nulstr);
}
if(!strncmp(sp,"UP:",3)) {
cursor_up(atoi(sp+3));
return(str);
}
if(!strncmp(sp,"DOWN:",5)) {
cursor_down(atoi(sp+5));
return(str);
}
if(!strncmp(sp,"LEFT:",5)) {
cursor_left(atoi(sp+5));
return(str);
}
if(!strncmp(sp,"RIGHT:",6)) {
cursor_right(atoi(sp+6));
return(str);
}
if(!strncmp(sp,"GOTOXY:",7)) {
const char* cp=strchr(sp,',');
if(cp!=NULL) {
cp++;
cursor_xy(atoi(sp+7),atoi(cp));
}
return(nulstr);
}
if(!strcmp(sp,"GRP")) {
if(SMB_IS_OPEN(&smb)) {
if(smb.subnum==INVALID_SUB)
return("Local");
if(is_valid_subnum(smb.subnum))
return(cfg.grp[cfg.sub[smb.subnum]->grp]->sname);
}
return(usrgrps ? cfg.grp[usrgrp[curgrp]]->sname : nulstr);
}
if(!strcmp(sp,"GRPL")) {
if(SMB_IS_OPEN(&smb)) {
if(smb.subnum==INVALID_SUB)
return("Local");
if(is_valid_subnum(smb.subnum))
return(cfg.grp[cfg.sub[smb.subnum]->grp]->lname);
}
return(usrgrps ? cfg.grp[usrgrp[curgrp]]->lname : nulstr);
}
if(!strcmp(sp,"GN")) {
if(SMB_IS_OPEN(&smb))
ugrp=getusrgrp(smb.subnum);
else
ugrp=usrgrps ? curgrp+1 : 0;
safe_snprintf(str,maxlen,"%u",ugrp);
return(str);
}
if(!strcmp(sp,"GL")) {
if(SMB_IS_OPEN(&smb))
ugrp=getusrgrp(smb.subnum);
else
ugrp=usrgrps ? curgrp+1 : 0;
safe_snprintf(str,maxlen,"%-4u",ugrp);
return(str);
}
if(!strcmp(sp,"GR")) {
if(SMB_IS_OPEN(&smb))
ugrp=getusrgrp(smb.subnum);
else
ugrp=usrgrps ? curgrp+1 : 0;
safe_snprintf(str,maxlen,"%4u",ugrp);
return(str);
}
if(!strcmp(sp,"SUB")) {
if(SMB_IS_OPEN(&smb)) {
if(smb.subnum==INVALID_SUB)
return("Mail");
else if(is_valid_subnum(smb.subnum))
return(cfg.sub[smb.subnum]->sname);
}
return(usrgrps ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
}
if(!strcmp(sp,"SUBL")) {
if(SMB_IS_OPEN(&smb)) {
if(smb.subnum==INVALID_SUB)
return("Mail");
else if(is_valid_subnum(smb.subnum))
return(cfg.sub[smb.subnum]->lname);
}
return(usrgrps ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->lname : nulstr);
}
if(!strcmp(sp,"SN")) {
if(SMB_IS_OPEN(&smb))
usub=getusrsub(smb.subnum);
else
usub=usrgrps ? cursub[curgrp]+1 : 0;
safe_snprintf(str,maxlen,"%u",usub);
return(str);
}
if(!strcmp(sp,"SL")) {
if(SMB_IS_OPEN(&smb))
usub=getusrsub(smb.subnum);
else
usub=usrgrps ? cursub[curgrp]+1 : 0;
safe_snprintf(str,maxlen,"%-4u",usub);
return(str);
}
if(!strcmp(sp,"SR")) {
if(SMB_IS_OPEN(&smb))
usub=getusrsub(smb.subnum);
else
usub=usrgrps ? cursub[curgrp]+1 : 0;
safe_snprintf(str,maxlen,"%4u",usub);
return(str);
}
if(!strcmp(sp,"LIB"))
return(usrlibs ? cfg.lib[usrlib[curlib]]->sname : nulstr);
if(!strcmp(sp,"LIBL"))
return(usrlibs ? cfg.lib[usrlib[curlib]]->lname : nulstr);
if(!strcmp(sp,"LN")) {
safe_snprintf(str,maxlen,"%u",usrlibs ? curlib+1 : 0);
return(str);
}
if(!strcmp(sp,"LL")) {
safe_snprintf(str,maxlen,"%-4u",usrlibs ? curlib+1 : 0);
return(str);
}
if(!strcmp(sp,"LR")) {
safe_snprintf(str,maxlen,"%4u",usrlibs ? curlib+1 : 0);
return(str);
}
if(!strcmp(sp,"DIR"))
return(usrlibs ? cfg.dir[usrdir[curlib][curdir[curlib]]]->sname :nulstr);
if(!strcmp(sp,"DIRL"))
return(usrlibs ? cfg.dir[usrdir[curlib][curdir[curlib]]]->lname : nulstr);
if(!strcmp(sp,"DN")) {
safe_snprintf(str,maxlen,"%u",usrlibs ? curdir[curlib]+1 : 0);
return(str);
}
if(!strcmp(sp,"DL")) {
safe_snprintf(str,maxlen,"%-4u",usrlibs ? curdir[curlib]+1 : 0);
return(str);
}
if(!strcmp(sp,"DR")) {
safe_snprintf(str,maxlen,"%4u",usrlibs ? curdir[curlib]+1 : 0);
return(str);
}
if(!strcmp(sp,"NOACCESS")) {
if(noaccess_str==text[NoAccessTime])
safe_snprintf(str,maxlen,noaccess_str,noaccess_val/60,noaccess_val%60);
else if(noaccess_str==text[NoAccessDay])
safe_snprintf(str,maxlen,noaccess_str,wday[noaccess_val]);
else
safe_snprintf(str,maxlen,noaccess_str,noaccess_val);
return(str);
}
if(!strcmp(sp,"LAST")) {
tp=strrchr(useron.alias,' ');
if(tp) tp++;
else tp=useron.alias;
return(tp);
}
if(!strcmp(sp,"REAL") || !strcmp(sp,"FIRSTREAL")) {
safe_snprintf(str,maxlen,"%s",useron.name);
tp=strchr(str,' ');
if(tp) *tp=0;
return(str);
}
if(!strcmp(sp,"LASTREAL")) {
tp=strrchr(useron.name,' ');
if(tp) tp++;
else tp=useron.name;
return(tp);
}
if(!strcmp(sp,"MAILR")) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number, /* Sent: */FALSE, /* attr: */MSG_READ));
return(str);
}
if(!strcmp(sp,"MAILU")) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number, /* Sent: */FALSE, /* attr: */~MSG_READ));
return(str);
}
if(!strcmp(sp,"MAILW")) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number, /* Sent: */FALSE, /* attr: */0));
return(str);
}
if(!strcmp(sp,"MAILP")) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number,/* Sent: */TRUE, /* attr: */0));
return(str);
}
if(!strcmp(sp,"SPAMW")) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number, /* Sent: */FALSE, /* attr: */MSG_SPAM));
return(str);
}
if(!strncmp(sp,"MAILR:",6) || !strncmp(sp,"MAILR#",6)) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6), /* Sent: */FALSE, /* attr: */MSG_READ));
return(str);
}
if(!strncmp(sp,"MAILU:",6) || !strncmp(sp,"MAILU#",6)) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6), /* Sent: */FALSE, /* attr: */~MSG_READ));
return(str);
}
if(!strncmp(sp,"MAILW:",6) || !strncmp(sp,"MAILW#",6)) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6), /* Sent: */FALSE, /* attr: */0));
return(str);
}
if(!strncmp(sp,"MAILP:",6) || !strncmp(sp,"MAILP#",6)) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6), /* Sent: */TRUE, /* attr: */0));
return(str);
}
if(!strncmp(sp,"SPAMW:",6) || !strncmp(sp,"SPAMW#",6)) {
safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6), /* Sent: */FALSE, /* attr: */MSG_SPAM));
return(str);
}
if(!strcmp(sp,"MSGREPLY")) {
safe_snprintf(str,maxlen,"%c",cfg.sys_misc&SM_RA_EMU ? 'R' : 'A');
return(str);
}
if(!strcmp(sp,"MSGREREAD")) {
safe_snprintf(str,maxlen,"%c",cfg.sys_misc&SM_RA_EMU ? 'A' : 'R');
return(str);
}
if(!strncmp(sp,"STATS.",6)) {
getstats(&cfg,0,&stats);
sp+=6;
if(!strcmp(sp,"LOGONS"))
safe_snprintf(str,maxlen,"%u", stats.logons);
else if(!strcmp(sp,"LTODAY"))
safe_snprintf(str,maxlen,"%u", stats.ltoday);
else if(!strcmp(sp,"TIMEON"))
safe_snprintf(str,maxlen,"%u", stats.timeon);
else if(!strcmp(sp,"TTODAY"))
safe_snprintf(str,maxlen,"%u", stats.ttoday);
else if(!strcmp(sp,"ULS"))
safe_snprintf(str,maxlen,"%u", stats.uls);
else if(!strcmp(sp,"ULB"))
safe_snprintf(str,maxlen,"%" PRIu64, stats.ulb);
else if(!strcmp(sp,"DLS"))
safe_snprintf(str,maxlen,"%u", stats.dls);
else if(!strcmp(sp,"DLB"))
safe_snprintf(str,maxlen,"%" PRIu64, stats.dlb);
else if(!strcmp(sp,"PTODAY"))
safe_snprintf(str,maxlen,"%u", stats.ptoday);
else if(!strcmp(sp,"ETODAY"))
safe_snprintf(str,maxlen,"%u", stats.etoday);
else if(!strcmp(sp,"FTODAY"))
safe_snprintf(str,maxlen,"%u", stats.ftoday);
else if(!strcmp(sp,"NUSERS"))
safe_snprintf(str,maxlen,"%u",stats.nusers);
return(str);
}
/* Message header codes */
if(!strcmp(sp,"MSG_TO") && current_msg != nullptr) {
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
if(current_msg->to_ext!=NULL)
safe_snprintf(str, maxlen, "%s #%s", current_msg_to == nullptr ? current_msg->to : current_msg_to, current_msg->to_ext);
else if(current_msg->to_net.addr != NULL) {
char tmp[128];
safe_snprintf(str,maxlen,"%s (%s)", current_msg_to == nullptr ? current_msg->to : current_msg_to
,smb_netaddrstr(¤t_msg->to_net,tmp));
} else
return current_msg_to == nullptr ? current_msg->to : current_msg_to;
return(str);
}
if(!strcmp(sp,"MSG_TO_NAME") && current_msg != nullptr) {
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
return current_msg_to == nullptr ? current_msg->to : current_msg_to;
}
if(!strcmp(sp,"MSG_TO_FIRST") && current_msg != nullptr) {
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
safe_snprintf(str, maxlen, "%s", current_msg_to == nullptr ? current_msg->to : current_msg_to);
if((tp = strchr(str, ' ')) != NULL)
*tp = '\0';
return str;
}
if(!strcmp(sp,"MSG_TO_EXT") && current_msg!=NULL) {
if(current_msg->to_ext==NULL)
return(nulstr);
return(current_msg->to_ext);
}
if(!strcmp(sp,"MSG_TO_NET") && current_msg!=NULL) {
if(current_msg->to_net.addr == NULL)
return nulstr;
return(smb_netaddrstr(¤t_msg->to_net,str));
}
if(!strcmp(sp,"MSG_TO_NETTYPE") && current_msg!=NULL) {
if(current_msg->to_net.type==NET_NONE)
return nulstr;
return(smb_nettype((enum smb_net_type)current_msg->to_net.type));
}
if(!strcmp(sp,"MSG_CC") && current_msg!=NULL)
return(current_msg->cc_list == NULL ? nulstr : current_msg->cc_list);
if(!strcmp(sp,"MSG_FROM") && current_msg != nullptr) {
if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
return(text[Anonymous]);
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
if(current_msg->from_ext!=NULL)
safe_snprintf(str,maxlen,"%s #%s", current_msg_from == nullptr ? current_msg->from : current_msg_from, current_msg->from_ext);
else if(current_msg->from_net.addr != NULL) {
safe_snprintf(str,maxlen,"%s (%s)", current_msg_from == nullptr ? current_msg->from : current_msg_from
,smb_netaddrstr(¤t_msg->from_net,tmp));
} else
return current_msg_from == nullptr ? current_msg->from : current_msg_from;
return(str);
}
if(!strcmp(sp,"MSG_FROM_NAME") && current_msg != nullptr) {
if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
return(text[Anonymous]);
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
return current_msg_from == nullptr ? current_msg->from : current_msg_from;
}
if(!strcmp(sp,"MSG_FROM_FIRST") && current_msg != nullptr) {
if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
safe_snprintf(str, maxlen, "%s", text[Anonymous]);
else
safe_snprintf(str, maxlen, "%s", current_msg_from == nullptr ? current_msg->from : current_msg_from);
if((tp = strchr(str, ' ')) != NULL)
*tp = '\0';
return str;
}
if(!strcmp(sp,"MSG_FROM_EXT") && current_msg!=NULL) {
if(!(current_msg->hdr.attr&MSG_ANONYMOUS) || SYSOP)
if(current_msg->from_ext!=NULL)
return(current_msg->from_ext);
return(nulstr);
}
if(!strcmp(sp,"MSG_FROM_NET") && current_msg!=NULL) {
if(current_msg->from_net.addr!=NULL
&& (!(current_msg->hdr.attr&MSG_ANONYMOUS) || SYSOP))
return(smb_netaddrstr(¤t_msg->from_net,str));
return(nulstr);
}
if(!strcmp(sp,"MSG_FROM_NETTYPE") && current_msg!=NULL) {
if(current_msg->from_net.type==NET_NONE)
return nulstr;
return(smb_nettype((enum smb_net_type)current_msg->from_net.type));
}
if(!strcmp(sp,"MSG_SUBJECT") && current_msg != nullptr) {
if(pmode != NULL)
*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
return current_msg_subj == nullptr ? current_msg->subj : current_msg_subj;
}
if(!strcmp(sp,"MSG_SUMMARY") && current_msg!=NULL)
return(current_msg->summary==NULL ? nulstr : current_msg->summary);
if(!strcmp(sp,"MSG_TAGS") && current_msg!=NULL)
return(current_msg->tags==NULL ? nulstr : current_msg->tags);
if(!strcmp(sp,"MSG_DATE") && current_msg!=NULL)
return(timestr(current_msg->hdr.when_written.time));
if(!strcmp(sp,"MSG_IMP_DATE") && current_msg!=NULL)
return(timestr(current_msg->hdr.when_imported.time));
if(!strcmp(sp,"MSG_AGE") && current_msg!=NULL)
return age_of_posted_item(str, maxlen
, current_msg->hdr.when_written.time - (smb_tzutc(current_msg->hdr.when_written.zone) * 60));
if(!strcmp(sp,"MSG_TIMEZONE") && current_msg!=NULL)
return(smb_zonestr(current_msg->hdr.when_written.zone,NULL));
if(!strcmp(sp,"MSG_IMP_TIMEZONE") && current_msg!=NULL)
return(smb_zonestr(current_msg->hdr.when_imported.zone,NULL));
if(!strcmp(sp,"MSG_ATTR") && current_msg!=NULL) {
uint16_t attr = current_msg->hdr.attr;
uint16_t poll = attr&MSG_POLL_VOTE_MASK;
uint32_t auxattr = current_msg->hdr.auxattr;
/* Synchronized with show_msgattr(): */
safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
,attr&MSG_PRIVATE ? "Private " :nulstr
,attr&MSG_SPAM ? "SPAM " :nulstr
,attr&MSG_READ ? "Read " :nulstr
,attr&MSG_DELETE ? "Deleted " :nulstr
,attr&MSG_KILLREAD ? "Kill " :nulstr
,attr&MSG_ANONYMOUS ? "Anonymous " :nulstr
,attr&MSG_LOCKED ? "Locked " :nulstr
,attr&MSG_PERMANENT ? "Permanent " :nulstr
,attr&MSG_MODERATED ? "Moderated " :nulstr
,attr&MSG_VALIDATED ? "Validated " :nulstr
,attr&MSG_REPLIED ? "Replied " :nulstr
,attr&MSG_NOREPLY ? "NoReply " :nulstr
,poll == MSG_POLL ? "Poll " :nulstr
,poll == MSG_POLL && auxattr&POLL_CLOSED ? "(Closed) " :nulstr
);
return(str);
}
if(!strcmp(sp,"MSG_AUXATTR") && current_msg!=NULL) {
safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s"
,current_msg->hdr.auxattr&MSG_FILEREQUEST ? "FileRequest " :nulstr
,current_msg->hdr.auxattr&MSG_FILEATTACH ? "FileAttach " :nulstr
,current_msg->hdr.auxattr&MSG_MIMEATTACH ? "MimeAttach " :nulstr
,current_msg->hdr.auxattr&MSG_KILLFILE ? "KillFile " :nulstr
,current_msg->hdr.auxattr&MSG_RECEIPTREQ ? "ReceiptReq " :nulstr
,current_msg->hdr.auxattr&MSG_CONFIRMREQ ? "ConfirmReq " :nulstr
,current_msg->hdr.auxattr&MSG_NODISP ? "DontDisplay " :nulstr
);
return(str);
}
if(!strcmp(sp,"MSG_NETATTR") && current_msg!=NULL) {
safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s%s"
,current_msg->hdr.netattr&NETMSG_LOCAL ? "Local " :nulstr
,current_msg->hdr.netattr&NETMSG_INTRANSIT ? "InTransit " :nulstr
,current_msg->hdr.netattr&NETMSG_SENT ? "Sent " :nulstr
,current_msg->hdr.netattr&NETMSG_KILLSENT ? "KillSent " :nulstr
,current_msg->hdr.netattr&NETMSG_HOLD ? "Hold " :nulstr
,current_msg->hdr.netattr&NETMSG_CRASH ? "Crash " :nulstr
,current_msg->hdr.netattr&NETMSG_IMMEDIATE ? "Immediate " :nulstr
,current_msg->hdr.netattr&NETMSG_DIRECT ? "Direct " :nulstr
);
return(str);
}
if(!strcmp(sp,"MSG_ID") && current_msg!=NULL)
return(current_msg->id==NULL ? nulstr : current_msg->id);
if(!strcmp(sp,"MSG_REPLY_ID") && current_msg!=NULL)
return(current_msg->reply_id==NULL ? nulstr : current_msg->reply_id);
if(!strcmp(sp,"MSG_NUM") && current_msg!=NULL) {
safe_snprintf(str,maxlen,"%lu", (ulong)current_msg->hdr.number);
return(str);
}
if(!strcmp(sp,"MSG_SCORE") && current_msg!=NULL) {
safe_snprintf(str, maxlen, "%ld", (long)current_msg->upvotes - (long)current_msg->downvotes);
return(str);
}
if(!strcmp(sp,"MSG_UPVOTES") && current_msg!=NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->upvotes);
return(str);
}
if(!strcmp(sp,"MSG_DOWNVOTES") && current_msg!=NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->downvotes);
return(str);
}
if(!strcmp(sp,"MSG_TOTAL_VOTES") && current_msg!=NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->total_votes);
return(str);
}
if(!strcmp(sp,"MSG_VOTED"))
return (current_msg != NULL && current_msg->user_voted) ? text[PollAnswerChecked] : nulstr;
if(!strcmp(sp,"MSG_UPVOTED"))
return (current_msg != NULL && current_msg->user_voted == 1) ? text[PollAnswerChecked] : nulstr;
if(!strcmp(sp,"MSG_DOWNVOTED"))
return (current_msg != NULL && current_msg->user_voted == 2) ? text[PollAnswerChecked] : nulstr;
if(strcmp(sp, "MSG_THREAD_ID") == 0 && current_msg != NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->hdr.thread_id);
return str;
}
if(strcmp(sp, "MSG_THREAD_BACK") == 0 && current_msg != NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->hdr.thread_back);
return str;
}
if(strcmp(sp, "MSG_THREAD_NEXT") == 0 && current_msg != NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->hdr.thread_next);
return str;
}
if(strcmp(sp, "MSG_THREAD_FIRST") == 0 && current_msg != NULL) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_msg->hdr.thread_first);
return str;
}
if(!strcmp(sp,"SMB_AREA")) {
if(is_valid_subnum(smb.subnum))
safe_snprintf(str,maxlen,"%s %s"
,cfg.grp[cfg.sub[smb.subnum]->grp]->sname
,cfg.sub[smb.subnum]->sname);
else
strncpy(str, "Email", maxlen);
return(str);
}
if(!strcmp(sp,"SMB_AREA_DESC")) {
if(is_valid_subnum(smb.subnum))
safe_snprintf(str,maxlen,"%s %s"
,cfg.grp[cfg.sub[smb.subnum]->grp]->lname
,cfg.sub[smb.subnum]->lname);
else
strncpy(str, "Personal Email", maxlen);
return(str);
}
if(!strcmp(sp,"SMB_GROUP")) {
if(is_valid_subnum(smb.subnum))
return(cfg.grp[cfg.sub[smb.subnum]->grp]->sname);
return(nulstr);
}
if(!strcmp(sp,"SMB_GROUP_DESC")) {
if(is_valid_subnum(smb.subnum))
return(cfg.grp[cfg.sub[smb.subnum]->grp]->lname);
return(nulstr);
}
if(!strcmp(sp,"SMB_GROUP_NUM")) {
if(is_valid_subnum(smb.subnum))
safe_snprintf(str,maxlen,"%u",getusrgrp(smb.subnum));
return(str);
}
if(!strcmp(sp,"SMB_SUB")) {
if(smb.subnum==INVALID_SUB)
return("Mail");
else if(is_valid_subnum(smb.subnum))
return(cfg.sub[smb.subnum]->sname);
return(nulstr);
}
if(!strcmp(sp,"SMB_SUB_DESC")) {
if(smb.subnum==INVALID_SUB)
return("Mail");
else if(is_valid_subnum(smb.subnum))
return(cfg.sub[smb.subnum]->lname);
return(nulstr);
}
if(!strcmp(sp,"SMB_SUB_CODE")) {
if(smb.subnum==INVALID_SUB)
return("MAIL");
else if(is_valid_subnum(smb.subnum))
return(cfg.sub[smb.subnum]->code);
return(nulstr);
}
if(!strcmp(sp,"SMB_SUB_NUM")) {
if(is_valid_subnum(smb.subnum))
safe_snprintf(str,maxlen,"%u",getusrsub(smb.subnum));
return(str);
}
if(!strcmp(sp,"SMB_MSGS")) {
safe_snprintf(str,maxlen,"%lu", (ulong)smb.msgs);
return(str);
}
if(!strcmp(sp,"SMB_CURMSG")) {
safe_snprintf(str,maxlen,"%lu", (ulong)(smb.curmsg+1));
return(str);
}
if(!strcmp(sp,"SMB_LAST_MSG")) {
safe_snprintf(str,maxlen,"%lu", (ulong)smb.status.last_msg);
return(str);
}
if(!strcmp(sp,"SMB_MAX_MSGS")) {
safe_snprintf(str,maxlen,"%lu", (ulong)smb.status.max_msgs);
return(str);
}
if(!strcmp(sp,"SMB_MAX_CRCS")) {
safe_snprintf(str,maxlen,"%lu", (ulong)smb.status.max_crcs);
return(str);
}
if(!strcmp(sp,"SMB_MAX_AGE")) {
safe_snprintf(str,maxlen,"%hu",smb.status.max_age);
return(str);
}
if(!strcmp(sp,"SMB_TOTAL_MSGS")) {
safe_snprintf(str,maxlen,"%lu", (ulong)smb.status.total_msgs);
return(str);
}
/* Currently viewed file */
if(current_file != NULL) {
if(is_valid_dirnum(current_file->dir)) {
if(strcmp(sp, "FILE_AREA") == 0) {
safe_snprintf(str, maxlen, "%s %s"
,cfg.lib[cfg.dir[current_file->dir]->lib]->sname
,cfg.dir[current_file->dir]->sname);
return str;
}
if(strcmp(sp, "FILE_AREA_DESC") == 0) {
safe_snprintf(str, maxlen, "%s %s"
,cfg.lib[cfg.dir[current_file->dir]->lib]->lname
,cfg.dir[current_file->dir]->lname);
return str;
}
if(strcmp(sp, "FILE_LIB") == 0)
return cfg.lib[cfg.dir[current_file->dir]->lib]->sname;
if(strcmp(sp, "FILE_LIB_DESC") == 0)
return cfg.lib[cfg.dir[current_file->dir]->lib]->lname;
if(strcmp(sp, "FILE_LIB_NUM") == 0) {
safe_snprintf(str, maxlen, "%u", getusrlib(current_file->dir));
return str;
}
if(strcmp(sp, "FILE_DIR") == 0)
return cfg.dir[current_file->dir]->sname;
if(strcmp(sp, "FILE_DIR_DESC") == 0)
return cfg.dir[current_file->dir]->lname;
if(strcmp(sp, "FILE_DIR_CODE") == 0)
return cfg.dir[current_file->dir]->code;
if(strcmp(sp, "FILE_DIR_NUM") == 0) {
safe_snprintf(str, maxlen, "%u", getusrdir(current_file->dir));
return str;
}
}
if(strcmp(sp, "FILE_NAME") == 0)
return current_file->name;
if(strcmp(sp, "FILE_DESC") == 0)
return current_file->desc;
if(strcmp(sp, "FILE_TAGS") == 0)
return current_file->tags;
if(strcmp(sp, "FILE_UPLOADER") == 0)
return current_file->from;
if(strcmp(sp, "FILE_SIZE") == 0) {
safe_snprintf(str, maxlen, "%ld", (long)current_file->size);
return str;
}
if(strcmp(sp, "FILE_CREDITS") == 0) {
safe_snprintf(str, maxlen, "%" PRIu64, current_file->cost);
return str;
}
if(strcmp(sp, "FILE_TIME") == 0)
return timestr(current_file->time);
if(strcmp(sp, "FILE_TIME_ULED") == 0)
return timestr(current_file->hdr.when_imported.time);
if(strcmp(sp, "FILE_TIME_DLED") == 0)
return timestr(current_file->hdr.last_downloaded);
if(strcmp(sp, "FILE_DATE") == 0)
return datestr(current_file->time);
if(strcmp(sp, "FILE_DATE_ULED") == 0)
return datestr(current_file->hdr.when_imported.time);
if(strcmp(sp, "FILE_DATE_DLED") == 0)
return datestr(current_file->hdr.last_downloaded);
if(strcmp(sp, "FILE_TIMES_DLED") == 0) {
safe_snprintf(str, maxlen, "%lu", (ulong)current_file->hdr.times_downloaded);
return str;
}
}
return get_text(sp);
}
char* sbbs_t::expand_atcodes(const char* src, char* buf, size_t size, const smbmsg_t* msg)
{
char* dst = buf;
char* end = dst + (size - 1);
const smbmsg_t* saved_msg{current_msg};
if (msg != NULL)
current_msg = msg;
while (*src != '\0' && dst < end) {
if (*src == '@') {
char str[32];
SAFECOPY(str, src + 1);
char* at = strchr(str, '@');
const char* sp = strchr(str, ' ');
if (at != NULL && (sp == NULL || sp > at)) {
char tmp[128];
*at = '\0';
src += strlen(str) + 2;
const char* p = formatted_atcode(str, tmp, sizeof tmp);
if(p != NULL)
dst += strlcpy(dst, p, end - dst);
continue;
}
}
*(dst++) = *(src++);
}
if(dst > end)
dst = end;
*dst = '\0';
current_msg = saved_msg;
return buf;
}