Carl Mummert: add unquote() function for removing quotes from RFC-2822 headers
[mmh] / sbr / fmt_scan.c
index 630cfc5..7558eca 100644 (file)
@@ -3,14 +3,29 @@
  * fmt_scan.c -- format string interpretation
  *
  * $Id$
+ *
+ * This code is Copyright (c) 2002, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
  */
 
 #include <h/mh.h>
 #include <h/addrsbr.h>
 #include <h/fmt_scan.h>
-#include <zotnet/tws/tws.h>
+#include <h/tws.h>
 #include <h/fmt_compile.h>
 
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef TM_IN_SYS_TIME
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
 #define        NFMTS MAXARGS
 
 extern char *formataddr ();    /* hook for custom address formatting */
@@ -73,7 +88,6 @@ match (char *str, char *sub)
 /*
  * macros to format data
  */
-
 #define PUTDF(cp, num, wid, fill)\
        if (cp + wid < ep) {\
            if ((i = (num)) < 0)\
@@ -94,26 +108,6 @@ match (char *str, char *sub)
            cp += c;\
            }
 
-#define PUTD(cp, num)\
-       if (cp < ep) {\
-           if ((i = (num)) == 0)\
-               *cp++ = '0';\
-           else {\
-               if ((i = (num)) < 0) {\
-                   *cp++ = '-';\
-                   i = -(num);\
-                   }\
-               c = 10;\
-               while (c <= i) \
-                   c *= 10;\
-               while (cp < ep && c > 1) {\
-                   c /= 10;\
-                   *cp++ = (i / c) + '0';\
-                   i %= c;\
-                   }\
-               }\
-           }
-
 #ifdef LOCALE
 #define PUTSF(cp, str, wid, fill) {\
                ljust = 0;\
@@ -136,7 +130,7 @@ match (char *str, char *sub)
                                sp++;\
                        }\
                        while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\
-                               if (isgraph(c)) \
+                               if (!iscntrl(c) && !isspace(c)) \
                                    *cp++ = c;\
                                else {\
                                        while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
@@ -154,7 +148,7 @@ match (char *str, char *sub)
                    while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
                        sp++;\
                    while((c = (unsigned char) *sp++) && cp < ep)\
-                       if (isgraph(c)) \
+                       if (!iscntrl(c) && !isspace(c)) \
                            *cp++ = c;\
                        else {\
                            while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
@@ -234,7 +228,7 @@ get_x400_friendly (char *mbox, char *buffer, int buffer_len)
        return NULL;
 
     if (get_x400_comp (mbox, "/PN=", buffer, buffer_len)) {
-       for (mbox = buffer; mbox = strchr(mbox, '.'); )
+       for (mbox = buffer; (mbox = strchr(mbox, '.')); )
            *mbox++ = ' ';
 
        return buffer;
@@ -271,7 +265,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
     char *cp, *ep, *sp;
     char *savestr, *str = NULL;
     char buffer[BUFSIZ], buffer2[BUFSIZ];
-    int i, c, ljust;
+    int i, c, ljust, n;
     int value = 0;
     time_t t;
     struct format *fmt;
@@ -281,6 +275,15 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
     cp = scanl;
     ep = scanl + width - 1;
+
+    for (fmt = format; fmt->f_type != FT_DONE; fmt++)
+       switch (fmt->f_type) {
+       case FT_PARSEADDR:
+       case FT_PARSEDATE:
+           fmt->f_comp->c_flags &= ~CF_PARSED;
+           break;
+       }
+
     fmt = format;
 
     while (cp < ep) {
@@ -322,7 +325,8 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            adios (NULL, "internal error (FT_STRFW)");
 
        case FT_NUM:
-           PUTD (cp, value);
+           n = snprintf(cp, ep - cp, "%d", value);
+           if (n >= 0) cp += n;
            break;
        case FT_NUMF:
            PUTDF (cp, value, fmt->f_width, fmt->f_fill);
@@ -475,7 +479,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            break;
 
        case FT_LV_COMPFLAG:
-           value = fmt->f_comp->c_flags;
+           value = (fmt->f_comp->c_flags & CF_TRUE) != 0;
            break;
        case FT_LV_COMP:
            value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
@@ -487,7 +491,10 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            value = dat[fmt->f_value];
            break;
        case FT_LV_STRLEN:
-           value = strlen(str);
+           if (str != NULL)
+                   value = strlen(str);
+           else
+                   value = 0;
            break;
        case FT_LV_CHAR_LEFT:
            value = width - (cp - scanl);
@@ -636,7 +643,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            }
            if (fmt->f_type == FT_LS_ADDR)
                goto unfriendly;
-           if ((str = mn->m_pers) == NULL)
+           if ((str = mn->m_pers) == NULL) {
                if ((str = mn->m_note)) {
                    strncpy (buffer, str, sizeof(buffer));
                    str = buffer;
@@ -674,6 +681,39 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                        break;
                  }
                }
+           }
+           break;  
+
+
+               /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
+       case FT_LS_UNQUOTE:
+           if (str) {          
+               int m;
+               strncpy(buffer, str, sizeof(buffer));
+               str = buffer;
+       
+               /* we will parse from buffer to buffer2 */
+               n = 0; /* n is the input position in str */
+               m = 0; /* m is the ouput position in buffer2 */
+
+               while ( str[n] != '\0') {
+                   switch ( str[n] ) {
+                       case '\\':
+                           n++;
+                           if ( str[n] != '\0') 
+                               buffer2[m++] = str[n++];
+                           break;
+                       case '"':
+                           n++;
+                           break;
+                       default:
+                           buffer2[m++] = str[n++];
+                           break;
+                       }                
+               }
+               buffer2[m] = '\0';
+               str = buffer2;
+            }
            break;
 
        case FT_LOCALDATE:
@@ -694,13 +734,16 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
        case FT_PARSEDATE:
            comp = fmt->f_comp;
+           if (comp->c_flags & CF_PARSED)
+               break;
            if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
                *comp->c_tws = *tws;
-               comp->c_flags = 0;
-           } else if (comp->c_flags >= 0) {
+               comp->c_flags &= ~CF_TRUE;
+           } else if ((comp->c_flags & CF_DATEFAB) == 0) {
                memset ((char *) comp->c_tws, 0, sizeof *comp->c_tws);
-               comp->c_flags = 1;
+               comp->c_flags = CF_TRUE;
            }
+           comp->c_flags |= CF_PARSED;
            break;
 
        case FT_FORMATADDR:
@@ -748,9 +791,6 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                len -= sp - lp + 1;
                while (cp < ep && lp <= sp)
                    *cp++ = *lp++;
-               *cp++ = '\n';
-               for (i=indent; cp < ep && i > 0; i--)
-                   *cp++ = ' ';
                while (isspace(*lp))
                    lp++, len--;
                if (*lp) {
@@ -766,6 +806,8 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
 
        case FT_PARSEADDR:
            comp = fmt->f_comp;
+           if (comp->c_flags & CF_PARSED)
+               break;
            if (comp->c_mn != &fmt_mnull)
                mnfree (comp->c_mn);
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
@@ -773,6 +815,7 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
                comp->c_mn = mn;
                while (getname(""))
                    ;
+               comp->c_flags |= CF_PARSED;
            } else {
                while (getname(""))             /* XXX */
                    ;
@@ -792,15 +835,22 @@ fmt_scan (struct format *format, char *scanl, int width, int *dat)
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                (mn = getm (sp, NULL, 0, AD_NAME, NULL))) {
                comp->c_mn = mn;
-               comp->c_flags = ismymbox(mn);
+               if (ismymbox(mn))
+                   comp->c_flags |= CF_TRUE;
+               else
+                   comp->c_flags &= ~CF_TRUE;
                while ((sp = getname(sp)))
-                   if (comp->c_flags == 0 &&
+                   if ((comp->c_flags & CF_TRUE) == 0 &&
                        (mn = getm (sp, NULL, 0, AD_NAME, NULL)))
-                       comp->c_flags |= ismymbox(mn);
+                       if (ismymbox(mn))
+                           comp->c_flags |= CF_TRUE;
            } else {
                while (getname(""))             /* XXX */
                    ;
-               comp->c_flags = (comp->c_text == 0);
+               if (comp->c_text == 0)
+                   comp->c_flags |= CF_TRUE;
+               else
+                   comp->c_flags &= ~CF_TRUE;
                comp->c_mn = &fmt_mnull;
            }
            break;