Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / dc / c2f8caa17b22f46780f66a2513a8bd44414f46
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 92498421167\r
6         for <notmuch@notmuchmail.org>; Tue, 17 Jan 2012 02:51:13 -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 aSSHtdVvfF20 for <notmuch@notmuchmail.org>;\r
17         Tue, 17 Jan 2012 02:51:09 -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 E2362429E35\r
20         for <notmuch@notmuchmail.org>; Tue, 17 Jan 2012 02:51:08 -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 26D076A002C;\r
23         Tue, 17 Jan 2012 11:51:08 +0100 (CET)\r
24 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=schnouki.net;\r
25         s=key-schnouki; t=1326797468;\r
26         bh=hQUKWmOzROeuIwxgc3SgfO0A4P47/IV0YTQ6a4B+vHY=;\r
27         h=From:To:Subject:Date:Message-Id:In-Reply-To:References;\r
28         b=Wg+XQRRBVz/gWqmDzrLy2Dsu5StcK2x9TxZKPi9NDtipxd/iM4VlwlkrGyFwBgSES\r
29         BxWzDUaiX/p9Q3901cjS+rSpixVZ1fC9Hkr6FRbHPSeTodRwA9f06WlR5tpRqLntFR\r
30         clmMlayDv7xDts8GGU8bevLCEAw+EY9XstJbcXk0=\r
31 From: Thomas Jost <schnouki@schnouki.net>\r
32 To: notmuch@notmuchmail.org\r
33 Subject: [PATCH v2 2/2] Add pseudo-compatibility with gmime 2.6\r
34 Date: Tue, 17 Jan 2012 11:50:53 +0100\r
35 Message-Id: <1326797453-9405-2-git-send-email-schnouki@schnouki.net>\r
36 X-Mailer: git-send-email 1.7.8.3\r
37 In-Reply-To: <1326797453-9405-1-git-send-email-schnouki@schnouki.net>\r
38 References: <8739bea9lc.fsf@thor.loria.fr>\r
39         <1326797453-9405-1-git-send-email-schnouki@schnouki.net>\r
40 X-BeenThere: notmuch@notmuchmail.org\r
41 X-Mailman-Version: 2.1.13\r
42 Precedence: list\r
43 List-Id: "Use and development of the notmuch mail system."\r
44         <notmuch.notmuchmail.org>\r
45 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
46         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
47 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
48 List-Post: <mailto:notmuch@notmuchmail.org>\r
49 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
50 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
51         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
52 X-List-Received-Date: Tue, 17 Jan 2012 10:51:13 -0000\r
53 \r
54 There are lots of API changes in gmime 2.6 crypto handling. By adding\r
55 preprocessor directives, it is however possible to add gmime 2.6 compatibility\r
56 while preserving compatibility with gmime 2.4 too.\r
57 \r
58 This is mostly based on id:"8762i8hrb9.fsf@bookbinder.fernseed.info".\r
59 \r
60 This was tested against both gmime 2.6.4 and 2.4.31. With gmime 2.4.31, the\r
61 crypto tests all work fine (as expected). With gmime 2.6.4, one crypto test\r
62 fails (signature verification with signer key unavailable) but this will be hard\r
63 to fix since the new API does not report the reason why a signature verification\r
64 fails (other than the human-readable error message).\r
65 ---\r
66  mime-node.c      |   56 ++++++++++++++++++++++++++++++--\r
67  notmuch-client.h |   28 +++++++++++++++-\r
68  notmuch-reply.c  |    7 ++++\r
69  notmuch-show.c   |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
70  show-message.c   |    4 ++\r
71  5 files changed, 185 insertions(+), 5 deletions(-)\r
72 \r
73 diff --git a/mime-node.c b/mime-node.c\r
74 index d26bb44..e575e1c 100644\r
75 --- a/mime-node.c\r
76 +++ b/mime-node.c\r
77 @@ -33,7 +33,11 @@ typedef struct mime_node_context {\r
78      GMimeMessage *mime_message;\r
79  \r
80      /* Context provided by the caller. */\r
81 +#ifdef GMIME_26\r
82 +    GMimeCryptoContext *cryptoctx;\r
83 +#else\r
84      GMimeCipherContext *cryptoctx;\r
85 +#endif\r
86      notmuch_bool_t decrypt;\r
87  } mime_node_context_t;\r
88  \r
89 @@ -57,8 +61,12 @@ _mime_node_context_free (mime_node_context_t *res)\r
90  \r
91  notmuch_status_t\r
92  mime_node_open (const void *ctx, notmuch_message_t *message,\r
93 -               GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
94 -               mime_node_t **root_out)\r
95 +#ifdef GMIME_26\r
96 +               GMimeCryptoContext *cryptoctx,\r
97 +#else\r
98 +               GMimeCipherContext *cryptoctx,\r
99 +#endif\r
100 +               notmuch_bool_t decrypt, mime_node_t **root_out)\r
101  {\r
102      const char *filename = notmuch_message_get_filename (message);\r
103      mime_node_context_t *mctx;\r
104 @@ -112,12 +120,21 @@ DONE:\r
105      return status;\r
106  }\r
107  \r
108 +#ifdef GMIME_26\r
109 +static int\r
110 +_signature_list_free (GMimeSignatureList **proxy)\r
111 +{\r
112 +    g_object_unref (*proxy);\r
113 +    return 0;\r
114 +}\r
115 +#else\r
116  static int\r
117  _signature_validity_free (GMimeSignatureValidity **proxy)\r
118  {\r
119      g_mime_signature_validity_free (*proxy);\r
120      return 0;\r
121  }\r
122 +#endif\r
123  \r
124  static mime_node_t *\r
125  _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
126 @@ -165,11 +182,22 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
127             GMimeMultipartEncrypted *encrypteddata =\r
128                 GMIME_MULTIPART_ENCRYPTED (part);\r
129             node->decrypt_attempted = TRUE;\r
130 +#ifdef GMIME_26\r
131 +           GMimeDecryptResult *decrypt_result = NULL;\r
132 +           node->decrypted_child = g_mime_multipart_encrypted_decrypt\r
133 +               (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err);\r
134 +#else\r
135             node->decrypted_child = g_mime_multipart_encrypted_decrypt\r
136                 (encrypteddata, node->ctx->cryptoctx, &err);\r
137 +#endif\r
138             if (node->decrypted_child) {\r
139 -               node->decrypt_success = node->verify_attempted = TRUE;\r
140 +               node->decrypt_success = node->verify_attempted =TRUE;\r
141 +#ifdef GMIME_26\r
142 +               /* This may be NULL if the part is not signed. */\r
143 +               node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result);\r
144 +#else\r
145                 node->sig_validity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata);\r
146 +#endif\r
147             } else {\r
148                 fprintf (stderr, "Failed to decrypt part: %s\n",\r
149                          (err ? err->message : "no error explanation given"));\r
150 @@ -182,6 +210,16 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
151                      "(must be exactly 2)\n",\r
152                      node->nchildren);\r
153         } else {\r
154 +#ifdef GMIME_26\r
155 +           GMimeSignatureList *sig_list = g_mime_multipart_signed_verify\r
156 +               (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err);\r
157 +           node->verify_attempted = TRUE;\r
158 +           node->sig_list = sig_list;\r
159 +\r
160 +           if (!sig_list)\r
161 +               fprintf (stderr, "Failed to verify signed part: %s\n",\r
162 +                        (err ? err->message : "no error explanation given"));\r
163 +#else\r
164             /* For some reason the GMimeSignatureValidity returned\r
165              * here is not a const (inconsistent with that\r
166              * returned by\r
167 @@ -200,12 +238,24 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part)\r
168                 *proxy = sig_validity;\r
169                 talloc_set_destructor (proxy, _signature_validity_free);\r
170             }\r
171 +#endif\r
172         }\r
173      }\r
174  \r
175 +#ifdef GMIME_26\r
176 +    /* sig_list may be created in both above cases, so we need to\r
177 +     * cleanly handle it here. */\r
178 +    if (node->sig_list) {\r
179 +       GMimeSignatureList **proxy =\r
180 +           talloc (node, GMimeSignatureList *);\r
181 +       *proxy = node->sig_list;\r
182 +       talloc_set_destructor (proxy, _signature_list_free);\r
183 +    }\r
184 +#else\r
185      if (node->verify_attempted && !node->sig_validity)\r
186         fprintf (stderr, "Failed to verify signed part: %s\n",\r
187                  (err ? err->message : "no error explanation given"));\r
188 +#endif\r
189  \r
190      if (err)\r
191         g_error_free (err);\r
192 diff --git a/notmuch-client.h b/notmuch-client.h\r
193 index 62ede28..9167042 100644\r
194 --- a/notmuch-client.h\r
195 +++ b/notmuch-client.h\r
196 @@ -30,6 +30,12 @@\r
197  \r
198  #include <gmime/gmime.h>\r
199  \r
200 +/* GMIME_CHECK_VERSION is only available in gmime >= 2.5. But so are\r
201 + * GMIME_MAJOR_VERSION and friends. */\r
202 +#ifdef GMIME_MAJOR_VERSION\r
203 +#define GMIME_26\r
204 +#endif\r
205 +\r
206  #include "notmuch.h"\r
207  \r
208  /* This is separate from notmuch-private.h because we're trying to\r
209 @@ -69,7 +75,11 @@ typedef struct notmuch_show_format {\r
210      void (*part_start) (GMimeObject *part,\r
211                         int *part_count);\r
212      void (*part_encstatus) (int status);\r
213 +#ifdef GMIME_26\r
214 +    void (*part_sigstatus) (GMimeSignatureList* siglist);\r
215 +#else\r
216      void (*part_sigstatus) (const GMimeSignatureValidity* validity);\r
217 +#endif\r
218      void (*part_content) (GMimeObject *part);\r
219      void (*part_end) (GMimeObject *part);\r
220      const char *part_sep;\r
221 @@ -83,7 +93,11 @@ typedef struct notmuch_show_params {\r
222      int entire_thread;\r
223      int raw;\r
224      int part;\r
225 +#ifdef GMIME_26\r
226 +    GMimeCryptoContext* cryptoctx;\r
227 +#else\r
228      GMimeCipherContext* cryptoctx;\r
229 +#endif\r
230      int decrypt;\r
231  } notmuch_show_params_t;\r
232  \r
233 @@ -290,11 +304,17 @@ typedef struct mime_node {\r
234  \r
235      /* True if signature verification on this part was attempted. */\r
236      notmuch_bool_t verify_attempted;\r
237 +#ifdef GMIME_26\r
238 +    /* The list of signatures for signed or encrypted containers. If\r
239 +      * there are no signatures, this will be NULL. */\r
240 +    GMimeSignatureList* sig_list;\r
241 +#else\r
242      /* For signed or encrypted containers, the validity of the\r
243       * signature.  May be NULL if signature verification failed.  If\r
244       * there are simply no signatures, this will be non-NULL with an\r
245       * empty signers list. */\r
246      const GMimeSignatureValidity *sig_validity;\r
247 +#endif\r
248  \r
249      /* Internal: Context inherited from the root iterator. */\r
250      struct mime_node_context *ctx;\r
251 @@ -319,8 +339,12 @@ typedef struct mime_node {\r
252   */\r
253  notmuch_status_t\r
254  mime_node_open (const void *ctx, notmuch_message_t *message,\r
255 -               GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt,\r
256 -               mime_node_t **node_out);\r
257 +#ifdef GMIME_26\r
258 +               GMimeCryptoContext *cryptoctx,\r
259 +#else\r
260 +               GMimeCipherContext *cryptoctx,\r
261 +#endif\r
262 +               notmuch_bool_t decrypt, mime_node_t **node_out);\r
263  \r
264  /* Return a new MIME node for the requested child part of parent.\r
265   * parent will be used as the talloc context for the returned child\r
266 diff --git a/notmuch-reply.c b/notmuch-reply.c\r
267 index 0f682db..b3d7127 100644\r
268 --- a/notmuch-reply.c\r
269 +++ b/notmuch-reply.c\r
270 @@ -688,15 +688,22 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
271         reply_format_func = notmuch_reply_format_default;\r
272  \r
273      if (decrypt) {\r
274 +#ifdef GMIME_26\r
275 +       /* TODO: GMimePasswordRequestFunc */\r
276 +       params.cryptoctx = g_mime_gpg_context_new (NULL, "gpg");\r
277 +#else\r
278         GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL);\r
279         params.cryptoctx = g_mime_gpg_context_new (session, "gpg");\r
280 +#endif\r
281         if (params.cryptoctx) {\r
282             g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE);\r
283             params.decrypt = TRUE;\r
284         } else {\r
285             fprintf (stderr, "Failed to construct gpg context.\n");\r
286         }\r
287 +#ifndef GMIME_26\r
288         g_object_unref (session);\r
289 +#endif\r
290      }\r
291  \r
292      config = notmuch_config_open (ctx, NULL, NULL);\r
293 diff --git a/notmuch-show.c b/notmuch-show.c\r
294 index 91f566c..10223e0 100644\r
295 --- a/notmuch-show.c\r
296 +++ b/notmuch-show.c\r
297 @@ -76,7 +76,11 @@ static void\r
298  format_part_encstatus_json (int status);\r
299  \r
300  static void\r
301 +#ifdef GMIME_26\r
302 +format_part_sigstatus_json (GMimeSignatureList* siglist);\r
303 +#else\r
304  format_part_sigstatus_json (const GMimeSignatureValidity* validity);\r
305 +#endif\r
306  \r
307  static void\r
308  format_part_content_json (GMimeObject *part);\r
309 @@ -486,6 +490,21 @@ show_text_part_content (GMimeObject *part, GMimeStream *stream_out)\r
310         g_object_unref(stream_filter);\r
311  }\r
312  \r
313 +#ifdef GMIME_26\r
314 +static const char*\r
315 +signature_status_to_string (GMimeSignatureStatus x)\r
316 +{\r
317 +    switch (x) {\r
318 +    case GMIME_SIGNATURE_STATUS_GOOD:\r
319 +       return "good";\r
320 +    case GMIME_SIGNATURE_STATUS_BAD:\r
321 +       return "bad";\r
322 +    case GMIME_SIGNATURE_STATUS_ERROR:\r
323 +       return "error";\r
324 +    }\r
325 +    return "unknown";\r
326 +}\r
327 +#else\r
328  static const char*\r
329  signer_status_to_string (GMimeSignerStatus x)\r
330  {\r
331 @@ -501,6 +520,7 @@ signer_status_to_string (GMimeSignerStatus x)\r
332      }\r
333      return "unknown";\r
334  }\r
335 +#endif\r
336  \r
337  static void\r
338  format_part_start_text (GMimeObject *part, int *part_count)\r
339 @@ -592,6 +612,73 @@ format_part_encstatus_json (int status)\r
340      printf ("}]");\r
341  }\r
342  \r
343 +#ifdef GMIME_26\r
344 +static void\r
345 +format_part_sigstatus_json (GMimeSignatureList *siglist)\r
346 +{\r
347 +    printf (", \"sigstatus\": [");\r
348 +\r
349 +    if (!siglist) {\r
350 +       printf ("]");\r
351 +       return;\r
352 +     }\r
353 +\r
354 +    void *ctx_quote = talloc_new (NULL);\r
355 +    int i;\r
356 +    for (i = 0; i < g_mime_signature_list_length (siglist); i++) {\r
357 +       GMimeSignature *signature = g_mime_signature_list_get_signature (siglist, i);\r
358 +\r
359 +       if (i > 0)\r
360 +           printf (", ");\r
361 +\r
362 +       printf ("{");\r
363 +\r
364 +       /* status */\r
365 +       GMimeSignatureStatus status = g_mime_signature_get_status (signature);\r
366 +       printf ("\"status\": %s",\r
367 +               json_quote_str (ctx_quote,\r
368 +                               signature_status_to_string (status)));\r
369 +\r
370 +       GMimeCertificate *certificate = g_mime_signature_get_certificate (signature);\r
371 +       if (status == GMIME_SIGNATURE_STATUS_GOOD) {\r
372 +           if (certificate)\r
373 +               printf (", \"fingerprint\": %s", json_quote_str (ctx_quote, g_mime_certificate_get_fingerprint (certificate)));\r
374 +           /* these dates are seconds since the epoch; should we\r
375 +            * provide a more human-readable format string? */\r
376 +           time_t created = g_mime_signature_get_created (signature);\r
377 +           if (created != -1)\r
378 +               printf (", \"created\": %d", (int) created);\r
379 +           time_t expires = g_mime_signature_get_expires (signature);\r
380 +           if (expires > 0)\r
381 +               printf (", \"expires\": %d", (int) expires);\r
382 +           /* output user id only if validity is FULL or ULTIMATE. */\r
383 +           /* note that gmime is using the term "trust" here, which\r
384 +            * is WRONG.  It's actually user id "validity". */\r
385 +           if (certificate) {\r
386 +               const char *name = g_mime_certificate_get_name (certificate);\r
387 +               GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate);\r
388 +               if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE))\r
389 +                   printf (", \"userid\": %s", json_quote_str (ctx_quote, name));\r
390 +           }\r
391 +       } else if (certificate) {\r
392 +           const char *key_id = g_mime_certificate_get_key_id (certificate);\r
393 +           if (key_id)\r
394 +               printf (", \"keyid\": %s", json_quote_str (ctx_quote, key_id));\r
395 +       }\r
396 +\r
397 +       GMimeSignatureError errors = g_mime_signature_get_errors (signature);\r
398 +       if (errors != GMIME_SIGNATURE_ERROR_NONE) {\r
399 +           printf (", \"errors\": %d", errors);\r
400 +       }\r
401 +\r
402 +       printf ("}");\r
403 +     }\r
404 +\r
405 +    printf ("]");\r
406 +\r
407 +    talloc_free (ctx_quote);\r
408 +}\r
409 +#else\r
410  static void\r
411  format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
412  {\r
413 @@ -652,6 +739,7 @@ format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
414  \r
415      talloc_free (ctx_quote);\r
416  }\r
417 +#endif\r
418  \r
419  static void\r
420  format_part_content_json (GMimeObject *part)\r
421 @@ -990,13 +1078,20 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
422         } else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) ||\r
423                    (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {\r
424             if (params.cryptoctx == NULL) {\r
425 +#ifdef GMIME_26\r
426 +               /* TODO: GMimePasswordRequestFunc */\r
427 +               if (NULL == (params.cryptoctx = g_mime_gpg_context_new(NULL, "gpg")))\r
428 +#else\r
429                 GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL);\r
430                 if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))\r
431 +#endif\r
432                     fprintf (stderr, "Failed to construct gpg context.\n");\r
433                 else\r
434                     g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE);\r
435 +#ifndef GMIME_26\r
436                 g_object_unref (session);\r
437                 session = NULL;\r
438 +#endif\r
439             }\r
440             if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)\r
441                 params.decrypt = 1;\r
442 diff --git a/show-message.c b/show-message.c\r
443 index 8768889..65269fd 100644\r
444 --- a/show-message.c\r
445 +++ b/show-message.c\r
446 @@ -48,7 +48,11 @@ show_message_part (mime_node_t *node,\r
447         format->part_encstatus (node->decrypt_success);\r
448  \r
449      if (node->verify_attempted && format->part_sigstatus)\r
450 +#ifdef GMIME_26\r
451 +       format->part_sigstatus (node->sig_list);\r
452 +#else\r
453         format->part_sigstatus (node->sig_validity);\r
454 +#endif\r
455  \r
456      format->part_content (part);\r
457  \r
458 -- \r
459 1.7.8.3\r
460 \r