* field, so we can attempt to convert the type to BODY here.
*/
switch (ct->type) {
- char buffer[SHORT_STRING];
+ char buffer[STRING];
case TYPETEXT:
ct->subtype = m_strdup("plain");
pc = parameter_getval(ct->parameter, "charset");
if (!pc) {
parameter_setval(&ct->parameter, "charset",
- charset_getfirst(AssumedCharset));
+ charset_getfirst(mod_cset.assumed_charset));
}
}
}
if (b->subtype) {
fseeko(fp, b->offset, SEEK_SET);
- if (mutt_is_message_type(b->type, b->subtype)) {
+ if (mutt_is_message_type(b)) {
b->parts = mutt_parse_messageRFC822(fp, b);
} else
if (mime_which_token(b->subtype, -1) == MIME_EXTERNAL_BODY) {
return (head);
}
-static const char *
-uncomment_timezone(char *buf, size_t buflen, const char *tz)
-{
- char *p;
-
- if (*tz != '(')
- return tz; /* no need to do anything */
-
- tz = vskipspaces(tz + 1);
- p = strpbrk(tz, " )");
- if (!p)
- return tz;
-
- m_strncpy(buf, buflen, tz, p - tz);
- return buf;
-}
-
/* parses a date string in RFC822 format:
*
* Date: [ weekday , ] day-of-month month year hour:minute:second timezone
*/
time_t mutt_parse_date(const char *s, HEADER *h)
{
- int zhours = 0, zminutes = 0, zoccident = 0;
- char scratch[SHORT_STRING];
struct tm tm;
- int count = 0;
- char *p;
-
- /* Don't modify our argument. Fixed-size buffer is ok here since
- the date format imposes a natural limit. */
-
- m_strcpy(scratch, sizeof(scratch), s);
-
- /* kill the day of the week, if it exists. */
- p = strchr(scratch, ',');
- p = vskipspaces(p ? p + 1 : scratch);
+ const char *loc;
+ time_t tz;
+ loc = setlocale(LC_ALL, "C");
p_clear(&tm, 1);
+ if (strptime(s, "%a, %d %b %Y %H:%M:%S %z", &tm))
+ goto ok;
+ p_clear(&tm, 1);
+ if (strptime(s, "%a, %d %b %Y %H:%M %z", &tm))
+ goto ok;
+ setlocale(LC_ALL, "");
+ return 0;
- while ((p = strtok (p, " \t")) != NULL) {
- char tzstr[SHORT_STRING];
- const char *ptz;
-
- switch (count) {
- case 0: /* day of the month */
- if (!isdigit((unsigned char)*p))
- return -1;
- tm.tm_mday = atoi(p);
- if (tm.tm_mday > 31)
- return -1;
- break;
-
- case 1: /* month of the year */
- tm.tm_mon = mutt_check_month(p);
- if (tm.tm_mon < 0)
- return -1;
- break;
-
- case 2: /* year */
- tm.tm_year = atoi(p);
- if (tm.tm_year < 50)
- tm.tm_year += 100;
- else if (tm.tm_year >= 1900)
- tm.tm_year -= 1900;
- break;
-
- case 3: /* time of day */
- tm.tm_hour = strtol(p, &p, 10);
- if (*p++ != ':')
- return -1;
- tm.tm_min = strtol(p, &p, 10);
- if (*p++ == ':') {
- tm.tm_sec = strtol(p, &p, 10);
- } else {
- tm.tm_sec = 0;
- }
- break;
-
- case 4: /* timezone */
- /* sometimes we see things like (MST) or (-0700) so attempt to
- * compensate by uncommenting the string if non-RFC822 compliant
- */
- ptz = uncomment_timezone(tzstr, sizeof(tzstr), p);
-
- if (*ptz == '+' || *ptz == '-') {
- if (isdigit((unsigned char)ptz[1])
- && isdigit((unsigned char)ptz[2])
- && isdigit((unsigned char)ptz[3])
- && isdigit((unsigned char)ptz[4]))
- {
- zoccident = ptz[0] == '-';
- zhours = (ptz[1] - '0') * 10 + (ptz[2] - '0');
- zminutes = (ptz[3] - '0') * 10 + (ptz[4] - '0');
- }
- }
- break;
- }
- count++;
- p = NULL;
- }
-
- if (count < 4) { /* don't check for missing timezone */
- return -1;
- }
-
- if (h) {
- h->zhours = zhours;
- h->zminutes = zminutes;
- h->zoccident = zoccident;
- }
-
- return mutt_mktime(&tm, 0) + (zoccident ? 1 : -1) * (zhours * 3600 + zminutes * 60);
+ ok:
+ setlocale(LC_ALL, "");
+ tz = tm.tm_gmtoff;
+ return timegm(&tm) - tz;
}
string_list_t **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p,
hdr->expired = 1;
break;
-#ifdef USE_NNTP
- case MIME_FOLLOWUP_TO:
- if (!e->followup_to) {
- m_strrtrim(p);
- e->followup_to = m_strdup(skipspaces(p));
- }
- break;
-#endif
-
case MIME_FROM:
e->from = rfc822_parse_adrlist(e->from, p);
/* don't leave from info NULL if there's an invalid address (or
hdr->mime = 1;
break;
-#ifdef USE_NNTP
- case MIME_NEWSGROUPS:
- p_delete(&e->newsgroups);
- m_strrtrim(p);
- e->newsgroups = m_strdup(skipspaces(p));
- break;
-#endif
-
case MIME_ORGANIZATION:
if (!e->organization && mime_which_token(p, -1) == MIME_UNKNOWN)
e->organization = m_strdup(p);
e->to = rfc822_parse_adrlist(e->to, p);
break;
-#ifdef USE_NNTP
- case MIME_X_COMMENT_TO:
- if (!e->x_comment_to)
- e->x_comment_to = m_strdup(p);
- break;
-#endif
-
case MIME_X_LABEL:
e->x_label = m_strdup(p);
break;
-#ifdef USE_NNTP
- case MIME_XREF:
- if (!e->xref)
- e->xref = m_strdup(p);
- break;
-#endif
-
case MIME_X_STATUS:
if (hdr) {
while (*p) {
/* restore the original line */
line[m_strlen(line)] = ':';
- if (weed && mutt_matches_ignore(line, Ignore)
- && !mutt_matches_ignore(line, UnIgnore)) {
+ if (weed && string_list_contains(Ignore, line, "*")
+ && !string_list_contains(UnIgnore, line, "*")) {
break;
}
{
/* if spam tag already exists, figure out how to amend it */
if (e->spam && *buf) {
- if (SpamSep) {
- /* If SpamSep defined, append with separator */
- mutt_buffer_addstr(e->spam, SpamSep);
- mutt_buffer_addstr(e->spam, buf);
+ if (mod_mime.spam_separator) {
+ mutt_buffer_addstr(e->spam, mod_mime.spam_separator);
} else {
- /* else overwrite */
mutt_buffer_reset(e->spam);
- mutt_buffer_addstr(e->spam, buf);
}
+ mutt_buffer_addstr(e->spam, buf);
}
if (!e->spam) {
hdr->attach_valid = 1;
return hdr->attach_total;
}
+
+/*
+ * A valid message separator looks like:
+ *
+ * From [ <return-path> ] <weekday> <month> <day> <time> [ <timezone> ] <year>
+ */
+bool is_from(const char *s, char *path, ssize_t pathlen, time_t *tp)
+{
+ const char *p;
+ struct tm tm;
+ char *loc;
+ int q = 0;
+
+ if (path)
+ *path = 0;
+
+ if (m_strncmp("From ", s, 5) != 0)
+ return false;
+
+ s = skipspaces(s + 5); /* skip over the From part. */
+ if (!*s)
+ return false;
+
+ for (p = s; *p && (q || !ISSPACE(*p)); p++) {
+ if (*p == '\\') {
+ if (*++p == '\0')
+ return false;
+ }
+ else if (*p == '"') {
+ q = !q;
+ }
+ }
+
+ if (q || !*p)
+ return false;
+
+ if (path)
+ m_strncpy(path, pathlen, s, p - s);
+
+ s = vskipspaces(p + 1);
+ if (!*s)
+ return false;
+
+ loc = setlocale(LC_TIME, "C");
+ for (int i = 0; i < 4; i++) {
+ static char const * const formats[] = {
+ "%a %b %d %H:%M:%S %Y",
+ "%a %b %d %H:%M:%S %z %Y",
+ "%a %b %d %H:%M %Y",
+ "%a %b %d %H:%M %z %Y",
+ };
+
+ p_clear(&tm, 1);
+ p = strptime(s, formats[i], &tm);
+ if (p) {
+ s = p;
+ goto ok;
+ }
+ }
+ setlocale(LC_TIME, loc);
+ return false;
+
+ ok:
+ if (tp) {
+ *tp = tm.tm_gmtoff;
+ *tp = timegm(&tm) - *tp;
+ }
+ return true;
+}