Newer
Older
/* 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"
#if defined(_WINSOCKAPI_)
extern WSADATA WSAData;
#define SOCKLIB_DESC WSAData.szDescription
#else
#define SOCKLIB_DESC NULL
#endif
static char* separate_thousands(const char* src, char *dest, size_t maxlen, char sep)
{
if(strlen(src) * 1.3 > maxlen)
return (char*)src;
const char* tail = src;
while(*tail && IS_DIGIT(*tail))
tail++;
if(tail == src)
return (char*)src;
size_t digits = tail - src;
char* d = dest;
for(size_t i = 0; i < digits; d++, i++) {
*d = src[i];
if(i && i + 3 < digits && (digits - (i + 1)) % 3 == 0)
*(++d) = sep;
}
*d = 0;
strcpy(d, tail);
return dest;
}
/****************************************************************************/
/* 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 disp_len;

rswindell
committed
enum {
none,
left,
right,
center
} align = none;
bool zero_padded=false;
bool thousep = false; // thousands-separated
bool uppercase = false;

rswindell
committed
bool width_specified = false;
long pmode = 0;
const char *cp;
if(*instr != '@')
return 0;
tp=strchr(str+1,'@');
if(!tp) /* no terminating @ */
return(0);
if(sp && sp<tp) /* space before terminating @ */
return(0);
len=(tp-str)+1;
(*tp)=0;
sp=(str+1);

rswindell
committed
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);

rswindell
committed
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);
disp_len=len;
if((p = strchr(sp, '|')) != NULL) {
if(strchr(p, 'T') != NULL)
thousep = true;
if(strchr(p, 'U') != NULL)
uppercase = true;
if(strchr(p, 'L') != NULL)

rswindell
committed
align = left;
else if(strchr(p, 'R') != NULL)

rswindell
committed
align = right;
else if(strchr(p, 'C') != NULL)

rswindell
committed
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)

rswindell
committed
align = left;

rswindell
committed
align = right;
else if((p=strstr(sp,"-C"))!=NULL)

rswindell
committed
align = center;
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;
if(p!=NULL) {
char* lp = p;

rswindell
committed
lp++; // skip the '|' or '-'
while(*lp == '>'|| IS_ALPHA(*lp))

rswindell
committed
lp++;
if(*lp)
width_specified = true;
while(*lp && !IS_DIGIT(*lp))
lp++;
if(*lp && IS_DIGIT(*lp)) {

rswindell
committed
width_specified = true;
}
}

rswindell
committed
cp = atcode(sp, str2, sizeof(str2), &pmode, align == center, obj);
if(cp==NULL)
char separated[128];
if(thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
if(uppercase) {
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}

rswindell
committed
if(p==NULL || truncated == false || (width_specified == false && align == none))

rswindell
committed
if(uppercase && align == none)
align = left;
if(truncated && strchr(cp, '\n') == NULL) {
if(column + disp_len > cols - 1) {
if(column >= cols - 1)
disp_len = 0;
else
disp_len = (cols - 1) - column;
}
}
if(pmode & P_UTF8) {
if(term_supports(UTF8))
disp_len += strlen(cp) - utf8_str_total_width(cp);
else
disp_len += strlen(cp) - utf8_str_count_width(cp, /* min: */1, /* max: */2);
}

rswindell
committed
if(align == left)
bprintf(pmode, "%-*.*s",disp_len,disp_len,cp);

rswindell
committed
else if(align == right)
bprintf(pmode, "%*.*s",disp_len,disp_len,cp);

rswindell
committed
else if(align == center) {
if(vlen < disp_len) {
int left = (disp_len - vlen) / 2;
bprintf(pmode, "%*s%-*s", left, "", disp_len - left, cp);
bprintf(pmode, "%.*s", disp_len, cp);
} else if(zero_padded) {
int vlen = strlen(cp);
if(vlen < disp_len)
bprintf(pmode, "%-.*s%s", (int)(disp_len - strlen(cp)), "0000000000", cp);
else
bprintf(pmode, "%.*s", disp_len, cp);
bprintf(pmode, "%.*s", disp_len, cp);
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::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool centered, JSObject* obj)
char* tp = NULL;
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;

rswindell
committed
if(strncmp(sp, "HOT:", 4) == 0) { // Auto-mouse hot-spot attribute

rswindell
committed
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 = attrstr(sp);

rswindell
committed
return nulstr;
}
if(strcmp(sp, "CLEAR_HOT") == 0) {
clear_hotspots();
return nulstr;
}

rswindell
committed
if(strncmp(sp, "U+", 2) == 0) { // UNICODE
enum unicode_codepoint codepoint = (enum unicode_codepoint)strtoul(sp + 2, &tp, 16);
outchar(codepoint, unicode_to_cp437(codepoint));
else if(*tp == ':')
outchar(codepoint, tp + 1);
else {
char fallback = (char)strtoul(tp + 1, NULL, 16);
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) {
return nulstr;
}
if(strcmp(sp, "DEGREE_F") == 0) {
if(strncmp(sp, "WIDE:", 5) == 0) {
wide(sp + 5);
return(nulstr);
}
safe_snprintf(str,maxlen,"%c",REVISION);
safe_snprintf(str,maxlen,"%s%c%s",VERSION,REVISION,beta_version);

rswindell
committed
#if defined(_DEBUG)

rswindell
committed
#endif

rswindell
committed
}
if(!strcmp(sp,"VER_NOTICE"))

rswindell
committed
if(!strcmp(sp,"OS_VER"))
return(os_version(str));

rswindell
committed
#ifdef JAVASCRIPT
if(!strcmp(sp,"JS_VER"))
return((char *)JS_GetImplementationVersion());

rswindell
committed
#endif
if(!strcmp(sp,"PLATFORM"))
return(PLATFORM_DESC);

rswindell
committed
if(!strcmp(sp,"COPYRIGHT"))
return(COPYRIGHT_NOTICE);

rswindell
committed
char compiler[32];
DESCRIBE_COMPILER(compiler);
strncpy(str, compiler, maxlen);

rswindell
committed
}
if(strcmp(sp, "GIT_HASH") == 0)
return git_hash;
if(strcmp(sp, "GIT_BRANCH") == 0)
return git_branch;
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,"%lu days ",(ulong)(up/(24L*60L*60L)));
up%=(24*60*60);
}
safe_snprintf(str,maxlen,"%s%lu:%02lu"
,(ulong)(up/(60L*60L))
,(ulong)((up/60L)%60L)
if(!strcmp(sp,"SERVED")) {
extern volatile ulong served;
safe_snprintf(str,maxlen,"%lu",served);
return(str);
}
if(!strcmp(sp,"SOCKET_LIB"))
return(socklib_version(str,SOCKLIB_DESC));

rswindell
committed
safe_snprintf(str,maxlen,"SMBLIB %s",smb_lib_ver());

rswindell
committed
if(!strcmp(sp,"BBS") || !strcmp(sp,"BOARDNAME"))
return(cfg.sys_name);
if(!strcmp(sp,"BAUD") || !strcmp(sp,"BPS")) {
safe_snprintf(str,maxlen,"%lu",cur_output_rate ? cur_output_rate : cur_rate);
if(!strcmp(sp,"COLS")) {
safe_snprintf(str,maxlen,"%lu",cols);
return(str);
}
if(!strcmp(sp,"ROWS")) {
safe_snprintf(str,maxlen,"%lu",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);
if(strcmp(sp, "TNODES") == 0 || strcmp(sp, "TNODE") == 0 || strcmp(sp, "TN") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.sys_nodes);
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();
return(smb_faddrtoa(&cfg.faddr[0],str));
if(!strcmp(sp,"EMAILADDR"))
,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name));
if(strcmp(sp, "NETMAIL") == 0)
return useron.netmail;
if(strcmp(sp, "FWD") == 0)
return (useron.misc & NETMAIL) ? text[On] : text[Off];
if(strcmp(sp, "TMP") == 0)
return useron.tmpext;
if(!strcmp(sp,"QWKID"))
return(cfg.sys_id);
if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
memset(&tm,0,sizeof(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");
if(!strcmp(sp,"TIMEZONE"))
return(smb_zonestr(sys_timezone(&cfg),str));
if(!strcmp(sp,"DATE") || !strcmp(sp,"SYSDATE")) {
return(unixtodstr(&cfg,time32(NULL),str));
if(strncmp(sp, "DATE:", 5) == 0 || strncmp(sp, "TIME:", 5) == 0) {
sp += 5;
c_unescape_str(sp);
now = time(NULL);
memset(&tm, 0, sizeof(tm));
localtime_r(&now, &tm);
strftime(str, maxlen, sp, &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 cfg.sys_misc&SM_EURODATE ? "DD/MM/YY" : "MM/DD/YY";
}
if(strcmp(sp, "BDATEFMT") == 0 || strcmp(sp, "BIRTHFMT") == 0) {
return birthdate_format(&cfg);
}
l=0;
for(i=0;i<cfg.total_subs;i++)
l+=getposts(&cfg,i); /* l=total posts */
safe_snprintf(str,maxlen,"%lu",l);
safe_snprintf(str,maxlen,"%u",total_users(&cfg));
l=0;
for(i=0;i<cfg.total_dirs;i++)
safe_snprintf(str,maxlen,"%lu",l);
if(strncmp(sp, "FILES:", 6) == 0) { // Number of files in specified directory
const char* path = getpath(&cfg, sp + 6);
safe_snprintf(str, maxlen, "%lu", getfilecount(path));
}
if(strcmp(sp, "FILES") == 0) { // Number of files in current directory
safe_snprintf(str, maxlen, "%lu", (ulong)getfiles(&cfg, usrdir[curlib][curdir[curlib]]));
return str;
}
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
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")) {
safe_snprintf(str,maxlen,"%lu", (ulong)stats.logons);
if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
|| !strcmp(sp,"LASTCALLERSYSTEM"))
if(strcmp(sp, "GETKEY") == 0) {
getkey();
return(nulstr);
}
if(strcmp(sp, "CONTINUE") == 0) {
char ch = getkey(K_UPPER);
if(ch == text[YNQP][1] || ch == text[YNQP][2])
sys_status|=SS_ABORT;
return(nulstr);
}
if(strncmp(sp, "WAIT:", 5) == 0) {
if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE")) {
lncntr=0;
if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF")) {
if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE")) {
long margin = centered ? column : 1;
if(margin < 1) margin = 1;
while(*sp && online && column < cols - margin)
bputs(sp, 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", text[YNQP][0]);
return str;
}
if(strcmp(sp, "NOCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", text[YNQP][1]);
return str;
}
if(strcmp(sp, "QUITCHAR") == 0) {
safe_snprintf(str, maxlen, "%c", text[YNQP][2]);
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];
return nulstr;
}
/* 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));
i=atoi(sp+4);
if(i && i<=cfg.sys_nodes) {
getnodedat(i,&node,0);
printnodedat(i,&node);
}
if(!strcmp(sp,"USER") || !strcmp(sp,"ALIAS") || !strcmp(sp,"NAME"))
return(useron.alias);
safe_snprintf(str,maxlen,"%s",useron.alias);
return(str);
safe_snprintf(str,maxlen,"%u",useron.number);
if(!strcmp(sp,"PHONE") || !strcmp(sp,"HOMEPHONE")
|| !strcmp(sp,"DATAPHONE") || !strcmp(sp,"DATA"))
if(!strcmp(sp,"ADDR1"))
return(useron.address);
if(!strcmp(sp,"FROM"))
return(useron.location);
safe_snprintf(str,maxlen,"%s",useron.location);
return(str);
}
if(!strcmp(sp,"STATE")) {
char* p=strchr(useron.location,',');
return(p);
}
if(!strcmp(sp,"CPU"))
return(useron.comp);
if(!strcmp(sp,"HOST"))
return(client_name);
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) {
sp += 6;
c_unescape_str(sp);
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, sp, &tm);
return str;
}
safe_snprintf(str,maxlen,"%u",getage(&cfg,useron.birth));
if(!strcmp(sp,"CALLS") || !strcmp(sp,"NUMTIMESON")) {
safe_snprintf(str,maxlen,"%u",useron.logons);
if(strcmp(sp, "PWAGE") == 0) {
time_t age = time(NULL) - useron.pwmod;
safe_snprintf(str, maxlen, "%ld", (long)(age/(24*60*60)));
return str;
}
if(strcmp(sp, "PWDATE") == 0 || strcmp(sp, "MEMO") == 0)
return(unixtodstr(&cfg,useron.pwmod,str));
if(strncmp(sp, "PWDATE:", 7) == 0) {
sp += 7;
c_unescape_str(sp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.pwmod;
localtime_r(&date, &tm);
strftime(str, maxlen, sp, &tm);
return str;
}
if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY")) {
safe_snprintf(str,maxlen,"%u",useron.level);
if(!strcmp(sp,"SINCE"))
return(unixtodstr(&cfg,useron.firston,str));
if(strncmp(sp, "SINCE:", 6) == 0) {
sp += 6;
c_unescape_str(sp);
memset(&tm, 0, sizeof(tm));
time_t date = useron.firston;
localtime_r(&date, &tm);
strftime(str, maxlen, sp, &tm);
return str;
}
if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
safe_snprintf(str,maxlen,"%lu",(ulong)(now-logontime)/60L);
if(!strcmp(sp,"TUSED")) { /* Synchronet only */
return(sectostr((uint)(now-logontime),str)+1);
if(!strcmp(sp,"TLEFT")) { /* Synchronet only */
return(sectostr(timeleft,str)+1);
if(!strcmp(sp,"TPERD")) /* Synchronet only */
if(!strcmp(sp,"TPERC")) /* Synchronet only */
safe_snprintf(str,maxlen,"%u",cfg.level_timepercall[useron.level]);
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")) {
safe_snprintf(str,maxlen,"%lu",timeleft/60);
if(!strcmp(sp,"LASTON"))
return(timestr(useron.laston));
if(!strcmp(sp,"LASTDATEON"))
return(unixtodstr(&cfg,useron.laston,str));