]> diplodocus.org Git - nmh/commitdiff
Add a new get_param_value(); redo iconv() parameter conversion code.
authorKen Hornstein <kenh@pobox.com>
Sun, 2 Mar 2014 04:24:47 +0000 (23:24 -0500)
committerKen Hornstein <kenh@pobox.com>
Sun, 2 Mar 2014 04:24:47 +0000 (23:24 -0500)
Start having code use get_param() and get_param_value() rather than
walking the whole parameter linked list.

h/mhparse.h
uip/mhlistsbr.c
uip/mhparse.c
uip/mhstoresbr.c

index d6afe09..1608381 100644 (file)
@@ -418,4 +418,21 @@ PM add_param(PM *first, PM *last, const char *name, const char *value);
 
 char *get_param(PM first, const char *name, char replace, int fetchonly);
 
+/*
+ * Fetch a parameter value from a parameter structure, converting it to
+ * the local character set.
+ *
+ * Arguments are:
+ *
+ * pm          - Pointer to parameter structure
+ * replace     - If characters in the parameter list cannot be converted to
+ *               the local character set, replace with this character.
+ *
+ * Returns a pointer to the parameter value.  Memory is stored in an
+ * internal buffer, so the returned value is only valid until the next
+ * call to get_param_value() or get_param() (get_param() uses get_param_value()
+ * internally).
+ */
+char *get_param_value(PM pm, char replace);
+
 extern int checksw;    /* Add Content-MD5 field */
index a3ac0c2..5105a6a 100644 (file)
@@ -202,8 +202,10 @@ list_content (CT ct, int toplevel, int realsize, int verbose, int debug)
        CI ci = &ct->c_ctinfo;
        PM pm;
 
-       for (pm = ci->ci_first_pm; pm; pm = pm->pm_next)
-           printf ("\t     %s=\"%s\"\n", pm->pm_name, pm->pm_value);
+       for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
+           printf ("\t     %s=\"%s\"\n", pm->pm_name,
+                   get_param_value(pm, '?'));
+       }
 
        /*
         * If verbose, print any RFC-822 comments in the
index 1781ee6..b659ce8 100644 (file)
@@ -3868,95 +3868,121 @@ get_param(PM first, const char *name, char replace, int fetchonly)
        if (strcasecmp(name, first->pm_name) == 0) {
            if (fetchonly)
                return first->pm_value;
-           else {
-               char convbuf[BUFSIZ];
-               size_t inbytes, outbytes = sizeof(convbuf);
+           else
+               return getcpy(get_param_value(first, replace));
+       }
+       first = first->pm_next;
+    }
+
+    return NULL;
+}
+
+/*
+ * Return a parameter value, converting to the local character set if
+ * necessary
+ */
+
+char *get_param_value(PM pm, char replace)
+{
+    static char buffer[4096];          /* I hope no parameters are larger */
+    size_t bufsize = sizeof(buffer);
 #ifdef HAVE_ICONV
-               int utf8;
-               iconv_t cd;
-               ICONV_CONST char *p;
-               char *q;
+    size_t inbytes;
+    int utf8;
+    iconv_t cd;
+    ICONV_CONST char *p;
 #endif /* HAVE_ICONV */
-               if (!first->pm_charset ||
-                               check_charset(first->pm_charset,
-                                             strlen(first->pm_charset))) {
-                   /*
-                    * No conversion necessary
-                    */
-                   return getcpy(first->pm_value);
-               }
-#ifdef HAVE_ICONV
-               utf8 = strcasecmp(first->pm_charset, "UTF-8") == 0;
+    char *q;
 
-               cd = iconv_open(get_charset(), first->pm_charset);
-               if (cd == (iconv_t) -1) {
-                   goto noconvert;
-               }
+    /*
+     * If we don't have a character set indicated, it's assumed to be
+     * US-ASCII.  If it matches our character set, we don't need to convert
+     * anything.
+     */
 
-               inbytes = strlen(first->pm_value);
-               outbytes = sizeof(convbuf);
-               p = first->pm_value;
-               q = convbuf;
+    if (!pm->pm_charset || check_charset(pm->pm_charset,
+                                        strlen(pm->pm_charset))) {
+       return pm->pm_value;
+    }
 
-               while (inbytes) {
-                   if (iconv(cd, &p, &inbytes, &q, &outbytes) == (size_t)-1) {
-                       if (errno != EILSEQ) {
-                           iconv_close(cd);
-                           goto noconvert;
-                       }
-                       /*
-                        * Reset shift state, substitute our character,
-                        * try to restart conversion.
-                        */
-                       iconv(cd, NULL, NULL, &q, &outbytes);
-                       if (outbytes == 0) {
-                           iconv_close(cd);
-                           goto noconvert;
-                       }
-                       *q++ = replace;
-                       outbytes--;
-                       if (outbytes == 0) {
-                           iconv_close(cd);
-                           goto noconvert;
-                       }
-                       if (utf8) {
-                           for (++p, --inbytes; inbytes > 0 &&
-                                       (((unsigned char) *q) & 0xc0) == 0x80;
-                                ++p, --inbytes)
-                               continue;
-                       } else {
-                           p++;
-                           inbytes--;
-                       }
-                   }
-               }
+    /*
+     * In this case, we need to convert.  If we have iconv support, use
+     * that.  Otherwise, go through and simply replace every non-ASCII
+     * character with the substitution character.
+     */
 
-               iconv_close(cd);
+#ifdef HAVE_ICONV
+    q = buffer;
+    bufsize = sizeof(buffer);
+    utf8 = strcasecmp(pm->pm_charset, "UTF-8") == 0;
 
-               if (outbytes == 0)
-                   q--;
-               *q = '\0';
+    cd = iconv_open(get_charset(), pm->pm_charset);
+    if (cd == (iconv_t) -1) {
+       goto noiconv;
+    }
 
-               return getcpy(convbuf);
-#endif /* HAVE_ICONV */
-noconvert:
-               for (p = first->pm_value, q = convbuf; *p && outbytes > 1;
-                    p++, q++, outbytes--) {
-                   if (isascii((unsigned char) p) &&
-                                       isprint((unsigned char) p))
-                       *q = *p;
-                   else
-                       *q = replace;
-               }
+    inbytes = strlen(pm->pm_value);
+    p = pm->pm_value;
+
+    while (inbytes) {
+       if (iconv(cd, &p, &inbytes, &q, &bufsize) == (size_t)-1) {
+           if (errno != EILSEQ) {
+               iconv_close(cd);
+               goto noiconv;
+           }
+           /*
+            * Reset shift state, substitute our character,
+            * try to restart conversion.
+            */
 
-               *q = '\0';
+           iconv(cd, NULL, NULL, &q, &bufsize);
 
-               return getcpy(convbuf);
+           if (bufsize == 0) {
+               iconv_close(cd);
+               goto noiconv;
+           }
+           *q++ = replace;
+           bufsize--;
+           if (bufsize == 0) {
+               iconv_close(cd);
+               goto noiconv;
+           }
+           if (utf8) {
+               for (++p, --inbytes;
+                    inbytes > 0 && (((unsigned char) *q) & 0xc0) == 0x80;
+                    ++p, --inbytes)
+                   continue;
+           } else {
+               p++;
+               inbytes--;
            }
        }
+    }
 
-       first = first->pm_next;
+    iconv_close(cd);
+
+    if (bufsize == 0)
+       q--;
+    *q = '\0';
+
+    return buffer;
+#endif /* HAVE_ICONV */
+
+noiconv:
+    /*
+     * Take everything non-ASCII and substituite the replacement character
+     */
+
+    q = buffer;
+    bufsize = sizeof(buffer);
+    for (p = pm->pm_value; *p != '\0' && bufsize > 1; p++, q++, bufsize--) {
+       if (isascii((unsigned char) *p) && !iscntrl((unsigned char) *p))
+           *q = *p;
+       else
+           *q = replace;
     }
 
-    return NULL;
+    *q = '\0';
+
+    return buffer;
 }
index 799bdb4..156411b 100644 (file)
@@ -194,7 +194,6 @@ static int
 store_application (CT ct)
 {
     CI ci = &ct->c_ctinfo;
-    PM pm;
 
     /* Check if the content specifies a filename */
     if (autosw)
@@ -207,32 +206,23 @@ store_application (CT ct)
      */
     if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) {
        int tarP = 0, zP = 0, gzP = 0;
+       char *cp;
 
-       for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
-           /* check for "type=tar" attribute */
-           if (!strcasecmp (pm->pm_name, "type")) {
-               if (strcasecmp (pm->pm_value, "tar"))
-                   break;
-
+       if ((cp = get_param(ci->ci_first_pm, "type", ' ', 1))) {
+           if (strcasecmp (cp, "tar") == 0)
                tarP = 1;
-               continue;
-           }
+       }
 
-           /* check for "conversions=compress" attribute */
-           if ((!strcasecmp (pm->pm_name, "conversions") ||
-                !strcasecmp (pm->pm_name, "x-conversions"))
-               && (!strcasecmp (pm->pm_value, "compress") ||
-                   !strcasecmp (pm->pm_value, "x-compress"))) {
+       /* check for "conversions=compress" attribute */
+       if ((cp = get_param(ci->ci_first_pm, "conversions", ' ', 1)) ||
+           (cp = get_param(ci->ci_first_pm, "x-conversions", ' ', 1))) {
+           if (strcasecmp (cp, "compress") == 0 ||
+                   strcasecmp (cp, "x-compress") == 0) {
                zP = 1;
-               continue;
            }
-           /* check for "conversions=gzip" attribute */
-           if ((!strcasecmp (pm->pm_name, "conversions") ||
-                !strcasecmp (pm->pm_name, "x-conversions"))
-               && (!strcasecmp (pm->pm_value, "gzip") ||
-                   !strcasecmp (pm->pm_value, "x-gzip"))) {
+           if (strcasecmp (cp, "gzip") == 0 ||
+                   strcasecmp (cp, "x-gzip") == 0) {
                gzP = 1;
-               continue;
            }
        }
 
@@ -970,7 +960,7 @@ parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir)
 
                        for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
                            snprintf (bp, buflen, "%s%s=\"%s\"", s,
-                                     pm->pm_name, pm->pm_value);
+                                     pm->pm_name, get_param_value(pm, '?'));
                            len = strlen (bp);
                            bp += len;
                            buflen -= len;
@@ -1044,7 +1034,6 @@ get_storeproc (CT ct)
 {
     char *cp;
     CI ci;
-    PM pm;
 
     /*
      * If the storeproc has already been defined,
@@ -1059,21 +1048,18 @@ get_storeproc (CT ct)
      * use that (RFC-2183).
      */
     if (ct->c_dispo) {
-       int found_filename = 0;
-
-       for (pm = ct->c_dispo_first; pm; pm = pm->pm_next) {
-           if (! strcasecmp (pm->pm_name, "filename")
-                   && *(cp = pm->pm_value) != '/'
-                   && *cp != '.'
-                   && *cp != '|'
-                   && *cp != '!'
-                   && !strchr (cp, '%')) {
+       if ((cp = get_param(ct->c_dispo_first, "filename", '_', 0))
+               && *cp != '/'
+               && *cp != '.'
+               && *cp != '|'
+               && *cp != '!'
+               && !strchr (cp, '%')) {
                ct->c_storeproc = add (cp, NULL);
-               found_filename = 1;
-           }
+               free(cp);
+               return;
        }
-
-       if (found_filename) return;
+       if (cp)
+           free(cp);
     }
 
     /*
@@ -1082,17 +1068,17 @@ get_storeproc (CT ct)
      * the storeproc.
      */
     ci = &ct->c_ctinfo;
-    for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
-       if (! strcasecmp (pm->pm_name, "name")
-           && *(cp = pm->pm_value) != '/'
-           && *cp != '.'
-           && *cp != '|'
-           && *cp != '!'
-           && !strchr (cp, '%')) {
+    if ((cp = get_param(ci->ci_first_pm, "name", '_', 0))
+         && *cp != '/'
+         && *cp != '.'
+         && *cp != '|'
+         && *cp != '!'
+         && !strchr (cp, '%')) {
            ct->c_storeproc = add (cp, NULL);
-           return;
-       }
+
     }
+    if (cp)
+       free(cp);
 }