return 1;
}
-static int handle_from(char *line)
+static int handle_from(char *in_line)
{
- char *at = strchr(line, '@');
+ char line[1000];
+ char *at;
char *dst;
+ strcpy(line, in_line);
+ at = strchr(line, '@');
if (!at)
return bogus_from(line);
#define SEEN_FROM 01
#define SEEN_DATE 02
#define SEEN_SUBJECT 04
-#define SEEN_PREFIX 0x08
+#define SEEN_BOGUS_UNIX_FROM 010
+#define SEEN_PREFIX 020
/* First lines of body can have From:, Date:, and Subject: */
static void handle_inbody_header(int *seen, char *line)
{
- if (*seen & SEEN_PREFIX)
- return;
+ if (!memcmp(">From", line, 5) && isspace(line[5])) {
+ if (!(*seen & SEEN_BOGUS_UNIX_FROM)) {
+ *seen |= SEEN_BOGUS_UNIX_FROM;
+ return;
+ }
+ }
if (!memcmp("From:", line, 5) && isspace(line[5])) {
if (!(*seen & SEEN_FROM) && handle_from(line+6)) {
*seen |= SEEN_FROM;
check_header(line, header);
}
+static int is_rfc2822_header(char *line)
+{
+ /*
+ * The section that defines the loosest possible
+ * field name is "3.6.8 Optional fields".
+ *
+ * optional-field = field-name ":" unstructured CRLF
+ * field-name = 1*ftext
+ * ftext = %d33-57 / %59-126
+ */
+ int ch;
+ char *cp = line;
+ while ((ch = *cp++)) {
+ if (ch == ':')
+ return cp != line;
+ if ((33 <= ch && ch <= 57) ||
+ (59 <= ch && ch <= 126))
+ continue;
+ break;
+ }
+ return 0;
+}
+
static int read_one_header_line(char *line, int sz, FILE *in)
{
int ofs = 0;
while (ofs < sz) {
- const char *colon;
int peek, len;
if (fgets(line + ofs, sz - ofs, in) == NULL)
break;
len = eatspace(line + ofs);
if (len == 0)
break;
- colon = strchr(line, ':');
- if (!colon || !isspace(colon[1])) {
+ if (!is_rfc2822_header(line)) {
/* Re-add the newline */
line[ofs + len] = '\n';
line[ofs + len + 1] = '\0';