jcs
/subtext
/amendments
/77
session: Support template variables in ternary expressions
Instead of only supporting hard-coded strings, we can now output the
value of a variable based on the conditional.
Since we're using ?: for ternary conditionals, switch variable length
character from : to | (e.g., "username|10")
jcs made amendment 77 over 2 years ago
--- mail.c Thu Feb 17 14:50:25 2022
+++ mail.c Fri Feb 18 14:22:52 2022
@@ -52,8 +52,6 @@ struct bile_object_field mail_object_fields[] = {
void mail_free_message_strings(struct private_message *msg);
short mail_save(struct session *s, struct private_message *msg);
-size_t mail_find_for_user_id(unsigned long user_id,
- unsigned long **mail_ids);
void mail_help(struct session *s);
void mail_read(struct session *s, unsigned long idx);
void mail_delete(struct session *s, unsigned long idx);
@@ -478,7 +476,8 @@ mail_find_for_user_id(unsigned long user_id, unsigned
short i, j;
mail_ids_size = sizeof(unsigned long) * 16;
- *mail_ids = xmalloc(mail_ids_size);
+ if (mail_ids != NULL)
+ *mail_ids = xmalloc(mail_ids_size);
msgs_for_user = 0;
nmsg = 0;
@@ -486,25 +485,30 @@ mail_find_for_user_id(unsigned long user_id, unsigned
bile_read(db->bile, DB_MESSAGE_RTYPE, o->id, (char *)&msg_user_id,
sizeof(msg_user_id));
if (msg_user_id == user_id) {
- EXPAND_TO_FIT(*mail_ids, mail_ids_size,
- msgs_for_user * sizeof(long), sizeof(long),
- sizeof(unsigned long) * 16);
- (*mail_ids)[msgs_for_user++] = o->id;
+ if (mail_ids != NULL) {
+ EXPAND_TO_FIT(*mail_ids, mail_ids_size,
+ msgs_for_user * sizeof(long), sizeof(long),
+ sizeof(unsigned long) * 16);
+ (*mail_ids)[msgs_for_user] = o->id;
+ }
+ msgs_for_user++;
}
free(o);
nmsg++;
}
- /* sort by message id for consistent ordering */
- for (i = 0; i < msgs_for_user; i++) {
- for (j = 0; j < msgs_for_user - i - 1; j++) {
- if ((*mail_ids)[j] > (*mail_ids)[j + 1]) {
- id = (*mail_ids)[j];
- (*mail_ids)[j] = (*mail_ids)[j + 1];
- (*mail_ids)[j + 1] = id;
+ if (mail_ids != NULL) {
+ /* sort by message id for consistent ordering */
+ for (i = 0; i < msgs_for_user; i++) {
+ for (j = 0; j < msgs_for_user - i - 1; j++) {
+ if ((*mail_ids)[j] > (*mail_ids)[j + 1]) {
+ id = (*mail_ids)[j];
+ (*mail_ids)[j] = (*mail_ids)[j + 1];
+ (*mail_ids)[j + 1] = id;
+ }
}
}
}
-
+
return msgs_for_user;
}
--- mail.h Sat Jan 29 23:36:48 2022
+++ mail.h Fri Feb 18 14:22:59 2022
@@ -39,5 +39,7 @@ extern struct bile_object_field mail_object_fields[];
void mail_menu(struct session *s);
void mail_compose(struct session *s, char *to, char *subject, char *body);
+size_t mail_find_for_user_id(unsigned long user_id,
+ unsigned long **mail_ids);
#endif
--- session.c Sat Jan 29 23:32:56 2022
+++ session.c Fri Feb 18 15:00:49 2022
@@ -38,6 +38,7 @@ char sessions_tally_day[9] = { 0 };
void session_run(struct uthread *uthread, void *arg);
short session_login(struct session *s);
+size_t session_expand_var(struct session *session, char *ivar, char **ret);
struct session *
session_create(char *node, char *via, struct node_funcs *node_funcs)
@@ -701,13 +702,11 @@ size_t
session_expand_template(struct session *session, const char *tmpl,
char **ret)
{
- char curvar[128], matchvar[128];
- struct tm *now;
+ static char curvar[128], matchvar[128];
size_t tmpllen, retsize, retpos;
size_t vallen;
- short n, j, quote, invar = 0, varlen = 0, valsize, count, pad, doif,
- sep;
- char *varseek, *curvarpos;
+ short n, quote, invar = 0, varlen = 0, doif, sep;
+ char *varseek, *curvarpos, *val;
retsize = 0;
retpos = 0;
@@ -740,45 +739,12 @@ session_expand_template(struct session *session, const
expand_var:
invar = 0;
- count = 0;
- pad = 0;
- vallen = 0;
curvar[varlen] = '\0';
-
- if (sscanf(curvar, "%[^:]:%d%n", matchvar, &valsize, &count) == 2 &&
- count > 0) {
- /* field of fixed length, either truncated or padded */
- if (valsize > sizeof(curvar))
- valsize = sizeof(curvar);
- varlen = strlcpy(curvar, matchvar, sizeof(curvar));
- pad = 1;
- } else {
- valsize = sizeof(curvar);
- }
+ varlen = 0;
- while (varlen && curvar[varlen - 1] == ' ') {
- curvar[varlen - 1] = '\0';
- varlen--;
- }
-
- if (strcmp(curvar, "B") == 0) {
- vallen = strlcpy(curvar,
- ansi(session, ANSI_BOLD, ANSI_END), valsize);
- } else if (strcmp(curvar, "/") == 0) {
- vallen = strlcpy(curvar,
- ansi(session, ANSI_RESET, ANSI_END), valsize);
- } else if (strcmp(curvar, "node") == 0) {
- vallen = strlcpy(curvar, session->node, valsize);
- } else if (strcmp(curvar, "phone_number") == 0) {
- vallen = strlcpy(curvar, db->config.phone_number, valsize);
- } else if (strcmp(curvar, "time") == 0) {
- now = localtime((time_t *)&Time);
- vallen = strftime(curvar, valsize, "%H:%M", now);
- } else if (strcmp(curvar, "username") == 0) {
- vallen = strlcpy(curvar, session->user ?
- session->user->username : GUEST_USERNAME, valsize);
- } else if (strchr(curvar, '?') != NULL && strchr(curvar, ':') != NULL) {
- /* user ? " Settings" : "Signup for Account" */
+ if (strpos_quoted(curvar, '?') != -1 &&
+ strpos_quoted(curvar, ':') != -1) {
+ /* ternary: user ? "a string" : time */
varseek = curvar;
while (varseek[0] == ' ')
varseek++;
@@ -791,6 +757,7 @@ expand_var:
while (matchvar[sep - 1] == ' ')
matchvar[--sep] = '\0';
+ /* matchvar is now the condition */
if (strcmp(matchvar, "user") == 0)
doif = (session->user != NULL);
else if (strcmp(matchvar, "sysop") == 0)
@@ -798,48 +765,114 @@ expand_var:
else
doif = 0;
+ while (curvarpos[0] == ' ')
+ curvarpos++;
+
sep = strpos_quoted(curvarpos, ':');
if (sep == -1)
continue;
+ while (curvarpos[sep] == ' ') {
+ curvarpos++;
+ sep--;
+ }
+
if (doif) {
- while (curvarpos[0] == ' ') {
- curvarpos++;
- sep--;
- }
+ /* copy the "then" */
memcpy(matchvar, curvarpos, sep);
matchvar[sep] = '\0';
} else {
- while (curvarpos[sep] == ' ') {
- curvarpos++;
- sep--;
- }
+ /* copy from after the "then" and : */
strlcpy(matchvar, curvarpos + sep, sizeof(matchvar));
}
+
sep = strlen(matchvar);
while (matchvar[sep - 1] == ' ')
matchvar[--sep] = '\0';
- /* remove leading and trailing quotes */
- vallen = sep - 2;
- memcpy(curvar, matchvar + 1, vallen);
- curvar[vallen] = '\0';
+ vallen = session_expand_var(session, matchvar, &val);
+ } else {
+ vallen = session_expand_var(session, curvar, &val);
}
if (vallen) {
- if (pad && vallen < valsize) {
- while (vallen < valsize)
- curvar[vallen++] = ' ';
- curvar[vallen] = '\0';
- }
EXPAND_TO_FIT(*ret, retsize, retpos, vallen, 128);
- memcpy(*ret + retpos, curvar, vallen);
+ memcpy(*ret + retpos, val, vallen);
retpos += vallen;
}
}
(*ret)[retpos] = '\0';
return retpos;
+}
+
+size_t
+session_expand_var(struct session *session, char *ivar, char **ret)
+{
+ static char var[128], retval[128];
+ size_t retsize, retlen, varlen, mcount;
+ struct tm *now;
+ short count;
+ bool pad = false;
+
+ *ret = (char *)&retval;
+ retlen = 0;
+
+ if (sscanf(ivar, "%[^|]|%ld%n", var, &retsize, &count) == 2 &&
+ count > 0) {
+ /* field of fixed length, either truncated or padded */
+ if (retsize > sizeof(retval))
+ retsize = sizeof(retval);
+ pad = true;
+ varlen = strlen(var);
+ } else {
+ varlen = strlcpy(var, ivar, sizeof(var));
+ retsize = sizeof(retval);
+ }
+
+ while (varlen && var[varlen - 1] == ' ') {
+ var[varlen - 1] = '\0';
+ varlen--;
+ }
+
+ if (strcmp(var, "B") == 0) {
+ retlen = strlcpy(retval,
+ ansi(session, ANSI_BOLD, ANSI_END), retsize);
+ } else if (strcmp(var, "/") == 0) {
+ retlen = strlcpy(retval,
+ ansi(session, ANSI_RESET, ANSI_END), retsize);
+ } else if (strcmp(var, "node") == 0) {
+ retlen = strlcpy(retval, session->node, retsize);
+ } else if (strcmp(var, "phone_number") == 0) {
+ retlen = strlcpy(retval, db->config.phone_number, retsize);
+ } else if (strcmp(var, "time") == 0) {
+ now = localtime((time_t *)&Time);
+ retlen = strftime(retval, retsize, "%H:%M", now);
+ } else if (strcmp(var, "username") == 0) {
+ retlen = strlcpy(retval, session->user ?
+ session->user->username : GUEST_USERNAME, retsize);
+ } else if (strcmp(var, "new_mail") == 0) {
+ if (session->user) {
+ if ((mcount = mail_find_for_user_id(session->user->id, NULL)))
+ retlen = sprintf(retval, "(%ld New)", mcount);
+ }
+ } else if (var[0] == '"') {
+ /* a literal string, remove leading and trailing quotes */
+ var[varlen - 1] = '\0';
+ varlen--;
+ if (varlen > retsize)
+ varlen = retsize;
+ strlcpy(retval, var + 1, varlen);
+ retlen = varlen - 1;
+ }
+
+ if (pad && retlen < retsize) {
+ while (retlen < retsize)
+ retval[retlen++] = ' ';
+ retval[retlen] = '\0';
+ }
+
+ return retlen;
}
void