--- /dev/null
+#!/bin/sh
+
+set -e
+
+expected=$MH_TEST_DIR/$$.expected
+actual=$MH_TEST_DIR/$$.actual
+
+# Write message with bogus quoted-printable data.
+msgfile=$(mhpath new)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<EOF
+From: foo@example.edu
+To: bar@example.edu
+Subject: test
+MIME-Version: 1.0
+Content-Transfer-Encoding: quoted-printable
+Date: Sun, 18 Dec 2005 00:52:39 +0100
+
+=3D
+=3d
+ignored space at end
+ignored tab at end
+just a newline =
+
+==3d ====3D
+= just a tab
+= just a space
+=cl
+=l with a space
+=l
+=\b ^H (backspace) character, probably erased = in diff output
+EOF
+
+# check it
+cat > $expected <<EOF
+Date: Sun, 18 Dec 2005 00:52:39 +0100
+To: bar@example.edu
+From: foo@example.edu
+Subject: test
+
+MIME-Version: 1.0
+
+part text/plain 181
+=
+=
+ignored space at end
+ignored tab at end
+just a newline
+== ====
+= just a tab
+= just a space
+=cl
+=l with a space
+=l
+=\b ^H (backspace) character, probably erased = in diff output
+EOF
+mhshow -nopause $msgnum > $actual 2>&1
+diff -u $expected $actual
fseek (ct->c_fp, ct->c_begin, SEEK_SET);
while (len > 0) {
- char *dp;
-
if (fgets (buffer, sizeof(buffer) - 1, ct->c_fp) == NULL) {
content_error (NULL, ct, "premature eof");
goto clean_up;
*++ep = '\n', ep++;
for (; cp < ep; cp++) {
- if (quoted) {
- if (quoted > 1) {
- if (!isxdigit (*cp)) {
-invalid_hex:
- dp = "expecting hexidecimal-digit";
- goto invalid_encoding;
- }
+ if (quoted > 0) {
+ /* in an escape sequence */
+ if (quoted == 1) {
+ /* at byte 1 of an escape sequence */
+ mask = hex2nib[*cp & 0x7f];
+ /* next is byte 2 */
+ quoted = 2;
+ } else {
+ /* at byte 2 of an escape sequence */
mask <<= 4;
mask |= hex2nib[*cp & 0x7f];
putc (mask, ce->ce_fp);
if (digested)
MD5Update (&mdContext, &mask, 1);
- } else {
- switch (*cp) {
- case ':':
- putc (*cp, ce->ce_fp);
- if (digested)
- MD5Update (&mdContext, (unsigned char *) ":", 1);
- break;
-
- default:
- if (!isxdigit (*cp))
- goto invalid_hex;
- mask = hex2nib[*cp & 0x7f];
- quoted = 2;
- continue;
+ if (ferror (ce->ce_fp)) {
+ content_error (ce->ce_file, ct, "error writing to");
+ goto clean_up;
}
+ /* finished escape sequence; next may be literal or a new
+ * escape sequence */
+ quoted = 0;
}
-
- if (ferror (ce->ce_fp)) {
- content_error (ce->ce_file, ct, "error writing to");
- goto clean_up;
- }
- quoted = 0;
+ /* on to next byte */
continue;
}
- switch (*cp) {
- default:
- if (*cp < '!' || *cp > '~') {
- int i;
- dp = "expecting character in range [!..~]";
-
-invalid_encoding:
- i = strlen (invo_name) + 2;
- content_error (NULL, ct,
- "invalid QUOTED-PRINTABLE encoding -- %s,\n%*.*sbut got char 0x%x",
- dp, i, i, "", *cp);
- goto clean_up;
- }
- /* and fall...*/
- case ' ':
- case '\t':
- case '\n':
- putc (*cp, ce->ce_fp);
- if (digested) {
- if (*cp == '\n')
- MD5Update (&mdContext, (unsigned char *) "\r\n",2);
- else
- MD5Update (&mdContext, (unsigned char *) cp, 1);
+ /* not in an escape sequence */
+ if (*cp == '=') {
+ /* starting an escape sequence, or invalid '='? */
+ if (cp + 1 < ep && cp[1] == '\n') {
+ /* "=\n" soft line break, eat the \n */
+ cp++;
+ continue;
}
- if (ferror (ce->ce_fp)) {
- content_error (ce->ce_file, ct, "error writing to");
- goto clean_up;
+ if (cp + 1 >= ep || cp + 2 >= ep) {
+ /* We don't have 2 bytes left, so this is an invalid
+ * escape sequence; just show the raw bytes (below). */
+ } else if (isxdigit (cp[1]) && isxdigit (cp[2])) {
+ /* Next 2 bytes are hex digits, making this a valid escape
+ * sequence; let's decode it (above). */
+ quoted = 1;
+ continue;
+ } else {
+ /* One or both of the next 2 is out of range, making this
+ * an invalid escape sequence; just show the raw bytes
+ * (below). */
}
- break;
+ }
- case '=':
- if (*++cp != '\n') {
- quoted = 1;
- cp--;
+ /* Just show the raw byte. */
+ putc (*cp, ce->ce_fp);
+ if (digested) {
+ if (*cp == '\n') {
+ MD5Update (&mdContext, (unsigned char *) "\r\n",2);
+ } else {
+ MD5Update (&mdContext, (unsigned char *) cp, 1);
}
- break;
+ }
+ if (ferror (ce->ce_fp)) {
+ content_error (ce->ce_file, ct, "error writing to");
+ goto clean_up;
}
}
}