FILE *mime_stream = NULL;
uschar *mime_current_boundary = NULL;
+static mime_header mime_header_list[] = {
+ { US"content-type:", 13, &mime_content_type },
+ { US"content-disposition:", 20, &mime_content_disposition },
+ { US"content-transfer-encoding:", 26, &mime_content_transfer_encoding },
+ { US"content-id:", 11, &mime_content_id },
+ { US"content-description:", 20, &mime_content_description }
+};
+
+static int mime_header_list_size = nelem(mime_header_list);
+
+static mime_parameter mime_parameter_list[] = {
+ { US"name=", 5, &mime_filename },
+ { US"filename=", 9, &mime_filename },
+ { US"charset=", 8, &mime_charset },
+ { US"boundary=", 9, &mime_boundary }
+};
+
+
/*************************************************
* set MIME anomaly level + text *
*************************************************/
/* Small wrapper to set the two expandables which
give info on detected "problems" in MIME
- encodings. Those are defined in mime.h. */
+ encodings. Indexes are defined in mime.h. */
-static void
-mime_set_anomaly(int level, const char *text)
+void
+mime_set_anomaly(int idx)
{
- mime_anomaly_level = level;
- mime_anomaly_text = CUS text;
+struct anom {
+ int level;
+ const uschar * text;
+} anom[] = { {1, CUS"Broken Quoted-Printable encoding detected"},
+ {2, CUS"Broken BASE64 encoding detected"} };
+
+mime_anomaly_level = anom[idx].level;
+mime_anomaly_text = anom[idx].text;
}
}
-/* decode base64 MIME part */
-static ssize_t
-mime_decode_base64(FILE* in, FILE* out, uschar* boundary)
-{
- uschar ibuf[MIME_MAX_LINE_LENGTH], obuf[MIME_MAX_LINE_LENGTH];
- uschar *ipos, *opos;
- ssize_t len, size = 0;
- int bytestate = 0;
-
- opos = obuf;
-
- while (Ufgets(ibuf, MIME_MAX_LINE_LENGTH, in) != NULL)
- {
- if (boundary != NULL
- && Ustrncmp(ibuf, "--", 2) == 0
- && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0
- )
- break;
-
- for (ipos = ibuf ; *ipos != '\r' && *ipos != '\n' && *ipos != 0; ++ipos)
- {
- if (*ipos == '=') /* skip padding */
- {
- ++bytestate;
- continue;
- }
- if (mime_b64[*ipos] == 128) /* skip bad characters */
- {
- mime_set_anomaly(MIME_ANOMALY_BROKEN_BASE64);
- continue;
- }
-
- /* simple state-machine */
- switch((bytestate++) & 3)
- {
- case 0:
- *opos = mime_b64[*ipos] << 2;
- break;
- case 1:
- *opos |= mime_b64[*ipos] >> 4;
- ++opos;
- *opos = mime_b64[*ipos] << 4;
- break;
- case 2:
- *opos |= mime_b64[*ipos] >> 2;
- ++opos;
- *opos = mime_b64[*ipos] << 6;
- break;
- case 3:
- *opos |= mime_b64[*ipos];
- ++opos;
- break;
- } /* switch */
- } /* for */
-
- /* something to write? */
- len = opos - obuf;
- if (len > 0)
- {
- if (fwrite(obuf, 1, len, out) != len) return -1; /* error */
- size += len;
- /* copy incomplete last byte to start of obuf, where we continue */
- if ((bytestate & 3) != 0)
- *obuf = *opos;
- opos = obuf;
- }
- } /* while */
-
- /* write out last byte if it was incomplete */
- if (bytestate & 3)
- {
- if (fwrite(obuf, 1, 1, out) != 1) return -1;
- ++size;
- }
-
- return size;
-}
-
/* decode quoted-printable MIME part */
static ssize_t
size_counter = decode_function(mime_stream, decode_file, mime_current_boundary);
clearerr(mime_stream);
-fseek(mime_stream, f_pos, SEEK_SET);
+if (fseek(mime_stream, f_pos, SEEK_SET))
+ return DEFER;
if (fclose(decode_file) != 0 || size_counter < 0)
return DEFER;