database error
[notmuch-archives.git] / 6c / 35787a81d123f6cb02ee69b84302abe4c833fa
1 Return-Path: <schnouki@schnouki.net>\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 DD367431FAF\r
6         for <notmuch@notmuchmail.org>; Fri, 20 Jan 2012 01:37:39 -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.1\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.1 tagged_above=-999 required=5\r
12         tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1]\r
13         autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id OTJ1aHT+j5iV for <notmuch@notmuchmail.org>;\r
17         Fri, 20 Jan 2012 01:37:36 -0800 (PST)\r
18 Received: from ks3536.kimsufi.com (schnouki.net [87.98.217.222])\r
19         by olra.theworths.org (Postfix) with ESMTP id C68B1431FAE\r
20         for <notmuch@notmuchmail.org>; Fri, 20 Jan 2012 01:37:35 -0800 (PST)\r
21 Received: from thor.loria.fr (thor.loria.fr [152.81.12.250])\r
22         by ks3536.kimsufi.com (Postfix) with ESMTPSA id EFF986C000A;\r
23         Fri, 20 Jan 2012 10:37:22 +0100 (CET)\r
24 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=schnouki.net;\r
25         s=key-schnouki; t=1327052243;\r
26         bh=sgW0+gNPsvpBvE3c/nzHbj3okhWdWEbgNcYQ/bt+NHU=;\r
27         h=From:To:Cc:Subject:In-Reply-To:References:Date:Message-ID:\r
28         MIME-Version:Content-Type;\r
29         b=TBbzxt9EKbY5TbG8hnGnw5Uo4cs3x9BlaEw9GklWcWhaKMn41RQBbKyuzObEUbiDp\r
30         sVIFROTvgGXh8PZscn3xVQfExt8/jLqlK+SXRPjH0Og/3uFEttv1DyZ1mkFi7rnxKM\r
31         hhRNDBcwMGw71CC/V5ReSi5xrVH9cwvyFx1GLIaw=\r
32 From: Thomas Jost <schnouki@schnouki.net>\r
33 To: Austin Clements <amdragon@MIT.EDU>\r
34 Subject: Re: [PATCH v3 2/2] Add compatibility with gmime 2.6\r
35 In-Reply-To: <20120120041044.GU16740@mit.edu>\r
36 References: <87ty3r2rqt.fsf@schnouki.net>\r
37         <1327017987-3361-1-git-send-email-schnouki@schnouki.net>\r
38         <1327017987-3361-3-git-send-email-schnouki@schnouki.net>\r
39         <20120120041044.GU16740@mit.edu>\r
40 User-Agent: Notmuch/0.11+95~gde2fd30 (http://notmuchmail.org) Emacs/24.0.92.1\r
41         (x86_64-unknown-linux-gnu)\r
42 Date: Fri, 20 Jan 2012 10:37:31 +0100\r
43 Message-ID: <87fwfaemuc.fsf@thor.loria.fr>\r
44 MIME-Version: 1.0\r
45 Content-Type: multipart/signed; boundary="=-=-=";\r
46         micalg=pgp-sha1; protocol="application/pgp-signature"\r
47 Cc: notmuch@notmuchmail.org\r
48 X-BeenThere: notmuch@notmuchmail.org\r
49 X-Mailman-Version: 2.1.13\r
50 Precedence: list\r
51 List-Id: "Use and development of the notmuch mail system."\r
52         <notmuch.notmuchmail.org>\r
53 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
54         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
55 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
56 List-Post: <mailto:notmuch@notmuchmail.org>\r
57 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
58 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
59         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
60 X-List-Received-Date: Fri, 20 Jan 2012 09:37:40 -0000\r
61 \r
62 --=-=-=\r
63 Content-Type: text/plain\r
64 Content-Transfer-Encoding: quoted-printable\r
65 \r
66 On Thu, 19 Jan 2012 23:10:44 -0500, Austin Clements <amdragon@MIT.EDU> wrot=\r
67 e:\r
68 > Nearly there.  A few more small comments.\r
69 \r
70 Thanks again :) Will post new version soon, including a new patch to\r
71 update NEWS and INSTALL.\r
72 \r
73 > Quoth Thomas Jost on Jan 20 at  1:06 am:\r
74 > > There are lots of API changes in gmime 2.6 crypto handling. By adding\r
75 > > preprocessor directives, it is however possible to add gmime 2.6 compat=\r
76 ibility\r
77 > > while preserving compatibility with gmime 2.4 too.\r
78 > >=20\r
79 > > This is mostly based on id:"8762i8hrb9.fsf@bookbinder.fernseed.info".\r
80 > >=20\r
81 > > This was tested against both gmime 2.6.4 and 2.4.31. With gmime 2.4.31,=\r
82  the\r
83 > > crypto tests all work fine (as expected). With gmime 2.6.4, one crypto =\r
84 test is\r
85 > > currently broken (signature verification with signer key unavailable), =\r
86 most\r
87 > > likely because of a bug in gmime which will hopefully be fixed in a fut=\r
88 ure\r
89 > > version.\r
90 > > ---\r
91 > >  mime-node.c      |   60 ++++++++++++++++++++++++++++++++--\r
92 > >  notmuch-client.h |   30 ++++++++++++++++-\r
93 > >  notmuch-reply.c  |    7 ++++\r
94 > >  notmuch-show.c   |   95 ++++++++++++++++++++++++++++++++++++++++++++++=\r
95 ++++++++\r
96 > >  show-message.c   |    4 ++\r
97 > >  test/crypto      |    2 +\r
98 > >  6 files changed, 192 insertions(+), 6 deletions(-)\r
99 > >=20\r
100 > > diff --git a/mime-node.c b/mime-node.c\r
101 > > index d26bb44..ad19f5e 100644\r
102 > > --- a/mime-node.c\r
103 > > +++ b/mime-node.c\r
104 > > @@ -33,7 +33,11 @@ typedef struct mime_node_context {\r
105 > >      GMimeMessage *mime_message;\r
106 > >=20=20\r
107 > >      /* Context provided by the caller. */\r
108 > > +#ifdef GMIME_ATLEAST_26\r
109 > > +    GMimeCryptoContext *cryptoctx;\r
110 > > +#else\r
111 > >      GMimeCipherContext *cryptoctx;\r
112 > > +#endif\r
113 > >      notmuch_bool_t decrypt;\r
114 > >  } mime_node_context_t;\r
115 > >=20=20\r
116 > > @@ -57,8 +61,12 @@ _mime_node_context_free (mime_node_context_t *res)\r
117 > >=20=20\r
118 > >  notmuch_status_t\r
119 > >  mime_node_open (const void *ctx, notmuch_message_t *message,\r
120 > > -           GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
121 > > -           mime_node_t **root_out)\r
122 > > +#ifdef GMIME_ATLEAST_26\r
123 > > +           GMimeCryptoContext *cryptoctx,\r
124 > > +#else\r
125 > > +           GMimeCipherContext *cryptoctx,\r
126 > > +#endif\r
127 > > +           notmuch_bool_t decrypt, mime_node_t **root_out)\r
128 > >  {\r
129 > >      const char *filename =3D notmuch_message_get_filename (message);\r
130 > >      mime_node_context_t *mctx;\r
131 > > @@ -112,12 +120,21 @@ DONE:\r
132 > >      return status;\r
133 > >  }\r
134 > >=20=20\r
135 > > +#ifdef GMIME_ATLEAST_26\r
136 > > +static int\r
137 > > +_signature_list_free (GMimeSignatureList **proxy)\r
138 > > +{\r
139 > > +    g_object_unref (*proxy);\r
140 > > +    return 0;\r
141 > > +}\r
142 > > +#else\r
143 > >  static int\r
144 > >  _signature_validity_free (GMimeSignatureValidity **proxy)\r
145 > >  {\r
146 > >      g_mime_signature_validity_free (*proxy);\r
147 > >      return 0;\r
148 > >  }\r
149 > > +#endif\r
150 > >=20=20\r
151 > >  static mime_node_t *\r
152 > >  _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
153 > > @@ -165,11 +182,24 @@ _mime_node_create (const mime_node_t *parent, GMi=\r
154 meObject *part)\r
155 > >         GMimeMultipartEncrypted *encrypteddata =3D\r
156 > >             GMIME_MULTIPART_ENCRYPTED (part);\r
157 > >         node->decrypt_attempted =3D TRUE;\r
158 > > +#ifdef GMIME_ATLEAST_26\r
159 > > +       GMimeDecryptResult *decrypt_result =3D NULL;\r
160 > > +       node->decrypted_child =3D g_mime_multipart_encrypted_decrypt\r
161 > > +           (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err);\r
162 > > +#else\r
163 > >         node->decrypted_child =3D g_mime_multipart_encrypted_decrypt\r
164 > >             (encrypteddata, node->ctx->cryptoctx, &err);\r
165 > > +#endif\r
166 > >         if (node->decrypted_child) {\r
167 > >             node->decrypt_success =3D node->verify_attempted =3D TRUE;\r
168 > > +#ifdef GMIME_ATLEAST_26\r
169 > > +           /* This may be NULL if the part is not signed. */\r
170 > > +           node->sig_list =3D g_mime_decrypt_result_get_signatures (decrypt_res=\r
171 ult);\r
172 > > +           g_object_ref (node->sig_list);\r
173 >=20\r
174 > Apparently you can't g_object_ref NULL, so there should be a\r
175 > conditional around this.\r
176 \r
177 Right, added. Thanks.\r
178 \r
179 > (Does g_mime_decrypt_result_get_signatures *really* return NULL for an\r
180 > empty list? I feel like various tests should have failed in various\r
181 > versions of this patch if it did.)\r
182 \r
183 Yes it does. I added some fprintf() in gmime (in gpg_decrypt() and\r
184 g_mime_decrypt_result_get_signatures()). Decryption tests (after "emacs\r
185 delivery of encrypted message with attachment") clearly show that\r
186 g_mime_decrypt_result_get_signatures returns NULL when there's no\r
187 signatures in an encrypted part.\r
188 \r
189 I guess the reason why tests did not fail is that\r
190 format_part_sigstatus_json just displays an empty JSON array if sig_list\r
191 is NULL. And that's also what's expected when an encrypted part has no\r
192 signature.\r
193 \r
194 I had a quick look at the GObject code; apparently if you pass NULL to\r
195 g_object_ref (or anything that is not a GObject) it will just return\r
196 NULL. So that's why this one did not fail either.\r
197 \r
198 >=20\r
199 > > +           g_object_unref (decrypt_result);\r
200 > > +#else\r
201 > >             node->sig_validity =3D g_mime_multipart_encrypted_get_signature_vali=\r
202 dity (encrypteddata);\r
203 > > +#endif\r
204 > >         } else {\r
205 > >             fprintf (stderr, "Failed to decrypt part: %s\n",\r
206 > >                      (err ? err->message : "no error explanation given"));\r
207 > > @@ -182,6 +212,15 @@ _mime_node_create (const mime_node_t *parent, GMim=\r
208 eObject *part)\r
209 > >                  "(must be exactly 2)\n",\r
210 > >                  node->nchildren);\r
211 > >     } else {\r
212 > > +#ifdef GMIME_ATLEAST_26\r
213 > > +       node->sig_list =3D g_mime_multipart_signed_verify\r
214 > > +           (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err);\r
215 > > +       node->verify_attempted =3D TRUE;\r
216 > > +\r
217 > > +       if (!node->sig_list)\r
218 > > +           fprintf (stderr, "Failed to verify signed part: %s\n",\r
219 > > +                    (err ? err->message : "no error explanation given"));\r
220 > > +#else\r
221 > >         /* For some reason the GMimeSignatureValidity returned\r
222 > >          * here is not a const (inconsistent with that\r
223 > >          * returned by\r
224 > > @@ -195,17 +234,30 @@ _mime_node_create (const mime_node_t *parent, GMi=\r
225 meObject *part)\r
226 > >         node->verify_attempted =3D TRUE;\r
227 > >         node->sig_validity =3D sig_validity;\r
228 > >         if (sig_validity) {\r
229 > > -           GMimeSignatureValidity **proxy =3D\r
230 > > -               talloc (node, GMimeSignatureValidity *);\r
231 > > +           GMimeSignatureValidity **proxy =3D talloc (node, GMimeSignatureValid=\r
232 ity *);\r
233 >=20\r
234 > (See below)\r
235 >=20\r
236 > >             *proxy =3D sig_validity;\r
237 > >             talloc_set_destructor (proxy, _signature_validity_free);\r
238 > >         }\r
239 > > +#endif\r
240 > >     }\r
241 > >      }\r
242 > >=20=20\r
243 > > +#ifdef GMIME_ATLEAST_26\r
244 > > +    /* sig_list may be created in both above cases, so we need to\r
245 > > +     * cleanly handle it here. */\r
246 > > +    if (node->sig_list) {\r
247 > > +   GMimeSignatureList **proxy =3D\r
248 > > +       talloc (node, GMimeSignatureList *);\r
249 >=20\r
250 > Oops.  I think you un-split the wrong line.  The one up above is now\r
251 > too long and this one is still unnecessarily split.\r
252 \r
253 Argh. Sorry about that. (I guess hacking while watching DS9 is not a\r
254 good idea: too distracting. Won't do it again until next time.)\r
255 \r
256 >=20\r
257 > > +   *proxy =3D node->sig_list;\r
258 > > +   talloc_set_destructor (proxy, _signature_list_free);\r
259 > > +    }\r
260 > > +#endif\r
261 > > +\r
262 > > +#ifndef GMIME_ATLEAST_26\r
263 > >      if (node->verify_attempted && !node->sig_validity)\r
264 > >     fprintf (stderr, "Failed to verify signed part: %s\n",\r
265 > >              (err ? err->message : "no error explanation given"));\r
266 > > +#endif\r
267 > >=20=20\r
268 > >      if (err)\r
269 > >     g_error_free (err);\r
270 > > diff --git a/notmuch-client.h b/notmuch-client.h\r
271 > > index 62ede28..9c1d383 100644\r
272 > > --- a/notmuch-client.h\r
273 > > +++ b/notmuch-client.h\r
274 > > @@ -30,6 +30,14 @@\r
275 > >=20=20\r
276 > >  #include <gmime/gmime.h>\r
277 > >=20=20\r
278 > > +/* GMIME_CHECK_VERSION in gmime 2.4 is not usable from the\r
279 > > + * preprocessor (it calls a runtime function). But since\r
280 > > + * GMIME_MAJOR_VERSION and friends were added in gmime 2.6, we can use\r
281 > > + * these to check the version number. */\r
282 > > +#ifdef GMIME_MAJOR_VERSION\r
283 > > +#define GMIME_ATLEAST_26\r
284 > > +#endif\r
285 > > +\r
286 > >  #include "notmuch.h"\r
287 > >=20=20\r
288 > >  /* This is separate from notmuch-private.h because we're trying to\r
289 > > @@ -69,7 +77,11 @@ typedef struct notmuch_show_format {\r
290 > >      void (*part_start) (GMimeObject *part,\r
291 > >                     int *part_count);\r
292 > >      void (*part_encstatus) (int status);\r
293 > > +#ifdef GMIME_ATLEAST_26\r
294 > > +    void (*part_sigstatus) (GMimeSignatureList* siglist);\r
295 > > +#else\r
296 > >      void (*part_sigstatus) (const GMimeSignatureValidity* validity);\r
297 > > +#endif\r
298 > >      void (*part_content) (GMimeObject *part);\r
299 > >      void (*part_end) (GMimeObject *part);\r
300 > >      const char *part_sep;\r
301 > > @@ -83,7 +95,11 @@ typedef struct notmuch_show_params {\r
302 > >      int entire_thread;\r
303 > >      int raw;\r
304 > >      int part;\r
305 > > +#ifdef GMIME_ATLEAST_26\r
306 > > +    GMimeCryptoContext* cryptoctx;\r
307 > > +#else\r
308 > >      GMimeCipherContext* cryptoctx;\r
309 > > +#endif\r
310 > >      int decrypt;\r
311 > >  } notmuch_show_params_t;\r
312 > >=20=20\r
313 > > @@ -290,11 +306,17 @@ typedef struct mime_node {\r
314 > >=20=20\r
315 > >      /* True if signature verification on this part was attempted. */\r
316 > >      notmuch_bool_t verify_attempted;\r
317 > > +#ifdef GMIME_ATLEAST_26\r
318 > > +    /* The list of signatures for signed or encrypted containers. If\r
319 > > +     * there are no signatures, this will be NULL. */\r
320 > > +    GMimeSignatureList* sig_list;\r
321 > > +#else\r
322 > >      /* For signed or encrypted containers, the validity of the\r
323 > >       * signature.  May be NULL if signature verification failed.  If\r
324 > >       * there are simply no signatures, this will be non-NULL with an\r
325 > >       * empty signers list. */\r
326 > >      const GMimeSignatureValidity *sig_validity;\r
327 > > +#endif\r
328 > >=20=20\r
329 > >      /* Internal: Context inherited from the root iterator. */\r
330 > >      struct mime_node_context *ctx;\r
331 > > @@ -319,8 +341,12 @@ typedef struct mime_node {\r
332 > >   */\r
333 > >  notmuch_status_t\r
334 > >  mime_node_open (const void *ctx, notmuch_message_t *message,\r
335 > > -           GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
336 > > -           mime_node_t **node_out);\r
337 > > +#ifdef GMIME_ATLEAST_26\r
338 > > +           GMimeCryptoContext *cryptoctx,\r
339 > > +#else\r
340 > > +           GMimeCipherContext *cryptoctx,\r
341 > > +#endif\r
342 > > +           notmuch_bool_t decrypt, mime_node_t **node_out);\r
343 > >=20=20\r
344 > >  /* Return a new MIME node for the requested child part of parent.\r
345 > >   * parent will be used as the talloc context for the returned child\r
346 > > diff --git a/notmuch-reply.c b/notmuch-reply.c\r
347 > > index 0f682db..bf67960 100644\r
348 > > --- a/notmuch-reply.c\r
349 > > +++ b/notmuch-reply.c\r
350 > > @@ -688,15 +688,22 @@ notmuch_reply_command (void *ctx, int argc, char =\r
351 *argv[])\r
352 > >     reply_format_func =3D notmuch_reply_format_default;\r
353 > >=20=20\r
354 > >      if (decrypt) {\r
355 > > +#ifdef GMIME_ATLEAST_26\r
356 > > +   /* TODO: GMimePasswordRequestFunc */\r
357 > > +   params.cryptoctx =3D g_mime_gpg_context_new (NULL, "gpg");\r
358 > > +#else\r
359 > >     GMimeSession* session =3D g_object_new (g_mime_session_get_type(), NU=\r
360 LL);\r
361 > >     params.cryptoctx =3D g_mime_gpg_context_new (session, "gpg");\r
362 > > +#endif\r
363 > >     if (params.cryptoctx) {\r
364 > >         g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cr=\r
365 yptoctx, FALSE);\r
366 > >         params.decrypt =3D TRUE;\r
367 > >     } else {\r
368 > >         fprintf (stderr, "Failed to construct gpg context.\n");\r
369 > >     }\r
370 > > +#ifndef GMIME_ATLEAST_26\r
371 > >     g_object_unref (session);\r
372 > > +#endif\r
373 > >      }\r
374 > >=20=20\r
375 > >      config =3D notmuch_config_open (ctx, NULL, NULL);\r
376 > > diff --git a/notmuch-show.c b/notmuch-show.c\r
377 > > index 91f566c..190210c 100644\r
378 > > --- a/notmuch-show.c\r
379 > > +++ b/notmuch-show.c\r
380 > > @@ -76,7 +76,11 @@ static void\r
381 > >  format_part_encstatus_json (int status);\r
382 > >=20=20\r
383 > >  static void\r
384 > > +#ifdef GMIME_ATLEAST_26\r
385 > > +format_part_sigstatus_json (GMimeSignatureList* siglist);\r
386 > > +#else\r
387 > >  format_part_sigstatus_json (const GMimeSignatureValidity* validity);\r
388 > > +#endif\r
389 > >=20=20\r
390 > >  static void\r
391 > >  format_part_content_json (GMimeObject *part);\r
392 > > @@ -486,6 +490,21 @@ show_text_part_content (GMimeObject *part, GMimeSt=\r
393 ream *stream_out)\r
394 > >     g_object_unref(stream_filter);\r
395 > >  }\r
396 > >=20=20\r
397 > > +#ifdef GMIME_ATLEAST_26\r
398 > > +static const char*\r
399 > > +signature_status_to_string (GMimeSignatureStatus x)\r
400 > > +{\r
401 > > +    switch (x) {\r
402 > > +    case GMIME_SIGNATURE_STATUS_GOOD:\r
403 > > +   return "good";\r
404 > > +    case GMIME_SIGNATURE_STATUS_BAD:\r
405 > > +   return "bad";\r
406 > > +    case GMIME_SIGNATURE_STATUS_ERROR:\r
407 > > +   return "error";\r
408 > > +    }\r
409 > > +    return "unknown";\r
410 > > +}\r
411 > > +#else\r
412 > >  static const char*\r
413 > >  signer_status_to_string (GMimeSignerStatus x)\r
414 > >  {\r
415 > > @@ -501,6 +520,7 @@ signer_status_to_string (GMimeSignerStatus x)\r
416 > >      }\r
417 > >      return "unknown";\r
418 > >  }\r
419 > > +#endif\r
420 > >=20=20\r
421 > >  static void\r
422 > >  format_part_start_text (GMimeObject *part, int *part_count)\r
423 > > @@ -592,6 +612,73 @@ format_part_encstatus_json (int status)\r
424 > >      printf ("}]");\r
425 > >  }\r
426 > >=20=20\r
427 > > +#ifdef GMIME_ATLEAST_26\r
428 > > +static void\r
429 > > +format_part_sigstatus_json (GMimeSignatureList *siglist)\r
430 > > +{\r
431 > > +    printf (", \"sigstatus\": [");\r
432 > > +\r
433 > > +    if (!siglist) {\r
434 > > +   printf ("]");\r
435 > > +   return;\r
436 > > +    }\r
437 > > +\r
438 > > +    void *ctx_quote =3D talloc_new (NULL);\r
439 > > +    int i;\r
440 > > +    for (i =3D 0; i < g_mime_signature_list_length (siglist); i++) {\r
441 > > +   GMimeSignature *signature =3D g_mime_signature_list_get_signature (si=\r
442 glist, i);\r
443 > > +\r
444 > > +   if (i > 0)\r
445 > > +       printf (", ");\r
446 > > +\r
447 > > +   printf ("{");\r
448 > > +\r
449 > > +   /* status */\r
450 > > +   GMimeSignatureStatus status =3D g_mime_signature_get_status (signatur=\r
451 e);\r
452 > > +   printf ("\"status\": %s",\r
453 > > +           json_quote_str (ctx_quote,\r
454 > > +                           signature_status_to_string (status)));\r
455 > > +\r
456 > > +   GMimeCertificate *certificate =3D g_mime_signature_get_certificate (s=\r
457 ignature);\r
458 > > +   if (status =3D=3D GMIME_SIGNATURE_STATUS_GOOD) {\r
459 > > +       if (certificate)\r
460 > > +           printf (", \"fingerprint\": %s", json_quote_str (ctx_quote, g_mime_c=\r
461 ertificate_get_fingerprint (certificate)));\r
462 > > +       /* these dates are seconds since the epoch; should we\r
463 > > +        * provide a more human-readable format string? */\r
464 > > +       time_t created =3D g_mime_signature_get_created (signature);\r
465 > > +       if (created !=3D -1)\r
466 > > +           printf (", \"created\": %d", (int) created);\r
467 > > +       time_t expires =3D g_mime_signature_get_expires (signature);\r
468 > > +       if (expires > 0)\r
469 > > +           printf (", \"expires\": %d", (int) expires);\r
470 > > +       /* output user id only if validity is FULL or ULTIMATE. */\r
471 > > +       /* note that gmime is using the term "trust" here, which\r
472 > > +        * is WRONG.  It's actually user id "validity". */\r
473 > > +       if (certificate) {\r
474 > > +           const char *name =3D g_mime_certificate_get_name (certificate);\r
475 > > +           GMimeCertificateTrust trust =3D g_mime_certificate_get_trust (certif=\r
476 icate);\r
477 > > +           if (name && (trust =3D=3D GMIME_CERTIFICATE_TRUST_FULLY || trust =3D=\r
478 =3D 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 =3D g_mime_certificate_get_key_id (certificate=\r
483 );\r
484 > > +       if (key_id)\r
485 > > +           printf (", \"keyid\": %s", json_quote_str (ctx_quote, key_id));\r
486 > > +   }\r
487 > > +\r
488 > > +   GMimeSignatureError errors =3D g_mime_signature_get_errors (signature=\r
489 );\r
490 > > +   if (errors !=3D GMIME_SIGNATURE_ERROR_NONE) {\r
491 > > +       printf (", \"errors\": %d", errors);\r
492 > > +   }\r
493 > > +\r
494 > > +   printf ("}");\r
495 > > +     }\r
496 > > +\r
497 > > +    printf ("]");\r
498 > > +\r
499 > > +    talloc_free (ctx_quote);\r
500 > > +}\r
501 > > +#else\r
502 > >  static void\r
503 > >  format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
504 > >  {\r
505 > > @@ -652,6 +739,7 @@ format_part_sigstatus_json (const GMimeSignatureVal=\r
506 idity* validity)\r
507 > >=20=20\r
508 > >      talloc_free (ctx_quote);\r
509 > >  }\r
510 > > +#endif\r
511 > >=20=20\r
512 > >  static void\r
513 > >  format_part_content_json (GMimeObject *part)\r
514 > > @@ -990,13 +1078,20 @@ notmuch_show_command (void *ctx, unused (int arg=\r
515 c), unused (char *argv[]))\r
516 > >     } else if ((STRNCMP_LITERAL (argv[i], "--verify") =3D=3D 0) ||\r
517 > >                (STRNCMP_LITERAL (argv[i], "--decrypt") =3D=3D 0)) {\r
518 > >         if (params.cryptoctx =3D=3D NULL) {\r
519 > > +#ifdef GMIME_ATLEAST_26\r
520 > > +           /* TODO: GMimePasswordRequestFunc */\r
521 > > +           if (NULL =3D=3D (params.cryptoctx =3D g_mime_gpg_context_new(NULL, "=\r
522 gpg")))\r
523 > > +#else\r
524 > >             GMimeSession* session =3D g_object_new(g_mime_session_get_type(), NU=\r
525 LL);\r
526 > >             if (NULL =3D=3D (params.cryptoctx =3D g_mime_gpg_context_new(session=\r
527 , "gpg")))\r
528 > > +#endif\r
529 > >                 fprintf (stderr, "Failed to construct gpg context.\n");\r
530 > >             else\r
531 > >                 g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cry=\r
532 ptoctx, FALSE);\r
533 > > +#ifndef GMIME_ATLEAST_26\r
534 > >             g_object_unref (session);\r
535 > >             session =3D NULL;\r
536 > > +#endif\r
537 > >         }\r
538 > >         if (STRNCMP_LITERAL (argv[i], "--decrypt") =3D=3D 0)\r
539 > >             params.decrypt =3D 1;\r
540 > > diff --git a/show-message.c b/show-message.c\r
541 > > index 8768889..83ecf81 100644\r
542 > > --- a/show-message.c\r
543 > > +++ b/show-message.c\r
544 > > @@ -48,7 +48,11 @@ show_message_part (mime_node_t *node,\r
545 > >     format->part_encstatus (node->decrypt_success);\r
546 > >=20=20\r
547 > >      if (node->verify_attempted && format->part_sigstatus)\r
548 > > +#ifdef GMIME_ATLEAST_26\r
549 > > +   format->part_sigstatus (node->sig_list);\r
550 > > +#else\r
551 > >     format->part_sigstatus (node->sig_validity);\r
552 > > +#endif\r
553 > >=20=20\r
554 > >      format->part_content (part);\r
555 > >=20=20\r
556 > > diff --git a/test/crypto b/test/crypto\r
557 > > index 0af4aa8..3779abc 100755\r
558 > > --- a/test/crypto\r
559 > > +++ b/test/crypto\r
560 > > @@ -104,6 +104,8 @@ test_expect_equal \\r
561 > >      "$expected"\r
562 > >=20=20\r
563 > >  test_begin_subtest "signature verification with signer key unavailable"\r
564 > > +# this is broken with current versions of gmime-2.6\r
565 > > +(ldd $(which notmuch) | grep -q gmime-2.6) && test_subtest_known_broken\r
566 >=20\r
567 > Just to be nitpicky, you should either escape the . in the regexp or\r
568 > pass -F to grep.  Otherwise I think this hack is fine (though it might\r
569 > have to get a little fancier once GMime fixes this bug).\r
570 \r
571 Added -F :)\r
572 \r
573 I guess we could also use pkg-config to test if gmime 2.6 is present. It\r
574 would also be simpler to test the version number once gmime fixes this\r
575 bug:\r
576 \r
577   pkg-config --atleast-version=3D2.6.x gmime-2.6 || test_subtest_known_brok=\r
578 en\r
579 \r
580 But this would mean assuming that notmuch is built against a system-wide\r
581 gmime. Or it would require setting PKG_CONFIG_PATH before tests...\r
582 Complicated.\r
583 \r
584 So IMHO once gmime fixes this bug we should just remove the\r
585 test_subtest_known_broken and maybe add something like this in\r
586 notmuch-client.h:\r
587 \r
588   #ifdef GMIME_MAJOR_VERSION\r
589   #define GMIME_ATLEAST_26\r
590   #if !GMIME_CHECK_VERSION(2, 6, x)\r
591   #warning "Building against an old and buggy version of gmime. Please upda=\r
592 te to 2.6.x."\r
593   #endif\r
594   #endif\r
595 \r
596 >=20\r
597 > >  # move the gnupghome temporarily out of the way\r
598 > >  mv "${GNUPGHOME}"{,.bak}\r
599 > >  output=3D$(notmuch show --format=3Djson --verify subject:"test signed =\r
600 message 001" \\r
601 \r
602 =2D-=20\r
603 Thomas/Schnouki\r
604 \r
605 --=-=-=\r
606 Content-Type: application/pgp-signature\r
607 \r
608 -----BEGIN PGP SIGNATURE-----\r
609 Version: GnuPG v1.4.11 (GNU/Linux)\r
610 \r
611 iQEcBAEBAgAGBQJPGTXbAAoJEMPdciX+bh5I3YoH/1UyDErgI8P14uoXlpNvSI/R\r
612 SW6nf/wJtiEYQBKYl/7tvFdYc45NendE4QMegYoJvRHy0NyVKHv94vQS9N+kxsnX\r
613 RN4GEoUPSseFneZVR9mcP7nCWUcMzSqFYGejoqH09BmDEPZPFDW6llKmXRQpjTqQ\r
614 G6PMd9rS/bt6Z4Vl9nOLIv6amTaT6m/MHMgKCHSJAT9x+/ZNwfOK4uFEKt1ODtvD\r
615 enTp16RAqfOnHyo+jtLjGpjWbIyiO8eZiL+mUvd6Hn3XaEqcbWgsNuKwKNHvJq1L\r
616 pbw7+nXOfTFAYahovy8btxp3faIJ5MafyZk4vbBjJtcbWZn3Fes5G+BTCcjCABY=\r
617 =Mr4d\r
618 -----END PGP SIGNATURE-----\r
619 --=-=-=--\r