database error
[notmuch-archives.git] / e6 / ee2a6b936ecd4b6c768e65acd09341456b367c
1 Return-Path: <amthrax@drake.mit.edu>\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 C8D81429E3F\r
6         for <notmuch@notmuchmail.org>; Fri, 23 Dec 2011 19:46:08 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\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 BP65cdge-J1E for <notmuch@notmuchmail.org>;\r
16         Fri, 23 Dec 2011 19:46:07 -0800 (PST)\r
17 Received: from dmz-mailsec-scanner-2.mit.edu (DMZ-MAILSEC-SCANNER-2.MIT.EDU\r
18         [18.9.25.13])\r
19         by olra.theworths.org (Postfix) with ESMTP id A3974429E30\r
20         for <notmuch@notmuchmail.org>; Fri, 23 Dec 2011 19:46:07 -0800 (PST)\r
21 X-AuditID: 1209190d-b7f576d0000008c4-98-4ef54aff5c29\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         by dmz-mailsec-scanner-2.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id 07.33.02244.FFA45FE4; Fri, 23 Dec 2011 22:46:07 -0500 (EST)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id pBO3k7Wk024227; \r
27         Fri, 23 Dec 2011 22:46:07 -0500\r
28 Received: from drake.mit.edu (c-76-21-105-205.hsd1.ca.comcast.net\r
29         [76.21.105.205]) (authenticated bits=0)\r
30         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
31         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id pBO3k4UY017821\r
32         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
33         Fri, 23 Dec 2011 22:46:06 -0500 (EST)\r
34 Received: from amthrax by drake.mit.edu with local (Exim 4.77)\r
35         (envelope-from <amthrax@drake.mit.edu>)\r
36         id 1ReIYe-0007IR-MD; Fri, 23 Dec 2011 22:46:04 -0500\r
37 From: Austin Clements <amdragon@MIT.EDU>\r
38 To: notmuch@notmuchmail.org\r
39 Subject: [PATCH v4 4/4] show: Rewrite show_message_body to use the MIME tree\r
40         interface.\r
41 Date: Fri, 23 Dec 2011 22:45:48 -0500\r
42 Message-Id: <1324698348-27620-5-git-send-email-amdragon@mit.edu>\r
43 X-Mailer: git-send-email 1.7.7.3\r
44 In-Reply-To: <1324698348-27620-1-git-send-email-amdragon@mit.edu>\r
45 References: <1323460468-4030-1-git-send-email-amdragon@mit.edu>\r
46         <1324698348-27620-1-git-send-email-amdragon@mit.edu>\r
47 X-Brightmail-Tracker:\r
48  H4sIAAAAAAAAA+NgFtrIIsWRmVeSWpSXmKPExsUixCmqrfvf66ufwZO1XBbXb85kdmD0eLbq\r
49         FnMAYxSXTUpqTmZZapG+XQJXxvmTH9gK7vlUzNj7ibWBcb9NFyMnh4SAicTck4uYIGwxiQv3\r
50         1rN1MXJxCAnsY5R4OvUrO4SzgVFi1cNrUJlzTBLb7s5ghHDmM0pcnvWfBaSfTUBDYtv+5Ywg\r
51         toiAtMTOu7NZuxg5OJgF1CT+dKmAmMIC4RIb95qCVLAIqEosaNgDtplXwEHi8M+3zBBXKEic\r
52         W32OHcTmFHCU2Lr1PSNIq5BAmUTzmaAJjPwLGBlWMcqm5Fbp5iZm5hSnJusWJyfm5aUW6Rrp\r
53         5WaW6KWmlG5iBIeMJO8OxncHlQ4xCnAwKvHwNi794ifEmlhWXJl7iFGSg0lJlPeq21c/Ib6k\r
54         /JTKjMTijPii0pzU4kOMEhzMSiK8mklA5bwpiZVVqUX5MClpDhYlcV5VrXd+QgLpiSWp2amp\r
55         BalFMFkZDg4lCd7pwNgQEixKTU+tSMvMKUFIM3FwggznARreDFLDW1yQmFucmQ6RP8WoKCXO\r
56         mwWSEABJZJTmwfXCYvoVozjQK8K8PSBVPMB0ANf9CmgwE9DgGCOQq4tLEhFSUg2MBwJPW7m3\r
57         nO3tn7jC34lxgu0XbY9/XcyHJCuvCsX8fNcpcWdqRxxXZJTinZcXMw6+es7dzqm5NH7p8Qfs\r
58         IWo6ex8o+mWIns7vmPB90fQTKx/nfLau0qntXeySLpq/paYnlu2kuWGN0erF/Hl/fpTwcYqX\r
59         rtj9IGjSh1mS6qs8dI6vub31cbaYEktxRqKhFnNRcSIAxqUWm8QCAAA=\r
60 X-BeenThere: notmuch@notmuchmail.org\r
61 X-Mailman-Version: 2.1.13\r
62 Precedence: list\r
63 List-Id: "Use and development of the notmuch mail system."\r
64         <notmuch.notmuchmail.org>\r
65 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
66         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
67 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
68 List-Post: <mailto:notmuch@notmuchmail.org>\r
69 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
70 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
71         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
72 X-List-Received-Date: Sat, 24 Dec 2011 03:46:09 -0000\r
73 \r
74 This removes all of the MIME traversal logic from show_message_body\r
75 and leaves only its interaction with the format callbacks.\r
76 \r
77 Besides isolating concerns, since traversal happens behind a trivial\r
78 interface, there is now much less code duplication in\r
79 show_message_part.  Also, this uses mime_node_seek_dfs to start at the\r
80 requested part, eliminating all of the logic about parts being\r
81 selected or being in_zone (and reducing the "show state" to only a\r
82 part counter).  notmuch_show_params_t no longer needs to be passed\r
83 through the recursion because the only two fields that mattered\r
84 (related to crypto) are now handled by the MIME tree.\r
85 \r
86 The few remaining complexities in show_message_part highlight\r
87 irregularities in the format callbacks with respect to top-level\r
88 messages and embedded message parts.\r
89 \r
90 Since this is a rewrite, the diff is not very enlightening.  It's\r
91 easier to look at the old code and the new code side-by-side.\r
92 ---\r
93  show-message.c |  229 +++++++++++++-------------------------------------------\r
94  1 files changed, 52 insertions(+), 177 deletions(-)\r
95 \r
96 diff --git a/show-message.c b/show-message.c\r
97 index 09fa607..d02e744 100644\r
98 --- a/show-message.c\r
99 +++ b/show-message.c\r
100 @@ -24,154 +24,54 @@\r
101  \r
102  typedef struct show_message_state {\r
103      int part_count;\r
104 -    int in_zone;\r
105  } show_message_state_t;\r
106  \r
107  static void\r
108 -show_message_part (GMimeObject *part,\r
109 +show_message_part (mime_node_t *node,\r
110                    show_message_state_t *state,\r
111                    const notmuch_show_format_t *format,\r
112 -                  notmuch_show_params_t *params,\r
113                    int first)\r
114  {\r
115 -    GMimeObject *decryptedpart = NULL;\r
116 -    int selected;\r
117 +    /* Formatters expect the envelope for embedded message parts */\r
118 +    GMimeObject *part = node->envelope_part ?\r
119 +       GMIME_OBJECT (node->envelope_part) : node->part;\r
120 +    int i;\r
121 +\r
122 +    if (!first)\r
123 +       fputs (format->part_sep, stdout);\r
124 +\r
125 +    /* Format this part */\r
126 +    if (format->part_start)\r
127 +       format->part_start (part, &(state->part_count));\r
128 +\r
129 +    if (node->decrypt_attempted && format->part_encstatus)\r
130 +       format->part_encstatus (node->decrypt_success);\r
131 +\r
132 +    if (node->sig_attempted && format->part_sigstatus)\r
133 +       format->part_sigstatus (node->sig_validity);\r
134 +\r
135 +    format->part_content (part);\r
136 +\r
137 +    if (node->envelope_part) {\r
138 +       fputs (format->header_start, stdout);\r
139 +       if (format->header_message_part)\r
140 +           format->header_message_part (GMIME_MESSAGE (node->part));\r
141 +       fputs (format->header_end, stdout);\r
142 +\r
143 +       fputs (format->body_start, stdout);\r
144 +    }\r
145 +\r
146 +    /* Recurse over the children */\r
147      state->part_count += 1;\r
148 +    for (i = 0; i < node->nchildren; i++)\r
149 +       show_message_part (mime_node_child (node, i), state, format, i == 0);\r
150  \r
151 -    if (! (GMIME_IS_PART (part) || GMIME_IS_MULTIPART (part) || GMIME_IS_MESSAGE_PART (part))) {\r
152 -       fprintf (stderr, "Warning: Not displaying unknown mime part: %s.\n",\r
153 -                g_type_name (G_OBJECT_TYPE (part)));\r
154 -       return;\r
155 -    }\r
156 +    /* Finish this part */\r
157 +    if (node->envelope_part)\r
158 +       fputs (format->body_end, stdout);\r
159  \r
160 -    selected = (params->part <= 0 || state->part_count == params->part);\r
161 -\r
162 -    if (selected || state->in_zone) {\r
163 -       if (!first && (params->part <= 0 || state->in_zone))\r
164 -           fputs (format->part_sep, stdout);\r
165 -\r
166 -       if (format->part_start)\r
167 -           format->part_start (part, &(state->part_count));\r
168 -    }\r
169 -\r
170 -    /* handle PGP/MIME parts */\r
171 -    if (GMIME_IS_MULTIPART (part) && params->cryptoctx) {\r
172 -       GMimeMultipart *multipart = GMIME_MULTIPART (part);\r
173 -       GError* err = NULL;\r
174 -\r
175 -       if (GMIME_IS_MULTIPART_ENCRYPTED (part) && params->decrypt)\r
176 -       {\r
177 -           if ( g_mime_multipart_get_count (multipart) != 2 ) {\r
178 -               /* this violates RFC 3156 section 4, so we won't bother with it. */\r
179 -               fprintf (stderr,\r
180 -                        "Error: %d part(s) for a multipart/encrypted message (should be exactly 2)\n",\r
181 -                        g_mime_multipart_get_count (multipart));\r
182 -           } else {\r
183 -               GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part);\r
184 -               decryptedpart = g_mime_multipart_encrypted_decrypt (encrypteddata, params->cryptoctx, &err);\r
185 -               if (decryptedpart) {\r
186 -                   if ((selected || state->in_zone) && format->part_encstatus)\r
187 -                       format->part_encstatus (1);\r
188 -                   const GMimeSignatureValidity *sigvalidity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata);\r
189 -                   if (!sigvalidity)\r
190 -                       fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given"));\r
191 -                   if ((selected || state->in_zone) && format->part_sigstatus)\r
192 -                       format->part_sigstatus (sigvalidity);\r
193 -               } else {\r
194 -                   fprintf (stderr, "Failed to decrypt part: %s\n", (err ? err->message : "no error explanation given"));\r
195 -                   if ((selected || state->in_zone) && format->part_encstatus)\r
196 -                       format->part_encstatus (0);\r
197 -               }\r
198 -           }\r
199 -       }\r
200 -       else if (GMIME_IS_MULTIPART_SIGNED (part))\r
201 -       {\r
202 -           if ( g_mime_multipart_get_count (multipart) != 2 ) {\r
203 -               /* this violates RFC 3156 section 5, so we won't bother with it. */\r
204 -               fprintf (stderr,\r
205 -                        "Error: %d part(s) for a multipart/signed message (should be exactly 2)\n",\r
206 -                        g_mime_multipart_get_count (multipart));\r
207 -           } else {\r
208 -               /* For some reason the GMimeSignatureValidity returned\r
209 -                * here is not a const (inconsistent with that\r
210 -                * returned by\r
211 -                * g_mime_multipart_encrypted_get_signature_validity,\r
212 -                * and therefore needs to be properly disposed of.\r
213 -                * Hopefully the API will become more consistent. */\r
214 -               GMimeSignatureValidity *sigvalidity = g_mime_multipart_signed_verify (GMIME_MULTIPART_SIGNED (part), params->cryptoctx, &err);\r
215 -               if (!sigvalidity) {\r
216 -                   fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given"));\r
217 -               }\r
218 -               if ((selected || state->in_zone) && format->part_sigstatus)\r
219 -                   format->part_sigstatus (sigvalidity);\r
220 -               if (sigvalidity)\r
221 -                   g_mime_signature_validity_free (sigvalidity);\r
222 -           }\r
223 -       }\r
224 -\r
225 -       if (err)\r
226 -           g_error_free (err);\r
227 -    }\r
228 -    /* end handle PGP/MIME parts */\r
229 -\r
230 -    if (selected || state->in_zone)\r
231 -       format->part_content (part);\r
232 -\r
233 -    if (GMIME_IS_MULTIPART (part)) {\r
234 -       GMimeMultipart *multipart = GMIME_MULTIPART (part);\r
235 -       int i;\r
236 -\r
237 -       if (selected)\r
238 -           state->in_zone = 1;\r
239 -\r
240 -       if (decryptedpart) {\r
241 -           /* We emit the useless application/pgp-encrypted version\r
242 -            * part here only to keep the emitted output as consistent\r
243 -            * as possible between decrypted output and the\r
244 -            * unprocessed multipart/mime. For some strange reason,\r
245 -            * the actual encrypted data is the second part of the\r
246 -            * multipart. */\r
247 -           show_message_part (g_mime_multipart_get_part (multipart, 0), state, format, params, TRUE);\r
248 -           show_message_part (decryptedpart, state, format, params, FALSE);\r
249 -       } else {\r
250 -           for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {\r
251 -               show_message_part (g_mime_multipart_get_part (multipart, i),\r
252 -                                  state, format, params, i == 0);\r
253 -           }\r
254 -       }\r
255 -\r
256 -       if (selected)\r
257 -           state->in_zone = 0;\r
258 -\r
259 -    } else if (GMIME_IS_MESSAGE_PART (part)) {\r
260 -       GMimeMessage *mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));\r
261 -\r
262 -       if (selected)\r
263 -           state->in_zone = 1;\r
264 -\r
265 -       if (selected || (!selected && state->in_zone)) {\r
266 -           fputs (format->header_start, stdout);\r
267 -           if (format->header_message_part)\r
268 -               format->header_message_part (mime_message);\r
269 -           fputs (format->header_end, stdout);\r
270 -\r
271 -           fputs (format->body_start, stdout);\r
272 -       }\r
273 -\r
274 -       show_message_part (g_mime_message_get_mime_part (mime_message),\r
275 -                          state, format, params, TRUE);\r
276 -\r
277 -       if (selected || (!selected && state->in_zone))\r
278 -           fputs (format->body_end, stdout);\r
279 -\r
280 -       if (selected)\r
281 -           state->in_zone = 0;\r
282 -    }\r
283 -\r
284 -    if (selected || state->in_zone) {\r
285 -       if (format->part_end)\r
286 -           format->part_end (part);\r
287 -    }\r
288 +    if (format->part_end)\r
289 +       format->part_end (part);\r
290  }\r
291  \r
292  notmuch_status_t\r
293 @@ -179,49 +79,24 @@ show_message_body (notmuch_message_t *message,\r
294                    const notmuch_show_format_t *format,\r
295                    notmuch_show_params_t *params)\r
296  {\r
297 -    GMimeStream *stream = NULL;\r
298 -    GMimeParser *parser = NULL;\r
299 -    GMimeMessage *mime_message = NULL;\r
300 -    notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
301 -    const char *filename = notmuch_message_get_filename (message);\r
302 -    FILE *file = NULL;\r
303 +    notmuch_status_t ret;\r
304      show_message_state_t state;\r
305 +    mime_node_t *root, *part;\r
306  \r
307 -    state.part_count = 0;\r
308 -    state.in_zone = 0;\r
309 +    ret = mime_node_open (NULL, message, params->cryptoctx, params->decrypt,\r
310 +                         &root);\r
311 +    if (ret)\r
312 +       return ret;\r
313  \r
314 -    file = fopen (filename, "r");\r
315 -    if (! file) {\r
316 -       fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));\r
317 -       ret = NOTMUCH_STATUS_FILE_ERROR;\r
318 -       goto DONE;\r
319 -    }\r
320 +    /* The caller of show_message_body has already handled the\r
321 +     * outermost envelope, so skip it. */\r
322 +    state.part_count = MAX (params->part, 1);\r
323  \r
324 -    stream = g_mime_stream_file_new (file);\r
325 -    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);\r
326 +    part = mime_node_seek_dfs (root, state.part_count);\r
327 +    if (part)\r
328 +       show_message_part (part, &state, format, TRUE);\r
329  \r
330 -    parser = g_mime_parser_new_with_stream (stream);\r
331 +    talloc_free (root);\r
332  \r
333 -    mime_message = g_mime_parser_construct_message (parser);\r
334 -\r
335 -    show_message_part (g_mime_message_get_mime_part (mime_message),\r
336 -                      &state,\r
337 -                      format,\r
338 -                      params,\r
339 -                      TRUE);\r
340 -\r
341 -  DONE:\r
342 -    if (mime_message)\r
343 -       g_object_unref (mime_message);\r
344 -\r
345 -    if (parser)\r
346 -       g_object_unref (parser);\r
347 -\r
348 -    if (stream)\r
349 -       g_object_unref (stream);\r
350 -\r
351 -    if (file)\r
352 -       fclose (file);\r
353 -\r
354 -    return ret;\r
355 +    return NOTMUCH_STATUS_SUCCESS;\r
356  }\r
357 -- \r
358 1.7.7.3\r
359 \r