Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / d0 / 633423dbcb1652618c6015f507875e7d5f12a6
1 Return-Path: <hohndel@gr8dns.org>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 9FFA5431FC1\r
6         for <notmuch@notmuchmail.org>; Fri, 16 Apr 2010 13:52:02 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -1.9\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5\r
12         tests=[BAYES_00=-1.9] autolearn=ham\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id WemCDZ5ZSTyw for <notmuch@notmuchmail.org>;\r
16         Fri, 16 Apr 2010 13:52:00 -0700 (PDT)\r
17 Received: from mail.hohndel.org (mail.hohndel.org [65.23.157.147])\r
18         by olra.theworths.org (Postfix) with ESMTP id 501724196F4\r
19         for <notmuch@notmuchmail.org>; Fri, 16 Apr 2010 13:51:57 -0700 (PDT)\r
20 Received: by mail.hohndel.org (Postfix, from userid 112)\r
21         id 0DAC0340FC; Fri, 16 Apr 2010 16:51:57 -0400 (EDT)\r
22 Received: from x200.gr8dns.org (unknown [65.23.157.147])\r
23         by mail.hohndel.org (Postfix) with ESMTP id 1E634340FA;\r
24         Fri, 16 Apr 2010 16:51:53 -0400 (EDT)\r
25 Received: by x200.gr8dns.org (Postfix, from userid 500)\r
26         id B8CD3C0162; Fri, 16 Apr 2010 13:51:52 -0700 (PDT)\r
27 From: Dirk Hohndel <hohndel@infradead.org>\r
28 To: <notmuch@notmuchmail.org>\r
29 Subject: [PATCH 1/2] Add interface to obtain the concatenation of all\r
30         instances of a specified header\r
31 Date: Fri, 16 Apr 2010 13:51:41 -0700\r
32 Message-Id: <1271451102-11336-2-git-send-email-hohndel@infradead.org>\r
33 X-Mailer: git-send-email 1.6.6.1\r
34 In-Reply-To: <1271451102-11336-1-git-send-email-hohndel@infradead.org>\r
35 References: <1271451102-11336-1-git-send-email-hohndel@infradead.org>\r
36 X-BeenThere: notmuch@notmuchmail.org\r
37 X-Mailman-Version: 2.1.13\r
38 Precedence: list\r
39 List-Id: "Use and development of the notmuch mail system."\r
40         <notmuch.notmuchmail.org>\r
41 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
42         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
43 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
44 List-Post: <mailto:notmuch@notmuchmail.org>\r
45 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
46 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
47         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
48 X-List-Received-Date: Fri, 16 Apr 2010 20:52:02 -0000\r
49 \r
50 notmuch_message_get_header only returns the first instance of the specified\r
51 header in a message.\r
52 notmuch_message_get_concat_header concatenates the values from ALL instances\r
53 of that header in a message. This is useful for example to get the full\r
54 delivery path as captured in all of the Received: headers.\r
55 \r
56 Signed-off-by: Dirk Hohndel <hohndel@infradead.org>\r
57 ---\r
58  lib/database.cc       |   14 +++++++-------\r
59  lib/message-file.c    |   49 +++++++++++++++++++++++++++++++++++--------------\r
60  lib/message.cc        |   12 +++++++++++-\r
61  lib/notmuch-private.h |    2 +-\r
62  lib/notmuch.h         |   16 ++++++++++++++++\r
63  5 files changed, 70 insertions(+), 23 deletions(-)\r
64 \r
65 diff --git a/lib/database.cc b/lib/database.cc\r
66 index 6842faf..d706263 100644\r
67 --- a/lib/database.cc\r
68 +++ b/lib/database.cc\r
69 @@ -1289,11 +1289,11 @@ _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch,\r
70      parents = g_hash_table_new_full (g_str_hash, g_str_equal,\r
71                                      _my_talloc_free_for_g_hash, NULL);\r
72  \r
73 -    refs = notmuch_message_file_get_header (message_file, "references");\r
74 +    refs = notmuch_message_file_get_header (message_file, "references", 0);\r
75      parse_references (message, notmuch_message_get_message_id (message),\r
76                       parents, refs);\r
77  \r
78 -    in_reply_to = notmuch_message_file_get_header (message_file, "in-reply-to");\r
79 +    in_reply_to = notmuch_message_file_get_header (message_file, "in-reply-to", 0);\r
80      parse_references (message, notmuch_message_get_message_id (message),\r
81                       parents, in_reply_to);\r
82  \r
83 @@ -1506,9 +1506,9 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
84          * let's make sure that what we're looking at looks like an\r
85          * actual email message.\r
86          */\r
87 -       from = notmuch_message_file_get_header (message_file, "from");\r
88 -       subject = notmuch_message_file_get_header (message_file, "subject");\r
89 -       to = notmuch_message_file_get_header (message_file, "to");\r
90 +       from = notmuch_message_file_get_header (message_file, "from", 0);\r
91 +       subject = notmuch_message_file_get_header (message_file, "subject", 0);\r
92 +       to = notmuch_message_file_get_header (message_file, "to", 0);\r
93  \r
94         if ((from == NULL || *from == '\0') &&\r
95             (subject == NULL || *subject == '\0') &&\r
96 @@ -1521,7 +1521,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
97         /* Now that we're sure it's mail, the first order of business\r
98          * is to find a message ID (or else create one ourselves). */\r
99  \r
100 -       header = notmuch_message_file_get_header (message_file, "message-id");\r
101 +       header = notmuch_message_file_get_header (message_file, "message-id", 0);\r
102         if (header && *header != '\0') {\r
103             message_id = _parse_message_id (message_file, header, NULL);\r
104  \r
105 @@ -1580,7 +1580,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
106             if (ret)\r
107                 goto DONE;\r
108  \r
109 -           date = notmuch_message_file_get_header (message_file, "date");\r
110 +           date = notmuch_message_file_get_header (message_file, "date", 0);\r
111             _notmuch_message_set_date (message, date);\r
112  \r
113             _notmuch_message_index_file (message, filename);\r
114 diff --git a/lib/message-file.c b/lib/message-file.c\r
115 index 0c152a3..a01adbb 100644\r
116 --- a/lib/message-file.c\r
117 +++ b/lib/message-file.c\r
118 @@ -209,15 +209,21 @@ copy_header_unfolding (header_value_closure_t *value,\r
119  \r
120  /* As a special-case, a value of NULL for header_desired will force\r
121   * the entire header to be parsed if it is not parsed already. This is\r
122 - * used by the _notmuch_message_file_get_headers_end function. */\r
123 + * used by the _notmuch_message_file_get_headers_end function. \r
124 + * If concat is 'true' then it parses the whole message and\r
125 + * concatenates all instances of the header in question. This is\r
126 + * currently used to get a complete Received: header when analyzing\r
127 + * the path the mail has taken from sender to recipient.\r
128 + */\r
129  const char *\r
130  notmuch_message_file_get_header (notmuch_message_file_t *message,\r
131 -                                const char *header_desired)\r
132 +                                const char *header_desired,\r
133 +                                int concat)\r
134  {\r
135      int contains;\r
136 -    char *header, *decoded_value;\r
137 +    char *header, *decoded_value, *header_sofar, *combined_header;\r
138      const char *s, *colon;\r
139 -    int match;\r
140 +    int match, newhdr, hdrsofar;\r
141      static int initialized = 0;\r
142  \r
143      if (! initialized) {\r
144 @@ -227,7 +233,7 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,\r
145  \r
146      message->parsing_started = 1;\r
147  \r
148 -    if (header_desired == NULL)\r
149 +    if (concat || header_desired == NULL) \r
150         contains = 0;\r
151      else\r
152         contains = g_hash_table_lookup_extended (message->headers,\r
153 @@ -237,6 +243,9 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,\r
154      if (contains && decoded_value)\r
155         return decoded_value;\r
156  \r
157 +    if (concat)\r
158 +       message->parsing_finished = 0;\r
159 +\r
160      if (message->parsing_finished)\r
161         return "";\r
162  \r
163 @@ -312,20 +321,32 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,\r
164  \r
165         NEXT_HEADER_LINE (&message->value);\r
166  \r
167 -       if (header_desired == 0)\r
168 +       if (concat || header_desired == NULL)\r
169             match = 0;\r
170         else\r
171             match = (strcasecmp (header, header_desired) == 0);\r
172  \r
173         decoded_value = g_mime_utils_header_decode_text (message->value.str);\r
174 -       if (g_hash_table_lookup (message->headers, header) == NULL) {\r
175 -           /* Only insert if we don't have a value for this header, yet.\r
176 -            * This way we always return the FIRST instance of any header\r
177 -            * we search for\r
178 -            * FIXME: we should be returning ALL instances of a header\r
179 -            *        or at least provide a way to iterate over them\r
180 -            */\r
181 -           g_hash_table_insert (message->headers, header, decoded_value);\r
182 +       header_sofar = (char *)g_hash_table_lookup (message->headers, header);\r
183 +       if (concat) {\r
184 +           if (header_sofar == NULL) {\r
185 +               /* Only insert if we don't have a value for this header, yet. */\r
186 +               g_hash_table_insert (message->headers, header, decoded_value);\r
187 +           } else {\r
188 +               /* the caller wants them all concatenated */\r
189 +               newhdr = strlen(decoded_value);\r
190 +               hdrsofar = strlen(header_sofar);\r
191 +               combined_header = xmalloc(hdrsofar + newhdr + 2);\r
192 +               strncpy(combined_header,header_sofar,hdrsofar);\r
193 +               *(combined_header+hdrsofar) = ' ';\r
194 +               strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);\r
195 +               g_hash_table_insert (message->headers, header, combined_header);\r
196 +           }\r
197 +       } else {\r
198 +           if (header_sofar == NULL) {\r
199 +               /* Only insert if we don't have a value for this header, yet. */\r
200 +               g_hash_table_insert (message->headers, header, decoded_value);\r
201 +           }\r
202         }\r
203         if (match)\r
204             return decoded_value;\r
205 diff --git a/lib/message.cc b/lib/message.cc\r
206 index 721c9a6..fb8fe95 100644\r
207 --- a/lib/message.cc\r
208 +++ b/lib/message.cc\r
209 @@ -264,7 +264,17 @@ notmuch_message_get_header (notmuch_message_t *message, const char *header)\r
210      if (message->message_file == NULL)\r
211         return NULL;\r
212  \r
213 -    return notmuch_message_file_get_header (message->message_file, header);\r
214 +    return notmuch_message_file_get_header (message->message_file, header, 0);\r
215 +}\r
216 +\r
217 +const char *\r
218 +notmuch_message_get_concat_header (notmuch_message_t *message, const char *header)\r
219 +{\r
220 +    _notmuch_message_ensure_message_file (message);\r
221 +    if (message->message_file == NULL)\r
222 +       return NULL;\r
223 +\r
224 +    return notmuch_message_file_get_header (message->message_file, header, 1);\r
225  }\r
226  \r
227  /* Return the message ID from the In-Reply-To header of 'message'.\r
228 diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
229 index d52d84d..9f8a10a 100644\r
230 --- a/lib/notmuch-private.h\r
231 +++ b/lib/notmuch-private.h\r
232 @@ -342,7 +342,7 @@ notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,\r
233   */\r
234  const char *\r
235  notmuch_message_file_get_header (notmuch_message_file_t *message,\r
236 -                                const char *header);\r
237 +                                const char *header, int concat);\r
238  \r
239  /* messages.c */\r
240  \r
241 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
242 index a7e66dd..d77eb5c 100644\r
243 --- a/lib/notmuch.h\r
244 +++ b/lib/notmuch.h\r
245 @@ -787,6 +787,22 @@ notmuch_message_get_date  (notmuch_message_t *message);\r
246  const char *\r
247  notmuch_message_get_header (notmuch_message_t *message, const char *header);\r
248  \r
249 +/* Get the concatenated value of all instances of the specified header\r
250 + * from 'message'.\r
251 + *\r
252 + * The value will be read from the actual message file, not from the\r
253 + * notmuch database. The header name is case insensitive.\r
254 + *\r
255 + * The returned string belongs to the message so should not be\r
256 + * modified or freed by the caller (nor should it be referenced after\r
257 + * the message is destroyed).\r
258 + *\r
259 + * Returns an empty string ("") if the message does not contain a\r
260 + * header line matching 'header'. Returns NULL if any error occurs.\r
261 + */\r
262 +const char *\r
263 +notmuch_message_get_concat_header (notmuch_message_t *message, const char *header);\r
264 +\r
265  /* Get the tags for 'message', returning a notmuch_tags_t object which\r
266   * can be used to iterate over all tags.\r
267   *\r
268 -- \r
269 1.6.6.1\r
270 \r