Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / d0 / fad9d10496096542756b3dfcfd2db0f5e9e004
1 Return-Path: <amdragon@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 7773A429E3B\r
6         for <notmuch@notmuchmail.org>; Mon, 16 Jan 2012 19:47:28 -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 gK9ZU-KeuhpI for <notmuch@notmuchmail.org>;\r
16         Mon, 16 Jan 2012 19:47:27 -0800 (PST)\r
17 Received: from dmz-mailsec-scanner-5.mit.edu (DMZ-MAILSEC-SCANNER-5.MIT.EDU\r
18         [18.7.68.34])\r
19         by olra.theworths.org (Postfix) with ESMTP id EC37B429E35\r
20         for <notmuch@notmuchmail.org>; Mon, 16 Jan 2012 19:47:26 -0800 (PST)\r
21 X-AuditID: 12074422-b7fd66d0000008f9-9a-4f14ef4e02aa\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         by dmz-mailsec-scanner-5.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id 1C.76.02297.E4FE41F4; Mon, 16 Jan 2012 22:47:26 -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 q0H3lPp9030664; \r
27         Mon, 16 Jan 2012 22:47:26 -0500\r
28 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
29         (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 q0H3lNoV017356\r
32         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
33         Mon, 16 Jan 2012 22:47:25 -0500 (EST)\r
34 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.77)\r
35         (envelope-from <amdragon@mit.edu>)\r
36         id 1Rn00w-0006Qw-Dq; Mon, 16 Jan 2012 22:47:14 -0500\r
37 Date: Mon, 16 Jan 2012 22:47:14 -0500\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: Thomas Jost <schnouki@schnouki.net>\r
40 Subject: Re: [PATCH] Add pseudo-compatibility with gmime 2.6\r
41 Message-ID: <20120117034714.GG16740@mit.edu>\r
42 References: <8762gbtd6p.fsf@schnouki.net>\r
43         <1326758199-18058-1-git-send-email-schnouki@schnouki.net>\r
44 MIME-Version: 1.0\r
45 Content-Type: text/plain; charset=us-ascii\r
46 Content-Disposition: inline\r
47 In-Reply-To: <1326758199-18058-1-git-send-email-schnouki@schnouki.net>\r
48 User-Agent: Mutt/1.5.21 (2010-09-15)\r
49 X-Brightmail-Tracker:\r
50  H4sIAAAAAAAAA+NgFmpmleLIzCtJLcpLzFFi42IR4hTV1vV7L+Jv0DBJ1uL6zZnMFvv6/R2Y\r
51         PJ6tusXsMWXWXPYApigum5TUnMyy1CJ9uwSujE33d7MX9NRXfPh6lK2BsSOli5GTQ0LARKL1\r
52         0kdWCFtM4sK99WxdjFwcQgL7GCUuXP/JDuFsYJTYPvk+VOYkk8Su13NZIZwljBK/J+xkBuln\r
53         EVCVePL3PBuIzSagIbFt/3JGEFtEQF2iYf5usDizgLTEt9/NTCC2sICNxLEZT8B28wroSJz6\r
54         /Q+sRkggVeL6k28sEHFBiZMzn7BA9GpJ3Pj3EqiXA2zO8n8cIGFOATeJBU+2g60SFVCRmHJy\r
55         G9sERqFZSLpnIemehdC9gJF5FaNsSm6Vbm5iZk5xarJucXJiXl5qka6pXm5miV5qSukmRlBY\r
56         s7so7WD8eVDpEKMAB6MSD+9NbxF/IdbEsuLK3EOMkhxMSqK8U14DhfiS8lMqMxKLM+KLSnNS\r
57         iw8xSnAwK4nwCvoA5XhTEiurUovyYVLSHCxK4rzqWu/8hATSE0tSs1NTC1KLYLIyHBxKErx3\r
58         3gE1ChalpqdWpGXmlCCkmTg4QYbzAA2PB6nhLS5IzC3OTIfIn2JUlBLnfQOSEABJZJTmwfXC\r
59         0s4rRnGgV4R5E0GqeIApC677FdBgJqDBOa1CIINLEhFSUg2MBjz2cjeYfTZuLE9Zs7Fd6HiR\r
60         7fx+VTmT2QGXl78XC/yqGHUp9cGsV8t3PdPrbjpzZ56dRVnGB+lTTGccmjLU9spHZKUIfJWr\r
61         yW5bf6Lnac9p5WXH5ab5/GlIXm6Vd/6T05OIN1NkjvT22GTNPKOzwOihn4eD/2PbAw8k9r6/\r
62         6Fe2T2wz5x8uJZbijERDLeai4kQAJq1maBYDAAA=\r
63 Cc: notmuch@notmuchmail.org\r
64 X-BeenThere: notmuch@notmuchmail.org\r
65 X-Mailman-Version: 2.1.13\r
66 Precedence: list\r
67 List-Id: "Use and development of the notmuch mail system."\r
68         <notmuch.notmuchmail.org>\r
69 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
70         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
71 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
72 List-Post: <mailto:notmuch@notmuchmail.org>\r
73 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
74 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
75         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
76 X-List-Received-Date: Tue, 17 Jan 2012 03:47:28 -0000\r
77 \r
78 Quoth Thomas Jost on Jan 17 at 12:56 am:\r
79 > There are lots of API changes in gmime 2.6 crypto handling. By adding\r
80 > preprocessor directives, it is however possible to add gmime 2.6 compatibility\r
81 > while preserving compatibility with gmime 2.4 too.\r
82 \r
83 Awesome.  Comments inline below.\r
84 \r
85 > This is mostly based on id:"8762i8hrb9.fsf@bookbinder.fernseed.info".\r
86\r
87 > This was tested against both gmime 2.6.4 and 2.4.31. With gmime 2.4.31, the\r
88 > crypto tests all work fine (as expected). With gmime 2.6.4, one crypto test\r
89 > fails (signature verification with signer key unavailable) but this will be hard\r
90 > to fix since the new API does not report the reason why a signature verification\r
91 > fails (other than the human-readable error message).\r
92 \r
93 What is the result of this failing test?\r
94 \r
95 > ---\r
96 >  mime-node.c      |   50 ++++++++++++++++++++++++++-\r
97 >  notmuch-client.h |   27 ++++++++++++++-\r
98 >  notmuch-reply.c  |    7 ++++\r
99 >  notmuch-show.c   |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
100 >  show-message.c   |    4 ++\r
101 >  5 files changed, 181 insertions(+), 4 deletions(-)\r
102\r
103 > diff --git a/mime-node.c b/mime-node.c\r
104 > index d26bb44..ae2473d 100644\r
105 > --- a/mime-node.c\r
106 > +++ b/mime-node.c\r
107 > @@ -33,7 +33,11 @@ typedef struct mime_node_context {\r
108 >      GMimeMessage *mime_message;\r
109 >  \r
110 >      /* Context provided by the caller. */\r
111 > +#ifdef GMIME_26\r
112 > +    GMimeCryptoContext *cryptoctx;\r
113 > +#else\r
114 >      GMimeCipherContext *cryptoctx;\r
115 > +#endif\r
116 >      notmuch_bool_t decrypt;\r
117 >  } mime_node_context_t;\r
118 >  \r
119 > @@ -57,8 +61,12 @@ _mime_node_context_free (mime_node_context_t *res)\r
120 >  \r
121 >  notmuch_status_t\r
122 >  mime_node_open (const void *ctx, notmuch_message_t *message,\r
123 > -             GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
124 > -             mime_node_t **root_out)\r
125 > +#ifdef GMIME_26\r
126 > +             GMimeCryptoContext *cryptoctx,\r
127 > +#else\r
128 > +             GMimeCipherContext *cryptoctx,\r
129 > +#endif\r
130 > +             notmuch_bool_t decrypt, mime_node_t **root_out)\r
131 >  {\r
132 >      const char *filename = notmuch_message_get_filename (message);\r
133 >      mime_node_context_t *mctx;\r
134 > @@ -112,12 +120,21 @@ DONE:\r
135 >      return status;\r
136 >  }\r
137 >  \r
138 > +#ifdef GMIME_26\r
139 > +static int\r
140 > +_signature_list_free (GMimeSignatureList **proxy)\r
141 > +{\r
142 > +    g_object_unref (*proxy);\r
143 > +    return 0;\r
144 > +}\r
145 > +#else\r
146 >  static int\r
147 >  _signature_validity_free (GMimeSignatureValidity **proxy)\r
148 >  {\r
149 >      g_mime_signature_validity_free (*proxy);\r
150 >      return 0;\r
151 >  }\r
152 > +#endif\r
153 >  \r
154 >  static mime_node_t *\r
155 >  _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
156 > @@ -165,11 +182,23 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
157 >           GMimeMultipartEncrypted *encrypteddata =\r
158 >               GMIME_MULTIPART_ENCRYPTED (part);\r
159 >           node->decrypt_attempted = TRUE;\r
160 > +#ifdef GMIME_26\r
161 > +         GMimeDecryptResult *decrypt_result = g_mime_decrypt_result_new ();\r
162 \r
163 I think g_mime_multipart_encrypted_decrypt allocates the\r
164 GMimeDecryptResult for you, so this will just leak memory.\r
165 \r
166 > +         node->decrypted_child = g_mime_multipart_encrypted_decrypt\r
167 > +             (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err);\r
168 > +         if (node->decrypted_child) {\r
169 > +             node->decrypt_success = node->verify_attempted = TRUE;\r
170 > +             node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result);\r
171 > +             if (!node->sig_list)\r
172 > +                 fprintf (stderr, "Failed to get signatures: %s\n",\r
173 > +                          (err ? err->message : "no error explanation given"));\r
174 \r
175 My understanding is that g_mime_decrypt_result_get_signatures returns\r
176 NULL if there are no signatures and that this isn't an error.  This\r
177 differs from 2.4, which would return an empty but non-NULL list.\r
178 \r
179 Also, I believe you have to free the sig_list in both branches now,\r
180 which means the talloc_set_destructor can be moved to common logic\r
181 outside of the if decrypted/signed.\r
182 \r
183 > +#else\r
184 >           node->decrypted_child = g_mime_multipart_encrypted_decrypt\r
185 >               (encrypteddata, node->ctx->cryptoctx, &err);\r
186 >           if (node->decrypted_child) {\r
187 >               node->decrypt_success = node->verify_attempted = TRUE;\r
188 >               node->sig_validity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata);\r
189 > +#endif\r
190 \r
191 It's confusing to have the open braces in the #ifdef'd region with a\r
192 matching close brace outside of it (and I imagine this confuses\r
193 editors and uncrustify, too).  You could either copy the else part in\r
194 both branches of the #ifdef or avoid duplicated code with something\r
195 like\r
196 \r
197 #ifdef GMIME_26\r
198   .. node->decrypted_child = ..\r
199 #else\r
200   .. node->decrypted_child = ..\r
201 #endif\r
202   if (node->decrypted_child) {\r
203     node->decrypt_success = node->verify_attempted = TRUE;\r
204 #ifdef GMIME_26\r
205     node->sig_list = ..\r
206 #else\r
207     node->sig_validity = ..\r
208 #endif\r
209   } else {\r
210     fprintf (stderr, ..);\r
211   }\r
212 \r
213 >           } else {\r
214 >               fprintf (stderr, "Failed to decrypt part: %s\n",\r
215 >                        (err ? err->message : "no error explanation given"));\r
216 > @@ -182,6 +211,18 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
217 >                    "(must be exactly 2)\n",\r
218 >                    node->nchildren);\r
219 >       } else {\r
220 > +#ifdef GMIME_26\r
221 > +         GMimeSignatureList *sig_list = g_mime_multipart_signed_verify\r
222 > +             (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err);\r
223 > +         node->verify_attempted = TRUE;\r
224 > +         node->sig_list = sig_list;\r
225 > +         if (sig_list) {\r
226 > +             GMimeSignatureList **proxy =\r
227 > +                 talloc (node, GMimeSignatureList *);\r
228 > +             *proxy = sig_list;\r
229 > +             talloc_set_destructor (proxy, _signature_list_free);\r
230 > +         }\r
231 > +#else\r
232 >           /* For some reason the GMimeSignatureValidity returned\r
233 >            * here is not a const (inconsistent with that\r
234 >            * returned by\r
235 > @@ -200,10 +241,15 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
236 >               *proxy = sig_validity;\r
237 >               talloc_set_destructor (proxy, _signature_validity_free);\r
238 >           }\r
239 > +#endif\r
240 >       }\r
241 >      }\r
242 >  \r
243 > +#ifdef GMIME_26\r
244 > +    if (node->verify_attempted && !node->sig_list)\r
245 \r
246 Hmm.  This is correct for signed parts, but will incorrectly trigger\r
247 for an encrypted part with no signatures.  For 2.6, I think this error\r
248 checking may have to move into the branches of the if encrypted/signed\r
249 since for encrypted parts you have to check if\r
250 g_mime_multipart_encrypted_decrypt returned NULL.\r
251 \r
252 > +#else\r
253 >      if (node->verify_attempted && !node->sig_validity)\r
254 > +#endif\r
255 >       fprintf (stderr, "Failed to verify signed part: %s\n",\r
256 >                (err ? err->message : "no error explanation given"));\r
257 >  \r
258 > diff --git a/notmuch-client.h b/notmuch-client.h\r
259 > index 517c010..e85f882 100644\r
260 > --- a/notmuch-client.h\r
261 > +++ b/notmuch-client.h\r
262 > @@ -30,6 +30,12 @@\r
263 >  \r
264 >  #include <gmime/gmime.h>\r
265 >  \r
266 > +/* GMIME_CHECK_VERSION is only available in gmime >= 2.5. But so are\r
267 > + * GMIME_MAJOR_VERSION and friends. */\r
268 \r
269 Hah.\r
270 \r
271 > +#ifdef GMIME_MAJOR_VERSION\r
272 > +#define GMIME_26\r
273 > +#endif\r
274 > +\r
275 >  #include "notmuch.h"\r
276 >  \r
277 >  /* This is separate from notmuch-private.h because we're trying to\r
278 > @@ -69,7 +75,11 @@ typedef struct notmuch_show_format {\r
279 >      void (*part_start) (GMimeObject *part,\r
280 >                       int *part_count);\r
281 >      void (*part_encstatus) (int status);\r
282 > +#ifdef GMIME_26\r
283 > +    void (*part_sigstatus) (GMimeSignatureList* siglist);\r
284 > +#else\r
285 >      void (*part_sigstatus) (const GMimeSignatureValidity* validity);\r
286 > +#endif\r
287 >      void (*part_content) (GMimeObject *part);\r
288 >      void (*part_end) (GMimeObject *part);\r
289 >      const char *part_sep;\r
290 > @@ -83,7 +93,11 @@ typedef struct notmuch_show_params {\r
291 >      int entire_thread;\r
292 >      int raw;\r
293 >      int part;\r
294 > +#ifdef GMIME_26\r
295 > +    GMimeCryptoContext* cryptoctx;\r
296 > +#else\r
297 >      GMimeCipherContext* cryptoctx;\r
298 > +#endif\r
299 >      int decrypt;\r
300 >  } notmuch_show_params_t;\r
301 >  \r
302 > @@ -286,7 +300,12 @@ typedef struct mime_node {\r
303 >       * signature.  May be NULL if signature verification failed.  If\r
304 >       * there are simply no signatures, this will be non-NULL with an\r
305 >       * empty signers list. */\r
306 > +#ifdef GMIME_26\r
307 > +    /* TODO: update the above comment... */\r
308 \r
309 Since this behaves very differently in 2.6, I think documenting it is\r
310 important (and being very careful about the differences).  Maybe\r
311 \r
312 /* The list of signatures for signed or encrypted containers.  If\r
313  * there are no signatures, this will be NULL. */\r
314 \r
315 > +    GMimeSignatureList* sig_list;\r
316 > +#else\r
317 >      const GMimeSignatureValidity *sig_validity;\r
318 > +#endif\r
319 >  \r
320 >      /* Internal: Context inherited from the root iterator. */\r
321 >      struct mime_node_context *ctx;\r
322 > @@ -311,8 +330,12 @@ typedef struct mime_node {\r
323 >   */\r
324 >  notmuch_status_t\r
325 >  mime_node_open (const void *ctx, notmuch_message_t *message,\r
326 > -             GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
327 > -             mime_node_t **node_out);\r
328 > +#ifdef GMIME_26\r
329 > +             GMimeCryptoContext *cryptoctx,\r
330 > +#else\r
331 > +             GMimeCipherContext *cryptoctx,\r
332 > +#endif\r
333 > +             notmuch_bool_t decrypt, mime_node_t **node_out);\r
334 >  \r
335 >  /* Return a new MIME node for the requested child part of parent.\r
336 >   * parent will be used as the talloc context for the returned child\r
337 > diff --git a/notmuch-reply.c b/notmuch-reply.c\r
338 > index da3acce..dc37c51 100644\r
339 > --- a/notmuch-reply.c\r
340 > +++ b/notmuch-reply.c\r
341 > @@ -688,15 +688,22 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
342 >       reply_format_func = notmuch_reply_format_default;\r
343 >  \r
344 >      if (decrypt) {\r
345 > +#ifdef GMIME_26\r
346 > +     /* TODO: GMimePasswordRequestFunc */\r
347 > +     params.cryptoctx = g_mime_gpg_context_new (NULL, "gpg");\r
348 > +#else\r
349 >       GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL);\r
350 >       params.cryptoctx = g_mime_gpg_context_new (session, "gpg");\r
351 > +#endif\r
352 >       if (params.cryptoctx) {\r
353 >           g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE);\r
354 >           params.decrypt = TRUE;\r
355 >       } else {\r
356 >           fprintf (stderr, "Failed to construct gpg context.\n");\r
357 >       }\r
358 > +#ifndef GMIME_26\r
359 >       g_object_unref (session);\r
360 > +#endif\r
361 >      }\r
362 >  \r
363 >      config = notmuch_config_open (ctx, NULL, NULL);\r
364 > diff --git a/notmuch-show.c b/notmuch-show.c\r
365 > index d14dac9..263ab72 100644\r
366 > --- a/notmuch-show.c\r
367 > +++ b/notmuch-show.c\r
368 > @@ -76,7 +76,11 @@ static void\r
369 >  format_part_encstatus_json (int status);\r
370 >  \r
371 >  static void\r
372 > +#ifdef GMIME_26\r
373 > +format_part_sigstatus_json (GMimeSignatureList* siglist);\r
374 > +#else\r
375 >  format_part_sigstatus_json (const GMimeSignatureValidity* validity);\r
376 > +#endif\r
377 >  \r
378 >  static void\r
379 >  format_part_content_json (GMimeObject *part);\r
380 > @@ -486,6 +490,21 @@ show_text_part_content (GMimeObject *part, GMimeStream *stream_out)\r
381 >       g_object_unref(stream_filter);\r
382 >  }\r
383 >  \r
384 > +#ifdef GMIME_26\r
385 > +static const char*\r
386 > +signature_status_to_string (GMimeSignatureStatus x)\r
387 > +{\r
388 > +    switch (x) {\r
389 > +    case GMIME_SIGNATURE_STATUS_GOOD:\r
390 > +     return "good";\r
391 > +    case GMIME_SIGNATURE_STATUS_BAD:\r
392 > +     return "bad";\r
393 > +    case GMIME_SIGNATURE_STATUS_ERROR:\r
394 > +     return "error";\r
395 > +    }\r
396 > +    return "unknown";\r
397 > +}\r
398 > +#else\r
399 >  static const char*\r
400 >  signer_status_to_string (GMimeSignerStatus x)\r
401 >  {\r
402 > @@ -501,6 +520,7 @@ signer_status_to_string (GMimeSignerStatus x)\r
403 >      }\r
404 >      return "unknown";\r
405 >  }\r
406 > +#endif\r
407 >  \r
408 >  static void\r
409 >  format_part_start_text (GMimeObject *part, int *part_count)\r
410 > @@ -592,6 +612,75 @@ format_part_encstatus_json (int status)\r
411 >      printf ("}]");\r
412 >  }\r
413 >  \r
414 > +#ifdef GMIME_26\r
415 > +static void\r
416 > +format_part_sigstatus_json (GMimeSignatureList *siglist)\r
417 > +{\r
418 > +    printf (", \"sigstatus\": [");\r
419 > +\r
420 > +    if (!siglist) {\r
421 > +     printf ("]");\r
422 > +     return;\r
423 > +     }\r
424 > +\r
425 > +    void *ctx_quote = talloc_new (NULL);\r
426 > +    int i;\r
427 > +    for (i = 0; i < g_mime_signature_list_length (siglist); ++i) {\r
428 \r
429 Style nit: notmuch uses i++.\r
430 \r
431 > +     GMimeSignature *signature = g_mime_signature_list_get_signature (siglist, i);\r
432 > +\r
433 > +     if (i > 0)\r
434 > +         printf (", ");\r
435 > +\r
436 > +     printf ("{");\r
437 > +\r
438 > +     /* status */\r
439 > +     GMimeSignatureStatus status = g_mime_signature_get_status (signature);\r
440 > +     printf ("\"status\": %s",\r
441 > +             json_quote_str (ctx_quote,\r
442 > +                             signature_status_to_string (status)));\r
443 > +\r
444 > +     GMimeCertificate *certificate = g_mime_signature_get_certificate (signature);\r
445 > +     if (status == GMIME_SIGNATURE_STATUS_GOOD)\r
446 > +     {\r
447 \r
448 Style nit: break after brace.\r
449 \r
450 (Presumably this is copied from the existing\r
451 format_part_sigstatus_json, but since it's technically new code\r
452 there's no reason not to fix these up.)\r
453 \r
454 > +         if (certificate)\r
455 > +             printf (", \"fingerprint\": %s", json_quote_str (ctx_quote, g_mime_certificate_get_fingerprint (certificate)));\r
456 > +         /* these dates are seconds since the epoch; should we\r
457 > +          * provide a more human-readable format string? */\r
458 > +         time_t created = g_mime_signature_get_created (signature);\r
459 > +         if (created != -1)\r
460 > +             printf (", \"created\": %d", (int) created);\r
461 > +         time_t expires = g_mime_signature_get_expires (signature);\r
462 > +         if (expires > 0)\r
463 > +             printf (", \"expires\": %d", (int) expires);\r
464 \r
465 Is it intentional that the two above checks are different?  I would\r
466 think the second should be expires != -1.\r
467 \r
468 > +         /* output user id only if validity is FULL or ULTIMATE. */\r
469 > +         /* note that gmime is using the term "trust" here, which\r
470 > +          * is WRONG.  It's actually user id "validity". */\r
471 > +         if (certificate)\r
472 > +         {\r
473 \r
474 Break after brace.\r
475 \r
476 > +             const char *name = g_mime_certificate_get_name (certificate);\r
477 > +             GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate);\r
478 > +             if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE))\r
479 > +                 printf (", \"userid\": %s", json_quote_str (ctx_quote, name));\r
480 > +         }\r
481 > +     } else if (certificate) {\r
482 > +         const char *key_id = g_mime_certificate_get_key_id (certificate);\r
483 > +         if (key_id)\r
484 > +             printf (", \"keyid\": %s", json_quote_str (ctx_quote, key_id));\r
485 > +     }\r
486 > +\r
487 > +     GMimeSignatureError errors = g_mime_signature_get_errors (signature);\r
488 > +     if (errors != GMIME_SIGNATURE_ERROR_NONE) {\r
489 > +         printf (", \"errors\": %x", errors);\r
490 \r
491 This should be %d (I would say 0x%x, but JSON doesn't support hex\r
492 literals).  I see this bug came from the original\r
493 format_part_sigstatus_json.  Maybe there should be a quick patch\r
494 before this one that fixes the source of the bug?\r
495 \r
496 > +     }\r
497 > +\r
498 > +     printf ("}");\r
499 > +     }\r
500 > +\r
501 > +    printf ("]");\r
502 > +\r
503 > +    talloc_free (ctx_quote);\r
504 > +}\r
505 > +#else\r
506 >  static void\r
507 >  format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
508 >  {\r
509 > @@ -652,6 +741,7 @@ format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
510 >  \r
511 >      talloc_free (ctx_quote);\r
512 >  }\r
513 > +#endif\r
514 >  \r
515 >  static void\r
516 >  format_part_content_json (GMimeObject *part)\r
517 > @@ -990,13 +1080,20 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
518 >       } else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) ||\r
519 >                  (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {\r
520 >           if (params.cryptoctx == NULL) {\r
521 > +#ifdef GMIME_26\r
522 > +             /* TODO: GMimePasswordRequestFunc */\r
523 > +             if (NULL == (params.cryptoctx = g_mime_gpg_context_new(NULL, "gpg")))\r
524 > +#else\r
525 >               GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL);\r
526 >               if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))\r
527 > +#endif\r
528 >                   fprintf (stderr, "Failed to construct gpg context.\n");\r
529 >               else\r
530 >                   g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE);\r
531 > +#ifndef GMIME_26\r
532 >               g_object_unref (session);\r
533 >               session = NULL;\r
534 > +#endif\r
535 >           }\r
536 >           if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)\r
537 >               params.decrypt = 1;\r
538 > diff --git a/show-message.c b/show-message.c\r
539 > index 8768889..65269fd 100644\r
540 > --- a/show-message.c\r
541 > +++ b/show-message.c\r
542 > @@ -48,7 +48,11 @@ show_message_part (mime_node_t *node,\r
543 >       format->part_encstatus (node->decrypt_success);\r
544 >  \r
545 >      if (node->verify_attempted && format->part_sigstatus)\r
546 > +#ifdef GMIME_26\r
547 > +     format->part_sigstatus (node->sig_list);\r
548 > +#else\r
549 >       format->part_sigstatus (node->sig_validity);\r
550 > +#endif\r
551 >  \r
552 >      format->part_content (part);\r
553 >  \r