📄 rfc822.c
字号:
/* * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include <string.h>#include <ctype.h>#include <stdlib.h>#ifndef TESTING#include "mutt.h"#else#define safe_strdup strdup#define safe_malloc malloc#define SKIPWS(x) while(isspace(*x))x++#define FREE(x) safe_free(x)#define ISSPACE isspace#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}}#define STRING 128#include "rfc822.h"#endif#include "mutt_idna.h"#define terminate_string(a, b, c) do { if ((b) < (c)) a[(b)] = 0; else \ a[(c)] = 0; } while (0)#define terminate_buffer(a, b) terminate_string(a, b, sizeof (a) - 1)const char RFC822Specials[] = "@.,:;<>[]\\\"()";#define is_special(x) strchr(RFC822Specials,x)int RFC822Error = 0;/* these must defined in the same order as the numerated errors given in rfc822.h */const char *RFC822Errors[] = { "out of memory", "mismatched parenthesis", "mismatched quotes", "bad route in <>", "bad address in <>", "bad address spec"};void rfc822_dequote_comment (char *s){ char *w = s; for (; *s; s++) { if (*s == '\\') { if (!*++s) break; /* error? */ *w++ = *s; } else if (*s != '\"') { if (w != s) *w = *s; w++; } } *w = 0;}void rfc822_free_address (ADDRESS **p){ ADDRESS *t; while (*p) { t = *p; *p = (*p)->next;#ifdef EXACT_ADDRESS FREE (&t->val);#endif FREE (&t->personal); FREE (&t->mailbox); FREE (&t); }}static const char *parse_comment (const char *s, char *comment, size_t *commentlen, size_t commentmax){ int level = 1; while (*s && level) { if (*s == '(') level++; else if (*s == ')') { if (--level == 0) { s++; break; } } else if (*s == '\\') { if (!*++s) break; } if (*commentlen < commentmax) comment[(*commentlen)++] = *s; s++; } if (level) { RFC822Error = ERR_MISMATCH_PAREN; return NULL; } return s;}static const char *parse_quote (const char *s, char *token, size_t *tokenlen, size_t tokenmax){ if (*tokenlen < tokenmax) token[(*tokenlen)++] = '"'; while (*s) { if (*tokenlen < tokenmax) token[*tokenlen] = *s; if (*s == '"') { (*tokenlen)++; return (s + 1); } if (*s == '\\') { if (!*++s) break; if (*tokenlen < tokenmax) token[*tokenlen] = *s; } (*tokenlen)++; s++; } RFC822Error = ERR_MISMATCH_QUOTE; return NULL;}static const char *next_token (const char *s, char *token, size_t *tokenlen, size_t tokenmax){ if (*s == '(') return (parse_comment (s + 1, token, tokenlen, tokenmax)); if (*s == '"') return (parse_quote (s + 1, token, tokenlen, tokenmax)); if (is_special (*s)) { if (*tokenlen < tokenmax) token[(*tokenlen)++] = *s; return (s + 1); } while (*s) { if (ISSPACE ((unsigned char) *s) || is_special (*s)) break; if (*tokenlen < tokenmax) token[(*tokenlen)++] = *s; s++; } return s;}static const char *parse_mailboxdomain (const char *s, const char *nonspecial, char *mailbox, size_t *mailboxlen, size_t mailboxmax, char *comment, size_t *commentlen, size_t commentmax){ const char *ps; while (*s) { SKIPWS (s); if (strchr (nonspecial, *s) == NULL && is_special (*s)) return s; if (*s == '(') { if (*commentlen && *commentlen < commentmax) comment[(*commentlen)++] = ' '; ps = next_token (s, comment, commentlen, commentmax); } else ps = next_token (s, mailbox, mailboxlen, mailboxmax); if (!ps) return NULL; s = ps; } return s;}static const char *parse_address (const char *s, char *token, size_t *tokenlen, size_t tokenmax, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr){ s = parse_mailboxdomain (s, ".\"(\\", token, tokenlen, tokenmax, comment, commentlen, commentmax); if (!s) return NULL; if (*s == '@') { if (*tokenlen < tokenmax) token[(*tokenlen)++] = '@'; s = parse_mailboxdomain (s + 1, ".([]\\", token, tokenlen, tokenmax, comment, commentlen, commentmax); if (!s) return NULL; } terminate_string (token, *tokenlen, tokenmax); addr->mailbox = safe_strdup (token); if (*commentlen && !addr->personal) { terminate_string (comment, *commentlen, commentmax); addr->personal = safe_strdup (comment); } return s;}static const char *parse_route_addr (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr){ char token[STRING]; size_t tokenlen = 0; SKIPWS (s); /* find the end of the route */ if (*s == '@') { while (s && *s == '@') { if (tokenlen < sizeof (token) - 1) token[tokenlen++] = '@'; s = parse_mailboxdomain (s + 1, ",.\\[](", token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax); } if (!s || *s != ':') { RFC822Error = ERR_BAD_ROUTE; return NULL; /* invalid route */ } if (tokenlen < sizeof (token) - 1) token[tokenlen++] = ':'; s++; } if ((s = parse_address (s, token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax, addr)) == NULL) return NULL; if (*s != '>') { RFC822Error = ERR_BAD_ROUTE_ADDR; return NULL; } if (!addr->mailbox) addr->mailbox = safe_strdup ("@"); s++; return s;}static const char *parse_addr_spec (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr){ char token[STRING]; size_t tokenlen = 0; s = parse_address (s, token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax, addr); if (s && *s && *s != ',' && *s != ';') { RFC822Error = ERR_BAD_ADDR_SPEC; return NULL; } return s;}static voidadd_addrspec (ADDRESS **top, ADDRESS **last, const char *phrase, char *comment, size_t *commentlen, size_t commentmax){ ADDRESS *cur = rfc822_new_address (); if (parse_addr_spec (phrase, comment, commentlen, commentmax, cur) == NULL) { rfc822_free_address (&cur); return; } if (*last) (*last)->next = cur; else *top = cur; *last = cur;}ADDRESS *rfc822_parse_adrlist (ADDRESS *top, const char *s){ int ws_pending; const char *begin, *ps; char comment[STRING], phrase[STRING]; size_t phraselen = 0, commentlen = 0; ADDRESS *cur, *last = NULL; RFC822Error = 0; last = top; while (last && last->next) last = last->next; ws_pending = isspace ((unsigned char) *s); SKIPWS (s); begin = s; while (*s) { if (*s == ',') { if (phraselen) { terminate_buffer (phrase, phraselen); add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { terminate_buffer (comment, commentlen); last->personal = safe_strdup (comment); }#ifdef EXACT_ADDRESS if (last && !last->val) last->val = mutt_substrdup (begin, s);#endif commentlen = 0; phraselen = 0; s++; begin = s; SKIPWS (begin); } else if (*s == '(') { if (commentlen && commentlen < sizeof (comment) - 1) comment[commentlen++] = ' '; if ((ps = next_token (s, comment, &commentlen, sizeof (comment) - 1)) == NULL) { rfc822_free_address (&top); return NULL; } s = ps; } else if (*s == ':') { cur = rfc822_new_address (); terminate_buffer (phrase, phraselen); cur->mailbox = safe_strdup (phrase); cur->group = 1; if (last) last->next = cur; else top = cur; last = cur;#ifdef EXACT_ADDRESS last->val = mutt_substrdup (begin, s);#endif phraselen = 0; commentlen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -