]> git.notmuchmail.org Git - notmuch/commitdiff
Merge branch 'release'
authorDavid Bremner <david@tethera.net>
Sat, 9 Dec 2017 02:19:06 +0000 (22:19 -0400)
committerDavid Bremner <david@tethera.net>
Sat, 9 Dec 2017 02:19:06 +0000 (22:19 -0400)
Conflicts:
        NEWS

Add in NEWS from point release

1  2 
NEWS
configure
debian/changelog
debian/control
emacs/notmuch-show.el
notmuch-show.c
test/T355-smime.sh
test/T450-emacs-show.sh
util/gmime-extra.h

diff --combined NEWS
index 0465b9e8e89cf2dfcbc1de49b67f8430ab08b914,a2ae2691fd5b987674286298bcaa7e9e98afe7f3..d720c1e0cf363ed29e31c8d7ad73535ab36f787b
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,33 -1,20 +1,50 @@@
 +Notmuch 0.26 (UNRELEASED)
 +=========================
 +
 +Test Suite
 +----------
 +
 +Out-of-tree builds
 +
 +  The test suite now works properly with out-of-tree builds, i.e. with
 +  separate source and build directories. The --root option to tests
 +  has been dropped. The same can now be achieved more reliably using
 +  out-of-tree builds.
 +
 +Encrypted Mail
 +--------------
 +
 +Indexing cleartext of encrypted e-mails
 +
 +  It's now possible to include the cleartext of encrypted e-mails in
 +  the notmuch index.  This makes it possible to search your encrypted
 +  e-mails with the same ease as searching cleartext.  This can be done
 +  on a per-message basis with the --decrypt argument to indexing
 +  commands (new, insert, reindex), or by default by running "notmuch
 +  config set index.decrypt true".
 +
 +  Note that the contents of the index are sufficient to roughly
 +  reconstruct the cleartext of the message itself, so please ensure
 +  that the notmuch index itself is adequately protected.  DO NOT USE
 +  this feature without considering the security of your index.
 +
+ Notmuch 0.25.3 (2017-12-08)
+ ===========================
+ Emacs
+ -----
+ Extend mitigation (disabling handling x-display in text/enriched) for
+ Emacs bug #28350 to Emacs versions before 24.4 (i.e. without
+ `advice-add`).
+ Command Line Interface
+ ----------------------
+ Correctly report userid validity. Fix test suite failure for GMime >=
+ 3.0.3. This change raises the minimum supported version of GMime 3.x
+ to 3.0.3.
  Notmuch 0.25.2 (2017-11-05)
  ===========================
  
diff --combined configure
index fc70031b31f746ac9fa452b846c2a2340ff1be9f,daee5a6e1637371cdda96d16c052ddd04a1ebfe6..b177b14130f0a966ccec5b1453affbf92ad577c7
+++ b/configure
@@@ -40,6 -40,10 +40,6 @@@ if [ "$srcdir" != "." ]; the
        cp "$srcdir"/"$dir"/Makefile "$dir"
      done
  
 -    # Easiest way to get the test suite to work is to just copy the
 -    # whole thing into the build directory.
 -    cp -a "$srcdir"/test/* test
 -
      # Emacs only likes to generate compiled files next to the .el files
      # by default so copy these as well (which is not ideal).
      cp -a "$srcdir"/emacs/*.el emacs
  # we need to have a version >= 2.6.5 to avoid a crypto bug. We need
  # 2.6.7 for permissive "From " header handling.
  GMIME_MINVER=2.6.7
+ GMIME3_MINVER=3.0.3
  
  printf "Checking for GMime development files... "
- if pkg-config --exists "gmime-3.0"; then
+ if pkg-config --exists "gmime-3.0 > $GMIME3_MINVER"; then
      printf "Yes (3.0).\n"
      have_gmime=1
      gmime_cflags=$(pkg-config --cflags gmime-3.0)
      gmime_ldflags=$(pkg-config --libs gmime-3.0)
      gmime_major=3
 +    have_gmime_session_keys=1
  elif pkg-config --exists "gmime-2.6 >= $GMIME_MINVER"; then
      printf "Yes (2.6).\n"
      have_gmime=1
      gmime_cflags=$(pkg-config --cflags gmime-2.6)
      gmime_ldflags=$(pkg-config --libs gmime-2.6)
      gmime_major=2
 +    if pkg-config --exists "gmime-2.6 >= 2.6.21"; then
 +        have_gmime_session_keys=1
 +    else
 +        have_gmime_session_keys=0
 +    fi
  else
      have_gmime=0
 +    have_gmime_session_keys=0
      printf "No.\n"
      errors=$((errors + 1))
  fi
@@@ -556,7 -554,7 +557,7 @@@ f
  printf "Checking for python... "
  have_python=0
  
 -for name in ${PYTHON} python python2 python3; do
 +for name in ${PYTHON} python3 python python2; do
      if command -v $name > /dev/null; then
        have_python=1
        python=$name
@@@ -649,15 -647,6 +650,15 @@@ if [ $WITH_DESKTOP = "1" ]; the
      fi
  fi
  
 +printf "Checking for cppcheck... "
 +if command -v cppcheck > /dev/null; then
 +    have_cppcheck=1
 +    printf "Yes.\n"
 +else
 +    have_cppcheck=0
 +    printf "No.\n"
 +fi
 +
  libdir_in_ldconfig=0
  
  printf "Checking which platform we are on... "
@@@ -1077,9 -1066,6 +1078,9 @@@ zsh_completion_dir = ${ZSHCOMLETIONDIR:
  # build its own version)
  HAVE_CANONICALIZE_FILE_NAME = ${have_canonicalize_file_name}
  
 +# Whether the cppcheck static checker is available
 +HAVE_CPPCHECK = ${have_cppcheck}
 +
  # Whether the getline function is available (if not, then notmuch will
  # build its own version)
  HAVE_GETLINE = ${have_getline}
@@@ -1103,9 -1089,6 +1104,9 @@@ HAVE_TIMEGM = ${have_timegm
  # Whether struct dirent has d_type (if not, then notmuch will use stat)
  HAVE_D_TYPE = ${have_d_type}
  
 +# Whether the GMime version can handle extraction and reuse of session keys
 +HAVE_GMIME_SESSION_KEYS = ${have_gmime_session_keys}
 +
  # Whether the Xapian version in use supports compaction
  HAVE_XAPIAN_COMPACT = ${have_xapian_compact}
  
@@@ -1184,7 -1167,6 +1185,7 @@@ COMMON_CONFIGURE_CFLAGS = \
        \$(GMIME_CFLAGS) \$(TALLOC_CFLAGS) \$(ZLIB_CFLAGS)      \\
        -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \$(VALGRIND_CFLAGS)   \\
        -DHAVE_GETLINE=\$(HAVE_GETLINE)                         \\
 +      -DWITH_EMACS=\$(WITH_EMACS)                             \\
        -DHAVE_CANONICALIZE_FILE_NAME=\$(HAVE_CANONICALIZE_FILE_NAME) \\
        -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR)                   \\
        -DHAVE_STRSEP=\$(HAVE_STRSEP)                           \\
        -DHAVE_D_TYPE=\$(HAVE_D_TYPE)                           \\
        -DSTD_GETPWUID=\$(STD_GETPWUID)                         \\
        -DSTD_ASCTIME=\$(STD_ASCTIME)                           \\
 +      -DHAVE_GMIME_SESSION_KEYS=\$(HAVE_GMIME_SESSION_KEYS)   \\
        -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT)           \\
        -DSILENCE_XAPIAN_DEPRECATION_WARNINGS                   \\
        -DHAVE_XAPIAN_FIELD_PROCESSOR=\$(HAVE_XAPIAN_FIELD_PROCESSOR) \\
@@@ -1221,9 -1202,6 +1222,9 @@@ NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR=${h
  # Whether the Xapian version in use supports lock retry
  NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK=${have_xapian_db_retry_lock}
  
 +# Whether the GMime version can handle extraction and reuse of session keys
 +NOTMUCH_HAVE_GMIME_SESSION_KEYS=${have_gmime_session_keys}
 +
  # Which backend will Xapian use by default?
  NOTMUCH_DEFAULT_XAPIAN_BACKEND=${default_xapian_backend}
  
diff --combined debian/changelog
index decef1e95f2d6b3ff3f6512129c57c1fb28bcdd3,0b636f3a55ca8f5f5ee3be41faa5ec0f671340d5..ec344ef49e7909034d7abe3072fc85f7cbe97df7
@@@ -1,3 -1,12 +1,12 @@@
+ notmuch (0.25.3-1) unstable; urgency=medium
+   * Upstream bugfix release. Fix for OpenPGP UID validity reporting,
+     and build failure with GMime 3.0.3+.
+   * Bug fix: "notmuch FTBFS on Alpha due to broken gdb", thanks to
+     Michael Cree (Closes: #881028).
+  -- David Bremner <bremner@debian.org>  Fri, 08 Dec 2017 21:08:00 -0400
  notmuch (0.25.2-1) unstable; urgency=medium
  
    * New upstream bugfix release: fix for segfault when compiled
@@@ -836,7 -845,7 +845,7 @@@ notmuch (0.9~rc2-1) experimental; urgen
      - New SONAME for libnotmuch
      - bindings changes for ruby and python
    * Less non-text parts reported in replies.
 -  * emacs: provide button action to fetch unknown gpg keys 
 +  * emacs: provide button action to fetch unknown gpg keys
  
   -- David Bremner <bremner@debian.org>  Fri, 07 Oct 2011 18:53:04 -0300
  
@@@ -845,7 -854,7 +854,7 @@@ notmuch (0.9~rc1-1) experimental; urgen
    * Upstream release candidate
      - Atomicity improvements, thanks to Austin Clements
      - Add missing call to g_type_init, thanks to Aaron Ecay
 -  * notmuch-emacs: add versioned dependency on notmuch.  
 +  * notmuch-emacs: add versioned dependency on notmuch.
      (Closes: #642240).
  
   -- David Bremner <bremner@debian.org>  Sun, 25 Sep 2011 11:26:01 -0300
@@@ -854,7 -863,7 +863,7 @@@ notmuch (0.8-1) unstable; urgency=lo
  
    * New upstream version.
      - Improved handling of message/rfc822 parts
 -    - Improved Build system portability 
 +    - Improved Build system portability
      - Documentation update for Ruby bindings
      - Unicode, iterator, PEP8 changes for python bindings
  
@@@ -936,7 -945,7 +945,7 @@@ notmuch (0.6~254) experimental; urgency
  
    [ Jameson Rollins ]
    * Bump standards version to 3.9.2 (No changes).
 -  
 +
   -- David Bremner <bremner@debian.org>  Thu, 23 Jun 2011 07:50:05 -0300
  
  notmuch (0.6~237) experimental; urgency=low
@@@ -981,8 -990,8 +990,8 @@@ notmuch (0.6~171) experimental; urgency
    * notmuch reply: Avoid segmentation fault when printing multiple parts
    * notmuch show: New part output handling.
    * emacs: Show cleaner `From:' addresses in the summary line.
 -  * emacs: Add custom `notmuch-show-elide-same-subject', 
 -    `notmuch-show-always-show-subject' 
 +  * emacs: Add custom `notmuch-show-elide-same-subject',
 +    `notmuch-show-always-show-subject'
    * emacs: Render text/x-vcalendar parts.
    * emacs: Add `notmuch-show-multipart/alternative-discouraged'.
    * vim: parse 'from' address, use sendmail directly, implement archive in
@@@ -1114,7 -1123,7 +1123,7 @@@ notmuch (0.2) unstable; urgency=lo
    * Fix headers to be properly decoded in "notmuch reply"
    * emacs: Show the last few lines of citations as well as the first few lines.
    * emacs: The '+' and '-' commands can now add and remove tags by region.
 -  * emacs: More meaningful buffer names for thread-view buffers. 
 +  * emacs: More meaningful buffer names for thread-view buffers.
    * emacs: Customized colors of threads in search view based on tags.
  
   -- Carl Worth <cworth@debian.org>  Fri, 16 Apr 2010 10:20:23 -0700
diff --combined debian/control
index 5112988653f149b3adcef488a6fc5e86ddc98c01,b316ce09082a7a84de95c5738890b7b93cd009ee..f644695b94bef2700f1f8a71c70e02fbd63af65d
@@@ -11,24 -11,24 +11,24 @@@ Build-Depends
   debhelper (>= 9),
   pkg-config,
   libxapian-dev,
-  libgmime-3.0-dev | libgmime-2.6-dev (>= 2.6.7~),
+  libgmime-3.0-dev (>= 3.0.3~) | libgmime-2.6-dev (>= 2.6.7~),
   libtalloc-dev,
   libz-dev,
   python-all (>= 2.6.6-3~),
   python3-all (>= 3.1.2-7~),
   dh-python,
   dh-elpa (>= 1.3),
 - python-sphinx (>= 1.0),
 + python3-sphinx,
   ruby, ruby-dev (>>1:1.9.3~),
   emacs25-nox | emacs25 (>=25~) | emacs25-lucid (>=25~) |
   emacs24-nox | emacs24 (>=24~) | emacs24-lucid (>=24~) |
   emacs23-nox | emacs23 (>=23~) | emacs23-lucid (>=23~),
-  gdb [!s390x !ia64 !armel !ppc64el !mips !mipsel !mips64el !kfreebsd-any],
+  gdb [!s390x !ia64 !armel !ppc64el !mips !mipsel !mips64el !kfreebsd-any !alpha],
   dtach (>= 0.8),
   gpgsm <!nocheck>,
   gnupg <!nocheck>,
   bash-completion (>=1.9.0~)
 -Standards-Version: 4.0.0
 +Standards-Version: 4.1.1
  Homepage: https://notmuchmail.org/
  Vcs-Git: git://notmuchmail.org/git/notmuch
  Vcs-Browser: https://git.notmuchmail.org/git/notmuch
@@@ -113,6 -113,7 +113,6 @@@ Description: Ruby interface to the notm
  
  Package: notmuch-emacs
  Section: oldlibs
 -Priority: extra
  Architecture: all
  Depends: elpa-notmuch, ${misc:Depends}
  Description: thread-based email index, search and tagging (transitional package)
diff --combined emacs/notmuch-show.el
index 9939027700952c0f5255700cc9be5a274ae4f99b,99e17185c0d2e729e504413ae7aab566129c8ff1..43debb260610d724a6100d74d7cf983c54ffd149
@@@ -773,14 -773,19 +773,19 @@@ will return nil if the CID is unknown o
  (defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth depth button)
    (notmuch-show-insert-part-text/calendar msg part content-type nth depth button))
  
- ;; https://bugs.gnu.org/28350
- (defun notmuch-show--enriched-decode-display-prop (start end &optional param)
-   (list start end))
- (defun notmuch-show-insert-part-text/enriched (msg part content-type nth depth button)
-   (advice-add 'enriched-decode-display-prop :override
-             #'notmuch-show--enriched-decode-display-prop)
-   nil)
+ (if (version< emacs-version "25.3")
+     ;; https://bugs.gnu.org/28350
+     ;;
+     ;; For newer emacs, we fall back to notmuch-show-insert-part-*/*
+     ;; (see notmuch-show-handlers-for)
+     (defun notmuch-show-insert-part-text/enriched (msg part content-type nth depth button)
+       ;; By requiring enriched below, we ensure that the function enriched-decode-display-prop
+       ;; is defined before it will be shadowed by the letf below. Otherwise the version
+       ;; in enriched.el may be loaded a bit later and used instead (for the first time).
+       (require 'enriched)
+       (letf (((symbol-function 'enriched-decode-display-prop)
+                (lambda (start end &optional param) (list start end))))
+       (notmuch-show-insert-part-*/* msg part content-type nth depth button))))
  
  (defun notmuch-show-get-mime-type-of-application/octet-stream (part)
    ;; If we can deduce a MIME type from the filename of the attachment,
@@@ -1269,9 -1274,7 +1274,9 @@@ matched.
      ;; aren't wiped out.
      (setq notmuch-show-thread-id thread-id
          notmuch-show-parent-buffer parent-buffer
 -        notmuch-show-query-context query-context
 +        notmuch-show-query-context (if (or (string= query-context "")
 +                                           (string= query-context "*"))
 +                                       nil query-context)
  
          notmuch-show-process-crypto notmuch-crypto-process-mime
          ;; If `elide-toggle', invert the default value.
diff --combined notmuch-show.c
index 4e22424bb713cb03ae00f0710a3af838089b0e87,bb44d93820b1f9236078b5ee42e5ef2e90575abb..d5adc37007b884a9719be042a1374667c176c81a
@@@ -196,7 -196,7 +196,7 @@@ _is_from_line (const char *line
  
  void
  format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
 -                       notmuch_bool_t reply)
 +                       bool reply)
  {
      /* Any changes to the JSON or S-Expression format should be
       * reflected in the file devel/schemata. */
@@@ -283,7 -283,7 +283,7 @@@ show_text_part_content (GMimeObject *pa
        return;
  
      stream_filter = g_mime_stream_filter_new (stream_out);
 -    crlf_filter = g_mime_filter_crlf_new (FALSE, FALSE);
 +    crlf_filter = g_mime_filter_crlf_new (false, false);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER (stream_filter),
                             crlf_filter);
      g_object_unref (crlf_filter);
  
      if (flags & NOTMUCH_SHOW_TEXT_PART_REPLY) {
        GMimeFilter *reply_filter;
 -      reply_filter = g_mime_filter_reply_new (TRUE);
 +      reply_filter = g_mime_filter_reply_new (true);
        if (reply_filter) {
            g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
                                      reply_filter);
@@@ -350,7 -350,7 +350,7 @@@ do_format_signature_errors (sprinter_t 
      for (unsigned int i = 0; i < array_map_len; i++) {
        if (errors & key_map[i].bit) {
            sp->map_key (sp, key_map[i].string);
 -          sp->boolean (sp, TRUE);
 +          sp->boolean (sp, true);
        }
      }
  
@@@ -446,15 -446,11 +446,11 @@@ format_part_sigstatus_sprinter (sprinte
                sp->map_key (sp, "expires");
                sp->integer (sp, expires);
            }
-           /* output user id only if validity is FULL or ULTIMATE. */
-           /* note that gmime is using the term "trust" here, which
-            * is WRONG.  It's actually user id "validity". */
            if (certificate) {
-               const char *name = g_mime_certificate_get_uid (certificate);
-               GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate);
-               if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE)) {
+               const char *uid = g_mime_certificate_get_valid_userid (certificate);
+               if (uid) {
                    sp->map_key (sp, "userid");
-                   sp->string (sp, name);
+                   sp->string (sp, uid);
                }
            }
        } else if (certificate) {
@@@ -490,7 -486,7 +486,7 @@@ format_part_text (const void *ctx, spri
      GMimeObject *meta = node->envelope_part ?
        GMIME_OBJECT (node->envelope_part) : node->part;
      GMimeContentType *content_type = g_mime_object_get_content_type (meta);
 -    const notmuch_bool_t leaf = GMIME_IS_PART (node->part);
 +    const bool leaf = GMIME_IS_PART (node->part);
      GMimeStream *stream = params->out_stream;
      const char *part_type;
      int i;
@@@ -603,8 -599,8 +599,8 @@@ format_omitted_part_meta_sprinter (spri
  
  void
  format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
 -                    notmuch_bool_t first, notmuch_bool_t output_body,
 -                    notmuch_bool_t include_html)
 +                    bool output_body,
 +                    bool include_html)
  {
      /* Any changes to the JSON or S-Expression format should be
       * reflected in the file devel/schemata. */
        format_message_sprinter (sp, node->envelope_file);
  
        sp->map_key (sp, "headers");
 -      format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE);
 +      format_headers_sprinter (sp, GMIME_MESSAGE (node->part), false);
  
        if (output_body) {
            sp->map_key (sp, "body");
            sp->begin_list (sp);
 -          format_part_sprinter (ctx, sp, mime_node_child (node, 0), first, TRUE, include_html);
 +          format_part_sprinter (ctx, sp, mime_node_child (node, 0), true, include_html);
            sp->end (sp);
        }
        sp->end (sp);
        sp->begin_map (sp);
  
        sp->map_key (sp, "headers");
 -      format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE);
 +      format_headers_sprinter (sp, GMIME_MESSAGE (node->part), false);
  
        sp->map_key (sp, "body");
        sp->begin_list (sp);
      }
  
      for (i = 0; i < node->nchildren; i++)
 -      format_part_sprinter (ctx, sp, mime_node_child (node, i), i == 0, TRUE, include_html);
 +      format_part_sprinter (ctx, sp, mime_node_child (node, i), true, include_html);
  
      /* Close content structures */
      for (i = 0; i < nclose; i++)
@@@ -735,7 -731,7 +731,7 @@@ format_part_sprinter_entry (const void 
                            mime_node_t *node, unused (int indent),
                            const notmuch_show_params_t *params)
  {
 -    format_part_sprinter (ctx, sp, node, TRUE, params->output_body, params->include_html);
 +    format_part_sprinter (ctx, sp, node, params->output_body, params->include_html);
  
      return NOTMUCH_STATUS_SUCCESS;
  }
@@@ -898,8 -894,8 +894,8 @@@ show_messages (void *ctx
               notmuch_show_params_t *params)
  {
      notmuch_message_t *message;
 -    notmuch_bool_t match;
 -    notmuch_bool_t excluded;
 +    bool match;
 +    bool excluded;
      int next_indent;
      notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
  
@@@ -1081,36 -1077,35 +1077,36 @@@ notmuch_show_command (notmuch_config_t 
      sprinter_t *sprinter;
      notmuch_show_params_t params = {
        .part = -1,
 -      .omit_excluded = TRUE,
 -      .output_body = TRUE,
 +      .omit_excluded = true,
 +      .output_body = true,
 +      .crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
      };
      int format = NOTMUCH_FORMAT_NOT_SPECIFIED;
 -    int exclude = TRUE;
 -
 -    /* This value corresponds to neither true nor false being passed
 -     * on the command line */
 -    int entire_thread = -1;
 -    notmuch_bool_t single_message;
 +    bool exclude = true;
 +    bool entire_thread_set = false;
 +    bool single_message;
 +    bool decrypt = false;
 +    bool decrypt_set = false;
  
      notmuch_opt_desc_t options[] = {
 -      { NOTMUCH_OPT_KEYWORD, &format, "format", 'f',
 +      { .opt_keyword = &format, .name = "format", .keywords =
          (notmuch_keyword_t []){ { "json", NOTMUCH_FORMAT_JSON },
                                  { "text", NOTMUCH_FORMAT_TEXT },
                                  { "sexp", NOTMUCH_FORMAT_SEXP },
                                  { "mbox", NOTMUCH_FORMAT_MBOX },
                                  { "raw", NOTMUCH_FORMAT_RAW },
                                  { 0, 0 } } },
 -      { NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &exclude, "exclude", 'x', 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &entire_thread, "entire-thread", 't', 0 },
 -      { NOTMUCH_OPT_INT, &params.part, "part", 'p', 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &params.crypto.decrypt, "decrypt", 'd', 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &params.crypto.verify, "verify", 'v', 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &params.output_body, "body", 'b', 0 },
 -      { NOTMUCH_OPT_BOOLEAN, &params.include_html, "include-html", 0, 0 },
 -      { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
 -      { 0, 0, 0, 0, 0 }
 +      { .opt_int = &notmuch_format_version, .name = "format-version" },
 +      { .opt_bool = &exclude, .name = "exclude" },
 +      { .opt_bool = &params.entire_thread, .name = "entire-thread",
 +        .present = &entire_thread_set },
 +      { .opt_int = &params.part, .name = "part" },
 +      { .opt_bool = &decrypt, .name = "decrypt", .present = &decrypt_set },
 +      { .opt_bool = &params.crypto.verify, .name = "verify" },
 +      { .opt_bool = &params.output_body, .name = "body" },
 +      { .opt_bool = &params.include_html, .name = "include-html" },
 +      { .opt_inherit = notmuch_shared_options },
 +      { }
      };
  
      opt_index = parse_arguments (argc, argv, options, 1);
  
      notmuch_process_shared_options (argv[0]);
  
 -    /* decryption implies verification */
 -    if (params.crypto.decrypt)
 -      params.crypto.verify = TRUE;
 +    if (decrypt_set) {
 +      if (decrypt) {
 +          /* we do not need or want to ask for session keys */
 +          params.crypto.decrypt = NOTMUCH_DECRYPT_NOSTASH;
 +          /* decryption implies verification */
 +          params.crypto.verify = true;
 +      } else {
 +          params.crypto.decrypt = NOTMUCH_DECRYPT_FALSE;
 +      }
 +    }
  
      /* specifying a part implies single message display */
      single_message = params.part >= 0;
        }
      } else if (format == NOTMUCH_FORMAT_RAW) {
        /* raw format only supports single message display */
 -      single_message = TRUE;
 +      single_message = true;
      }
  
      notmuch_exit_if_unsupported_format ();
  
 -    /* Default is entire-thread = FALSE except for format=json and
 +    /* Default is entire-thread = false except for format=json and
       * format=sexp. */
 -    if (entire_thread != FALSE && entire_thread != TRUE) {
 -      if (format == NOTMUCH_FORMAT_JSON || format == NOTMUCH_FORMAT_SEXP)
 -          params.entire_thread = TRUE;
 -      else
 -          params.entire_thread = FALSE;
 -    } else {
 -      params.entire_thread = entire_thread;
 -    }
 +    if (! entire_thread_set &&
 +      (format == NOTMUCH_FORMAT_JSON || format == NOTMUCH_FORMAT_SEXP))
 +      params.entire_thread = true;
  
      if (!params.output_body) {
        if (params.part > 0) {
            fprintf (stderr, "Warning: --body=false is incompatible with --part > 0. Disabling.\n");
 -          params.output_body = TRUE;
 +          params.output_body = true;
        } else {
            if (format != NOTMUCH_FORMAT_JSON && format != NOTMUCH_FORMAT_SEXP)
                fprintf (stderr,
            }
        }
  
 -      if (exclude == FALSE) {
 -          notmuch_query_set_omit_excluded (query, FALSE);
 -          params.omit_excluded = FALSE;
 +      if (exclude == false) {
 +          notmuch_query_set_omit_excluded (query, false);
 +          params.omit_excluded = false;
        }
  
        ret = do_show (config, query, formatter, sprinter, &params);
      g_mime_stream_flush (params.out_stream);
      g_object_unref (params.out_stream);
  
 -    notmuch_crypto_cleanup (&params.crypto);
 +    _notmuch_crypto_cleanup (&params.crypto);
      notmuch_query_destroy (query);
      notmuch_database_destroy (notmuch);
  
diff --combined test/T355-smime.sh
index 1523f17b9f6f26f184deb01f98efc80a79a790c2,532cd84baff07f9877cab45025796e34615bfc9b..be45e3b11f22655833c7de7978b8cb68bbe21cde
@@@ -1,7 -1,7 +1,7 @@@
  #!/usr/bin/env bash
  
  test_description='S/MIME signature verification and decryption'
 -. ./test-lib.sh || exit 1
 +. $(dirname "$0")/test-lib.sh || exit 1
  
  add_gpgsm_home ()
  {
@@@ -10,7 -10,7 +10,7 @@@
      _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; }
      at_exit_function _gnupg_exit
      mkdir -m 0700 "$GNUPGHOME"
 -    gpgsm --no-tty --no-common-certs-import --disable-dirmngr --import < $TEST_DIRECTORY/smime/test.crt >"$GNUPGHOME"/import.log 2>&1
 +    gpgsm --no-tty --no-common-certs-import --disable-dirmngr --import < $NOTMUCH_SRCDIR/test/smime/test.crt >"$GNUPGHOME"/import.log 2>&1
      fpr=$(gpgsm  --list-key test_suite@notmuchmail.org | sed -n 's/.*fingerprint: //p')
      echo "$fpr S relax" >> $GNUPGHOME/trustlist.txt
      test_debug "cat $GNUPGHOME/import.log"
@@@ -19,7 -19,7 +19,7 @@@
  test_require_external_prereq openssl
  test_require_external_prereq gpgsm
  
 -cp $TEST_DIRECTORY/smime/key+cert.pem test_suite.pem
 +cp $NOTMUCH_SRCDIR/test/smime/key+cert.pem test_suite.pem
  
  FINGERPRINT=$(openssl x509 -fingerprint -in test_suite.pem -noout | sed -e 's/^.*=//' -e s/://g)
  
@@@ -41,13 -41,19 +41,19 @@@ test_expect_success 
  
  test_begin_subtest "Signature verification (openssl)"
  notmuch show --format=raw subject:"test signed message 001" |\
 -    openssl smime -verify -CAfile $TEST_DIRECTORY/smime/test.crt 2>OUTPUT
 +    openssl smime -verify -CAfile $NOTMUCH_SRCDIR/test/smime/test.crt 2>OUTPUT
  cat <<EOF > EXPECTED
  Verification successful
  EOF
  test_expect_equal_file EXPECTED OUTPUT
  
  test_begin_subtest "signature verification (notmuch CLI)"
+ if [ "${NOTMUCH_GMIME_MAJOR}" -lt 3 ]; then
+     # gmime 2 can't report User IDs properly for S/MIME
+     USERID=''
+ else
+     USERID='"userid": "CN=Notmuch Test Suite",'
+ fi
  output=$(notmuch show --format=json --verify subject:"test signed message 001" \
      | notmuch_json_show_sanitize \
      | sed -e 's|"created": [-1234567890]*|"created": 946728000|' \
@@@ -65,7 -71,7 +71,7 @@@ expected='[[[{"id": "XXXXX"
   "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
   "body": [{"id": 1,
   "sigstatus": [{"fingerprint": "'$FINGERPRINT'",
-  "status": "good",
+  "status": "good",'$USERID'
   "expires": 424242424,
   "created": 946728000}],
   "content-type": "multipart/signed",
@@@ -86,7 -92,7 +92,7 @@@ test_expect_equal_json 
  test_begin_subtest "Decryption and signature verification (openssl)"
  notmuch show --format=raw subject:"test encrypted message 001" |\
      openssl smime -decrypt -recip test_suite.pem |\
 -    openssl smime -verify -CAfile $TEST_DIRECTORY/smime/test.crt 2>OUTPUT
 +    openssl smime -verify -CAfile $NOTMUCH_SRCDIR/test/smime/test.crt 2>OUTPUT
  cat <<EOF > EXPECTED
  Verification successful
  EOF
diff --combined test/T450-emacs-show.sh
index d6aa5b4158b85a10bf67f857fbcfb5c56a428ef4,6a458565bc9a5210d737162ecf4fe31d5c5dd011..8db0e49bcdd4df797f00f14a829d2c3b7fb331ea
@@@ -1,9 -1,9 +1,9 @@@
  #!/usr/bin/env bash
  
  test_description="emacs notmuch-show view"
 -. ./test-lib.sh || exit 1
 +. $(dirname "$0")/test-lib.sh || exit 1
  
 -EXPECTED=$TEST_DIRECTORY/emacs-show.expected-output
 +EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output
  
  add_email_corpus
  
@@@ -198,5 -198,14 +198,14 @@@ This is an erro
  stdout:
  This is output"
  
+ test_begin_subtest "text/enriched exploit mitigation"
+ add_message '[content-type]="text/enriched"
+              [body]="
+ <x-display><param>(when (progn (read-only-mode -1) (insert ?p ?0 ?w ?n ?e ?d)) nil)</param>test</x-display>
+ "'
+ test_emacs '(notmuch-show "id:'$gen_msg_id'")
+       (test-visible-output "OUTPUT.raw")'
+ output=$(head -1 OUTPUT.raw|cut -f1-4 -d' ')
+ test_expect_equal "$output" "Notmuch Test Suite <test_suite@notmuchmail.org>"
  
  test_done
diff --combined util/gmime-extra.h
index 40bf1454d00dfee0496fd186b60db9a03c1d93c4,18888b5545df2405f76e2f24f6d08ec0db2af9b9..ca822b8cf53b4e0b1b0509b3dcb5d4d92d46ca54
@@@ -16,11 -16,10 +16,9 @@@ GMimeStream *g_mime_stream_stdout_new(v
  #define g_mime_2_6_unref(obj) g_object_unref (obj)
  #define g_mime_3_unused(arg) arg
  #define g_mime_certificate_get_fpr16(cert) g_mime_certificate_get_key_id (cert)
- #define g_mime_certificate_get_uid(cert) g_mime_certificate_get_name (cert);
  #else /* GMime >= 3.0 */
 -typedef GMimeAddressType GMimeRecipientType;
  
  #define GMIME_ENABLE_RFC_2047_WORKAROUNDS 0xdeadbeef
- #define g_mime_certificate_get_uid(cert) g_mime_certificate_get_key_id (cert);
  #define g_mime_content_type_to_string(c) g_mime_content_type_get_mime_type (c)
  #define g_mime_filter_crlf_new(encode,dots) g_mime_filter_dos2unix_new (FALSE)
  #define g_mime_gpg_context_new(func,path) g_mime_gpg_context_new ()
@@@ -29,6 -28,7 +27,6 @@@
  #define g_mime_init(flags) g_mime_init()
  #define g_mime_message_add_recipient(m,t,n,a) g_mime_message_add_mailbox (m,t,n,a)
  #define g_mime_message_set_subject(m,s) g_mime_message_set_subject(m,s,NULL)
 -#define g_mime_multipart_encrypted_decrypt(mpe,ctx,out,err) g_mime_multipart_encrypted_decrypt(mpe, GMIME_DECRYPT_NONE, NULL, out, err)
  #define g_mime_multipart_signed_verify(mps,ctx,err) g_mime_multipart_signed_verify(mps, GMIME_ENCRYPT_NONE, err)
  #define g_mime_object_write_to_stream(o,s) g_mime_object_write_to_stream (o,NULL,s)
  #define g_mime_object_set_header(o,h,v) g_mime_object_set_header (o,h,v,NULL)
@@@ -45,15 -45,6 +43,6 @@@ typedef GMimeAddressType GMimeRecipient
  
  typedef GMimeSignatureStatus GMimeSignatureError;
  
- typedef GMimeTrust GMimeCertificateTrust;
- #define GMIME_CERTIFICATE_TRUST_UNKNOWN GMIME_TRUST_UNKNOWN
- #define GMIME_CERTIFICATE_TRUST_UNDEFINED GMIME_TRUST_UNDEFINED
- #define GMIME_CERTIFICATE_TRUST_NEVER GMIME_TRUST_NEVER
- #define GMIME_CERTIFICATE_TRUST_MARGINAL GMIME_TRUST_MARGINAL
- #define GMIME_CERTIFICATE_TRUST_FULLY GMIME_TRUST_FULL
- #define GMIME_CERTIFICATE_TRUST_ULTIMATE GMIME_TRUST_ULTIMATE
  #define g_mime_2_6_unref(obj) /*ignore*/
  #define g_mime_3_unused(arg) unused(arg)
  #endif
@@@ -105,4 -96,10 +94,10 @@@ gboolean g_mime_signature_status_bad (G
  gboolean g_mime_signature_status_error (GMimeSignatureError status);
  
  gint64 g_mime_utils_header_decode_date_unix (const char *date);
+ /**
+  * Return string for valid User ID (or NULL if no valid User ID exists)
+  */
+ const char * g_mime_certificate_get_valid_userid (GMimeCertificate *cert);
  #endif