From: Thomas Roessler Date: Wed, 25 Apr 2001 22:08:41 +0000 (+0000) Subject: Implement RFC 2822's idea of the In-Reply-To header. In particular, X-Git-Tag: mutt-1-3-18-rel~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f16589816ab217ec425ecbf026a9a5ade18333f;p=mutt Implement RFC 2822's idea of the In-Reply-To header. In particular, we have to drop the $in_reply_to configuration variable. Also, the change in the specification makes some changes to the threading code reasonable. --- diff --git a/globals.h b/globals.h index 9a38542d..5697061e 100644 --- a/globals.h +++ b/globals.h @@ -55,7 +55,6 @@ WHERE char *ImapHomeNamespace INITVAL (NULL); WHERE char *ImapPass INITVAL (NULL); WHERE char *ImapUser INITVAL (NULL); #endif -WHERE char *InReplyTo; WHERE char *Inbox; WHERE char *Ispell; WHERE char *Locale; diff --git a/init.h b/init.h index dc1f7920..87298215 100644 --- a/init.h +++ b/init.h @@ -764,17 +764,6 @@ struct option_t MuttVars[] = { ** message to which you are replying. You are strongly encouraged not to ** change this value, as it tends to agitate the more fanatical netizens. */ - { "in_reply_to", DT_STR, R_NONE, UL &InReplyTo, UL "%i; from %a on %{!%a, %b %d, %Y at %I:%M:%S%p %Z}" }, - /* - ** .pp - ** This specifies the format of the \fIIn-Reply-To\fP header field - ** added when replying to a message. For a full listing of - ** defined escape sequences, see the section on $$index_format. - ** .pp - ** \fBNote:\fP Don't use any sequences in this format string which - ** may include 8-bit characters. Using such escape sequences may - ** lead to bad headers. - */ { "indent_str", DT_SYN, R_NONE, UL "indent_string", 0 }, /* */ diff --git a/mutt.h b/mutt.h index 1d3065bf..e7bb18a8 100644 --- a/mutt.h +++ b/mutt.h @@ -501,6 +501,7 @@ typedef struct envelope char *date; char *x_label; LIST *references; /* message references (in reverse order) */ + LIST *in_reply_to; /* in-reply-to header content */ LIST *userhdrs; /* user defined headers */ } ENVELOPE; diff --git a/parse.c b/parse.c index b87da402..b3888fec 100644 --- a/parse.c +++ b/parse.c @@ -903,7 +903,7 @@ void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur) } int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed, - short do_2047, LIST **lastp, char **in_reply_to) + short do_2047, LIST **lastp) { int matched = 0; LIST *last = NULL; @@ -1008,12 +1008,9 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short case 'i': if (!mutt_strcasecmp (line+1, "n-reply-to")) { - if (hdr && in_reply_to) - { - mutt_str_replace (in_reply_to, p); - if (do_2047) - rfc2047_decode (in_reply_to); - } + mutt_free_list (&e->in_reply_to); + e->in_reply_to = mutt_parse_references (p); + matched = 1; } break; @@ -1223,7 +1220,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs, LIST *last = NULL; char *line = safe_malloc (LONG_STRING); char *p; - char *in_reply_to = 0; long loc; int matched; size_t linelen = LONG_STRING; @@ -1276,7 +1272,7 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs, if (!*p) continue; /* skip empty header fields */ - matched = mutt_parse_rfc822_line (e, hdr, line, p, user_hdrs, weed, 1, &last, &in_reply_to); + matched = mutt_parse_rfc822_line (e, hdr, line, p, user_hdrs, weed, 1, &last); } @@ -1287,24 +1283,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs, hdr->content->hdr_offset = hdr->offset; hdr->content->offset = ftell (f); - /* if an in-reply-to was given, check to see if it is in the references - * list already. if not, add it so we can do a better job of threading. - */ - if (in_reply_to && (p = extract_message_id (in_reply_to)) != NULL) - { - if (!e->references || - (e->references && mutt_strcmp (e->references->data, p) != 0)) - { - LIST *tmp = mutt_new_list (); - - tmp->data = p; - tmp->next = e->references; - e->references = tmp; - } - else - safe_free ((void **) &p); - } - /* do RFC2047 decoding */ rfc2047_decode_adrlist (e->from); rfc2047_decode_adrlist (e->to); @@ -1334,7 +1312,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs, } } - safe_free ((void *) &in_reply_to); return (e); } diff --git a/protos.h b/protos.h index 2c388091..a221e5f6 100644 --- a/protos.h +++ b/protos.h @@ -296,7 +296,7 @@ int mutt_parse_unmono (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_push (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_rc_line (/* const */ char *, BUFFER *, BUFFER *); int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed, - short do_2047, LIST **lastp, char **in_reply_to); + short do_2047, LIST **lastp); int mutt_parse_score (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_unscore (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_unhook (BUFFER *, BUFFER *, unsigned long, BUFFER *); diff --git a/send.c b/send.c index 848d9a1e..56082ca0 100644 --- a/send.c +++ b/send.c @@ -586,9 +586,6 @@ void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur) void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, ENVELOPE *curenv) { - LIST *tmp; - char buffer[STRING]; - if (curenv->real_subj) { env->subject = safe_malloc (mutt_strlen (curenv->real_subj) + 5); @@ -597,22 +594,44 @@ void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, else env->subject = safe_strdup ("Re: your mail"); - /* add the In-Reply-To field */ - if (InReplyTo) +} + +static void +mutt_make_reference_headers (ENVELOPE *curenv, ENVELOPE *env, CONTEXT *ctx) +{ + HEADER *h; + LIST **p, **q; + int i; + + if (!curenv) { - strfcpy (buffer, "In-Reply-To: ", sizeof (buffer)); - mutt_make_string (buffer + 13, sizeof (buffer) - 13, InReplyTo, ctx, cur); - tmp = env->userhdrs; - while (tmp && tmp->next) - tmp = tmp->next; - if (tmp) + env->references = NULL; + env->in_reply_to = NULL; + p = &env->references; + q = &env->in_reply_to; + + for(i = 0; i < ctx->vcount; i++) { - tmp->next = mutt_new_list (); - tmp = tmp->next; + while(*p) p = &(*p)->next; + while (*q) q = &(*q)->next; + + h = ctx->hdrs[ctx->v2r[i]]; + if(h->tagged) + { + *p = mutt_make_references(h->env); + if (h->env->message_id) + { + *q = mutt_new_list (); + (*q)->data = safe_strdup (h->env->message_id); + } + } } - else - tmp = env->userhdrs = mutt_new_list (); - tmp->data = safe_strdup (buffer); + } + else + { + env->references = mutt_make_references (curenv); + env->in_reply_to = mutt_new_list (); + env->in_reply_to->data = safe_strdup (curenv->message_id); } } @@ -669,26 +688,7 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) mutt_fix_reply_recipients (env); mutt_make_misc_reply_headers (env, ctx, cur, curenv); - - if(tag) - { - HEADER *h; - LIST **p; - - env->references = NULL; - p = &env->references; - - for(i = 0; i < ctx->vcount; i++) - { - while(*p) p = &(*p)->next; - h = ctx->hdrs[ctx->v2r[i]]; - if(h->tagged) - *p = mutt_make_references(h->env); - } - } - else - env->references = mutt_make_references(curenv); - + mutt_make_reference_headers (tag ? NULL : curenv, env, ctx); } else if (flags & SENDFORWARD) mutt_make_forward_subject (env, ctx, cur); diff --git a/sendlib.c b/sendlib.c index 532f4094..ee19d3a8 100644 --- a/sendlib.c +++ b/sendlib.c @@ -1624,6 +1624,13 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, mutt_write_mime_header (attach, fp); } + if (env->in_reply_to) + { + fputs ("In-Reply-To:", fp); + write_references (env->in_reply_to, fp); + fputc ('\n', fp); + } + if (mode == 0 && !privacy && option (OPTXMAILER)) { /* Add a vanity header */ diff --git a/thread.c b/thread.c index f13f6cd4..1228af0f 100644 --- a/thread.c +++ b/thread.c @@ -1,8 +1,3 @@ -/* - * WORK IN PROGRESS ALERT: Daniel Eisenbud - * is currently working on this code. Contact him before working on it! - */ - /* * Copyright (C) 1996-2000 Michael R. Elkins * @@ -41,9 +36,8 @@ static int is_descendant (HEADER *a, HEADER *b) * to find the most recent message to which "cur" refers itself. */ -static HEADER *find_reference (HEADER *cur, CONTEXT *ctx) +static HEADER *find_ref (LIST *refs, HEADER *cur, CONTEXT *ctx) { - LIST *refs = cur->env->references; HEADER *ptr; for (; refs; refs = refs->next) @@ -51,7 +45,7 @@ static HEADER *find_reference (HEADER *cur, CONTEXT *ctx) /* ups, this message is in a reference loop. bad. */ if (cur->env->message_id && !strcmp (cur->env->message_id, refs->data)) continue; - + if ((ptr = hash_find (ctx->id_hash, refs->data))) { if (is_descendant (ptr, cur)) @@ -64,6 +58,24 @@ static HEADER *find_reference (HEADER *cur, CONTEXT *ctx) return NULL; } +/* + * In-Reply-To contains the direct parents according to RFC 2822. + * References is second best, since it may contain indirect parents, + * too. + */ + +static HEADER *find_reference (HEADER *cur, CONTEXT *ctx) +{ + HEADER *ptr; + + if ((ptr = find_ref (cur->env->in_reply_to, cur, ctx))) + return ptr; + if ((ptr = find_ref (cur->env->references, cur, ctx))) + return ptr; + + return NULL; +} + /* Determines whether to display a message's subject. */ static int need_display_subject (CONTEXT *ctx, HEADER *tree) { @@ -465,15 +477,26 @@ static HEADER *sort_last (HEADER *top) return top; } +static int matches_in_reply_to (HEADER *t, const char *p) +{ + LIST *irt; + + for (irt = t->env->in_reply_to; irt; irt = irt->next) + if (mutt_strcmp (irt->data, p) == 0) + return 1; + + return 0; +} + static void move_descendants (HEADER **tree, HEADER *cur, sort_t *usefunc) { HEADER *ptr, *tmp = *tree; while (tmp) { - /* only need to look at the last reference */ - if (tmp->env->references && - mutt_strcmp (tmp->env->references->data, cur->env->message_id) == 0) + /* Look at the entire in-reply-to header, and at the last (!) reference. */ + if (matches_in_reply_to (tmp, cur->env->message_id) || + (tmp->env->references && mutt_strcmp (tmp->env->references->data, cur->env->message_id) == 0)) { /* remove message from current location */ unlink_message (tree, tmp); diff --git a/url.c b/url.c index 5eb552b0..d28a25b3 100644 --- a/url.c +++ b/url.c @@ -236,7 +236,7 @@ int url_parse_mailto (ENVELOPE *e, char **body, const char *src) scratch[taglen] = '\0'; value = &scratch[taglen+1]; SKIPWS (value); - mutt_parse_rfc822_line (e, NULL, scratch, value, 1, 0, 0, &last, NULL); + mutt_parse_rfc822_line (e, NULL, scratch, value, 1, 0, 0, &last); } }