From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ben Schmidt Date: Thu, 25 Feb 2010 11:44:44 +0000 Subject: PATCHES: richer listtext Message-Id: <4B8662AC.60201@yahoo.com.au> MIME-Version: 1 Content-Type: multipart/mixed; boundary="------------010300020200030000020005" List-Id: To: mlmmj@mlmmj.org This is a multi-part message in MIME format. --------------010300020200030000020005 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi, all, Given there has been positive interest, and there will be minimal/no disruption to mlmmj's operation, I have implemented the richer listtext features I wrote about earlier. I'm sending these patches through now, though they have had only minimal testing, particularly as Robin Johnson has volunteered to help test. mlmmj-listtext-headers.patch - Allows arbitrary headers to be included at the beginning of listtexts. - All the headers in the listtext will be included in the mails mlmmj sends. - Mlmmj standard headers of the same name as those in the listtext will be omitted. - Substitutions using the $whatever$ mechanism can be used. - \uNNNN escaping is supported in the headers, as with the rest of the listtext. - Automatic =?utf-8?q?...?= quoting is done for (and only for) the Subject: header. - Also includes a couple of bugfixes related to sending digests. - This is compatible with current behaviour. - The interface to prepstdreply() is changed, however; there is no longer a customheaders argument. It was never used, and since this patch allows custom headers to be included in listtext, is not really necessary as a function argument. Incorporating it in the implementation would have been more trouble than value. mlmmj-origmail-count.patch - Alters the way $originalmail$ works; it doesn't buffer the entire $originalmail$ substitution in memory, but does it a line at a time. - $originalmail$ must be first on a line, optionally preceded by whitespace. The whitespace is prepended to each line of the mail that is included. - The rest of the line following $originalmail$ is ignored. - $originalmailNNN$ can be used, where NNN is a number of lines to include. Use a large number such as 1000000000 to include the whole mail (but be aware of integer overflow so don't go too big!). - If NNN is omitted, the default is 100. - To get current behaviour, a space must be prepended to the lines currently containing $originalmail$ in the listtexts. Apart from that, this is compatible with current behaviour. - Again, there is an interface change. substitute() and substitute_one() no longer take the original mail filename, and cannot be used to do $originalmail$ substitution. This was never used except by prepstdreply() which now incorporates that substitution itself. mlmmj-subject-substitute.patch - Allows $subject$ to be used for the subject of the mail being moderated (or denied, etc.). - Compatible. mlmmj-random-substitute.patch - Allows $random0$ through $random5$ to be used as distinct random strings. - Compatible. mlmmj-efficient-random.patch - Makes random number generation more efficient by only seeding the generator once. - Compatible, though behaviour will change slightly. mlmmj-fixed-length-random.patch - Makes the random strings produced always the same length rather the smaller random numbers producing shorter strings which could be problematic. - Compatible, though behaviour will change slightly. I still plan to include proper documentation (in the patches or as a separate patch), but for testing purposes, this email should suffice. The moderation listtext I have tested with is attached. I believe the patches will not all apply cleanly unless you have already applied these patches: - patch-mlmmj-1.2.17-origmail.diff (mlmmj+get-1844@mlmmj.org) - mlmmj-notifymod.patch (mlmmj+get-1826@mlmmj.org) (I've attached them for convenience, since one of them doesn't seem to have made it into the web archive, and the +get trick hasn't worked for me yet, though I suspect the latter problem is just a delay.) Nor will all apply cleanly unless you apply them in order. If you have trouble, let me know. It's possible another of my patches I have applied affects this, though I don't think so. The following is a rough list of things that should be tested that I made as I implemented: - digests with and without thread summary work - Content-Transfer-Encoding headers correctly output for both digest and listtext - multiple headers of same type in listtext are preserved - \uNNNN escaping works - number of lines of $originalmail$ correctly honoured - when larger than mail length - when smaller than mail length - when equal to mail length - number of lines of $originalmail$ handled as 100 when not given - whitespace preceding $originalmail$ correctly prepended to every line of included mail - content after $originalmail$ ignored (no crash) - six random values are distinct, but the same when reused in the same listtext - subject substitution - including when original subject contains utf8 - headerless listtext (warnings output) - with and without blank line - invalid header in listtext OK (no crash) Help testing will be particularly appreciated. Code review and other feedback also welcome. Ben. --------------010300020200030000020005 Content-Type: text/x-patch; name="mlmmj-listtext-headers.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="mlmmj-listtext-headers.patch" diff -r 6e97ed95f9a8 include/prepstdreply.h --- a/include/prepstdreply.h Thu Feb 25 14:55:50 2010 +1100 +++ b/include/prepstdreply.h Thu Feb 25 19:31:37 2010 +1100 @@ -32,6 +32,6 @@ int open_listtext(const char *listdir, const char *filename); char *prepstdreply(const char *listdir, const char *filename, const char *from, const char *to, const char *replyto, size_t tokencount, - char **data, char *customheaders, const char *mailname); + char **data, const char *mailname); #endif /* PREPSTDREPLY_H */ diff -r 6e97ed95f9a8 src/mlmmj-bounce.c --- a/src/mlmmj-bounce.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/mlmmj-bounce.c Thu Feb 25 19:31:37 2010 +1100 @@ -146,7 +146,7 @@ maildata[1] = indexstr; queuefilename = prepstdreply(listdir, "bounce-probe", "$listowner$", - myaddr, NULL, 1, maildata, NULL, NULL); + myaddr, NULL, 1, maildata, NULL); MY_ASSERT(queuefilename); myfree(indexstr); diff -r 6e97ed95f9a8 src/mlmmj-process.c --- a/src/mlmmj-process.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/mlmmj-process.c Thu Feb 25 19:31:37 2010 +1100 @@ -133,7 +133,7 @@ myfree(listfqdn); queuefilename = prepstdreply(listdir, "moderation", "$listowner$", - to, replyto, 2, maildata, NULL, + to, replyto, 2, maildata, mailfilename); /* we might need to exec more than one mlmmj-send */ @@ -176,7 +176,7 @@ queuefilename = prepstdreply(listdir, "moderation-poster", "$listowner$", efromsender, - NULL, 1, maildata+2, NULL, mailfilename); + NULL, 1, maildata+2, mailfilename); execlp(mlmmjsend, mlmmjsend, "-l", "1", @@ -696,7 +696,7 @@ queuefilename = prepstdreply(listdir, "maxmailsize", "$listowner$", fromemails.emaillist[0], - NULL, 2, maildata, NULL, donemailname); + NULL, 2, maildata, donemailname); MY_ASSERT(queuefilename) myfree(listdelim); myfree(listname); @@ -811,7 +811,7 @@ listfqdn); queuefilename = prepstdreply(listdir, "notintocc", "$listowner$", fromemails.emaillist[0], - NULL, 0, NULL, NULL, donemailname); + NULL, 0, NULL, donemailname); MY_ASSERT(queuefilename) myfree(listdelim); myfree(listname); @@ -872,7 +872,7 @@ "bounces-help@", listfqdn); queuefilename = prepstdreply(listdir, "subonlypost", "$listowner$", fromemails.emaillist[0], - NULL, 1, maildata, NULL, donemailname); + NULL, 1, maildata, donemailname); MY_ASSERT(queuefilename) myfree(listaddr); myfree(listdelim); @@ -926,7 +926,7 @@ queuefilename = prepstdreply(listdir, "access", "$listowner$", fromemails.emaillist[0], - NULL, 0, NULL, NULL, donemailname); + NULL, 0, NULL, donemailname); MY_ASSERT(queuefilename) myfree(listaddr); myfree(listdelim); diff -r 6e97ed95f9a8 src/mlmmj-sub.c --- a/src/mlmmj-sub.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/mlmmj-sub.c Thu Feb 25 19:31:37 2010 +1100 @@ -147,7 +147,7 @@ maildata[5] = moderators; queuefilename = prepstdreply(listdir, "submod-moderator", - "$listowner$", to, replyto, 3, maildata, NULL, NULL); + "$listowner$", to, replyto, 3, maildata, NULL); myfree(maildata[1]); @@ -189,7 +189,7 @@ from = concatstr(4, listname, listdelim, "bounces-help@", listfqdn); queuefilename = prepstdreply(listdir, "submod-requester", "$listowner$", - subaddr, NULL, 0, NULL, NULL, NULL); + subaddr, NULL, 0, NULL, NULL); myfree(listname); myfree(listfqdn); @@ -282,7 +282,7 @@ } queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", - subaddr, NULL, 0, NULL, NULL, NULL); + subaddr, NULL, 0, NULL, NULL); MY_ASSERT(queuefilename); myfree(listtext); @@ -329,7 +329,7 @@ } queuefilename = prepstdreply(listdir, listtext, "$listowner$", - "$listowner$", NULL, 1, maildata, NULL, NULL); + "$listowner$", NULL, 1, maildata, NULL); MY_ASSERT(queuefilename) myfree(listtext); myfree(maildata[1]); @@ -416,7 +416,7 @@ maildata[3] = mystrdup(confirmaddr); queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", subaddr, - confirmaddr, 2, maildata, NULL, NULL); + confirmaddr, 2, maildata, NULL); myfree(maildata[1]); myfree(maildata[3]); @@ -469,7 +469,7 @@ myfree(listdelim); queuefilename = prepstdreply(listdir, "sub-subscribed", "$helpaddr$", - subaddr, NULL, 0, NULL, NULL, NULL); + subaddr, NULL, 0, NULL, NULL); MY_ASSERT(queuefilename); myfree(listaddr); diff -r 6e97ed95f9a8 src/mlmmj-unsub.c --- a/src/mlmmj-unsub.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/mlmmj-unsub.c Thu Feb 25 19:31:37 2010 +1100 @@ -76,7 +76,7 @@ } queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", - subaddr, NULL, 0, NULL, NULL, NULL); + subaddr, NULL, 0, NULL, NULL); MY_ASSERT(queuefilename); myfree(listtext); @@ -124,7 +124,7 @@ } queuefilename = prepstdreply(listdir, listtext, "$listowner$", - "$listowner$", NULL, 1, maildata, NULL, NULL); + "$listowner$", NULL, 1, maildata, NULL); MY_ASSERT(queuefilename); myfree(listtext); myfree(maildata[1]); @@ -213,7 +213,7 @@ maildata[3] = mystrdup(confirmaddr); queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", subaddr, - confirmaddr, 2, maildata, NULL, NULL); + confirmaddr, 2, maildata, NULL); myfree(maildata[1]); myfree(maildata[3]); @@ -305,7 +305,7 @@ myfree(listdelim); queuefilename = prepstdreply(listdir, "unsub-notsubscribed", - "$helpaddr$", subaddr, NULL, 0, NULL, NULL, NULL); + "$helpaddr$", subaddr, NULL, 0, NULL, NULL); MY_ASSERT(queuefilename); myfree(listaddr); diff -r 6e97ed95f9a8 src/prepstdreply.c --- a/src/prepstdreply.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/prepstdreply.c Thu Feb 25 19:31:37 2010 +1100 @@ -208,12 +208,14 @@ char *prepstdreply(const char *listdir, const char *filename, const char *from, const char *to, const char *replyto, size_t tokencount, - char **data, char *customheaders, const char *mailname) + char **data, const char *mailname) { + size_t i, len; int infd, outfd; - char *listaddr, *listdelim, *myfrom, *tmp, *subject, *retstr = NULL; + char *listaddr, *listdelim, *tmp, *retstr = NULL; char *listfqdn, *line, *utfline, *utfsub, *utfsub2; - char *myreplyto, *myto, *str = NULL, *mydate, *mymsgid; + char *str = NULL; + char *headers[10] = { NULL }; /* relies on NULL to flag end */ if ((infd = open_listtext(listdir, filename)) < 0) { return NULL; @@ -223,49 +225,6 @@ listdelim = getlistdelim(listdir); listfqdn = genlistfqdn(listaddr); - line = mygetline(infd); - if(!line || (strncasecmp(line, "Subject: ", 9) != 0)) { - log_error(LOG_ARGS, "No Subject in '%s' listtext. Using " - "standard subject", filename); - subject = mystrdup("mlmmj administrativa"); - } else { - chomp(line); - utfsub = unistr_escaped_to_utf8(line + 9); - utfsub2 = substitute(utfsub, listaddr, listdelim, tokencount, - data, NULL); - subject = unistr_utf8_to_header(utfsub2); - myfree(utfsub); - myfree(utfsub2); - myfree(line); - - /* skip empty line after subject */ - line = mygetline(infd); - if (line && (line[0] == '\n')) { - myfree(line); - line = NULL; - } - } - if (line) { - utfline = unistr_escaped_to_utf8(line); - myfree(line); - } else { - utfline = NULL; - } - - myfrom = substitute(from, listaddr, listdelim, tokencount, data, NULL); - myto = substitute(to, listaddr, listdelim, tokencount, data, NULL); - mydate = gendatestr(); - mymsgid = genmsgid(listfqdn); - - if(replyto) { - myreplyto = substitute(replyto, listaddr, listdelim, - tokencount, data, NULL); - tmp = concatstr(3, "Reply-To: ", myreplyto, "\n"); - myfree(myreplyto); - myreplyto = tmp; - } else - myreplyto = NULL; - do { tmp = random_str(); myfree(retstr); @@ -278,48 +237,164 @@ if(outfd < 0) { log_error(LOG_ARGS, "Could not open std mail %s", retstr); - myfree(str); - myfree(listaddr); - myfree(listdelim); - myfree(listfqdn); - myfree(utfline); - return NULL; - } - - str = concatstr(14, - "From: ", myfrom, - "\nTo: ", myto, - "\n", myreplyto, - mymsgid, - mydate, - "Subject: ", subject, - "\nMIME-Version: 1.0" - "\nContent-Type: text/plain; charset=utf-8" - "\nContent-Encoding: 8bit" - "\n", customheaders, - "\n", utfline); - - myfree(utfline); - - if(writen(outfd, str, strlen(str)) < 0) { - log_error(LOG_ARGS, "Could not write std mail"); - myfree(str); myfree(listaddr); myfree(listdelim); myfree(listfqdn); return NULL; } - myfree(str); + tmp = substitute(from, listaddr, listdelim, + tokencount, data, NULL); + headers[0] = concatstr(2, "From: ", tmp); + myfree(tmp); + tmp = substitute(to, listaddr, listdelim, + tokencount, data, NULL); + headers[1] = concatstr(2, "To: ", tmp); + myfree(tmp); + headers[2] = genmsgid(listfqdn); + chomp(headers[2]); + headers[3] = gendatestr(); + chomp(headers[3]); + headers[4] = mystrdup("Subject: mlmmj administrivia"); + headers[5] = mystrdup("MIME-Version: 1.0"); + headers[6] = mystrdup("Content-Type: text/plain; charset=utf-8"); + headers[7] = mystrdup("Content-Transfer-Encoding: 8bit"); - while((str = mygetline(infd))) { - tmp = str; + if(replyto) { + tmp = substitute(replyto, listaddr, listdelim, + tokencount, data, NULL); + headers[8] = concatstr(2, "Reply-To: ", tmp); + myfree(tmp); + } + + for(;;) { + line = mygetline(infd); + if (!line) { + log_error(LOG_ARGS, "No body in '%s' listtext", + filename); + break; + } + if (*line == '\n') { + /* end of headers */ + myfree(line); + line = NULL; + break; + } + chomp(line); + if (*line == ' ' || *line == '\t') { + /* line beginning with linear whitespace is a + continuation of previous header line */ + utfsub = unistr_escaped_to_utf8(line); + str = substitute(utfsub, listaddr, listdelim, + tokencount, data, NULL); + myfree(utfsub); + len = strlen(str); + str[len] = '\n'; + if(writen(outfd, str, len+1) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + myfree(str); + myfree(line); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + return NULL; + } + myfree(str); + } else { + tmp = line; + len = 0; + while (*tmp && *tmp != ':') { + tmp++; + len++; + } + if (!*tmp) { + log_error(LOG_ARGS, "No headers or invalid " + "header in '%s' listtext", + filename); + break; + } + tmp++; + len++; + /* remove the standard header if one matches */ + for (i=0; headers[i] != NULL; i++) { + if (strncasecmp(line, headers[i], len) == 0) { + myfree(headers[i]); + while (headers[i] != NULL) { + headers[i] = headers[i+1]; + i++; + } + break; + } + } + utfsub = unistr_escaped_to_utf8(tmp); + *tmp = '\0'; + utfsub2 = substitute(utfsub, listaddr, listdelim, + tokencount, data, NULL); + myfree(utfsub); + if (strncasecmp(line, "Subject:", len) == 0) { + tmp = unistr_utf8_to_header(utfsub2); + myfree(utfsub2); + str = concatstr(2, line, tmp); + myfree(tmp); + } else { + str = concatstr(2, line, utfsub2); + myfree(utfsub2); + } + len = strlen(str); + str[len] = '\n'; + if(writen(outfd, str, len+1) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + myfree(str); + myfree(line); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + return NULL; + } + myfree(str); + } + myfree(line); + } + + for (i=0; headers[i] != NULL; i++) { + len = strlen(headers[i]); + headers[i][len] = '\n'; + if(writen(outfd, headers[i], len+1) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + if (line) + myfree(line); + myfree(str); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + return NULL; + } + } + + /* end the headers */ + if(writen(outfd, "\n", 1) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + myfree(str); + if (line) + myfree(line); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + return NULL; + } + + if (line) { + str = concatstr(2, line, "\n"); + myfree(line); + } else { + str = mygetline(infd); + } + while(str) { utfline = unistr_escaped_to_utf8(str); - myfree(tmp); + myfree(str); - tmp = utfline; str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname); - myfree(tmp); + myfree(utfline); if(writen(outfd, str, strlen(str)) < 0) { myfree(str); @@ -330,8 +405,9 @@ return NULL; } myfree(str); + str = mygetline(infd); } - + fsync(outfd); close(outfd); diff -r 6e97ed95f9a8 src/send_digest.c --- a/src/send_digest.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/send_digest.c Thu Feb 25 19:31:37 2010 +1100 @@ -321,7 +321,7 @@ tmp = concatstr(3, "\n--", boundary, "\nContent-Type: text/plain; charset=UTF-8" - "\nContent-Encoding: 8bit" + "\nContent-Transfer-Encoding: 8bit" "\n\n"); if (writen(fd, tmp, strlen(tmp)) == -1) { log_error(LOG_ARGS, "Could not write digest text/plain" @@ -376,6 +376,8 @@ } close(txtfd); + } else if (txtfd > 0) { + close(txtfd); } myfree(line); diff -r 6e97ed95f9a8 src/send_help.c --- a/src/send_help.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/send_help.c Thu Feb 25 19:31:37 2010 +1100 @@ -57,7 +57,7 @@ myfree(listdelim); queuefilename = prepstdreply(listdir, textfile, "$listowner$", - emailaddr, NULL, 0, NULL, NULL, NULL); + emailaddr, NULL, 0, NULL, NULL); if(queuefilename == NULL) { log_error(LOG_ARGS, "Could not prepare %s mail", name); exit(EXIT_FAILURE); diff -r 6e97ed95f9a8 src/send_list.c --- a/src/send_list.c Thu Feb 25 14:55:50 2010 +1100 +++ b/src/send_list.c Thu Feb 25 19:31:37 2010 +1100 @@ -99,7 +99,7 @@ myfree(listdelim); queuefilename = prepstdreply(listdir, "listsubs", "$listowner$", - emailaddr, NULL, 0, NULL, NULL, NULL); + emailaddr, NULL, 0, NULL, NULL); if(queuefilename == NULL) { log_error(LOG_ARGS, "Could not prepare sub list mail"); exit(EXIT_FAILURE); --------------010300020200030000020005 Content-Type: text/x-patch; name="mlmmj-origmail-count.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="mlmmj-origmail-count.patch" diff -r b4d1fe2b5b93 include/prepstdreply.h --- a/include/prepstdreply.h Thu Feb 25 17:55:38 2010 +1100 +++ b/include/prepstdreply.h Thu Feb 25 17:55:48 2010 +1100 @@ -25,10 +25,9 @@ #define PREPSTDREPLY_H char *substitute(const char *line, const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char* mailname); + size_t datacount, char **data); char *substitute_one(const char *line, const char *listaddr, - const char *listdelim, size_t datacount, char **data, - const char* mailname); + const char *listdelim, size_t datacount, char **data); int open_listtext(const char *listdir, const char *filename); char *prepstdreply(const char *listdir, const char *filename, const char *from, const char *to, const char *replyto, size_t tokencount, diff -r b4d1fe2b5b93 src/prepstdreply.c --- a/src/prepstdreply.c Thu Feb 25 17:55:38 2010 +1100 +++ b/src/prepstdreply.c Thu Feb 25 17:55:48 2010 +1100 @@ -44,13 +44,13 @@ #include "unistr.h" char *substitute(const char *line, const char *listaddr, const char *listdelim, - size_t datacount, char **data, const char *mailname) + size_t datacount, char **data) { char *s1, *s2; - s1 = substitute_one(line, listaddr, listdelim, datacount, data, mailname); + s1 = substitute_one(line, listaddr, listdelim, datacount, data); while(s1) { - s2 = substitute_one(s1, listaddr, listdelim, datacount, data, mailname); + s2 = substitute_one(s1, listaddr, listdelim, datacount, data); if(s2) { myfree(s1); s1 = s2; @@ -62,8 +62,7 @@ } char *substitute_one(const char *line, const char *listaddr, - const char *listdelim, size_t datacount, char **data, - const char* mailname) + const char *listdelim, size_t datacount, char **data) { char *fqdn, *listname, *d1, *d2, *token, *value = NULL; char *retstr, *origline; @@ -133,26 +132,6 @@ value = concatstr(4, listname, listdelim, "subscribe-nomail@", fqdn); goto concatandreturn; - } else if(strcmp(token, "originalmail") == 0) { - /* append the first 100 lines of the mail inline */ - int mailfd; - if(mailname && - ((mailfd = open(mailname, O_RDONLY)) > 0)){ - size_t count = 0; - char* str = NULL; - while(count < 100 && (str = mygetline(mailfd))) { - char* tmp = value; - value = concatstr(3, value, " ", str); - if(tmp) - myfree(tmp); - myfree(str); - count++; - } - close(mailfd); - }else{ - log_error(LOG_ARGS, "Could not substitute $originalmail$ (mailname == %s)",mailname); - } - goto concatandreturn; } if(data) { for(i = 0; i < datacount; i++) { @@ -211,7 +190,7 @@ char **data, const char *mailname) { size_t i, len; - int infd, outfd; + int infd, outfd, mailfd; char *listaddr, *listdelim, *tmp, *retstr = NULL; char *listfqdn, *line, *utfline, *utfsub, *utfsub2; char *str = NULL; @@ -244,11 +223,11 @@ } tmp = substitute(from, listaddr, listdelim, - tokencount, data, NULL); + tokencount, data); headers[0] = concatstr(2, "From: ", tmp); myfree(tmp); tmp = substitute(to, listaddr, listdelim, - tokencount, data, NULL); + tokencount, data); headers[1] = concatstr(2, "To: ", tmp); myfree(tmp); headers[2] = genmsgid(listfqdn); @@ -262,7 +241,7 @@ if(replyto) { tmp = substitute(replyto, listaddr, listdelim, - tokencount, data, NULL); + tokencount, data); headers[8] = concatstr(2, "Reply-To: ", tmp); myfree(tmp); } @@ -286,7 +265,7 @@ continuation of previous header line */ utfsub = unistr_escaped_to_utf8(line); str = substitute(utfsub, listaddr, listdelim, - tokencount, data, NULL); + tokencount, data); myfree(utfsub); len = strlen(str); str[len] = '\n'; @@ -329,7 +308,7 @@ utfsub = unistr_escaped_to_utf8(tmp); *tmp = '\0'; utfsub2 = substitute(utfsub, listaddr, listdelim, - tokencount, data, NULL); + tokencount, data); myfree(utfsub); if (strncasecmp(line, "Subject:", len) == 0) { tmp = unistr_utf8_to_header(utfsub2); @@ -393,18 +372,65 @@ utfline = unistr_escaped_to_utf8(str); myfree(str); - str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname); - myfree(utfline); + tmp = utfline; + while (*tmp && (*tmp == ' ' || *tmp == '\t')) { + tmp++; + } + if (strncmp(tmp,"$originalmail",13) == 0) { + *tmp = '\0'; + tmp += 13; + str = tmp; + while (*tmp >= '0' && *tmp <= '9') + tmp++; + if (*tmp == '$') { + *tmp = '\0'; + len = 100; + if (str != tmp) + len = atol(str); + if (mailname && + ((mailfd = open(mailname, O_RDONLY)) > 0)){ + str = NULL; + i = 0; + while (i < len && + (str = mygetline(mailfd))) { + tmp = str; + str = concatstr(2,utfline,str); + myfree(tmp); + if(writen(outfd,str,strlen(str)) < 0) { + myfree(str); + myfree(utfline); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + log_error(LOG_ARGS, "Could not write std mail"); + return NULL; + } + myfree(str); + i++; + } + close(mailfd); + } else { + log_error(LOG_ARGS, "Could not substitute $originalmail%d$ (mailname == %s)",len,mailname); + } + } else { + log_error(LOG_ARGS, "Bad $originalmailNNN$ substitution"); + } + myfree(utfline); + } else { + str = substitute(utfline, listaddr, listdelim, + tokencount, data); + myfree(utfline); + if(writen(outfd, str, strlen(str)) < 0) { + myfree(str); + myfree(listaddr); + myfree(listdelim); + myfree(listfqdn); + log_error(LOG_ARGS, "Could not write std mail"); + return NULL; + } + myfree(str); + } - if(writen(outfd, str, strlen(str)) < 0) { - myfree(str); - myfree(listaddr); - myfree(listdelim); - myfree(listfqdn); - log_error(LOG_ARGS, "Could not write std mail"); - return NULL; - } - myfree(str); str = mygetline(infd); } diff -r b4d1fe2b5b93 src/send_digest.c --- a/src/send_digest.c Thu Feb 25 17:55:38 2010 +1100 +++ b/src/send_digest.c Thu Feb 25 17:55:48 2010 +1100 @@ -263,7 +263,7 @@ utfsub = unistr_escaped_to_utf8(line + 9); } - utfsub2 = substitute(utfsub, listaddr, listdelim, 5, subst_data, NULL); + utfsub2 = substitute(utfsub, listaddr, listdelim, 5, subst_data); subject = unistr_utf8_to_header(utfsub2); myfree(utfsub); myfree(utfsub2); @@ -362,7 +362,7 @@ myfree(line); tmp = substitute(utfline, listaddr, listdelim, - 5, subst_data, NULL); + 5, subst_data); myfree(utfline); if(writen(fd, tmp, strlen(tmp)) < 0) { --------------010300020200030000020005 Content-Type: text/x-patch; name="mlmmj-subject-substitute.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="mlmmj-subject-substitute.patch" diff -r 7d9d860c36b3 src/mlmmj-process.c --- a/src/mlmmj-process.c Thu Feb 25 20:51:39 2010 +1100 +++ b/src/mlmmj-process.c Thu Feb 25 22:21:57 2010 +1100 @@ -52,6 +52,7 @@ #include "memory.h" #include "log_oper.h" #include "chomp.h" +#include "unistr.h" enum action { ALLOW, @@ -71,14 +72,16 @@ void newmoderated(const char *listdir, const char *mailfilename, - const char *mlmmjsend, const char *efromsender) + const char *mlmmjsend, const char *efromsender, + size_t tokencount, char **data) { + size_t i; char *from, *listfqdn, *listname, *moderators = NULL; char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim; char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL; char *mailbasename = mybasename(mailfilename), *tmp, *to; int moderatorsfd, foundaddr = 0, notifymod = 0, status; - char *maildata[4] = { "moderateaddr", NULL, "moderators", NULL }; + char *maildata[10] = { "moderateaddr", NULL, "moderators", NULL }; pid_t childpid, pid; #if 0 printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename, @@ -87,6 +90,13 @@ listfqdn = genlistfqdn(listaddr); listname = genlistname(listaddr); + MY_ASSERT(tokencount<=3) + for (i=0; i +$originalmail$ diff -r 2918436fa450 src/mlmmj-process.c --- a/src/mlmmj-process.c Tue Jan 26 22:19:57 2010 +1100 +++ b/src/mlmmj-process.c Tue Jan 26 22:45:06 2010 +1100 @@ -76,8 +76,9 @@ char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim; char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL; char *mailbasename = mybasename(mailfilename), *tmp, *to; - int moderatorsfd, foundaddr = 0; + int moderatorsfd, foundaddr = 0, notifymod = 0, status; char *maildata[4] = { "moderateaddr", NULL, "moderators", NULL }; + pid_t childpid, pid; #if 0 printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename, mailbasename); @@ -131,24 +132,59 @@ myfree(listfqdn); queuefilename = prepstdreply(listdir, "moderation", "$listowner$", - to, replyto, 2, maildata, NULL, mailfilename); + to, replyto, 2, maildata, NULL, + mailfilename); - if(efromismod) - execlp(mlmmjsend, mlmmjsend, - "-l", "1", - "-L", listdir, - "-F", from, - "-m", queuefilename, - "-T", efromsender, (char *)NULL); - else - execlp(mlmmjsend, mlmmjsend, - "-l", "2", - "-L", listdir, - "-F", from, - "-m", queuefilename, (char *)NULL); + /* we might need to exec more than one mlmmj-send */ + + notifymod = !efromismod && statctrl(listdir,"notifymod"); + + if (notifymod) { + childpid = fork(); + if(childpid < 0) + log_error(LOG_ARGS, "Could not fork; poster not notified"); + } else + childpid = -1; + + if(childpid != 0) { + if(childpid > 0) { + do /* Parent waits for the child */ + pid = waitpid(childpid, &status, 0); + while(pid == -1 && errno == EINTR); + } + if(efromismod) + execlp(mlmmjsend, mlmmjsend, + "-l", "1", + "-L", listdir, + "-F", from, + "-m", queuefilename, + "-T", efromsender, (char *)NULL); + else + execlp(mlmmjsend, mlmmjsend, + "-l", "2", + "-L", listdir, + "-F", from, + "-m", queuefilename, (char *)NULL); + log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend); + exit(EXIT_FAILURE); + } + + myfree(queuefilename); + + /* send mail to poster that the list is moderated */ + + queuefilename = prepstdreply(listdir, "moderation-poster", + "$listowner$", efromsender, + NULL, 1, maildata+2, NULL, mailfilename); + + execlp(mlmmjsend, mlmmjsend, + "-l", "1", + "-L", listdir, + "-F", from, + "-m", queuefilename, + "-T", efromsender, (char *)NULL); log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend); - exit(EXIT_FAILURE); } --------------010300020200030000020005--