From: Ken Hornstein Date: Wed, 4 Dec 2013 02:52:30 +0000 (-0500) Subject: Merge branch 'encode-rfc2047' X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/6ba5b855ebc737cc46cabfbe799b0c7706f437f4?ds=inline;hp=-c Merge branch 'encode-rfc2047' --- 6ba5b855ebc737cc46cabfbe799b0c7706f437f4 diff --combined Makefile.am index 0749c07d,19519569..a056b24b --- a/Makefile.am +++ b/Makefile.am @@@ -55,6 -55,7 +55,7 @@@ TESTS = test/ali/test-ali test/anno/tes test/format/test-localmbox test/format/test-myname \ test/format/test-myhost test/format/test-mymbox \ test/format/test-rightjustify \ + test/format/test-unquote \ test/forw/test-forw-digest test/forw/test-forw-format \ test/inc/test-deb359167 test/inc/test-eom-align \ test/inc/test-inc-scanout test/inc/test-msgchk \ @@@ -62,11 -63,11 +63,12 @@@ test/install-mh/test-install-mh \ test/locking/test-datalocking test/locking/test-spoollocking \ test/manpages/test-manpages \ - test/mhbuild/test-forw test/mhbuild/test-utf8-body \ + test/mhbuild/test-forw test/mhbuild/test-header-encode \ + test/mhbuild/test-utf8-body \ test/mhfixmsg/test-mhfixmsg \ test/mhlist/test-mhlist test/mhmail/test-mhmail \ test/mhparam/test-mhparam test/mhpath/test-mhpath \ + test/mhshow/test-charset \ test/mhshow/test-cte-binary test/mhshow/test-qp \ test/mhshow/test-subpart test/mhshow/test-msg-buffer-boundaries \ test/mhstore/test-mhstore test/new/test-basic \ @@@ -521,6 -522,7 +523,7 @@@ sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr sbr/copy.c sbr/copyip.c sbr/cpydata.c \ sbr/cpydgst.c sbr/crawl_folders.c sbr/credentials.c \ sbr/discard.c sbr/done.c sbr/dtimep.l sbr/dtime.c \ + sbr/encode_rfc2047.c \ sbr/escape_addresses.c \ sbr/error.c sbr/ext_hook.c sbr/fdcompare.c \ sbr/folder_addmsg.c sbr/folder_delmsgs.c \ @@@ -546,7 -548,8 +549,8 @@@ sbr/seq_setcur.c sbr/seq_setprev.c sbr/seq_setunseen.c \ sbr/showfile.c sbr/signals.c sbr/smatch.c \ sbr/snprintb.c sbr/ssequal.c \ - sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \ + sbr/strindex.c sbr/trimcpy.c sbr/unquote.c \ + sbr/uprf.c sbr/vfgets.c \ sbr/fmt_def.c sbr/mf.c sbr/utils.c sbr/ctype-checked.c \ sbr/m_mktemp.c sbr/getansreadline.c sbr/vector.c \ config/config.c config/version.c @@@ -580,7 -583,6 +584,7 @@@ man/man.sed: Makefil @echo 's,%nmhwarning%,THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DO NOT EDIT.,g' > $@ @echo 's,%nmhversion%,nmh-$(VERSION),g' >> $@ @echo 's,%bindir%,$(bindir),g' >> $@ + @echo 's,%docdir%,$(docdir),g' >> $@ @echo 's,%etcdir%,$(sysconfdir),g' >> $@ @echo 's,%libdir%,$(libdir),g' >> $@ @echo 's,%mandir%,$(mandir),g' >> $@ diff --combined h/prototypes.h index b1a53cde,6db99958..3797fecc --- a/h/prototypes.h +++ b/h/prototypes.h @@@ -59,6 -59,27 +59,27 @@@ char *cpytrim (const char *) int decode_rfc2047 (char *, char *, size_t); void discard (FILE *); int default_done (int); + + /* + * Encode a message header using RFC 2047 encoding. If the message contains + * no non-ASCII characters, then leave the header as-is. + * + * Arguments include: + * + * name - Message header name + * value - Message header content; must point to allocated memory + * (may be changed if encoding is necessary) + * encoding - Encoding type. May be one of CE_UNKNOWN (function chooses + * the encoding), CE_BASE64 or CE_QUOTED + * charset - Charset used for encoding. If NULL, obtain from system + * locale. + * + * Returns 0 on success, any other value on failure. + */ + + int encode_rfc2047(const char *name, char **value, int encoding, + const char *charset); + void escape_display_name (char *, size_t); void escape_local_part (char *, size_t); int ext_hook(char *, char *, char *); @@@ -186,44 -207,28 +207,61 @@@ void seq_setprev (struct msgs *) void seq_setunseen (struct msgs *, int); int showfile (char **, char *); int smatch(char *, struct swit *); -char *snprintb (char *, size_t, unsigned, char *); + +/* + * Convert a set of bit flags to printable format. + * + * Arguments: + * + * buffer - Buffer to output string to. + * size - Size of buffer in bytes. Buffer is always NUL terminated. + * flags - Binary flags to output + * bitfield - Textual representation of bits to output. This string + * is in the following format: + * + * Option byte 0x01 STRING1 0x02 STRING2 .... + * + * The first byte is an option byte to snprintb(). Currently the only option + * supported is 0x08, which indicates that the flags should be output in + * octal format; if the option byte is any other value, the flags will be + * output in hexadecimal. + * + * After the option bytes are series of text strings, prefixed by the number + * of the bit they correspond to. For example, the bitfield string: + * + * "\020\01FLAG1\02FLAG2\03FLAG3\04FLAG4" + * + * will output the following string if "flags" is set to 0x09: + * + * 0x2 + * + * You don't have to use octal in the bitfield string, that's just the + * convention currently used by the nmh code. The order of flags in the + * bitfield string is not significant, but again, general convention is + * from least significant bit to most significant. + */ +char *snprintb (char *buffer, size_t size, unsigned flags, char *bitfield); int ssequal (char *, char *); int stringdex (char *, char *); char *trimcpy (char *); int unputenv (char *); + + /* + * Remove quotes and quoted-pair sequences from RFC-5322 atoms. + * + * Currently the actual algorithm is simpler than it technically should + * be: any quotes are simply eaten, unless they're preceded by the escape + * character (\). This seems to be sufficient for our needs for now. + * + * Arguments: + * + * input - The input string + * output - The output string; is assumed to have at least as much + * room as the input string. At worst the output string will + * be the same size as the input string; it might be smaller. + * + */ + void unquote_string(const char *input, char *output); int uprf (char *, char *); int vfgets (FILE *, char **); char *write_charset_8bit (void); @@@ -262,6 -267,7 +300,7 @@@ int what_now (char *, int, int, char * int WhatNow(int, char **); int writeBase64aux(FILE *, FILE *); int writeBase64 (unsigned char *, size_t, unsigned char *); + int writeBase64raw (unsigned char *, size_t, unsigned char *); /* * credentials management diff --combined sbr/addrsbr.c index ce14394e,a073e707..e5b20520 --- a/sbr/addrsbr.c +++ b/sbr/addrsbr.c @@@ -242,13 -242,10 +242,13 @@@ auxformat (struct mailname *mp, int ext strncpy (addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr)); else - if (mp->m_type != UUCPHOST) - snprintf (addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s", - empty(mp->m_path), empty(mp->m_mbox), mp->m_host); - else + if (mp->m_type != UUCPHOST) { + if (mp->m_host) + snprintf (addr, sizeof(addr), "%s%s@%s", empty(mp->m_path), + empty(mp->m_mbox), mp->m_host); + else snprintf (addr, sizeof(addr), "%s%s", empty(mp->m_path), + empty(mp->m_mbox)); + } else snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox); if (!extras) @@@ -274,24 -271,6 +274,6 @@@ } - /* - * This used to be adrsprintf() (where it would format an address for you - * given a username and a domain). But somewhere we got to the point where - * the only caller was post, and it only called it with both arguments NULL. - * So the function was renamed with a more sensible name. - */ - - char * - getlocaladdr(void) - { - char *username; - - username = getusername(); - - return username; - } - - #define W_NIL 0x0000 #define W_MBEG 0x0001 #define W_MEND 0x0002 diff --combined uip/fmttest.c index b3deda81,858732c0..4794c7bf --- a/uip/fmttest.c +++ b/uip/fmttest.c @@@ -21,6 -21,8 +21,8 @@@ X("raw", 0, RAWSW) \ X("date", 0, DATESW) \ X("message", 0, MESSAGESW) \ + X("file", 0, FILESW) \ + X("nofile", 0, NFILESW) \ X("-component-name component-text", 0, OTHERSW) \ X("dupaddrs", 0, DUPADDRSW) \ X("nodupaddrs", 0, NDUPADDRSW) \ @@@ -58,7 -60,7 +60,7 @@@ static struct format **lvec = NULL static int lused = 0; static int lallocated = 0; -enum mode_t { MESSAGE, ADDRESS, RAW }; +enum mode_t { MESSAGE, ADDRESS, DATE, RAW }; #define DEFADDRFORMAT "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>" #define DEFDATEFORMAT "%<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%>" @@@ -91,7 -93,10 +93,10 @@@ static void process_raw(struct format * int, int, int *, struct fmt_callbacks *); static void process_messages(struct format *, struct msgs_array *, struct msgs_array *, char *, char *, int, - int, int *, struct fmt_callbacks *); + int, int, int *, struct fmt_callbacks *); + static void process_single_file(FILE *, struct msgs_array *, int *, int, + struct format *, char *, int, int, + struct fmt_callbacks *); static void test_trace(void *, struct format *, int, char *, char *); static char *test_formataddr(char *, char *); static char *test_concataddr(char *, char *); @@@ -112,7 -117,7 +117,7 @@@ main (int argc, char **argv struct comp *cptr; struct msgs_array msgs = { 0, 0, NULL }, compargs = { 0, 0, NULL}; int dump = 0, i; - int outputsize = 0, bufsize = 0, dupaddrs = 1, trace = 0; + int outputsize = 0, bufsize = 0, dupaddrs = 1, trace = 0, files = 0; int colwidth = -1, msgnum = -1, msgcur = -1, msgsize = -1, msgunseen = -1; int normalize = AD_HOST; enum mode_t mode = MESSAGE; @@@ -218,10 -223,17 +223,17 @@@ dupaddrs = 0; continue; case DATESW: - mode = RAW; + mode = DATE; defformat = DEFDATEFORMAT; continue; + case FILESW: + files++; + continue; + case NFILESW: + files = 0; + continue; + case DUPADDRSW: dupaddrs++; continue; @@@ -276,7 -288,7 +288,7 @@@ * Only interpret as a folder if we're in message mode */ - if (mode == MESSAGE && (*cp == '+' || *cp == '@')) { + if (mode == MESSAGE && !files && (*cp == '+' || *cp == '@')) { if (folder) adios (NULL, "only one folder at a time!"); else @@@ -380,7 -392,7 +392,7 @@@ if (mode == MESSAGE) { process_messages(fmt, &compargs, &msgs, buffer, folder, bufsize, - outputsize, dat, cbp); + outputsize, files, dat, cbp); } else { if (compargs.size) { for (i = 0; i < compargs.size; i += 2) { @@@ -394,7 -406,7 +406,7 @@@ fmt_norm = normalize; process_addresses(fmt, &msgs, buffer, bufsize, outputsize, dat, normalize, cbp); - } else + } else /* Fall-through for RAW or DATE */ process_raw(fmt, &msgs, buffer, bufsize, outputsize, dat, cbp); } @@@ -488,17 -500,33 +500,33 @@@ process_addresses(struct format *fmt, s static void process_messages(struct format *fmt, struct msgs_array *comps, struct msgs_array *msgs, char *buffer, char *folder, - int bufsize, int outwidth, int *dat, struct fmt_callbacks *cb) + int bufsize, int outwidth, int files, int *dat, + struct fmt_callbacks *cb) { - int i, state, msgnum, msgsize = dat[2], num = dat[0], cur = dat[1]; + int i, msgnum, msgsize = dat[2], num = dat[0], cur = dat[1]; int num_unseen_seq = 0; ivector_t seqnum = ivector_create (0); - char *maildir, *cp, name[NAMESZ], rbuf[BUFSIZ]; + char *maildir, *cp; struct msgs *mp; - struct comp *c; FILE *in; - m_getfld_state_t gstate = 0; - int bufsz; + + /* + * If 'files' is set, short-circuit everything else and just process + * everything now. + */ + + if (files) { + for (i = 0; i < msgs->size; i++) { + if ((in = fopen(cp = msgs->msgs[i], "r")) == NULL) { + admonish(cp, "unable to open file"); + continue; + } + process_single_file(in, comps, dat, msgsize, fmt, buffer, + bufsize, outwidth, cb); + } + + return; + } if (! folder) folder = getfolder(1); @@@ -558,19 -586,6 +586,6 @@@ if (cur == -1) dat[1] = msgnum == mp->curmsg; - /* - * Get our size if we didn't include one - */ - - if (msgsize == -1) { - struct stat st; - - if (fstat(fileno(in), &st) < 0) - dat[2] = 0; - else - dat[2] = st.st_size; - } - /* * Check to see if this is in the unseen sequence */ @@@ -587,69 -602,116 +602,116 @@@ * Read in the message and process the components */ - for (state = FLD;;) { - bufsz = sizeof(rbuf); - state = m_getfld(&gstate, name, rbuf, &bufsz, in); - switch (state) { - case FLD: - case FLDPLUS: - i = fmt_addcomptext(name, rbuf); - if (i != -1) { - while (state == FLDPLUS) { - bufsz = sizeof(rbuf); - state = m_getfld(&gstate, name, rbuf, &bufsz, in); - fmt_appendcomp(i, name, rbuf); - } - } - - while (state == FLDPLUS) { - bufsz = sizeof(rbuf); - state = m_getfld(&gstate, name, rbuf, &bufsz, in); - } - break; + process_single_file(in, comps, dat, msgsize, fmt, buffer, + bufsize, outwidth, cb); + } + } + + ivector_free (seqnum); + folder_free(mp); + return; + } + + /* + * Process a single file in message mode + */ + + static void + process_single_file(FILE *in, struct msgs_array *comps, int *dat, int msgsize, + struct format *fmt, char *buffer, int bufsize, + int outwidth, struct fmt_callbacks *cb) + { + int i, state; + char name[NAMESZ], rbuf[BUFSIZ]; + m_getfld_state_t gstate = 0; + struct comp *c; + int bufsz; - case BODY: - if (fmt_findcomp("body")) { - if ((i = strlen(rbuf)) < outwidth) { - bufsz = outwidth - 1; - state = m_getfld(&gstate, name, rbuf + i, - &bufsz, in); - } + /* + * Get our size if we didn't include one + */ + + if (msgsize == -1) { + struct stat st; + + if (fstat(fileno(in), &st) < 0) + dat[2] = 0; + else + dat[2] = st.st_size; + } - fmt_addcomptext("body", rbuf); - } - /* fall through */ + /* + * Initialize everyting else + */ - default: - goto finished; + if (dat[0] == -1) + dat[0] = 0; + if (dat[1] == -1) + dat[1] = 0; + if (dat[4] == -1) + dat[4] = 0; + + /* + * Read in the message and process the components + */ + + for (state = FLD;;) { + bufsz = sizeof(rbuf); + state = m_getfld(&gstate, name, rbuf, &bufsz, in); + switch (state) { + case FLD: + case FLDPLUS: + i = fmt_addcomptext(name, rbuf); + if (i != -1) { + while (state == FLDPLUS) { + bufsz = sizeof(rbuf); + state = m_getfld(&gstate, name, rbuf, &bufsz, in); + fmt_appendcomp(i, name, rbuf); } } - finished: - fclose(in); - m_getfld_state_destroy(&gstate); - /* - * Do this now to override any components in the original message - */ - if (comps->size) { - for (i = 0; i < comps->size; i += 2) { - c = fmt_findcomp(comps->msgs[i]); - if (c) { - if (c->c_text) - free(c->c_text); - c->c_text = getcpy(comps->msgs[i + 1]); - } + while (state == FLDPLUS) { + bufsz = sizeof(rbuf); + state = m_getfld(&gstate, name, rbuf, &bufsz, in); + } + break; + + case BODY: + if (fmt_findcomp("body")) { + if ((i = strlen(rbuf)) < outwidth) { + bufsz = outwidth - 1; + state = m_getfld(&gstate, name, rbuf + i, + &bufsz, in); } + + fmt_addcomptext("body", rbuf); } - fmt_scan(fmt, buffer, bufsize, outwidth, dat, cb); - fputs(buffer, stdout); - mlistfree(); + /* fall through */ + + default: + goto finished; } } + finished: + fclose(in); + m_getfld_state_destroy(&gstate); - ivector_free (seqnum); - folder_free(mp); - return; + /* + * Do this now to override any components in the original message + */ + if (comps->size) { + for (i = 0; i < comps->size; i += 2) { + c = fmt_findcomp(comps->msgs[i]); + if (c) { + if (c->c_text) + free(c->c_text); + c->c_text = getcpy(comps->msgs[i + 1]); + } + } + } + fmt_scan(fmt, buffer, bufsize, outwidth, dat, cb); + fputs(buffer, stdout); + mlistfree(); } /* @@@ -1081,23 -1143,47 +1143,23 @@@ f_typestr(int t } } -#define FNORD(v, s) if (t & (v)) { \ - if (i++ > 0) \ - strcat(buf, "|"); \ - strcat(buf, s); } - static char * c_typestr(int t) { - register int i; static char buf[64]; - buf[0] = '\0'; - if (t & ~(CT_ADDR|CT_DATE)) - printf(buf, "0x%x ", t); - strcat(buf, "<"); - i = 0; - FNORD(CT_ADDR, "ADDR"); - FNORD(CT_DATE, "DATE"); - strcat(buf, ">"); + snprintb(buf, sizeof(buf), t, CT_BITS); return(buf); } static char * c_flagsstr(int t) { - register int i; static char buf[64]; - buf[0] = '\0'; - if (t & ~(CF_TRUE|CF_PARSED|CF_DATEFAB|CF_TRIMMED)) - printf(buf, "0x%x ", t); - strcat(buf, "<"); - i = 0; - FNORD(CF_TRUE, "TRUE"); - FNORD(CF_PARSED, "PARSED"); - FNORD(CF_DATEFAB, "DATEFAB"); - FNORD(CF_TRIMMED, "TRIMMED"); - strcat(buf, ">"); + snprintb(buf, sizeof(buf), t, CF_BITS); return(buf); } -#undef FNORD static void litputs(char *s) diff --combined uip/post.c index 9bbaa5f5,cfec7b96..679ae6df --- a/uip/post.c +++ b/uip/post.c @@@ -223,7 -223,6 +223,6 @@@ static char from[BUFSIZ]; /* my networ static char sender[BUFSIZ]; /* my Sender: header */ static char efrom[BUFSIZ]; /* my Envelope-From: header */ static char fullfrom[BUFSIZ]; /* full contents of From header */ - static char signature[BUFSIZ]; /* my signature */ static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ static char *fccfold[FCCS]; /* foldernames for FCC'ing */ @@@ -649,13 -648,9 +648,13 @@@ main (int argc, char **argv p_refile (tmpfil); unlink (tmpfil); - if (verbose) - printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n", - partno); + if (verbose) { + if (partno) + printf ("Partial Message #%s Processed\n", partno); + else + printf ("Message Processed\n"); + } + done (0); return 1; } @@@ -934,9 -929,6 +933,6 @@@ putfmt (char *name, char *str, FILE *ou static void start_headers (void) { - char *cp, sigbuf[BUFSIZ]; - struct mailname *mp; - time (&tclock); /* @@@ -947,21 -939,6 +943,6 @@@ efrom[0] = '\0'; sender[0] = '\0'; fullfrom[0] = '\0'; - - if ((cp = getfullname ()) && *cp) { - strncpy (sigbuf, cp, sizeof(sigbuf)); - snprintf (signature, sizeof(signature), "%s <%s>", - sigbuf, getlocaladdr()); - if ((cp = getname (signature)) == NULL) - adios (NULL, "getname () failed -- you lose extraordinarily big"); - if ((mp = getm (cp, NULL, 0, AD_HOST, NULL)) == NULL) - adios (NULL, "bad signature '%s'", sigbuf); - mnfree (mp); - while (getname ("")) - continue; - } else { - strncpy (signature, getlocaladdr(), sizeof(signature)); - } }