📄 parse.c
字号:
mutt_str_replace (&b->subtype, "plain"); }}/* parse a MESSAGE/RFC822 body * * args: * fp stream to read from * * parent structure which contains info about the message/rfc822 * body part * * NOTE: this assumes that `parent->length' has been set! */BODY *mutt_parse_messageRFC822 (FILE *fp, BODY *parent){ BODY *msg; parent->hdr = mutt_new_header (); parent->hdr->offset = ftello (fp); parent->hdr->env = mutt_read_rfc822_header (fp, parent->hdr, 0, 0); msg = parent->hdr->content; /* ignore the length given in the content-length since it could be wrong and we already have the info to calculate the correct length */ /* if (msg->length == -1) */ msg->length = parent->length - (msg->offset - parent->offset); /* if body of this message is empty, we can end up with a negative length */ if (msg->length < 0) msg->length = 0; mutt_parse_part(fp, msg); return (msg);}/* parse a multipart structure * * args: * fp stream to read from * * boundary body separator * * end_off length of the multipart body (used when the final * boundary is missing to avoid reading too far) * * digest 1 if reading a multipart/digest, 0 otherwise */BODY *mutt_parse_multipart (FILE *fp, const char *boundary, LOFF_T end_off, int digest){#ifdef SUN_ATTACHMENT int lines;#endif int blen, len, crlf = 0; char buffer[LONG_STRING]; BODY *head = 0, *last = 0, *new = 0; int i; int final = 0; /* did we see the ending boundary? */ if (!boundary) { mutt_error _("multipart message has no boundary parameter!"); return (NULL); } blen = mutt_strlen (boundary); while (ftello (fp) < end_off && fgets (buffer, LONG_STRING, fp) != NULL) { len = mutt_strlen (buffer); crlf = (len > 1 && buffer[len - 2] == '\r') ? 1 : 0; if (buffer[0] == '-' && buffer[1] == '-' && mutt_strncmp (buffer + 2, boundary, blen) == 0) { if (last) { last->length = ftello (fp) - last->offset - len - 1 - crlf; if (last->parts && last->parts->length == 0) last->parts->length = ftello (fp) - last->parts->offset - len - 1 - crlf; /* if the body is empty, we can end up with a -1 length */ if (last->length < 0) last->length = 0; } /* Remove any trailing whitespace, up to the length of the boundary */ for (i = len - 1; ISSPACE (buffer[i]) && i >= blen + 2; i--) buffer[i] = 0; /* Check for the end boundary */ if (mutt_strcmp (buffer + blen + 2, "--") == 0) { final = 1; break; /* done parsing */ } else if (buffer[2 + blen] == 0) { new = mutt_read_mime_header (fp, digest);#ifdef SUN_ATTACHMENT if (mutt_get_parameter ("content-lines", new->parameter)) { for (lines = atoi(mutt_get_parameter ("content-lines", new->parameter)); lines; lines-- ) if (ftello (fp) >= end_off || fgets (buffer, LONG_STRING, fp) == NULL) break; }#endif /* * Consistency checking - catch * bad attachment end boundaries */ if(new->offset > end_off) { mutt_free_body(&new); break; } if (head) { last->next = new; last = new; } else last = head = new; } } } /* in case of missing end boundary, set the length to something reasonable */ if (last && last->length == 0 && !final) last->length = end_off - last->offset; /* parse recursive MIME parts */ for(last = head; last; last = last->next) mutt_parse_part(fp, last); return (head);}static const char *uncomment_timezone (char *buf, size_t buflen, const char *tz){ char *p; size_t len; if (*tz != '(') return tz; /* no need to do anything */ tz++; SKIPWS (tz); if ((p = strpbrk (tz, " )")) == NULL) return tz; len = p - tz; if (len > buflen - 1) len = buflen - 1; memcpy (buf, tz, len); buf[len] = 0; return buf;}static struct tz_t{ char tzname[5]; unsigned char zhours; unsigned char zminutes; unsigned char zoccident; /* west of UTC? */}TimeZones[] ={ { "aat", 1, 0, 1 }, /* Atlantic Africa Time */ { "adt", 4, 0, 0 }, /* Arabia DST */ { "ast", 3, 0, 0 }, /* Arabia *//*{ "ast", 4, 0, 1 },*/ /* Atlantic */ { "bst", 1, 0, 0 }, /* British DST */ { "cat", 1, 0, 0 }, /* Central Africa */ { "cdt", 5, 0, 1 }, { "cest", 2, 0, 0 }, /* Central Europe DST */ { "cet", 1, 0, 0 }, /* Central Europe */ { "cst", 6, 0, 1 },/*{ "cst", 8, 0, 0 },*/ /* China *//*{ "cst", 9, 30, 0 },*/ /* Australian Central Standard Time */ { "eat", 3, 0, 0 }, /* East Africa */ { "edt", 4, 0, 1 }, { "eest", 3, 0, 0 }, /* Eastern Europe DST */ { "eet", 2, 0, 0 }, /* Eastern Europe */ { "egst", 0, 0, 0 }, /* Eastern Greenland DST */ { "egt", 1, 0, 1 }, /* Eastern Greenland */ { "est", 5, 0, 1 }, { "gmt", 0, 0, 0 }, { "gst", 4, 0, 0 }, /* Presian Gulf */ { "hkt", 8, 0, 0 }, /* Hong Kong */ { "ict", 7, 0, 0 }, /* Indochina */ { "idt", 3, 0, 0 }, /* Israel DST */ { "ist", 2, 0, 0 }, /* Israel *//*{ "ist", 5, 30, 0 },*/ /* India */ { "jst", 9, 0, 0 }, /* Japan */ { "kst", 9, 0, 0 }, /* Korea */ { "mdt", 6, 0, 1 }, { "met", 1, 0, 0 }, /* this is now officially CET */ { "msd", 4, 0, 0 }, /* Moscow DST */ { "msk", 3, 0, 0 }, /* Moscow */ { "mst", 7, 0, 1 }, { "nzdt", 13, 0, 0 }, /* New Zealand DST */ { "nzst", 12, 0, 0 }, /* New Zealand */ { "pdt", 7, 0, 1 }, { "pst", 8, 0, 1 }, { "sat", 2, 0, 0 }, /* South Africa */ { "smt", 4, 0, 0 }, /* Seychelles */ { "sst", 11, 0, 1 }, /* Samoa *//*{ "sst", 8, 0, 0 },*/ /* Singapore */ { "utc", 0, 0, 0 }, { "wat", 0, 0, 0 }, /* West Africa */ { "west", 1, 0, 0 }, /* Western Europe DST */ { "wet", 0, 0, 0 }, /* Western Europe */ { "wgst", 2, 0, 1 }, /* Western Greenland DST */ { "wgt", 3, 0, 1 }, /* Western Greenland */ { "wst", 8, 0, 0 }, /* Western Australia */};/* parses a date string in RFC822 format: * * Date: [ weekday , ] day-of-month month year hour:minute:second timezone * * This routine assumes that `h' has been initialized to 0. the `timezone' * field is optional, defaulting to +0000 if missing. */time_t mutt_parse_date (const char *s, HEADER *h){ int count = 0; char *t; int hour, min, sec; struct tm tm; int i; int tz_offset = 0; int zhours = 0; int zminutes = 0; int zoccident = 0; const char *ptz; char tzstr[SHORT_STRING]; char scratch[SHORT_STRING]; /* Don't modify our argument. Fixed-size buffer is ok here since * the date format imposes a natural limit. */ strfcpy (scratch, s, sizeof (scratch)); /* kill the day of the week, if it exists. */ if ((t = strchr (scratch, ','))) t++; else t = scratch; SKIPWS (t); memset (&tm, 0, sizeof (tm)); while ((t = strtok (t, " \t")) != NULL) { switch (count) { case 0: /* day of the month */ if (!isdigit ((unsigned char) *t)) return (-1); tm.tm_mday = atoi (t); if (tm.tm_mday > 31) return (-1); break; case 1: /* month of the year */ if ((i = mutt_check_month (t)) < 0) return (-1); tm.tm_mon = i; break; case 2: /* year */ tm.tm_year = atoi (t); 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 */ if (sscanf (t, "%d:%d:%d", &hour, &min, &sec) == 3) ; else if (sscanf (t, "%d:%d", &hour, &min) == 2) sec = 0; else { dprint(1, (debugfile, "parse_date: could not process time format: %s\n", t)); return(-1); } tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; 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), t); if (*ptz == '+' || *ptz == '-') { if (ptz[1] && ptz[2] && ptz[3] && ptz[4] && isdigit ((unsigned char) ptz[1]) && isdigit ((unsigned char) ptz[2]) && isdigit ((unsigned char) ptz[3]) && isdigit ((unsigned char) ptz[4])) { zhours = (ptz[1] - '0') * 10 + (ptz[2] - '0'); zminutes = (ptz[3] - '0') * 10 + (ptz[4] - '0'); if (ptz[0] == '-') zoccident = 1; } } else { struct tz_t *tz; tz = bsearch (ptz, TimeZones, sizeof TimeZones/sizeof (struct tz_t), sizeof (struct tz_t), (int (*)(const void *, const void *)) ascii_strcasecmp /* This is safe to do: A pointer to a struct equals * a pointer to its first element*/); if (tz) { zhours = tz->zhours; zminutes = tz->zminutes; zoccident = tz->zoccident; } /* ad hoc support for the European MET (now officially CET) TZ */ if (ascii_strcasecmp (t, "MET") == 0) { if ((t = strtok (NULL, " \t")) != NULL) { if (!ascii_strcasecmp (t, "DST")) zhours++; } } } tz_offset = zhours * 3600 + zminutes * 60; if (!zoccident) tz_offset = -tz_offset; break; } count++; t = 0; } if (count < 4) /* don't check for missing timezone */ { dprint(1,(debugfile, "parse_date(): error parsing date format, using received time\n")); return (-1); } if (h) { h->zhours = zhours; h->zminutes = zminutes; h->zoccident = zoccident; } return (mutt_mktime (&tm, 0) + tz_offset);}/* extract the first substring that looks like a message-id */static char *extract_message_id (const char *s){ const char *p; char *r; size_t l; if ((s = strchr (s, '<')) == NULL || (p = strchr (s, '>')) == NULL) return (NULL); l = (size_t)(p - s) + 1; r = safe_malloc (l + 1); memcpy (r, s, l); r[l] = 0; return (r);}void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur){ MESSAGE *msg; do { if (cur->content->type != TYPEMESSAGE && cur->content->type != TYPEMULTIPART) break; /* nothing to do */ if (cur->content->parts) break; /* The message was parsed earlier. */ if ((msg = mx_open_message (ctx, cur->msgno))) { mutt_parse_part (msg->fp, cur->content); if (WithCrypto) cur->security = crypt_query (cur->content); mx_close_message (&msg); } } while (0); cur->attach_valid = 0;}int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed, short do_2047, LIST **lastp){ int matched = 0; LIST *last = NULL; if (lastp) last = *lastp; switch (ascii_tolower (line[0])) { case 'a': if (ascii_strcasecmp (line+1, "pparently-to") == 0) { e->to = rfc822_parse_adrlist (e->to, p); matched = 1; } else if (ascii_strcasecmp (line+1, "pparently-from") == 0) { e->from = rfc822_parse_adrlist (e->from, p); matched = 1; } break; case 'b': if (ascii_strcasecmp (line+1, "cc") == 0) { e->bcc = rfc822_parse_adrlist (e->bcc, p); matched = 1; } break; case 'c': if (ascii_strcasecmp (line+1, "c") == 0) { e->cc = rfc822_parse_adrlist (e->cc, p); matched = 1; } else if (ascii_strncasecmp (line + 1, "ontent-", 7) == 0) { if (ascii_strcasecmp (line+8, "type") == 0) { if (hdr) mutt_parse_content_type (p, hdr->content); matched = 1; } else if (ascii_strcasecmp (line+8, "transfer-encoding") == 0) { if (hdr) hdr->content->encoding = mutt_check_encoding (p); matched = 1; } else if (ascii_strcasecmp (line+8, "length") == 0) { if (hdr) { if ((hdr->content->length = atoi (p)) < 0) hdr->content->length = -1; } matched = 1; } else if (ascii_strcasecmp (line+8, "description") == 0) { if (hdr) { mutt_str_replace (&hdr->content->description, p); rfc2047_decode (&hdr->content->description); } matched = 1; } else if (ascii_strcasecmp (line+8, "disposition") == 0) { if (hdr) parse_content_disposition (p, hdr->content); matched = 1; } } break; case 'd': if (!ascii_strcasecmp ("ate", line + 1)) { mutt_str_replace (&e->date, p); if (hdr) hdr->date_sent = mutt_parse_date (p, hdr); matched = 1; } break; case 'e': if (!ascii_strcasecmp ("xpires", line + 1) && hdr && mutt_parse_date (p, NULL) < time (NULL)) hdr->expired = 1; break; case 'f': if (!ascii_strcasecmp ("rom", line + 1)) { e->from = rfc822_parse_adrlist (e->from, p); matched = 1; } break; case 'i': if (!ascii_strcasecmp (line+1, "n-reply-to")) { mutt_free_list (&e->in_reply_to); e->in_reply_to = mutt_parse_references (p, 1); matched = 1; } break; case 'l': if (!ascii_strcasecmp (line + 1, "ines")) { if (hdr) { hdr->lines = atoi (p); /* * HACK - mutt has, for a very short time, produced negative * Lines header values. Ignore them. */ if (hdr->lines < 0) hdr->lines = 0; } matched = 1; } else if (!ascii_strcasecmp (line + 1, "ist-Post")) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -