]> diplodocus.org Git - nmh/blobdiff - sbr/fmt_rfc2047.c
print_sw.c: Move interface to own file.
[nmh] / sbr / fmt_rfc2047.c
index 4d3fc296d0e90d987d5002035446f30884dd0e5e..4537476563199916ecbc6aa4877ad7a309293294 100644 (file)
@@ -1,20 +1,17 @@
-
-/*
- * fmt_rfc2047.c -- decode RFC-2047 header format 
+/* fmt_rfc2047.c -- decode RFC-2047 header format 
  *
  * 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/utils.h>
+#include "h/mh.h"
+#include "h/utils.h"
 #ifdef HAVE_ICONV
 #  include <iconv.h>
-#  include <errno.h>
 #endif
 
-static signed char hexindex[] = {
+static const signed char hexindex[] = {
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
@@ -22,10 +19,18 @@ static signed char hexindex[] = {
     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
 };
 
-static signed char index_64[128] = {
+static const signed char index_64[128] = {
     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
@@ -38,12 +43,16 @@ static signed char index_64[128] = {
 
 #define char64(c) (((unsigned char) (c) > 127) ? -1 : index_64[(unsigned char) (c)])
 
-static int
-unqp (unsigned char byte1, unsigned char byte2)
+/*
+ * Decode two quoted-pair characters
+ */
+
+int
+decode_qp (unsigned char byte1, unsigned char byte2)
 {
     if (hexindex[byte1] == -1 || hexindex[byte2] == -1)
        return -1;
-    return (hexindex[byte1] << 4 | hexindex[byte2]);
+    return hexindex[byte1] << 4 | hexindex[byte2];
 }
 
 /* Check if character is linear whitespace */
@@ -61,14 +70,11 @@ int
 decode_rfc2047 (char *str, char *dst, size_t dstlen)
 {
     char *p, *q, *pp;
-    char *startofmime, *endofmime;
+    char *startofmime, *endofmime, *endofcharset;
     int c, quoted_printable;
     int encoding_found = 0;    /* did we decode anything?                */
-    int between_encodings = 0; /* are we between two encodings?          */
-    int equals_pending = 0;    /* is there a '=' pending?                */
     int whitespace = 0;                /* how much whitespace between encodings? */
 #ifdef HAVE_ICONV
-    int use_iconv = 0;          /* are we converting encoding with iconv? */
     iconv_t cd = NULL;
     int fromutf8 = 0;
     char *saveq, *convbuf = NULL;
@@ -85,13 +91,16 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
     if (!strchr (str, '='))
        return 0;
 
+    bool use_iconv = false; /* are we converting encoding with iconv? */
+    bool between_encodings = false;
+    bool equals_pending = false;
     for (p = str, q = dst; *p; p++) {
 
         /* reset iconv */
 #ifdef HAVE_ICONV
         if (use_iconv) {
            iconv_close(cd);
-           use_iconv = 0;
+           use_iconv = false;
         }
 #endif
        /*
@@ -100,8 +109,8 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
         */
        if (equals_pending) {
            ADDCHR('=');
-           equals_pending = 0;
-           between_encodings = 0;      /* we have added non-whitespace text */
+           equals_pending = false;
+           between_encodings = false;  /* we have added non-whitespace text */
        }
 
        if (*p != '=') {
@@ -109,15 +118,15 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
            if (between_encodings && is_lws(*p))
                whitespace++;
            else
-               between_encodings = 0;  /* we have added non-whitespace text */
+               between_encodings = false;      /* we have added non-whitespace text */
            ADDCHR(*p);
            continue;
        }
 
-       equals_pending = 1;     /* we have a '=' pending */
+       equals_pending = true;
 
        /* Check for initial =? */
-       if (*p == '=' && p[1] && p[1] == '?' && p[2]) {
+       if (*p == '=' && p[1] == '?' && p[2]) {
            startofmime = p + 2;
 
            /* Scan ahead for the next '?' character */
@@ -127,16 +136,30 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
            if (!*pp)
                continue;
 
+           /*
+            * RFC 2231 specifies that language information can appear
+            * in a charset specification like so:
+            *
+            * =?us-ascii*en?Q?Foo?=
+            *
+            * Right now we don't use language information, so ignore it.
+            */
+
+           for (endofcharset = startofmime;
+                       *endofcharset != '*' && endofcharset < pp;
+                                                       endofcharset++)
+               ;
+
            /* Check if character set can be handled natively */
-           if (!check_charset(startofmime, pp - startofmime)) {
+           if (!check_charset(startofmime, endofcharset - startofmime)) {
 #ifdef HAVE_ICONV
                /* .. it can't. We'll use iconv then. */
-               *pp = '\0';
+               *endofcharset = '\0';
                cd = iconv_open(get_charset(), startofmime);
-               fromutf8 = !mh_strcasecmp(startofmime, "UTF-8");
+               fromutf8 = !strcasecmp(startofmime, "UTF-8");
                *pp = '?';
                 if (cd == (iconv_t)-1) continue;
-               use_iconv = 1;
+               use_iconv = true;
 #else
                continue;
 #endif
@@ -166,9 +189,9 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
             */
            endofmime = NULL;
            for (pp = startofmime; *pp && *(pp+1); pp++) {
-               if (is_lws(*pp)) {
+               if (is_lws(*pp))
                    break;
-               } else if (*pp == '?' && pp[1] == '=') {
+               if (*pp == '?' && pp[1] == '=') {
                    endofmime = pp;
                    break;
                }
@@ -180,7 +203,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
             * We've found an encoded word, so we can drop
             * the '=' that was pending
             */
-           equals_pending = 0;
+           equals_pending = false;
 
            /*
             * If we are between two encoded words separated only by
@@ -199,14 +222,14 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
             * malloc 0 bytes but skip on to the end
             */
            if (endofmime == startofmime && use_iconv) {
-               use_iconv = 0;
+               use_iconv = false;
                iconv_close(cd);
             }
 
            if (use_iconv) {
                saveq = q;
                savedstlen = dstlen;
-                q = convbuf = (char *) mh_xmalloc(endofmime - startofmime);
+                q = convbuf = mh_xmalloc(endofmime - startofmime);
             }
 /* ADDCHR2 is for adding characters when q is or might be convbuf:
  * in this case on buffer-full we want to run iconv before returning.
@@ -221,7 +244,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
            if (quoted_printable) {
                for (pp = startofmime; pp < endofmime; pp++) {
                    if (*pp == '=') {
-                       c = unqp (pp[1], pp[2]);
+                       c = decode_qp (pp[1], pp[2]);
                        if (c == -1)
                            continue;
                        if (c != 0)
@@ -303,8 +326,10 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
                            break;
                        /* skip to next input character */
                        if (fromutf8) {
-                           for (start++;(start < q) && ((*start & 192) == 128);start++)
-                               inbytes--;
+                           for (++start, --inbytes;
+                                start < q  &&  (*start & 192) == 128;
+                                ++start, --inbytes)
+                               continue;
                        } else
                            start++, inbytes--;
                        if (start >= q)
@@ -330,7 +355,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen)
            p = endofmime + 1;
 
            encoding_found = 1;         /* we found (at least 1) encoded word */
-           between_encodings = 1;      /* we have just decoded something     */
+           between_encodings = true;   /* we have just decoded something     */
            whitespace = 0;             /* re-initialize amount of whitespace */
        }
     }