From: Pierre Habouzit Date: Wed, 8 Nov 2006 00:14:58 +0000 (+0100) Subject: generalize the idea of tokens a bit more, don't restrict it to the rfc822 X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=commitdiff_plain;h=3a3420a4cb3369d51eecc9287d556596f98e7314 generalize the idea of tokens a bit more, don't restrict it to the rfc822 headers, use it for all mime tokens we need. I suppose I'll do a mutt-tokens module at some point Signed-off-by: Pierre Habouzit --- diff --git a/lib-mime/.gitignore b/lib-mime/.gitignore index 2e9a39f..5d6768d 100644 --- a/lib-mime/.gitignore +++ b/lib-mime/.gitignore @@ -1,2 +1,2 @@ -rfc822hdrs.h -rfc822hdrs.c +mime-token.h +mime-token.c diff --git a/lib-mime/Makefile.am b/lib-mime/Makefile.am index 362022e..003aaf3 100644 --- a/lib-mime/Makefile.am +++ b/lib-mime/Makefile.am @@ -1,4 +1,4 @@ -BUILT_SOURCES = rfc822hdrs.h rfc822hdrs.c +BUILT_SOURCES = mime-token.h mime-token.c CLEANFILES = $(BUILT_SOURCES) noinst_LIBRARIES = libmime.a @@ -9,7 +9,7 @@ libmime_a_SOURCES = mime.h mime-types.h $(BUILT_SOURCES) \ noinst_HEADERS = mime.h mime-types.h -rfc822hdrs.c rfc822hdrs.h: rfc822hdrs.def - sh rfc822hdrs.sh $@ < $< +mime-token.c mime-token.h: mime-token.def mime-token.sh + sh mime-token.sh $@ < $< -include ../cflags.mk diff --git a/lib-mime/rfc822hdrs.def b/lib-mime/mime-token.def similarity index 67% rename from lib-mime/rfc822hdrs.def rename to lib-mime/mime-token.def index 1d073e2..06b8ca7 100644 --- a/lib-mime/rfc822hdrs.def +++ b/lib-mime/mime-token.def @@ -1,6 +1,13 @@ +7bit +8bit +alternative apparently-from apparently-to +application +audio +base64 bcc +binary cc content-description content-disposition @@ -8,18 +15,28 @@ content-length content-transfer-encoding content-type date +digest expires +external-body followup-to from +image in-reply-to +news +rfc822 +iso-2022-jp lines list-post mail-followup-to mail-reply-to +message message-id mime-version +model +multipart newsgroups organization +quoted-printable received references reply-to @@ -29,8 +46,14 @@ status subject supercedes supersedes +text to +unknown +us-ascii +utf-8 +video x-comment-to x-label xref x-status +x-uuencode diff --git a/lib-mime/mime-token.sh b/lib-mime/mime-token.sh new file mode 100644 index 0000000..bb55179 --- /dev/null +++ b/lib-mime/mime-token.sh @@ -0,0 +1,87 @@ +#! /bin/sh -e + +die() { + echo "$@" 1>&2 + exit 2 +} + +do_hdr() { + cat < +#include "mime-token.h" + +%} +struct tok { const char *name; int val; }; +%% +`awk '{print $0 ", " NR }'` +%% + +enum mime_token mime_which_token(const char *s, ssize_t len) { + const struct tok *res; + + if (len < 0) + len = m_strlen(s); + if (!len) + return MUTT_MIME_TOKEN_UNKNOWN; + + res = in_word_set(s, len); + return res ? res->val : MUTT_MIME_TOKEN_UNKNOWN; +} +EOF +} + +trap "rm -f $1" 1 2 3 15 + +case "$1" in + *.h) do_h > "$1";; + *.c) do_c > "$1";; + *) die "you must ask for the 'h' or 'c' generation";; +esac + +exit 0 diff --git a/lib-mime/mime-types.h b/lib-mime/mime-types.h index 474a223..59fe54e 100644 --- a/lib-mime/mime-types.h +++ b/lib-mime/mime-types.h @@ -60,7 +60,7 @@ enum { ENCQUOTEDPRINTABLE, ENCBASE64, ENCBINARY, - ENCUUENCODED + ENCUUENCODED, }; /* Content-Disposition values */ diff --git a/lib-mime/mime.h b/lib-mime/mime.h index b235acc..8c0d3b8 100644 --- a/lib-mime/mime.h +++ b/lib-mime/mime.h @@ -34,6 +34,7 @@ #include #include "mime-types.h" +#include "mime-token.h" extern const char MimeSpecials[]; extern const char *BodyTypes[]; @@ -43,8 +44,9 @@ extern const char *BodyEncodings[]; #define is_multipart(x) \ ((x)->type == TYPEMULTIPART \ - || ((x)->type == TYPEMESSAGE && (!strcasecmp((x)->subtype, "rfc822") \ - || !strcasecmp((x)->subtype, "news")))) + || ((x)->type == TYPEMESSAGE && \ + (!mime_which_token((x)->subtype, -1) == MIME_RFC822) \ + || !mime_which_token((x)->subtype, -1) == MIME_NEWS)) #define TYPE(X) ((X->type == TYPEOTHER) && (X->xtype != NULL) ? X->xtype : BodyTypes[(X->type)]) #define ENCODING(X) BodyEncodings[(X)] diff --git a/lib-mime/rfc2047.c b/lib-mime/rfc2047.c index 3bd353c..264caff 100644 --- a/lib-mime/rfc2047.c +++ b/lib-mime/rfc2047.c @@ -304,7 +304,7 @@ static size_t try_block(const char *d, ssize_t dlen, len_q = len + (ob - buf1) + 2 * count; /* Apparently RFC 1468 says to use B encoding for iso-2022-jp. */ - if (!ascii_strcasecmp(tocode, "ISO-2022-JP")) + if (mime_which_token(tocode, -1) == MIME_ISO_2022_JP) len_q = ENCWORD_LEN_MAX + 1; if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) { @@ -361,7 +361,7 @@ static size_t choose_block(char *d, size_t dlen, int col, encoder_t **encoder, ssize_t *wlen) { size_t n, nn; - int utf8 = fromcode && !ascii_strcasecmp(fromcode, "UTF-8"); + int utf8 = mime_which_token(fromcode, -1) == MIME_UTF_8; n = dlen; for (;;) { @@ -807,7 +807,7 @@ void rfc2047_decode(char **pd) n -= m, s += m; } - if (ascii_strcasecmp(AssumedCharset, "us-ascii")) { + if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) { char *t; t = p_dupstr(s, n); diff --git a/lib-mime/rfc2231.c b/lib-mime/rfc2231.c index ff6a02c..e7c1053 100644 --- a/lib-mime/rfc2231.c +++ b/lib-mime/rfc2231.c @@ -242,8 +242,8 @@ void rfc2231_decode_parameters (PARAMETER ** headp) if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?")) rfc2047_decode (&p->value); else if (!option (OPTSTRICTMIME)) { - if (ascii_strcasecmp (AssumedCharset, "us-ascii")) - mutt_convert_nonmime_string (&p->value); + if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) + mutt_convert_nonmime_string(&p->value); } *last = p; diff --git a/lib-mime/rfc822hdrs.sh b/lib-mime/rfc822hdrs.sh deleted file mode 100644 index 1124536..0000000 --- a/lib-mime/rfc822hdrs.sh +++ /dev/null @@ -1,42 +0,0 @@ -#! /bin/sh - -die() { - echo "$@" 1>&2 - exit 2 -} - -do_h() { - echo "#ifndef MUTT_LIB_MIME_RFC822HDRS_H" - echo "#define MUTT_LIB_MIME_RFC822HDRS_H" - echo "/* THIS FILE IS AUTOGENERATED FROM $< DO NOT MODIFY */" - echo "enum rfc822hdr {" - echo " HDR_UNKNOWN," - tr 'a-z-' 'A-Z_' | sed -e 's/.*/ HDR_&,/' - echo "};" - echo - echo "enum rfc822hdr rfc822_well_known(const char *s);" - echo "#endif /* MUTT_LIB_MIME_RFC822HDRS_H */" -} - -do_c() { - echo "%{" - echo "#include " - echo "#include \"rfc822hdrs.h\"" - echo "%}" - echo "struct hdr { const char *name; int val; };" - echo "%%" - awk '{print $$0 ", " NR }' - echo "%%" - echo "enum rfc822hdr rfc822_well_known(const char *s) {" - echo " const struct hdr *res = in_word_set(s, strlen(s));" - echo " return res ? res->val : HDR_UNKNOWN;" - echo "}" -} - -case "$1" in - *.h) do_h > "$1" ;; - *.c) do_c | gperf --ignore-case -t -C -F,0 > "$1" ;; - *) die "you must ask for the 'h' or 'c' generation" ;; -esac - -exit 0 diff --git a/lib-mime/rfc822parse.c b/lib-mime/rfc822parse.c index 70f405e..40414d9 100644 --- a/lib-mime/rfc822parse.c +++ b/lib-mime/rfc822parse.c @@ -162,40 +162,44 @@ LIST *mutt_parse_references(char *s, int in_reply_to) int mutt_check_encoding(const char *s) { -#define COMPARE(tok, value) \ - if (!ascii_strncasecmp(tok, s, sizeof(tok) - 1)) { \ - return value; \ + int tok = mime_which_token(s, -1); + switch (tok) { + case MIME_7BIT: + return ENC7BIT; + case MIME_8BIT: + return ENC8BIT; + case MIME_BINARY: + return ENCBINARY; + case MIME_QUOTED_PRINTABLE: + return ENCQUOTEDPRINTABLE; + case MIME_BASE64: + return ENCBASE64; + case MIME_X_UUENCODE: + return ENCUUENCODED; + default: + return ENCOTHER; } - COMPARE("7bit", ENC7BIT); - COMPARE("8bit", ENC8BIT); - COMPARE("binary", ENCBINARY); - COMPARE("quoted-printable", ENCQUOTEDPRINTABLE); - COMPARE("base64", ENCBASE64); - COMPARE("x-uuencode", ENCUUENCODED); -#undef COMPARE - - return ENCOTHER; } int mutt_check_mime_type(const char *s) { -#define COMPARE(tok, value) \ - if (!ascii_strncasecmp(tok, s, sizeof(tok) - 1)) { \ - return value; \ + int tok; + + if (!m_strcmp(s, "*") || !m_strcmp(s, ".*")) + return TYPEANY; + + tok = mime_which_token(s, -1); + switch (tok) { + case MIME_TEXT: return TYPETEXT; + case MIME_MULTIPART: return TYPEMULTIPART; + case MIME_APPLICATION: return TYPEAPPLICATION; + case MIME_MESSAGE: return TYPEMESSAGE; + case MIME_IMAGE: return TYPEIMAGE; + case MIME_AUDIO: return TYPEAUDIO; + case MIME_VIDEO: return TYPEVIDEO; + case MIME_MODEL: return TYPEMODEL; + default: return TYPEOTHER; } - COMPARE("text", TYPETEXT); - COMPARE("multipart", TYPEMULTIPART); - COMPARE("application", TYPEAPPLICATION); - COMPARE("message", TYPEMESSAGE); - COMPARE("image", TYPEIMAGE); - COMPARE("audio", TYPEAUDIO); - COMPARE("video", TYPEVIDEO); - COMPARE("model", TYPEMODEL); - COMPARE("*", TYPEANY); - COMPARE(".*", TYPEANY); -#undef COMPARE - - return TYPEOTHER; } static PARAMETER *parse_parameters(const char *s) @@ -403,17 +407,25 @@ BODY *mutt_read_mime_header(FILE *fp, int digest) break; } - if (!ascii_strncasecmp(line, "content-", 8)) { - if (!ascii_strcasecmp("type", line + 8)) - mutt_parse_content_type (p, body); - else if (!ascii_strcasecmp ("transfer-encoding", line + 8)) - body->encoding = mutt_check_encoding (p); - else if (!ascii_strcasecmp ("disposition", line + 8)) - parse_content_disposition(p, body); - else if (!ascii_strcasecmp ("description", line + 8)) { - m_strreplace(&body->description, p); - rfc2047_decode(&body->description); - } + switch (mime_which_token(line, -1)) { + case MIME_CONTENT_TYPE: + mutt_parse_content_type (p, body); + break; + + case MIME_CONTENT_TRANSFER_ENCODING: + body->encoding = mutt_check_encoding (p); + break; + + case MIME_CONTENT_DISPOSITION: + parse_content_disposition(p, body); + break; + + case MIME_CONTENT_DESCRIPTION: + m_strreplace(&body->description, p); + rfc2047_decode(&body->description); + break; + + default: break; } } @@ -438,7 +450,7 @@ void mutt_parse_part(FILE *fp, BODY *b) bound = mutt_get_parameter("boundary", b->parameter); fseeko(fp, b->offset, SEEK_SET); b->parts = mutt_parse_multipart(fp, bound, b->offset + b->length, - !ascii_strcasecmp("digest", b->subtype)); + mime_which_token(b->subtype, -1) == MIME_DIGEST); break; case TYPEMESSAGE: @@ -448,7 +460,7 @@ void mutt_parse_part(FILE *fp, BODY *b) if (mutt_is_message_type(b->type, b->subtype)) { b->parts = mutt_parse_messageRFC822(fp, b); } else - if (!ascii_strcasecmp(b->subtype, "external-body") == 0) { + if (mime_which_token(b->subtype, -1) == MIME_EXTERNAL_BODY) { b->parts = mutt_read_mime_header(fp, 0); } else { return; @@ -783,70 +795,68 @@ time_t mutt_parse_date(const char *s, HEADER *h) return mutt_mktime(&tm, 0) + (zoccident ? 1 : -1) * (zhours * 3600 + zminutes * 60); } -#include "rfc822hdrs.h" - LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, short weed, short do_2047, LIST **user_hdrs) { - switch (rfc822_well_known(line)) { - case HDR_APPARENTLY_FROM: + switch (mime_which_token(line, -1)) { + case MIME_APPARENTLY_FROM: e->from = rfc822_parse_adrlist (e->from, p); break; - case HDR_APPARENTLY_TO: + case MIME_APPARENTLY_TO: e->to = rfc822_parse_adrlist (e->to, p); break; - case HDR_BCC: + case MIME_BCC: e->bcc = rfc822_parse_adrlist (e->bcc, p); break; - case HDR_CC: + case MIME_CC: e->cc = rfc822_parse_adrlist (e->cc, p); break; - case HDR_CONTENT_DESCRIPTION: + case MIME_CONTENT_DESCRIPTION: if (hdr) { m_strreplace(&hdr->content->description, p); rfc2047_decode(&hdr->content->description); } break; - case HDR_CONTENT_DISPOSITION: + case MIME_CONTENT_DISPOSITION: if (hdr) parse_content_disposition(p, hdr->content); break; - case HDR_CONTENT_LENGTH: + case MIME_CONTENT_LENGTH: if (hdr) { if ((hdr->content->length = atoi(p)) < 0) hdr->content->length = -1; } break; - case HDR_CONTENT_TRANSFER_ENCODING: + case MIME_CONTENT_TRANSFER_ENCODING: if (hdr) hdr->content->encoding = mutt_check_encoding(p); break; - case HDR_CONTENT_TYPE: + case MIME_CONTENT_TYPE: if (hdr) mutt_parse_content_type (p, hdr->content); break; - case HDR_DATE: + case MIME_DATE: m_strreplace(&e->date, p); if (hdr) hdr->date_sent = mutt_parse_date (p, hdr); break; - case HDR_EXPIRES: + case MIME_EXPIRES: if (hdr && mutt_parse_date (p, NULL) < time (NULL)) hdr->expired = 1; break; #ifdef USE_NNTP - case HDR_FOLLOWUP_TO: + case MIME_FOLLOWUP_TO: if (!e->followup_to) { m_strrtrim(p); e->followup_to = m_strdup(skipspaces(p)); @@ -854,7 +864,7 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, break; #endif - case HDR_FROM: + case MIME_FROM: e->from = rfc822_parse_adrlist(e->from, p); /* don't leave from info NULL if there's an invalid address (or * whatever) in From: field; mutt would just display it as empty @@ -866,12 +876,12 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_IN_REPLY_TO: + case MIME_IN_REPLY_TO: mutt_free_list(&e->in_reply_to); e->in_reply_to = mutt_parse_references(p, 1); break; - case HDR_LINES: + case MIME_LINES: if (hdr) { /* HACK - mutt has, for a very short time, produced negative Lines header values. Ignore them. */ @@ -879,7 +889,7 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_LIST_POST: + case MIME_LIST_POST: /* RFC 2369. FIXME: We should ignore whitespace, but don't. */ if (strncmp(p, "NO", 2)) { char *beg, *end; @@ -899,16 +909,16 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_MAIL_FOLLOWUP_TO: + case MIME_MAIL_FOLLOWUP_TO: e->mail_followup_to = rfc822_parse_adrlist(e->mail_followup_to, p); break; - case HDR_MAIL_REPLY_TO: + case MIME_MAIL_REPLY_TO: address_delete (&e->reply_to); e->reply_to = rfc822_parse_adrlist(e->reply_to, p); break; - case HDR_MESSAGE_ID: + case MIME_MESSAGE_ID: { const char *beg, *end; @@ -920,25 +930,25 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_MIME_VERSION: + case MIME_MIME_VERSION: if (hdr) hdr->mime = 1; break; #ifdef USE_NNTP - case HDR_NEWSGROUPS: + case MIME_NEWSGROUPS: p_delete(&e->newsgroups); m_strrtrim(p); e->newsgroups = m_strdup(skipspaces(p)); break; #endif - case HDR_ORGANIZATION: - if (!e->organization && m_strcasecmp(p, "unknown")) + case MIME_ORGANIZATION: + if (!e->organization && mime_which_token(p, -1) == MIME_UNKNOWN) e->organization = m_strdup(p); break; - case HDR_RECEIVED: + case MIME_RECEIVED: if (hdr && !hdr->received) { char *d = strchr(p, ';'); if (d) @@ -946,24 +956,24 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_REFERENCES: + case MIME_REFERENCES: mutt_free_list(&e->references); e->references = mutt_parse_references(p, 0); break; - case HDR_REPLY_TO: + case MIME_REPLY_TO: e->reply_to = rfc822_parse_adrlist(e->reply_to, p); break; - case HDR_RETURN_PATH: + case MIME_RETURN_PATH: e->return_path = rfc822_parse_adrlist(e->return_path, p); break; - case HDR_SENDER: + case MIME_SENDER: e->sender = rfc822_parse_adrlist (e->sender, p); break; - case HDR_STATUS: + case MIME_STATUS: if (hdr) { while (*p) { switch (*p) { @@ -982,40 +992,40 @@ LIST **mutt_parse_rfc822_line(ENVELOPE *e, HEADER *hdr, char *line, char *p, } break; - case HDR_SUBJECT: + case MIME_SUBJECT: if (!e->subject) e->subject = m_strdup(p); break; - case HDR_SUPERCEDES: - case HDR_SUPERSEDES: + case MIME_SUPERCEDES: + case MIME_SUPERSEDES: if (hdr) e->supersedes = m_strdup(p); break; - case HDR_TO: + case MIME_TO: e->to = rfc822_parse_adrlist(e->to, p); break; #ifdef USE_NNTP - case HDR_X_COMMENT_TO: + case MIME_X_COMMENT_TO: if (!e->x_comment_to) e->x_comment_to = m_strdup(p); break; #endif - case HDR_X_LABEL: + case MIME_X_LABEL: e->x_label = m_strdup(p); break; #ifdef USE_NNTP - case HDR_XREF: + case MIME_XREF: if (!e->xref) e->xref = m_strdup(p); break; #endif - case HDR_X_STATUS: + case MIME_X_STATUS: if (hdr) { while (*p) { switch (*p) { @@ -1221,7 +1231,7 @@ int count_body_parts (BODY *body, int flags) { shallrecurse = 1; /* If it's an external body pointer, don't recurse it. */ - if (!ascii_strcasecmp (bp->subtype, "external-body")) + if (mime_which_token(bp->subtype, -1) == MIME_EXTERNAL_BODY) shallrecurse = 0; /* Don't count containers if they're top-level. */ @@ -1230,7 +1240,7 @@ int count_body_parts (BODY *body, int flags) { } else if (bp->type == TYPEMULTIPART) { /* Always recurse multiparts, except multipart/alternative. */ shallrecurse = 1; - if (!m_strcasecmp(bp->subtype, "alternative")) + if (mime_which_token(bp->subtype, -1) == MIME_ALTERNATIVE) shallrecurse = 0; /* Don't count containers if they're top-level. */