# HG changeset patch # User Ben Schmidt # Date 1326724005 -39600 # Node ID 74d5ebb67b34d4c8b626a5d600ad220b182ecf55 # Parent 58a2cba0be3ef156280fc33ab876307bfe8e7e04 Rework the internals of list text substitution and add some substitutions. This includes making some substitutions more widely available, too, and marking some old ones as deprecated, too. diff -r 58a2cba0be3e -r 74d5ebb67b34 ChangeLog --- a/ChangeLog Mon Jan 16 21:30:29 2012 +1100 +++ b/ChangeLog Tue Jan 17 01:26:45 2012 +1100 @@ -1,3 +1,7 @@ + o Deprecate various list text substitutions such as $newsub$, $oldsub$, + $moderateaddr$ + o Add $permitaddr$ and $releaseaddr$ substitutions + o Make $subject$, $posteraddr$ and $subaddr$ more widely available o Fix potential crash when mail to the owner arrives with no From: header o Add %originalmail% directive and restore backward compatibility of $originalmail$ diff -r 58a2cba0be3e -r 74d5ebb67b34 README.listtexts --- a/README.listtexts Mon Jan 16 21:30:29 2012 +1100 +++ b/README.listtexts Tue Jan 17 01:26:45 2012 +1100 @@ -324,9 +324,11 @@ DEPRECATED: use %bouncenumbers% - $confaddr$ +- $confirmaddr$ (available only in confirm-[un]sub-*) the address to which to send mail to confirm the (un-)subscription in question + NOTE: the short version of this substitution is DEPRECATED - $control C$ the contents of the control file named C in listdir/control, with its final @@ -410,15 +412,17 @@ (available only in moderate-post-* and gatekeep-sub) the address to which to send mail to approve the post or subscription in question + DEPRECATED: use $releaseaddr$ or $permitaddr$ instead - $moderators$ (available only in moderate-post-*, wait-post-*, gatekeep-sub and wait-sub) the formatted list of moderators to whom the moderation request has been sent - DEPRECATED: use %moderators% or %gatekeepers% + DEPRECATED: use %moderators% or %gatekeepers% instead - $newsub$ (available only in notify-sub-*-*) the address that has been subscribed + DEPRECATED: use $subaddr$ instead - $nomailsubaddr$ listname+subscribe-nomail@domain.tld @@ -429,16 +433,21 @@ DEPRECATED: use $list+$unsubscribe-nomail@$domain$ instead - $oldsub$ - (available only in notify-nsub-*-*) + (available only in notify-sub-*-*) the address that has been unsubscribed + DEPRECATED: use $subaddr$ instead - $originalmail$ the same as %originalmail 100% preceded by a space DEPRECATED: use %originalmail% +- $permitaddr$ + (available only in gatekeep-sub) + the address to which to send mail to permit the subscription in question + - $posteraddr$ - (available only in deny-post-{access|tocc|subonlypost}, moderate-post-* and - wait-post-*) + (available only in deny-post-{access|tocc|subonlypost|maxmailsize}, + moderate-post-* and wait-post-*) the from address of the message that was received as determined by Mlmmj - $random0$ @@ -451,13 +460,18 @@ that are MIME messages with attachments by creating boundaries that are unlikely to appear in the attached messages +- $releaseaddr$ + (available only in moderate-post-*) + the address to which to send mail to release the post in question + - $subaddr$ - (available only in gatekeep-sub and confirm-[un]sub-*) + (available only in gatekeep-sub, confirm-[un]sub-*, finish-[un]sub-*, + notify-[un]sub-* and deny-[un]sub-*) the address requested to be (un-)subscribed - $subject$ - (available only in deny-post-{access|tocc|subonlypost}, moderate-post-* and - wait-post-*) + (available only in deny-post-{access|tocc|subonlypost|maxmailsize}, + moderate-post-* and wait-post-*) the subject line of the message in question - $text T$ diff -r 58a2cba0be3e -r 74d5ebb67b34 include/prepstdreply.h --- a/include/prepstdreply.h Mon Jan 16 21:30:29 2012 +1100 +++ b/include/prepstdreply.h Tue Jan 17 01:26:45 2012 +1100 @@ -29,18 +29,16 @@ typedef struct text text; char *substitute(const char *line, const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char *listdir); + const char *listdir, text *txt); text *open_text_file(const char *listdir, const char *filename); text *open_text(const char *listdir, const char *purpose, const char *action, const char *reason, const char *type, const char *compat); +void register_unformatted(text *txt, const char *token, const char *subst); +void register_originalmail(text *txt, const char *mailname); char *get_processed_text_line(text *txt, - const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char *listdir, - const char *mailname); + const char *listaddr, const char *listdelim, const char *listdir); void close_text(text *txt); -char *prepstdreply(const char *listdir, const char *purpose, const char *action, - const char *reason, const char *type, const char *compat, - const char *from, const char *to, const char *replyto, - size_t tokencount, char **data, const char *mailname); +char *prepstdreply(text *txt, const char *listdir, + const char *from, const char *to, const char *replyto); #endif /* PREPSTDREPLY_H */ diff -r 58a2cba0be3e -r 74d5ebb67b34 include/send_help.h --- a/include/send_help.h Mon Jan 16 21:30:29 2012 +1100 +++ b/include/send_help.h Tue Jan 17 01:26:45 2012 +1100 @@ -24,8 +24,7 @@ #ifndef SEND_HELP_H #define SEND_HELP_H -void send_help(const char *listdir, const char *emailaddr, - const char *mlmmjsend, const char *purpose, const char *action, - const char *reason, const char *type, const char *compat); +void send_help(const char *listdir, const char *queuefilename, + const char *emailaddr, const char *mlmmjsend); #endif diff -r 58a2cba0be3e -r 74d5ebb67b34 src/listcontrol.c --- a/src/listcontrol.c Mon Jan 16 21:30:29 2012 +1100 +++ b/src/listcontrol.c Tue Jan 17 01:26:45 2012 +1100 @@ -36,6 +36,7 @@ #include "find_email_adr.h" #include "getlistdelim.h" #include "strgen.h" +#include "prepstdreply.h" #include "send_help.h" #include "send_list.h" #include "log_error.h" @@ -116,6 +117,8 @@ unsigned int ctrl; struct strlist *owners; int owner_idx; + text *txt; + char *queuefilename; /* A closed list doesn't allow subscribtion and unsubscription */ closedlist = statctrl(listdir, "closedlist"); @@ -209,10 +212,20 @@ } if (statctrl(listdir, "nodigestsub")) { errno = 0; - log_error(LOG_ARGS, "A subcribe-digest request was" + log_error(LOG_ARGS, "A subscribe-digest request was" " denied"); - send_help(listdir, fromemails->emaillist[0], - mlmmjsend, "deny", "sub", "disabled", "digest", "sub-deny-digest"); + txt = open_text(listdir, "deny", "sub", "disabled", + "digest", "sub-deny-digest"); + MY_ASSERT(txt); + register_unformatted(txt, "subaddr", + fromemails->emaillist[0]); + queuefilename = prepstdreply(txt, listdir, + "$listowner$", + fromemails->emaillist[0], NULL); + MY_ASSERT(queuefilename); + close_text(txt); + send_help(listdir, queuefilename, + fromemails->emaillist[0], mlmmjsend); return -1; } log_oper(listdir, OPLOGFNAME, "mlmmj-sub: request for digest" @@ -246,10 +259,20 @@ } if (statctrl(listdir, "nonomailsub")) { errno = 0; - log_error(LOG_ARGS, "A subcribe-nomail request was" + log_error(LOG_ARGS, "A subscribe-nomail request was" " denied"); - send_help(listdir, fromemails->emaillist[0], - mlmmjsend, "deny", "sub", "disabled", "nomail", "sub-deny-nomail"); + txt = open_text(listdir, "deny", "sub", "disabled", + "nomail", "sub-deny-nomail"); + MY_ASSERT(txt); + register_unformatted(txt, "subaddr", + fromemails->emaillist[0]); + queuefilename = prepstdreply(txt, listdir, + "$listowner$", + fromemails->emaillist[0], NULL); + MY_ASSERT(queuefilename); + close_text(txt); + send_help(listdir, queuefilename, + fromemails->emaillist[0], mlmmjsend); return -1; } log_oper(listdir, OPLOGFNAME, "mlmmj-sub: request for nomail" @@ -664,8 +687,14 @@ } log_oper(listdir, OPLOGFNAME, "%s requested help", fromemails->emaillist[0]); - send_help(listdir, fromemails->emaillist[0], mlmmjsend, - "help", NULL, NULL, NULL, "listhelp"); + txt = open_text(listdir, "help", NULL, NULL, NULL, "listhelp"); + MY_ASSERT(txt); + queuefilename = prepstdreply(txt, listdir, + "$listowner$", fromemails->emaillist[0], NULL); + MY_ASSERT(queuefilename); + close_text(txt); + send_help(listdir, queuefilename, + fromemails->emaillist[0], mlmmjsend); break; /* listname+faq@domain.tld */ @@ -680,8 +709,14 @@ } log_oper(listdir, OPLOGFNAME, "%s requested faq", fromemails->emaillist[0]); - send_help(listdir, fromemails->emaillist[0], mlmmjsend, - "faq", NULL, NULL, NULL, "listfaq"); + txt = open_text(listdir, "faq", NULL, NULL, NULL, "listfaq"); + MY_ASSERT(txt); + queuefilename = prepstdreply(txt, listdir, + "$listowner$", fromemails->emaillist[0], NULL); + MY_ASSERT(queuefilename); + close_text(txt); + send_help(listdir, queuefilename, + fromemails->emaillist[0], mlmmjsend); break; /* listname+get-INDEX@domain.tld */ diff -r 58a2cba0be3e -r 74d5ebb67b34 src/mlmmj-bounce.c --- a/src/mlmmj-bounce.c Mon Jan 16 21:30:29 2012 +1100 +++ b/src/mlmmj-bounce.c Tue Jan 17 01:26:45 2012 +1100 @@ -108,9 +108,9 @@ void do_probe(const char *listdir, const char *mlmmjsend, const char *addr) { + text *txt; char *myaddr, *from, *a, *indexstr, *queuefilename, *listaddr; char *listfqdn, *listname, *probefile, *listdelim=getlistdelim(listdir); - char *maildata[] = { "bouncenumbers", NULL }; int fd; time_t t; @@ -144,12 +144,13 @@ exit(EXIT_FAILURE); } - maildata[1] = indexstr; - queuefilename = prepstdreply(listdir, - "probe", NULL, NULL, NULL, "bounce-probe", - "$listowner$", myaddr, NULL, 1, maildata, NULL); + txt = open_text(listdir, "probe", NULL, NULL, NULL, "bounce-probe"); + MY_ASSERT(txt); + register_unformatted(txt, "bouncenumbers", indexstr); + myfree(indexstr); + queuefilename = prepstdreply(txt, listdir, "$listowner$", myaddr, NULL); MY_ASSERT(queuefilename); - myfree(indexstr); + close_text(txt); probefile = concatstr(4, listdir, "/bounce/", addr, "-probe"); MY_ASSERT(probefile); diff -r 58a2cba0be3e -r 74d5ebb67b34 src/mlmmj-process.c --- a/src/mlmmj-process.c Mon Jan 16 21:30:29 2012 +1100 +++ b/src/mlmmj-process.c Tue Jan 17 01:26:45 2012 +1100 @@ -86,17 +86,17 @@ }; -void newmoderated(const char *listdir, const char *mailfilename, +static void newmoderated(const char *listdir, const char *mailfilename, const char *mlmmjsend, const char *efromsender, - size_t tokencount, char **data, enum modreason modreason) + const char *subject, const char *posteraddr, + enum modreason modreason) { - size_t i; char *from, *listfqdn, *listname, *moderators = NULL; char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim; + text *txt; char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL; char *mailbasename = mybasename(mailfilename), *tmp, *to; int moderatorsfd, foundaddr = 0, notifymod = 0, status; - char *maildata[10] = { "moderateaddr", NULL, "moderators", NULL }; pid_t childpid, pid; #if 0 printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename, @@ -105,13 +105,6 @@ listfqdn = genlistfqdn(listaddr); listname = genlistname(listaddr); - MY_ASSERT(tokencount<=3) - for (i=0; isubsts; + while (subst != NULL) { + if(strcmp(token, subst->token) == 0) { + value = mystrdup(subst->subst); break; } + subst = subst->next; } } @@ -198,7 +210,7 @@ char *substitute(const char *line, const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char *listdir) + const char *listdir, text *txt) { char *new; char *pos; @@ -209,8 +221,7 @@ while (*pos != '\0') { if (*pos == '$') { substitute_one(&new, &pos, - listaddr, listdelim, - datacount, data, listdir); + listaddr, listdelim, listdir, txt); /* The function sets up for the next character * to process, so continue straight away. */ continue; @@ -235,6 +246,8 @@ txt->src->suffix = NULL; txt->src->transparent = 0; txt->src->limit = -1; + txt->substs = NULL; + txt->mailname = NULL; tmp = concatstr(3, listdir, "/text/", filename); txt->src->fd = open(tmp, O_RDONLY); @@ -295,6 +308,22 @@ } +void register_unformatted(text *txt, const char *token, const char *replacement) +{ + substitution * subst = mymalloc(sizeof(substitution)); + subst->token = mystrdup(token); + subst->subst = mystrdup(replacement); + subst->next = txt->substs; + txt->substs = subst; +} + + +void register_originalmail(text *txt, const char *mailname) +{ + txt->mailname = mystrdup(mailname); +} + + static void begin_new_source_file(text *txt, char **line_p, char **pos_p, const char *filename) { char *line = *line_p; @@ -339,7 +368,7 @@ static void handle_directive(text *txt, char **line_p, char **pos_p, - const char *listdir, const char *mailname) { + const char *listdir) { char *line = *line_p; char *pos = *pos_p; char *token = pos + 1; @@ -397,7 +426,8 @@ myfree(filename); return; } - } else if(strncmp(token, "originalmail", 12) == 0 && mailname != NULL) { + } else if(strncmp(token, "originalmail", 12) == 0 && + txt->mailname != NULL) { token += 12; limit = 0; if (*token == '\0') { @@ -410,7 +440,8 @@ if (token != NULL) limit = atol(token); } if (limit != 0) { - begin_new_source_file(txt, line_p, pos_p, mailname); + begin_new_source_file(txt, line_p, pos_p, + txt->mailname); txt->src->transparent = 1; if (limit == -1) txt->src->limit = -1; else txt->src->limit = limit - 1; @@ -436,8 +467,7 @@ char *get_processed_text_line(text *txt, const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char *listdir, - const char *mailname) + const char *listdir) { char *line = NULL; char *pos; @@ -493,13 +523,12 @@ * transparently */ } else if (*pos == '$') { substitute_one(&line, &pos, - listaddr, listdelim, - datacount, data, listdir); + listaddr, listdelim, listdir, txt); /* The function sets up for the next character * to process, so continue straight away. */ continue; } else if (*pos == '%') { - handle_directive(txt, &line, &pos, listdir, mailname); + handle_directive(txt, &line, &pos, listdir); /* The function sets up for the next character * to process, so continue straight away. */ continue; @@ -519,32 +548,35 @@ void close_text(text *txt) { source *tmp; + substitution *subst; while (txt->src != NULL) { close(txt->src->fd); tmp = txt->src; txt->src = txt->src->prev; myfree(tmp); } + while (txt->substs != NULL) { + subst = txt->substs; + myfree(subst->token); + myfree(subst->subst); + txt->substs = txt->substs->next; + myfree(subst); + } + if (txt->mailname != NULL) myfree(txt->mailname); + myfree(txt); } -char *prepstdreply(const char *listdir, const char *purpose, const char *action, - const char *reason, const char *type, const char *compat, - const char *from, const char *to, const char *replyto, - size_t tokencount, char **data, const char *mailname) +char *prepstdreply(text *txt, const char *listdir, + const char *from, const char *to, const char *replyto) { size_t len, i; int outfd; - text *txt; char *listaddr, *listdelim, *tmp, *retstr = NULL; char *listfqdn, *line; char *str; - char **moredata; char *headers[10] = { NULL }; /* relies on NULL to flag end */ - txt = open_text(listdir, purpose, action, reason, type, compat); - if (txt == NULL) return NULL; - listaddr = getlistaddr(listdir); listdelim = getlistdelim(listdir); listfqdn = genlistfqdn(listaddr); @@ -570,23 +602,19 @@ return NULL; } - moredata = mymalloc(2*(tokencount+6) * sizeof(char *)); - for (i=0; i<2*tokencount; i++) { - moredata[i] = data[i]; + for (i=0; i<6; i++) { + tmp = mystrdup("randomN"); + tmp[6] = '0' + i; + str = random_str(); + register_unformatted(txt, tmp, str); + myfree(tmp); + myfree(str); } - for (i=0; i<6; i++) { - moredata[2*(tokencount+i)] = mystrdup("randomN"); - moredata[2*(tokencount+i)][6] = '0' + i; - moredata[2*(tokencount+i)+1] = random_str(); - } - tokencount += 6; - tmp = substitute(from, listaddr, listdelim, - tokencount, moredata, listdir); + tmp = substitute(from, listaddr, listdelim, listdir, txt); headers[0] = concatstr(2, "From: ", tmp); myfree(tmp); - tmp = substitute(to, listaddr, listdelim, - tokencount, moredata, listdir); + tmp = substitute(to, listaddr, listdelim, listdir, txt); headers[1] = concatstr(2, "To: ", tmp); myfree(tmp); headers[2] = genmsgid(listfqdn); @@ -599,15 +627,14 @@ headers[7] = mystrdup("Content-Transfer-Encoding: 8bit"); if(replyto) { - tmp = substitute(replyto, listaddr, listdelim, - tokencount, moredata, listdir); + tmp = substitute(replyto, listaddr, listdelim, listdir, txt); headers[8] = concatstr(2, "Reply-To: ", tmp); myfree(tmp); } for(;;) { line = get_processed_text_line(txt, listaddr, listdelim, - tokencount, moredata, listdir, NULL); + listdir); if (!line) { log_error(LOG_ARGS, "No body in listtext"); break; @@ -700,7 +727,7 @@ if (line == NULL) { line = get_processed_text_line(txt, listaddr, listdelim, - tokencount, moredata, listdir, mailname); + listdir); } while(line) { len = strlen(line); @@ -714,7 +741,7 @@ } myfree(line); line = get_processed_text_line(txt, listaddr, listdelim, - tokencount, moredata, listdir, mailname); + listdir); } fsync(outfd); @@ -725,14 +752,5 @@ myfree(listdelim); myfree(listfqdn); - for (i=tokencount-6; i