AmendHub

Download:

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