]> diplodocus.org Git - nmh/commitdiff
Merge branch 'encode-rfc2047'
authorKen Hornstein <kenh@pobox.com>
Wed, 4 Dec 2013 02:52:30 +0000 (21:52 -0500)
committerKen Hornstein <kenh@pobox.com>
Wed, 4 Dec 2013 02:52:30 +0000 (21:52 -0500)
1  2 
Makefile.am
h/prototypes.h
sbr/addrsbr.c
uip/fmttest.c
uip/post.c

diff --combined Makefile.am
index 0749c07dc06562589c7c04383ce8e78635c1992f,19519569dbcbf4fe69e394f0b48fc5b7573478df..a056b24bfd75425dbcd184517b5fec59f917f71b
@@@ -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 \
        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 \
                      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 b1a53cde469dbd21708daa508cc0142bd50038f4,6db999584ac21bce99b56ce5654979f0e87c9b6a..3797fecce3d5ce19b5fcf1b263bf332ad352f0dc
@@@ -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<FLAG1,FLAG4>
 + *
 + * 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 ce14394ec27df5ba9df38b33a4da1f1dde11ed2f,a073e70768be633a66e68d16ab6d0f6138c33c5c..e5b2052004f74c143915e1d9899ac237569c8e28
@@@ -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)
  }
  
  
- /*
-  * 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 b3deda811ee4a820bf8b578729df13e8d49069ba,858732c0524e06c25e07d8604e4a5af909ac7dbb..4794c7bf377e5d02ee572f67b55b7f490b8f57c6
@@@ -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;
                    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;
         * 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
  
      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) {
            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);
            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
             */
             * 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 9bbaa5f547766ea8197f0eb6a59fde1709a8e796,cfec7b9611edac22fe48fc7301b2b932fd7b8854..679ae6dfe49807e2e1353d26476200792eecf180
@@@ -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);
  
      /*
      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));
-     }
  }