Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Dear release team,

I uploaded a new version of mblaze, which reset the package's transition
countdown, which will cause it to miss the hard freeze window:

  https://qa.debian.org/excuses.php?package=mblaze


I did so as the newest upstream release includes security-relevant changes:

  mblaze (0.5.1-1) unstable; urgency=high (security fixes)
  
    * New upstream release (2019-03-03)
      + Fixes for buffer-overflows, found by fuzzing.
      + Fixes for memleaks.
  
    * Remove unused lintian override
    * debian/rules: Remove useless dh_missing invocation.
      A single binary package is being produced.
  
   -- Nicolas Braud-Santoni <ni...@debian.org>  Mon, 04 Mar 2019 18:40:01 +0100


Moreover, version 0.5-1 closes several Debian bugs (including a RC one):

  mblaze (0.5-1) unstable; urgency=medium
  
    * New upstream release (2019-02-09)
      + Closes: 921891
      + GNUmakefile: correct reference to SOURCE_DATE_EPOCH, patch by Chris Lamb
        Closes: #907537 
  
    * Rename mless and msort to mblaze-less and mblaze-sort
      Closes: #887988 correctly, avoids conflicts on mpdtoys & msort
  
    * Switch to debhelper 12.
      The compatibility level is now controlled by a Build-Depends.
  
    * Declare compliance with policy v4.2.1.
      No change required.
  
    * debian/rules
      + Make dh_missing fail the build
      + Symlink docs from mblaze-* to mblaze
  
   -- Nicolas Braud-Santoni <ni...@debian.org>  Tue, 12 Feb 2019 11:44:33 +0100


The debdiff is attached.


Best,

  nicoo

unblock mblaze/0.5.1-1

- -- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-2-amd64 (SMP w/4 CPU cores)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL 
set to en_US.UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set 
to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

-----BEGIN PGP SIGNATURE-----

iQJFBAEBCgAvFiEEU7EqA8ZVHYoLJhPE5vmO4pLV7MsFAlx9wacRHG5pY29vQGRl
Ymlhbi5vcmcACgkQ5vmO4pLV7MsdVw//X2febyz+EoW+0lN1iSGZYSeqJhIzC11m
zOippy/KMeCjbjPuqgI1xBTuLBzNYbV+Y6gwf94+4O8KdqRcxHhjP1zE5ttWqVQD
bzMmIB4hr1xIua11OG9Oy1FdG+Fs49nqmaYvo4q7k0qg0VfohwBJEuHnPZEea14y
iT/7o/nnhqNnhZIlNv1dhCJWA00hlMt18/7QjG9bSdYRo8iJUdNmkVY750Adv1+S
MicSLHtnGy+/2AGYxU/0oW6sPFPBLiXli9gpqN6KhwdF4L6aroRnMswfbThxtc/s
GmFETyK/UIJ/6N5pt3ff9fSeU3CHvJclNm4TljKFPfGg4r49Oj+rZeXepddg5Acv
7AaXhB3gMZEwgKtmM02kqwMDdWPRZ3Fwlo6La/3ZJuflNnaBgytlr90Bh8lCAyPI
rMjrtP0jcWq1EIRWUgqCaIPFMfvwPMAyTRtORfzOdGtC9ZOBnEBzuqNgHqv5qpEt
dLQGHFRQJwDrpFc0veWqXZ01UcIO39fNFIMxUf1nAYw80NRcMRvvCT8IUucCLybq
PKn6lLwUfyu+MbfIdyuw7F9hSgMVINmTX1lH8u+Mk1L9p2sn+96JXh1YWAVtrVhn
+k8sSA2P5lOBWQLrRtq34VIjv9zlNRKz+5JO4vbdQ9AuZI+0C77PKK08nnixPCrc
EL4q69REWC0=
=AOMb
-----END PGP SIGNATURE-----
diff -Nru mblaze-0.4/blaze822.c mblaze-0.5.1/blaze822.c
--- mblaze-0.4/blaze822.c       2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/blaze822.c     2019-03-03 17:12:56.000000000 +0100
@@ -152,14 +152,20 @@
 // never writes more than dstmax to dst
 // returns how many bytes were appended
 static size_t
-safe_append(char *dst, size_t dstmax, char *strbeg, char *strend)
+safe_append(char *dst, size_t dstmax, char *srcbeg, char *srcend)
 {
-       size_t dstlen = strlen(dst);
-       if (dstmax - dstlen - 1 < strend - strbeg)
-               strend = strbeg + (dstmax - dstlen - 1);
-       memcpy(dst + dstlen, strbeg, strend - strbeg);
-       dst[dstlen + (strend - strbeg)] = 0;
-       return strend - strbeg;
+       size_t srclen = srcend - srcbeg;
+       size_t dstlen = strnlen(dst, dstmax);
+
+       if (dstlen == dstmax)
+               return 0;
+
+       if (dstmax - dstlen < srclen + 1)
+               srclen = dstmax - dstlen - 1;
+       memcpy(dst + dstlen, srcbeg, srclen);
+       dst[dstlen + srclen] = 0;
+
+       return srclen;
 }
 
 static size_t
@@ -213,8 +219,9 @@
                                s++;
                                if (*addr || *disp)
                                        break;
+                       } else {
+                               s++;
                        }
-                       s++;
                } else if (*s == '<') {
                        char tok[1024] = { 0 };
                        char *c = tok;
@@ -222,7 +229,9 @@
                        s++;
                        while (*s && c < e && *s != '>') {
                                s = skip_comment(s);
-                               if (*s == '"') {
+                               if (!*s) {
+                                       break;
+                               } else if (*s == '"') {
                                        // local part may be quoted, allow all
                                        s++;
                                        while (*s && c < e && *s != '"') {
@@ -258,7 +267,7 @@
                        char *e = tok + sizeof tok;
                        s++;
                        while (*s && c < e && *s != '"') {
-                               if (*s == '\\')
+                               if (*s == '\\' && *(s+1))
                                        s++;
                                *c++ = *s++;
                        }
@@ -274,7 +283,8 @@
                } else if (*s == '(') {
                        char *z = skip_comment(s);
                        if (!*disp && *addr)  // user@host (name)
-                               safe_append(disp, sizeof disp, s + 1, z - 1);
+                               safe_append(disp, sizeof disp, s + 1,
+                                   *z ? z-1 : (*(z-1) == ')' ? z-1 : z));
                        else if (*disp) {  // copy comment
                                safe_append_space(disp, sizeof disp);
                                safe_append(disp, sizeof disp, s, z);
@@ -285,6 +295,8 @@
                                // in ipv6 address
                                if (tc < te)
                                        *tc++ = *s++;
+                               else
+                                       s++;
                        } else {  // ignore group name and start over
                                s++;
                                tc = ttok;
@@ -298,6 +310,8 @@
                                s++;
                        if (tc < te)
                                *tc++ = *s++;
+                       else
+                               s++;
                }
        }
 
@@ -504,8 +518,10 @@
        size_t hlen = end - src;
 
        buf = malloc(hlen+1);
-       if (!buf)
+       if (!buf) {
+               free(mesg);
                return 0;
+       }
        memcpy(buf, src, hlen);
 
        end = buf+hlen;
@@ -664,6 +680,7 @@
 
        char *buf = mmap(0, len+1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
        if (buf == MAP_FAILED) {
+               free(mesg);
                perror("mmap");
                goto error;
        }
diff -Nru mblaze-0.4/contrib/_mblaze mblaze-0.5.1/contrib/_mblaze
--- mblaze-0.4/contrib/_mblaze  1970-01-01 01:00:00.000000000 +0100
+++ mblaze-0.5.1/contrib/_mblaze        2019-03-03 17:12:56.000000000 +0100
@@ -0,0 +1,402 @@
+#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd 
mgenmid mhdr minc mless mlist mmime mmkdir mpick mrep mscan msed mseq mshow 
msort mthread
+
+_mblaze_colon_separated_headers() {
+  _message 'headers (colon separated)'
+}
+
+_mblaze_message() {
+  local ret=1 expl tmp curmsg
+  local -a mseq mseqnums mshortcuts mshortcutdescrs
+  setopt localoptions extendedglob
+
+  if [[ -prefix './' ]]; then
+    _description files expl 'message file'
+    _files "$expl[@]" && ret=0
+  fi
+
+  curmsg=$(mseq .)
+  if [[ -z $curmsg || ! -f $curmsg ]]; then
+    _message 'no current sequence'
+    return $ret
+  fi
+
+  mseq=( ${(f)"$(mscan -f '%3n %c%u%r %10d %17f %t %2i%s' : 2>/dev/null)"} )
+  mseq=( ${(M)mseq:# #<->*} )
+  mseqnums=( ${(M)${mseq## #}##<->} )
+  mseq=( ${mseq//:/\\:} )
+  _describe -V -t mseq 'seq messages' mseq mseqnums && ret=0
+
+  mshortcuts=( '.' '+' '$' '^' '=' '_' )
+  mshortcutdescrs=(
+    ' . current message'
+    ' + next message'
+    # ' - previous message'
+    ' $ last message'
+    ' ^ parent message'
+    ' = current thread'
+    ' _ current subthread'
+  )
+
+  _describe -t mshortcuts 'shortcuts' mshortcutdescrs mshortcuts -S '' && ret=0
+
+  return $ret
+}
+
+_mblaze_message_part() {
+  setopt localoptions noksharrays extendedglob
+  local ret=1 expl tmp msgarg parts partnums
+  tmp=$words[(i)(-O|-x)]
+  if (( tmp >= $#words )); then
+    _message -e mparts 'message parts (parse error)'
+    return 1
+  fi
+
+  msgarg=$words[$tmp+1]
+  parts=( ${(f)"$(mshow -t $msgarg)"} )
+  parts=( ${(M)parts:# ##<->:*} )
+  if [[ -n $parts ]]; then
+    partnums=( ${${parts## #}%%:*} )
+    parts=( ${parts//:/\\:} )
+    _describe -V -t mparts 'message parts' parts partnums -l && ret=0
+  else
+    _message -e mparts 'message parts (none found)'
+  fi
+
+  return $ret
+}
+
+_mblaze_dirs() {
+  local ret=1 expl countnew countcur
+  local -a mailboxes mailbox_descriptions
+  setopt localoptions extendedglob
+
+  mailboxes=( */cur(:h) )
+  mailbox_descriptions=( ${(f)"$(mlist -i $mailboxes)"} )
+  _describe -t mailboxes "mailboxes" mailbox_descriptions mailboxes && ret=0
+
+  _description files expl 'directories'
+  _path_files "$expl[@]" -g "^(${(j:|:)mailboxes})(/)" && ret=0
+}
+
+_mblaze_header_regex() {
+  _message header\ regex
+}
+
+_mblaze_flags() {
+  _message flags
+}
+
+
+_maddr() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-a[print addr-spec address without display name]' \
+    '-h[search only given headers]:header 
list:_mblaze_colon_separated_headers' \
+    '*:message:_mblaze_message'
+}
+
+_magrep() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-a[search for regex in RFC 2822 address header parts only]' \
+    '-c[only print a count of matching messages]' \
+    '-d[decode the header according to RFC 2047 prior to searching]' \
+    '-i[match regex case insensitively]' \
+    '-m[do not show more than max matches]:max: ' \
+    '(-c -q -v)-o[print matches only]' \
+    '(-c -q -v)-p[print filename, header and matching]' \
+    '-q[quiet mode: do not print anything]' \
+    '-v[invert match]' \
+    '*:message:_mblaze_header_regex'
+}
+
+_mbnc() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    ':message:_mblaze_message'
+}
+
+_mcom() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    - resume \
+      '-r[resume editing]:draft: ' \
+    - recip \
+      '*:recipients: '
+}
+
+_mdeliver() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-c[deliver into cur/ instead of new/]' \
+    '-v[print message filename after delivery]' \
+    '-X[override flags]:flags:_mblaze_flags' \
+    '-M[deliver messages from mbox]' \
+    ':dir:_mblaze_dirs'
+}
+
+_mdirs() {
+  _mblaze_dirs
+}
+
+_mexport() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-S[add Status and X-Status headers according to flags]' \
+    '*:messages:_mblaze_message'
+}
+
+_mflag() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '(-d)-D[mark as draft]' \
+    '(-f)-F[mark as flagged]' \
+    '(-p)-P[mark as passed (resent/forwarded/bounced)]' \
+    '(-r)-R[mark as replied-to]' \
+    '(-s)-S[mark as seen]' \
+    '(-t)-T[mark as trashed]' \
+    '-X[mark with characters]:marking characters: ' \
+    '(-D)-d[unmark as draft]' \
+    '(-F)-f[unmark as flagged]' \
+    '(-P)-p[unmark as passed (resent/forwarded/bounced)]' \
+    '(-R)-r[unmark as replied-to]' \
+    '(-S)-s[unmark as seen]' \
+    '(-T)-t[unmark as trashed]' \
+    '-x[unmark with characters]:marked chacaters: ' \
+    '-v[read messages from standard input or current sequence]' \
+    '*:messages:_mblaze_message'
+}
+
+_mflow() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-f[force wrapping of long lines]' \
+    '*-q[prefix lines with >]' \
+    '-w[set maximum line length]:width: ' \
+    '*:dirs:_mblaze_dirs'
+}
+
+_mfwd() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-r[forward as plain text]' \
+    ':*:message:_mblaze_message'
+}
+
+_mgenmid() {
+  _message 'no arguments'
+}
+
+_mhdr() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-h[print specific headers only]:headers: ' \
+    '-p[print specific parameter from header only]:parameter: ' \
+    '-d[print headers decoded]' \
+    '-H[prefix output with filename]' \
+    '-M[print all occurrences, not only the first]' \
+    '(-D)-A[print addresses from headers]' \
+    '(-A)-D[print date as unix timestamp]' \
+    '*:message:_mblaze_message'
+}
+
+_minc() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-q[quiet mode: don'\''t print filenames]' \
+    '*:dirs:_mblaze_dirs'
+}
+
+_mless() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    ':message:_mblaze_message'
+}
+
+_mlist() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '(-d)-D[only list messages marked as draft]' \
+    '(-f)-F[only list messages marked as flagged]' \
+    '(-p)-P[only list messages marked as passed (resent/forwarded/bounced)]' \
+    '(-r)-R[only list messages marked as replied-to]' \
+    '(-s)-S[only list messages marked as seen]' \
+    '(-t)-T[only list messages marked as trashed]' \
+    '-X[only list messages marked with characters]:marked characters: ' \
+    '(-D)-d[don'\''t list messages marked as draft]' \
+    '(-F)-f[don'\''t list messages marked as flagged]' \
+    '(-P)-p[don'\''t list messages marked as passed 
(resent/forwarded/bounced)]' \
+    '(-R)-r[don'\''t list messages marked as replied-to]' \
+    '(-S)-s[don'\''t list messages marked as seen]' \
+    '(-T)-t[don'\''t list messages marked as trashed]' \
+    '-x[don'\''t list messages marked with characters]:marked chacaters: ' \
+    '(-c -N)-C[only list messages in cur]' \
+    '(-n -C)-N[only list messages in new]' \
+    '(-C -N)-c[don'\''t list messages in cur]' \
+    '(-N -C)-n[don'\''t list messages in new]' \
+    '-i[print summaries instead of folder names]' \
+    '*:dirs:_mblaze_dirs'
+}
+
+_mmkdir() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '*:directory name: '
+}
+
+_mmime() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '(-r)-c[check mode (don'\''t output anything)]' \
+    '(-c)-r[raw mode (generate text/plain)]' \
+    '-t[override Content-Type of toplevel part]:Content-Type: '
+}
+
+_mpick() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-T[include whole thread]' \
+    '-t[limit messages to test]:test: ' \
+    '*:message:_mblaze_message'
+}
+
+_mrep() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    ':message:_mblaze_message'
+}
+
+_mscan() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-n[only print message numbers]' \
+    '-I[force ISO date output]' \
+    '-f[specify output format]:format: ' \
+    '*:messages:_mblaze_message'
+}
+
+_msed() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    ':sed script: ' \
+    '*:messages:_mblaze_message'
+}
+
+_mseq() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '(Cmode)-f[fix non-existing filenames]' \
+    '(Cmode)-r[remove leading indentation from filenames]' \
+    - argmode \
+      '-c[use current message]:message:_mblaze_message' \
+      '*:messages:_mblaze_message' \
+    - Smode \
+      '-S[set message sequence from stdin]' \
+    - Amode \
+      '-A[append message sequence from stdin]' \
+    - Cmode \
+      '-C[set current message]:message:_mblaze_message'
+}
+
+_mshow() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    - regular \
+      '-n[only print message numbers]' \
+      '-h[display only given headers]:header 
list:_mblaze_colon_separated_headers' \
+      '-A[mixed/alternative preference]:mime type: ' \
+      '-n[don'\''t update current message link]' \
+      '(-r)-q[print only header]' \
+      '(-q)-r[print body raw]' \
+      '(-q)-F[don'\''t apply MIME filters]' \
+      '-H[print headers raw]' \
+      '-L[don'\''t filter headers]' \
+      '(-q)-N[don'\''t show MIME structure markers]' \
+      '*:messages:_mblaze_message' \
+    - xmode \
+      '-x[extraction 
mode]:message:_mblaze_message:*:part:_mblaze_message_part' \
+    - Omode \
+      '-O[extraction mode to standard 
output]:message:_mblaze_message:*:part:_mblaze_message_part' \
+    - tmode \
+      '-t[list mode]:*:message:_mblaze_message' \
+    - Rmode \
+      '-R[render text parts]:message:_mblaze_message'
+}
+
+_msort() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-r[reverse order]' \
+    '*:message:_mblaze_message' \
+    + '(order)' \
+      '-f[sort by From]' \
+      '-d[sort by Date]' \
+      '-s[sort by Subject]' \
+      '-F[sort by filename]' \
+      '-M[sort by file modification time]' \
+      '-S[sort by file size]' \
+      '-U[sort unread messages after read messages]' \
+      '-I[sort flagged messages before unflagged messages]'
+}
+
+_mthread() {
+  local context state line expl
+  local -A opt_args
+
+  _arguments \
+    '-a[don'\''t prune unresolved Message-IDs]' \
+    '-S[treat as optional messages]:optional message:_mblaze_message' \
+    '*:message:_mblaze_message'
+}
+
+_mblaze() {
+  local ret=1
+  _call_function ret _$service
+  return ret
+}
+
+_mblaze "$@"
diff -Nru mblaze-0.4/contrib/mencrypt mblaze-0.5.1/contrib/mencrypt
--- mblaze-0.4/contrib/mencrypt 2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/mencrypt       2019-03-03 17:12:56.000000000 +0100
@@ -5,17 +5,20 @@
 
 IFS='
 '
-FLAGS=$(mhdr -d -A -h from:to:cc:bcc: "$1" |sort -u |sed 's/^/--recipient=/')
+FLAGS=$(maddr -a -h from:to:cc:bcc: "$1" |sort -u |sed 's/^/--recipient=/')
+
+FROM=$(maddr -a -h from "$1" | sed 1q)
+[ "$FROM" ] && key="--default-key=$FROM"
 
 TMPD=$(mktemp -d -t mencrypt.XXXXXX)
 trap "rm -rf '$TMPD'" INT TERM EXIT
 
 awk '/^$/,0' "$1" |
        mmime |
-       gpg --armor --encrypt --sign $FLAGS -o $TMPD/msg.asc ||
+       gpg2 "$key" --armor --encrypt --sign $FLAGS -o "$TMPD/msg.asc" ||
        exit $?
 
-printf 'Version: 1\n' >$TMPD/version
+printf 'Version: 1\n' >"$TMPD/version"
 
 {
        sed '/^$/q' "$1"
diff -Nru mblaze-0.4/contrib/menter mblaze-0.5.1/contrib/menter
--- mblaze-0.4/contrib/menter   2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/menter 2019-03-03 17:12:56.000000000 +0100
@@ -1,14 +1,17 @@
 #!/bin/sh -e
 # menter [MSG] - run subshell in temporary directory with MSG extracted
 
-[ "$#" -eq 0 ] && set -- :
+[ "$#" -eq 0 ] && set -- .
+
+f="$(mseq "$1" | sed 1q)"
+[ -z "$f" ] && printf 'No message %s.\n' "$1" 1>&2 && exit 1
 
 dir=$(mktemp -d -t menter.XXXXXX)
 cd "$dir"
 mshow -t "$1"
 mshow -x "$1" 2>/dev/null
 ls -l
-ln -s "$(mseq "$1")" msg
+ln -s "$f" msg
 "${SHELL:-/bin/sh}" || true
 echo rm -r "$dir"
 rm -r "$dir"
diff -Nru mblaze-0.4/contrib/mgpg mblaze-0.5.1/contrib/mgpg
--- mblaze-0.4/contrib/mgpg     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/mgpg   2019-03-03 17:12:56.000000000 +0100
@@ -14,7 +14,7 @@
        /: application\/octet-stream/ {if (supported) print $1}')
 
 if [ "$n" ]; then
-       mshow -O "$tmp" "$n" | gpg -d 2>&1
+       mshow -O "$tmp" "$n" | gpg2 -d 2>&1 || exit 0
        exit 64
 fi
 exit 63
diff -Nru mblaze-0.4/contrib/mmairix mblaze-0.5.1/contrib/mmairix
--- mblaze-0.4/contrib/mmairix  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/mmairix        2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
 #!/bin/sh
 # mmairix QUERY - mblaze wrapper around mairix
 
-mairix -r "$@" | sed 's,//*,/,g' | mless
+mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mless
diff -Nru mblaze-0.4/contrib/msearch mblaze-0.5.1/contrib/msearch
--- mblaze-0.4/contrib/msearch  1970-01-01 01:00:00.000000000 +0100
+++ mblaze-0.5.1/contrib/msearch        2019-03-03 17:12:56.000000000 +0100
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+MBLAZE=${MBLAZE:-$HOME/.mblaze}
+engine=$(mhdr -h search-engine "$MBLAZE/profile")
+
+while getopts nmx opt; do
+    case $opt in
+       n)
+           engine=notmuch
+           ;;
+       m)
+           engine=mu
+           ;;
+       x)
+           engine=mairix
+           ;;
+       '?')
+           printf "Usage: %s: [-n | -m | -x] query\n" "$0" 1>&2
+           exit 1
+           ;;
+    esac
+done
+shift $(($OPTIND - 1))
+
+[ -z "$engine" ] && engine=notmuch
+
+case $engine in
+    notmuch)
+       exec notmuch search --output=files "$@"
+       ;;
+    mu)
+       exec mu find --fields l "$@"
+       ;;
+    mairix)
+       if [ "$#" -eq 0 ]; then
+          printf "Usage: %s -x query\n" "$0" 1>&2
+          exit 1
+       fi
+        exec mairix -r "$@"
+       ;;
+    *)
+       echo "Unsupported search engine: $engine"
+       exit 1
+       ;;
+esac
diff -Nru mblaze-0.4/contrib/msearch.1 mblaze-0.5.1/contrib/msearch.1
--- mblaze-0.4/contrib/msearch.1        1970-01-01 01:00:00.000000000 +0100
+++ mblaze-0.5.1/contrib/msearch.1      2019-03-03 17:12:56.000000000 +0100
@@ -0,0 +1,75 @@
+.Dd September 27, 2018
+.Dt MSEARCH 1
+.Os
+.Sh NAME
+.Nm msearch
+.Nd search messages
+.Sh SYNOPSIS
+.Nm
+.Op Fl n | Fl m | Fl x
+.Op Fl -
+.Op Ar query
+.Sh DESCRIPTION
+.Nm
+searches for messages matching
+.Ar query ,
+using an external search engine, and prints file names separated by newlines.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl n
+Search using
+.Xr notmuch-search 1 .
+.It Fl m
+Search using
+.Xr mu-find 1 .
+.It Fl x
+Search using
+.Xr mairix 1 .
+.It Fl -
+Stop scanning for arguments.
+.It Ar query
+The search query, whose interpretation is up to the search engine.
+This can also contain additional arguments for them
+.El
+.Pp
+If no search engine is specified as an argument,
+.Sq Li Search-Engine\&:
+from
+.Pa "${MBLAZE:-$HOME/.mblaze}/profile"
+is used.
+Valid values for this setting are
+.Sq notmuch ,
+.Sq mairix ,
+and
+.Sq mu .
+If that is unset,
+.Xr notmuch-search 1
+is used.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev MBLAZE
+Directory containing mblaze configuration files.
+(Default:
+.Pa $HOME/.mblaze )
+.El
+.Sh EXIT STATUS
+.Ex -std
+Note that the called programs may have their own exit values.
+.Sh SEE ALSO
+.Xr mairix 1 ,
+.Xr mu-find 1 ,
+.Xr notmuch-search 1 ,
+.Xr mblaze-profile 5
+.Sh AUTHORS
+.An Thomas Schneider Aq Mt q...@chaotikum.eu
+.Sh LICENSE
+.Nm
+is in the public domain.
+.Pp
+To the extent possible under law,
+the creator of this work
+has waived all copyright and related or
+neighboring rights to this work.
+.Pp
+.Lk http://creativecommons.org/publicdomain/zero/1.0/
diff -Nru mblaze-0.4/contrib/msign mblaze-0.5.1/contrib/msign
--- mblaze-0.4/contrib/msign    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/msign  2019-03-03 17:12:56.000000000 +0100
@@ -9,8 +9,11 @@
 TMPD=$(mktemp -d -t msign.XXXXXX)
 trap "rm -rf '$TMPD'" INT TERM EXIT
 
+FROM=$(maddr -a -h from "$1" | sed 1q)
+[ "$FROM" ] && key="--default-key=$FROM"
+
 awk '/^$/,0' "$1" | mmime | sed 's/$/
/' >"$TMPD"/content
-gpg --armor --detach-sign -o "$TMPD"/signature.asc "$TMPD"/content ||
+gpg2 $key --armor --detach-sign -o "$TMPD"/signature.asc "$TMPD"/content ||
        exit $?
 
 {
diff -Nru mblaze-0.4/contrib/mverify mblaze-0.5.1/contrib/mverify
--- mblaze-0.4/contrib/mverify  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/contrib/mverify        2019-03-03 17:12:56.000000000 +0100
@@ -1,7 +1,7 @@
 #!/bin/sh
 # mverify MSG - verify a OpenPGP or SMIME message
 
-# Needs gpg (for OpenPGP) and openssl (for SMIME).
+# Needs gpg2 (for OpenPGP) and openssl (for SMIME).
 
 [ "$#" -eq 0 ] && set -- .
 
@@ -14,7 +14,7 @@
 function q(a) { gsub("\\47", "\47\\\47\47", a); return "\47"a"\47" }
 END {
        if (type == "" && plain) {  // guess plain text armored signature
-               exit(system("mshow -r " q(msg) " | gpg --verify"));
+               exit(system("mshow -r " q(msg) " | gpg2 --verify"));
        } else if (type == "") {
                print("No signature found.")
                exit(100)
@@ -22,7 +22,7 @@
                exit(system("mshow -r -O " q(msg) " " q(content) \
                        " | sed $DOS2UNIX | " \
                        " { mshow -O " q(msg) " " q(signature) \
-                       " | gpg --verify - /dev/fd/3; } 3<&0"))
+                       " | gpg2 --verify - /dev/fd/3; } 3<&0"))
        } else if (type == "application/pkcs7-signature") {
                exit(system("mshow -r -O " q(msg) " " q(signed) \
                        " | openssl smime -verify"))
diff -Nru mblaze-0.4/debian/changelog mblaze-0.5.1/debian/changelog
--- mblaze-0.4/debian/changelog 2018-08-19 12:22:49.000000000 +0200
+++ mblaze-0.5.1/debian/changelog       2019-03-04 18:40:01.000000000 +0100
@@ -1,3 +1,37 @@
+mblaze (0.5.1-1) unstable; urgency=high (security fixes)
+
+  * New upstream release (2019-03-03)
+    + Fixes for buffer-overflows, found by fuzzing.
+    + Fixes for memleaks.
+
+  * Remove unused lintian override
+  * debian/rules: Remove useless dh_missing invocation.
+    A single binary package is being produced.
+
+ -- Nicolas Braud-Santoni <ni...@debian.org>  Mon, 04 Mar 2019 18:40:01 +0100
+
+mblaze (0.5-1) unstable; urgency=medium
+
+  * New upstream release (2019-02-09)
+    + Closes: 921891
+    + GNUmakefile: correct reference to SOURCE_DATE_EPOCH, patch by Chris Lamb
+      Closes: #907537 
+
+  * Rename mless and msort to mblaze-less and mblaze-sort
+    Closes: #887988 correctly, avoids conflicts on mpdtoys & msort
+
+  * Switch to debhelper 12.
+    The compatibility level is now controlled by a Build-Depends.
+
+  * Declare compliance with policy v4.2.1.
+    No change required.
+
+  * debian/rules
+    + Make dh_missing fail the build
+    + Symlink docs from mblaze-* to mblaze
+
+ -- Nicolas Braud-Santoni <ni...@debian.org>  Tue, 12 Feb 2019 11:44:33 +0100
+
 mblaze (0.4-1) unstable; urgency=medium
 
   * New upstream version (2018-08-15)
diff -Nru mblaze-0.4/debian/compat mblaze-0.5.1/debian/compat
--- mblaze-0.4/debian/compat    2018-02-13 12:47:54.000000000 +0100
+++ mblaze-0.5.1/debian/compat  1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-11
diff -Nru mblaze-0.4/debian/control mblaze-0.5.1/debian/control
--- mblaze-0.4/debian/control   2018-08-19 12:22:49.000000000 +0200
+++ mblaze-0.5.1/debian/control 2019-03-04 18:40:01.000000000 +0100
@@ -1,17 +1,17 @@
 Source: mblaze
-Maintainer: Nicolas Braud-Santoni <nico...@braud-santoni.eu>
+Maintainer: Nicolas Braud-Santoni <ni...@debian.org>
 Section: utils
 Priority: optional
-Build-Depends: debhelper (>= 11)
-Standards-Version: 4.2.0
+Build-Depends: debhelper-compat (= 12)
+Standards-Version: 4.3.0
 Homepage: https://github.com/chneukirchen/mblaze
 Vcs-Browser: https://salsa.debian.org/debian/mblaze
 Vcs-Git: https://salsa.debian.org/debian/mblaze.git
 
+
 Package: mblaze
 Architecture: any
 Depends: ${shlibs:Depends}, ${misc:Depends}
-Conflicts: msort, mpdtoys
 Description: UNIX utilities to deal with Maildir
  The mblaze message system is a set of Unix utilities to deal with mail kept in
  Maildir folders. It is a classic command line MUA and has no features for
diff -Nru mblaze-0.4/debian/mblaze.lintian-overrides 
mblaze-0.5.1/debian/mblaze.lintian-overrides
--- mblaze-0.4/debian/mblaze.lintian-overrides  2018-02-13 12:47:54.000000000 
+0100
+++ mblaze-0.5.1/debian/mblaze.lintian-overrides        1970-01-01 
01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-# Ignore false-negative in hardening-check
-mblaze: hardening-no-fortify-functions usr/bin/mdirs
diff -Nru mblaze-0.4/debian/patches/Rename-mless-to-mblaze-less.patch 
mblaze-0.5.1/debian/patches/Rename-mless-to-mblaze-less.patch
--- mblaze-0.4/debian/patches/Rename-mless-to-mblaze-less.patch 1970-01-01 
01:00:00.000000000 +0100
+++ mblaze-0.5.1/debian/patches/Rename-mless-to-mblaze-less.patch       
2019-03-04 18:40:01.000000000 +0100
@@ -0,0 +1,42 @@
+Subject: Rename mless to mblaze-less
+
+---
+ contrib/_mblaze | 4 ++--
+ contrib/mmairix | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/contrib/_mblaze b/contrib/_mblaze
+index f58cb65..41207e3 100644
+Origin: vendor
+Bug-Debian: https://bugs.debian.org/887988
+Forwarded: not-needed
+From: Nicolas Braud-Santoni <ni...@debian.org>
+Last-Update: 2019-02-23
+
+--- a/contrib/_mblaze
++++ b/contrib/_mblaze
+@@ -1,4 +1,4 @@
+-#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd 
mgenmid mhdr minc mless mlist mmime mmkdir mpick mrep mscan msed mseq mshow 
msort mthread
++#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd 
mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq 
mshow msort mthread
+ 
+ _mblaze_colon_separated_headers() {
+   _message 'headers (colon separated)'
+@@ -229,7 +229,7 @@ _minc() {
+     '*:dirs:_mblaze_dirs'
+ }
+ 
+-_mless() {
++_mblaze-less() {
+   local context state line expl
+   local -A opt_args
+ 
+diff --git a/contrib/mmairix b/contrib/mmairix
+index e4c9844..810bb59 100755
+--- a/contrib/mmairix
++++ b/contrib/mmairix
+@@ -1,4 +1,4 @@
+ #!/bin/sh
+ # mmairix QUERY - mblaze wrapper around mairix
+ 
+-mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mless
++mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mblaze-less
diff -Nru mblaze-0.4/debian/patches/Rename-msort-to-mblaze-sort.patch 
mblaze-0.5.1/debian/patches/Rename-msort-to-mblaze-sort.patch
--- mblaze-0.4/debian/patches/Rename-msort-to-mblaze-sort.patch 1970-01-01 
01:00:00.000000000 +0100
+++ mblaze-0.5.1/debian/patches/Rename-msort-to-mblaze-sort.patch       
2019-03-04 18:40:01.000000000 +0100
@@ -0,0 +1,56 @@
+Subject: Rename msort to mblaze-sort
+
+---
+ contrib/_mblaze | 4 ++--
+ contrib/mmairix | 2 +-
+ mcom            | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/contrib/_mblaze b/contrib/_mblaze
+index 41207e3..3d11390 100644
+Origin: vendor
+Bug-Debian: https://bugs.debian.org/887988
+Forwarded: not-needed
+From: Nicolas Braud-Santoni <ni...@debian.org>
+Last-Update: 2019-02-23
+
+--- a/contrib/_mblaze
++++ b/contrib/_mblaze
+@@ -1,4 +1,4 @@
+-#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd 
mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq 
mshow msort mthread
++#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd 
mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq 
mshow mblaze-sort mthread
+ 
+ _mblaze_colon_separated_headers() {
+   _message 'headers (colon separated)'
+@@ -365,7 +365,7 @@ _mshow() {
+       '-R[render text parts]:message:_mblaze_message'
+ }
+ 
+-_msort() {
++_mblaze-sort() {
+   local context state line expl
+   local -A opt_args
+ 
+diff --git a/contrib/mmairix b/contrib/mmairix
+index 810bb59..6caff93 100755
+--- a/contrib/mmairix
++++ b/contrib/mmairix
+@@ -1,4 +1,4 @@
+ #!/bin/sh
+ # mmairix QUERY - mblaze wrapper around mairix
+ 
+-mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mblaze-less
++mairix -r "$@" | sed 's,//*,/,g' | mblaze-sort -rd | mblaze-less
+diff --git a/mcom b/mcom
+index 91498c9..73c5fbb 100755
+--- a/mcom
++++ b/mcom
+@@ -245,7 +245,7 @@ else
+                       exit 1
+               fi
+       elif [ -z "$draft" ]; then
+-              draft=$(mlist -D "$outbox" | msort -r -M | sed 1q)
++              draft=$(mlist -D "$outbox" | mblaze-sort -r -M | sed 1q)
+       fi
+       draftmime="$(printf '%s\n' "$draft" | sed 
's,\(.*\)/cur/,\1/tmp/mime-,')"
+ fi
diff -Nru mblaze-0.4/debian/patches/series mblaze-0.5.1/debian/patches/series
--- mblaze-0.4/debian/patches/series    1970-01-01 01:00:00.000000000 +0100
+++ mblaze-0.5.1/debian/patches/series  2019-03-04 18:40:01.000000000 +0100
@@ -0,0 +1,2 @@
+Rename-mless-to-mblaze-less.patch
+Rename-msort-to-mblaze-sort.patch
diff -Nru mblaze-0.4/debian/README.Debian mblaze-0.5.1/debian/README.Debian
--- mblaze-0.4/debian/README.Debian     1970-01-01 01:00:00.000000000 +0100
+++ mblaze-0.5.1/debian/README.Debian   2019-03-04 18:40:01.000000000 +0100
@@ -0,0 +1,4 @@
+Executables mless and msort got renamed to mblaze-less and mblaze-sort, due to
+conflicts with packages mpdtoys and msort.
+
+ -- Nicolas Braud-Santoni <ni...@debian.org>, Sat, 23 Feb 2019 20:09:22 +0100
diff -Nru mblaze-0.4/debian/rules mblaze-0.5.1/debian/rules
--- mblaze-0.4/debian/rules     2018-08-19 12:22:49.000000000 +0200
+++ mblaze-0.5.1/debian/rules   2019-03-04 18:40:01.000000000 +0100
@@ -11,5 +11,15 @@
 override_dh_auto_test:
        : # Testsuite is currently broken under sbuild
 
+override_dh_install:
+       mv debian/mblaze/usr/bin/mless              
debian/mblaze/usr/bin/mblaze-less
+       mv debian/mblaze/usr/share/man/man1/mless.1 
debian/mblaze/usr/share/man/man1/mblaze-less.1
+       mv debian/mblaze/usr/bin/msort              
debian/mblaze/usr/bin/mblaze-sort
+       mv debian/mblaze/usr/share/man/man1/msort.1 
debian/mblaze/usr/share/man/man1/mblaze-sort.1
+       dh_install
+
 override_dh_installchangelogs:
        dh_installchangelogs NEWS.md
+
+override_dh_installdocs:
+       dh_installdocs --link-doc=mblaze
diff -Nru mblaze-0.4/GNUmakefile mblaze-0.5.1/GNUmakefile
--- mblaze-0.4/GNUmakefile      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/GNUmakefile    2019-03-03 17:12:56.000000000 +0100
@@ -28,17 +28,16 @@
 maddr magrep mdeliver mexport mflag mflow mgenmid mhdr mpick mscan msed mshow \
   msort mthread : blaze822.o mymemmem.o mytimegm.o
 maddr magrep mdeliver mexport mflag mgenmid mhdr mlist mpick mscan msed mseq \
-  mshow msort mthread : seq.o slurp.o
+  mshow msort mthread : seq.o slurp.o mystrverscmp.o
 maddr magrep mflow mhdr mpick mscan mshow : rfc2047.o
 magrep mflow mhdr mshow : rfc2045.o
 mshow : filter.o safe_u8putstr.o rfc2231.o pipeto.o
 mscan : pipeto.o
-msort : mystrverscmp.o
 mmime : slurp.o
 minc mlist : squeeze_slash.o
 
 museragent: FRC
-       @test -n "$$SOURCE_TIME_EPOCH" || BUILDDATE=$$(date '+ (%Y-%m-%d)'); \
+       @test -n "$$SOURCE_DATE_EPOCH" || BUILDDATE=$$(date '+ (%Y-%m-%d)'); \
                printf '#!/bin/sh\nprintf "User-Agent: mblaze/%s%s\\n"\n' \
                "$$({ git describe --always --dirty 2>/dev/null || cat VERSION; 
} | sed 's/^v//')" \
                "$$BUILDDATE" >$@
@@ -59,8 +58,6 @@
                $(DESTDIR)$(MANDIR)/man5 \
                $(DESTDIR)$(MANDIR)/man7
        install -m0755 $(ALL) $(SCRIPT) $(DESTDIR)$(BINDIR)
-       ln -sf mless $(DESTDIR)$(BINDIR)/mnext
-       ln -sf mless $(DESTDIR)$(BINDIR)/mprev
        ln -sf mcom $(DESTDIR)$(BINDIR)/mbnc
        ln -sf mcom $(DESTDIR)$(BINDIR)/mfwd
        ln -sf mcom $(DESTDIR)$(BINDIR)/mrep
diff -Nru mblaze-0.4/magrep.c mblaze-0.5.1/magrep.c
--- mblaze-0.4/magrep.c 2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/magrep.c       2019-03-03 17:12:56.000000000 +0100
@@ -14,6 +14,7 @@
 static int aflag;
 static int cflag;
 static int dflag;
+static int hflag;
 static int iflag;
 static int lflag;
 static int oflag;
@@ -31,7 +32,7 @@
 match(char *file, char *hdr, char *s)
 {
        if (oflag && !cflag && !qflag && !vflag && !lflag) {
-               regmatch_t pmatch;
+               regmatch_t pmatch = {0};
                int len, matched;
                matched = 0;
                while (*s && regexec(&pattern, s, 1, &pmatch, 0) == 0) {
@@ -42,6 +43,8 @@
                        }
                        if (pflag)
                                printf("%s: %s: ", file, hdr);
+                       else if (hflag)
+                               printf("%s: ", hdr);
                        printf("%.*s\n", len, s);
                        s += len;
                        matched++;
@@ -52,9 +55,12 @@
                        exit(0);
                matches++;
                if (!cflag) {
-                       printf("%s", file);
+                       if (vflag || !hflag)
+                               printf("%s", file);
                        if (pflag && !vflag)
                                printf(": %s: %s", hdr, s);
+                       else if (hflag && !vflag)
+                               printf("%s: %s", hdr, s);
                        putchar('\n');
                }
                if (mflag && matches >= mflag)
@@ -82,7 +88,7 @@
                    strcasecmp(charset, "utf-8") == 0 ||
                    strcasecmp(charset, "utf8") == 0 ||
                    strcasecmp(charset, "us-ascii") == 0) {
-                       if (pflag && !cflag && !oflag && !vflag) {
+                       if ((hflag || pflag) && !cflag && !oflag && !vflag) {
                                char *s, *p;
                                for (p = s = body; p < body+bodylen+1; p++) {
                                        if (*p == '\r' || *p == '\n') {
@@ -117,6 +123,7 @@
                return;
 
        blaze822_walk_mime(msg, 0, match_part);
+       blaze822_free(msg);
 }
 
 int
@@ -183,11 +190,12 @@
 main(int argc, char *argv[])
 {
        int c;
-       while ((c = getopt(argc, argv, "acdilm:opqv")) != -1)
+       while ((c = getopt(argc, argv, "acdhilm:opqv")) != -1)
                switch (c) {
                case 'a': aflag = 1; break;
                case 'c': cflag = 1; break;
                case 'd': dflag = 1; break;
+               case 'h': hflag = 1; break;
                case 'i': iflag = REG_ICASE; break;
                case 'l': lflag = 1; break;
                case 'm': mflag = atol(optarg); break;
@@ -198,7 +206,7 @@
                default:
 usage:
                        fprintf(stderr,
-"Usage: magrep [-c|-o|-p|-q|-m max] [-v] [-i] [-l] [-a|-d] header:regex 
[msgs...]\n");
+"Usage: magrep [-c|-h|-o|-p|-q|-m max] [-v] [-i] [-l] [-a|-d] header:regex 
[msgs...]\n");
                        exit(2);
                }
 
diff -Nru mblaze-0.4/man/magrep.1 mblaze-0.5.1/man/magrep.1
--- mblaze-0.4/man/magrep.1     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/magrep.1   2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
-.Dd July 7, 2018
+.Dd September 10, 2018
 .Dt MAGREP 1
 .Os
 .Sh NAME
@@ -6,7 +6,7 @@
 .Nd search messages matching a pattern
 .Sh SYNOPSIS
 .Nm
-.Op Fl c | Fl q | Fl m Ar max
+.Op Fl c | Fl h | Fl o | Fl p | Fl q | Fl m Ar max
 .Op Fl v
 .Op Fl i
 .Op Fl l
@@ -75,6 +75,10 @@
 Decode the
 .Ar header
 according to RFC 2047 prior to searching.
+.It Fl h
+Like
+.Fl p
+but do not print the file name.
 .It Fl i
 Match
 .Ar regex
diff -Nru mblaze-0.4/man/mblaze.7 mblaze-0.5.1/man/mblaze.7
--- mblaze-0.4/man/mblaze.7     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mblaze.7   2019-03-03 17:12:56.000000000 +0100
@@ -32,7 +32,7 @@
 .It Xr mexport 1
 export messages as mbox file
 .It Xr mflag 1
-manipulate maildir flags
+manipulate maildir message flags
 .It Xr mflow 1
 reflow format=flowed plain text messages
 .It Xr mfwd 1
diff -Nru mblaze-0.4/man/mcom.1 mblaze-0.5.1/man/mcom.1
--- mblaze-0.4/man/mcom.1       2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mcom.1     2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
-.Dd January 6, 2017
+.Dd January 29, 2019
 .Dt MCOM 1
 .Os
 .Sh NAME
@@ -14,6 +14,7 @@
 .Nm mcom
 .Fl r Op draft
 .Nm mrep
+.Op Fl noquote
 .Op Fl Ar header Ar values\ ... Fl -
 .Ar msg
 .Nm mfwd
@@ -36,6 +37,9 @@
 .Nm mrep
 creates the draft such that the message will be a reply to
 .Ar msg .
+Unless
+.Fl noquote
+is passed, it will contain the original mail quoted.
 .Pp
 .Nm mfwd
 creates the draft with a subject and body appropriate
@@ -93,6 +97,12 @@
 .Nm mfwd ,
 or
 .Nm mbnc .
+.Pp
+If the flag
+.Fl send
+is passed,
+the message will be sent directly using the data on
+the command line, and no editor or edit loop will be run.
 .Sh MENU COMMANDS
 .Bl -tag -width 2n
 .It Ic s
diff -Nru mblaze-0.4/man/mdirs.1 mblaze-0.5.1/man/mdirs.1
--- mblaze-0.4/man/mdirs.1      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mdirs.1    2019-03-03 17:12:56.000000000 +0100
@@ -6,6 +6,7 @@
 .Nd list maildir folders, recursively
 .Sh SYNOPSIS
 .Nm
+.Op Fl 0
 .Ar dirs\ ...
 .Sh DESCRIPTION
 .Nm
@@ -27,7 +28,11 @@
 names must begin with
 .Sq Li \&. .
 .Pp
-There are currently no options.
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 0
+Print folders separated by a NUL character.
+.El
 .Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
diff -Nru mblaze-0.4/man/mflag.1 mblaze-0.5.1/man/mflag.1
--- mblaze-0.4/man/mflag.1      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mflag.1    2019-03-03 17:12:56.000000000 +0100
@@ -3,7 +3,7 @@
 .Os
 .Sh NAME
 .Nm mflag
-.Nd manipulate maildir flags
+.Nd manipulate maildir message flags
 .Sh SYNOPSIS
 .Nm
 .Op Fl DFPRST
diff -Nru mblaze-0.4/man/mgenmid.1 mblaze-0.5.1/man/mgenmid.1
--- mblaze-0.4/man/mgenmid.1    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mgenmid.1  2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
-.Dd August 1, 2016
+.Dd December 25, 2018
 .Dt MGENMID 1
 .Os
 .Sh NAME
@@ -9,7 +9,7 @@
 .Sh DESCRIPTION
 .Nm
 generates and prints a unique Message-ID.
-The Message-ID consists of an encoded timestamp,
+The Message-ID consists of an encrypted timestamp,
 a random value,
 and a fully qualified domain name.
 .Pp
diff -Nru mblaze-0.4/man/mpick.1 mblaze-0.5.1/man/mpick.1
--- mblaze-0.4/man/mpick.1      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mpick.1    2019-03-03 17:12:56.000000000 +0100
@@ -7,6 +7,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl T
+.Op Fl v
 .Op Fl t Ar test
 .Op Ar msglist\ ...
 .Sh DESCRIPTION
@@ -29,6 +30,8 @@
 .Ar test ,
 see
 .Sx TESTS .
+.It Fl v
+Print how many messages were tested and picked to standard error.
 .El
 .Sh MSGLISTS
 .Nm
diff -Nru mblaze-0.4/man/mscan.1 mblaze-0.5.1/man/mscan.1
--- mblaze-0.4/man/mscan.1      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mscan.1    2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
-.Dd June 28, 2017
+.Dd September 25, 2018
 .Dt MSCAN 1
 .Os
 .Sh NAME
@@ -6,9 +6,10 @@
 .Nd generate one-line message summaries
 .Sh SYNOPSIS
 .Nm
+.Op Fl I
 .Op Fl n
+.Op Fl v
 .Op Fl f Ar format
-.Op Fl I
 .Ar msgs\ ...
 .Sh DESCRIPTION
 .Nm
@@ -55,13 +56,15 @@
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
-.It Fl n
-Only print message numbers
-.Pq or filenames, if the message is not in the current sequence .
 .It Fl I
 Force ISO date output,
 even for
 .Sq Cm "%d" .
+.It Fl n
+Only print message numbers
+.Pq or filenames, if the message is not in the current sequence .
+.It Fl v
+Print how many messages were scanned to standard error.
 .It Fl f Ar format
 Format according to the string
 .Ar format ,
@@ -186,7 +189,7 @@
 .Sq Li To\&:
 .It Li \&+
 You are in
-.Sq Li Cc\:&
+.Sq Li Cc\&:
 .It Li \&:
 You are in
 .Sq Li Resent\&-To\&:
diff -Nru mblaze-0.4/man/msed.1 mblaze-0.5.1/man/msed.1
--- mblaze-0.4/man/msed.1       2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/msed.1     2019-03-03 17:12:56.000000000 +0100
@@ -123,6 +123,7 @@
 .Ex -std
 .Sh SEE ALSO
 .Xr sed 1 ,
+.Xr mhdr 1 ,
 .Xr mmsg 7 ,
 .Xr regex 7 /
 .Xr re_format 7
diff -Nru mblaze-0.4/man/mshow.1 mblaze-0.5.1/man/mshow.1
--- mblaze-0.4/man/mshow.1      2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/man/mshow.1    2019-03-03 17:12:56.000000000 +0100
@@ -1,4 +1,4 @@
-.Dd April 17, 2018
+.Dd August 24, 2018
 .Dt MSHOW 1
 .Os
 .Sh NAME
@@ -91,6 +91,9 @@
 can be specified by number, filename or
 .Xr fnmatch 3
 pattern.
+If no
+.Ar parts
+are specified, extracts all attachments with a filename.
 .It Fl O Ar msg
 Like
 .Fl x
@@ -121,7 +124,11 @@
 and re-encodes them into UTF-8 if necessary.
 .Pp
 Other filters can be specified in the file
-.Pa ${MBLAZE:-$HOME/.mblaze}/filter ,
+.Pa ${MBLAZE:-$HOME/.mblaze}/filter
+.Po
+or via
+.Ev MAILFILTER
+.Pc ,
 in the format:
 .Pp
 .D1 Ar type/subtype Ns Li \&: Ar command
@@ -132,6 +139,7 @@
 will then spawn a pipe to
 .Ar command ,
 write the MIME part
+to standard input
 and display the output.
 The environment variable
 .Ev PIPE_CHARSET
@@ -158,6 +166,14 @@
 All other exit statuses are regarded as errors.
 .Sh ENVIRONMENT
 .Bl -tag -width MBLAZE_NOCOLOR
+.It Ev MAILFILTER
+Path to an alternative
+.Pa filter
+file.
+.It Ev MBLAZE_NOCOLOR
+If non-empty,
+.Nm
+will not spawn a colorization filter.
 .It Ev MBLAZE_PAGER
 Any non-empty value of the environment variable
 .Ev MBLAZE_PAGER
@@ -166,10 +182,6 @@
 When empty or set to
 .Sq Ic cat ,
 no pager is spawned.
-.It Ev MBLAZE_NOCOLOR
-If non-empty,
-.Nm
-will not spawn a colorization filter.
 .El
 .Sh EXIT STATUS
 .Ex -std
diff -Nru mblaze-0.4/mbnc mblaze-0.5.1/mbnc
--- mblaze-0.4/mbnc     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mbnc   2019-03-03 17:12:56.000000000 +0100
@@ -11,7 +11,7 @@
 }
 
 notmine() {
-       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)"
+       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: 
"$MBLAZE/profile")"
        grep -Fv -e "$mine"
 }
 
@@ -40,6 +40,27 @@
        fi
 }
 
+checksensible() {
+       awk '
+               /^$/ {
+                       seenheader=1
+                       exit
+               }
+               !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) {
+                       bad=1
+                       print "invalid header line: "$0 >"/dev/stderr"
+               }
+               END {
+                       if (!seenheader) {
+                               print "warning: message does not contain an 
empty line between headers and body." >"/dev/stderr"
+                               exit 1
+                       }
+                       if (bad)
+                               exit 1
+               }
+' "$1"
+}
+
 stripempty() {
        tmp=$(mktemp -t mcom.XXXXXX)
        msed 's/^[ \t]*$//d' "$1" >"$tmp"
@@ -55,13 +76,13 @@
        if needs_multipart "$draft"; then
                (
                        IFS=$NL
-                       msed '/attach/d' $draft
-                       for f in $(mhdr -M -h attach $draft); do
+                       msed '/attach/d' "$draft"
+                       for f in $(mhdr -M -h attach "$draft"); do
                                printf '#%s %s\n' \
-                                      "$(file -Lbi $f | sed 's/ //g')" \
+                                      "$(file -Lbi "$f" | sed 's/ //g')" \
                                       "$f"
                        done
-               ) | mmime >$draftmime
+               ) | mmime >"$draftmime"
        else
                mmime -r <"$draft" >"$draftmime"
        fi
@@ -74,8 +95,11 @@
 sendmail="${sendmail:-sendmail} ${sendmail_args:--t}"
 default_from=$(mhdr -h local-mailbox "$MBLAZE/profile")
 
+defaultc=e
+
 hdrs=
 resume=
+noquote=
 case "$0" in
 *mcom*)
        hdr=to
@@ -90,11 +114,22 @@
                        shift
                        resume=1
                        if [ "$#" -gt 0 ]; then
-                               echo "used draft $1"
-                               draft="$1"
+                               case "$1" in
+                                       /*|./*) draft="$1";;
+                                       *) draft="./$1";;
+                               esac
+                               if ! [ -f "$draft" ]; then
+                                       printf 'mcom: no such draft %s\n' \
+                                              "$draft" 1>&2
+                                       exit 1
+                               fi
+                               echo "using draft $draft"
                                shift
                        fi
                        ;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -118,6 +153,9 @@
                -r)
                        shift
                        raw=1;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -139,6 +177,9 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -160,6 +201,12 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
+               -noquote)
+                       noquote=1
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -280,8 +327,8 @@
                if [ "$ng" ]; then
                        printf 'Newsgroups: %s\n' "$ng"
                else
-                       to=$(mhdr -h reply-to "$1")
-                       [ -z "$to" ] && to=$(mhdr -h from "$1")
+                       to=$(mhdr -d -h reply-to "$1")
+                       [ -z "$to" ] && to=$(mhdr -d -h from "$1")
                        printf 'To: %s\n' "$to"
                        printf 'Cc: %s\n' \
                               "$(mhdr -d -A -h to:cc: "$1" |
@@ -308,8 +355,10 @@
                cat "$MBLAZE/headers" 2>/dev/null
                printf '\n'
 
-               mquote "$1"
-               printf '\n'
+               if [ -z "$noquote" ]; then
+                       mquote "$1"
+                       printf '\n'
+               fi
                (
                        IFS=$NL
                        cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h 
body /dev/stdin)
@@ -332,10 +381,10 @@
                        cat "$SIGNATURE"
                fi
        esac
-} >$draft
+} >"$draft"
 
 automime=
-c=e
+c=$defaultc
 while :; do
        case "$c" in
        s|send)
@@ -352,15 +401,15 @@
                        ;;
                esac
 
-               if [ -e $draftmime ]; then
-                       if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; 
then
-                               stampdate $draftmime
-                               if $sendmail <$draftmime; then
+               if [ -e "$draftmime" ]; then
+                       if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 
]; then
+                               stampdate "$draftmime"
+                               if $sendmail <"$draftmime"; then
                                        if [ "$outbox" ]; then
-                                               mv $draftmime $draft
-                                               mflag -d -S $draft
+                                               mv "$draftmime" "$draft"
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft $draftmime
+                                               rm "$draft" "$draftmime"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -369,15 +418,16 @@
                        else
                                printf 'mcom: re-run mmime first.\n'
                                c=
+                               continue
                        fi
                else
-                       if mmime -c <$draft; then
-                               stampdate $draft
-                               if $sendmail <$draft; then
+                       if mmime -c <"$draft"; then
+                               stampdate "$draft"
+                               if $sendmail <"$draft"; then
                                        if [ "$outbox" ]; then
-                                               mflag -d -S $draft
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft
+                                               rm "$draft"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -386,6 +436,7 @@
                        else
                                printf '%s\n' "mcom: message needs to be 
MIME-encoded first."
                                c=
+                               continue
                        fi
                fi
 
@@ -398,49 +449,64 @@
                exit 0
                ;;
        c|cancel)
-               stampdate $draft
+               stampdate "$draft"
                printf '%s\n' "mcom: cancelled draft $draft"
                exit 1
                ;;
        m|mime)
                do_mime
-               mshow -t $draftmime
+               mshow -t "$draftmime"
                c=
                ;;
        e|edit)
                c=
-               if ! ${EDITOR:-vi} $draft; then
-                       c=c
+               if ! ${EDITOR:-vi} "$draft"; then
+                       c=d
+               else
+                       if checksensible "$draft"; then
+                               stripempty "$draft"
+                               if mmime -c <"$draft" && ! needs_multipart 
"$draft"; then
+                                       automime=
+                               else
+                                       automime=1
+                                       do_mime
+                               fi
+                       else
+                               printf '\n'
+                       fi
                fi
-               stripempty $draft
-               if mmime -c <$draft && ! needs_multipart $draft; then
+               ;;
+       justsend)
+               stripempty "$draft"
+               if mmime -c <"$draft" && ! needs_multipart "$draft"; then
                        automime=
                else
                        automime=1
                        do_mime
                fi
+               c=send
                ;;
        d|delete)
-               rm -i $draft
-               if ! [ -f $draft ]; then
-                       rm -f $draftmime
+               rm -i "$draft"
+               if ! [ -f "$draft" ]; then
+                       rm -f "$draftmime"
                        printf '%s\n' "mcom: deleted draft $draft"
                        exit 0
                fi
                c=
                ;;
        sign)
-               msign $draft >$draftmime
-               mshow -t $draftmime
+               msign "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        encrypt)
-               mencrypt $draft >$draftmime
-               mshow -t $draftmime
+               mencrypt "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        show)
-               if [ -e $draftmime ]; then
+               if [ -e "$draftmime" ]; then
                        mshow "$draftmime"
                else
                        mshow "$draft"
diff -Nru mblaze-0.4/mcom mblaze-0.5.1/mcom
--- mblaze-0.4/mcom     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mcom   2019-03-03 17:12:56.000000000 +0100
@@ -11,7 +11,7 @@
 }
 
 notmine() {
-       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)"
+       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: 
"$MBLAZE/profile")"
        grep -Fv -e "$mine"
 }
 
@@ -40,6 +40,27 @@
        fi
 }
 
+checksensible() {
+       awk '
+               /^$/ {
+                       seenheader=1
+                       exit
+               }
+               !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) {
+                       bad=1
+                       print "invalid header line: "$0 >"/dev/stderr"
+               }
+               END {
+                       if (!seenheader) {
+                               print "warning: message does not contain an 
empty line between headers and body." >"/dev/stderr"
+                               exit 1
+                       }
+                       if (bad)
+                               exit 1
+               }
+' "$1"
+}
+
 stripempty() {
        tmp=$(mktemp -t mcom.XXXXXX)
        msed 's/^[ \t]*$//d' "$1" >"$tmp"
@@ -55,13 +76,13 @@
        if needs_multipart "$draft"; then
                (
                        IFS=$NL
-                       msed '/attach/d' $draft
-                       for f in $(mhdr -M -h attach $draft); do
+                       msed '/attach/d' "$draft"
+                       for f in $(mhdr -M -h attach "$draft"); do
                                printf '#%s %s\n' \
-                                      "$(file -Lbi $f | sed 's/ //g')" \
+                                      "$(file -Lbi "$f" | sed 's/ //g')" \
                                       "$f"
                        done
-               ) | mmime >$draftmime
+               ) | mmime >"$draftmime"
        else
                mmime -r <"$draft" >"$draftmime"
        fi
@@ -74,8 +95,11 @@
 sendmail="${sendmail:-sendmail} ${sendmail_args:--t}"
 default_from=$(mhdr -h local-mailbox "$MBLAZE/profile")
 
+defaultc=e
+
 hdrs=
 resume=
+noquote=
 case "$0" in
 *mcom*)
        hdr=to
@@ -90,11 +114,22 @@
                        shift
                        resume=1
                        if [ "$#" -gt 0 ]; then
-                               echo "used draft $1"
-                               draft="$1"
+                               case "$1" in
+                                       /*|./*) draft="$1";;
+                                       *) draft="./$1";;
+                               esac
+                               if ! [ -f "$draft" ]; then
+                                       printf 'mcom: no such draft %s\n' \
+                                              "$draft" 1>&2
+                                       exit 1
+                               fi
+                               echo "using draft $draft"
                                shift
                        fi
                        ;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -118,6 +153,9 @@
                -r)
                        shift
                        raw=1;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -139,6 +177,9 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -160,6 +201,12 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
+               -noquote)
+                       noquote=1
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -280,8 +327,8 @@
                if [ "$ng" ]; then
                        printf 'Newsgroups: %s\n' "$ng"
                else
-                       to=$(mhdr -h reply-to "$1")
-                       [ -z "$to" ] && to=$(mhdr -h from "$1")
+                       to=$(mhdr -d -h reply-to "$1")
+                       [ -z "$to" ] && to=$(mhdr -d -h from "$1")
                        printf 'To: %s\n' "$to"
                        printf 'Cc: %s\n' \
                               "$(mhdr -d -A -h to:cc: "$1" |
@@ -308,8 +355,10 @@
                cat "$MBLAZE/headers" 2>/dev/null
                printf '\n'
 
-               mquote "$1"
-               printf '\n'
+               if [ -z "$noquote" ]; then
+                       mquote "$1"
+                       printf '\n'
+               fi
                (
                        IFS=$NL
                        cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h 
body /dev/stdin)
@@ -332,10 +381,10 @@
                        cat "$SIGNATURE"
                fi
        esac
-} >$draft
+} >"$draft"
 
 automime=
-c=e
+c=$defaultc
 while :; do
        case "$c" in
        s|send)
@@ -352,15 +401,15 @@
                        ;;
                esac
 
-               if [ -e $draftmime ]; then
-                       if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; 
then
-                               stampdate $draftmime
-                               if $sendmail <$draftmime; then
+               if [ -e "$draftmime" ]; then
+                       if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 
]; then
+                               stampdate "$draftmime"
+                               if $sendmail <"$draftmime"; then
                                        if [ "$outbox" ]; then
-                                               mv $draftmime $draft
-                                               mflag -d -S $draft
+                                               mv "$draftmime" "$draft"
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft $draftmime
+                                               rm "$draft" "$draftmime"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -369,15 +418,16 @@
                        else
                                printf 'mcom: re-run mmime first.\n'
                                c=
+                               continue
                        fi
                else
-                       if mmime -c <$draft; then
-                               stampdate $draft
-                               if $sendmail <$draft; then
+                       if mmime -c <"$draft"; then
+                               stampdate "$draft"
+                               if $sendmail <"$draft"; then
                                        if [ "$outbox" ]; then
-                                               mflag -d -S $draft
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft
+                                               rm "$draft"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -386,6 +436,7 @@
                        else
                                printf '%s\n' "mcom: message needs to be 
MIME-encoded first."
                                c=
+                               continue
                        fi
                fi
 
@@ -398,49 +449,64 @@
                exit 0
                ;;
        c|cancel)
-               stampdate $draft
+               stampdate "$draft"
                printf '%s\n' "mcom: cancelled draft $draft"
                exit 1
                ;;
        m|mime)
                do_mime
-               mshow -t $draftmime
+               mshow -t "$draftmime"
                c=
                ;;
        e|edit)
                c=
-               if ! ${EDITOR:-vi} $draft; then
-                       c=c
+               if ! ${EDITOR:-vi} "$draft"; then
+                       c=d
+               else
+                       if checksensible "$draft"; then
+                               stripempty "$draft"
+                               if mmime -c <"$draft" && ! needs_multipart 
"$draft"; then
+                                       automime=
+                               else
+                                       automime=1
+                                       do_mime
+                               fi
+                       else
+                               printf '\n'
+                       fi
                fi
-               stripempty $draft
-               if mmime -c <$draft && ! needs_multipart $draft; then
+               ;;
+       justsend)
+               stripempty "$draft"
+               if mmime -c <"$draft" && ! needs_multipart "$draft"; then
                        automime=
                else
                        automime=1
                        do_mime
                fi
+               c=send
                ;;
        d|delete)
-               rm -i $draft
-               if ! [ -f $draft ]; then
-                       rm -f $draftmime
+               rm -i "$draft"
+               if ! [ -f "$draft" ]; then
+                       rm -f "$draftmime"
                        printf '%s\n' "mcom: deleted draft $draft"
                        exit 0
                fi
                c=
                ;;
        sign)
-               msign $draft >$draftmime
-               mshow -t $draftmime
+               msign "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        encrypt)
-               mencrypt $draft >$draftmime
-               mshow -t $draftmime
+               mencrypt "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        show)
-               if [ -e $draftmime ]; then
+               if [ -e "$draftmime" ]; then
                        mshow "$draftmime"
                else
                        mshow "$draft"
diff -Nru mblaze-0.4/mdeliver.c mblaze-0.5.1/mdeliver.c
--- mblaze-0.4/mdeliver.c       2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mdeliver.c     2019-03-03 17:12:56.000000000 +0100
@@ -1,3 +1,4 @@
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 
@@ -30,6 +31,8 @@
 
 char *targetdir;
 long delivery;
+int preserve_mtime;
+int try_rename;
 
 char host[64];
 void
@@ -45,9 +48,10 @@
 }
 
 int
-deliver(FILE *infile)
+deliver(char *infilename)
 {
        int outfd;
+       FILE *infile;
        FILE *outfile;
        char dst[PATH_MAX];
        char tmp[PATH_MAX];
@@ -57,6 +61,22 @@
        char *line = 0;
        size_t linelen = 0;
 
+       if (infilename) {
+               if (try_rename) {
+                       infile = 0;
+               } else {
+                       infile = fopen(infilename, "r");
+                       if (!infile) {
+                               fprintf(stderr, "mrefile: %s: %s\n",
+                                   infilename, strerror(errno));
+                               return -1;
+                       }
+               }
+       } else {
+               // mdeliver
+               infile = stdin;
+       }
+
        if (Mflag) {
                // skip to first "From " line
                while (1) {
@@ -65,7 +85,7 @@
                        if (rd == -1) {
                                if (errno == 0)
                                        errno = EINVAL;  // invalid mbox file
-                               return -1;
+                               goto fail;
                        }
 
                        if (strncmp("From ", line, 5) == 0)
@@ -73,9 +93,9 @@
                }
        }
 
-       while (!feof(infile)) {
+       do {
                delivery++;
-tryagain:
+try_again:
                gettimeofday(&tv, 0);
 
                snprintf(id, sizeof id, "%ld.M%06ldP%ldQ%ld.%s",
@@ -84,13 +104,39 @@
 
                snprintf(tmp, sizeof tmp, "%s/tmp/%s", targetdir, id);
 
-               outfd = open(tmp, O_CREAT | O_WRONLY | O_EXCL, 0666);
+               if (try_rename) {
+                       snprintf(dst, sizeof dst, "%s/%s/%s:2,%s",
+                           targetdir, cflag ? "cur" : "new", id, Xflag);
+                       if (rename(infilename, dst) == 0)
+                               goto success;
+
+                       /* rename failed, open file and try copying */
+
+                       infile = fopen(infilename, "r");
+                       if (!infile) {
+                               fprintf(stderr, "mrefile: %s: %s\n",
+                                   infilename, strerror(errno));
+                               return -1;
+                       }
+               }
+
+               struct stat st;
+               if (fstat(fileno(infile), &st) < 0)
+                       st.st_mode = 0600;
+               if (S_ISFIFO(st.st_mode))
+                       st.st_mode = 0600;
+               outfd = open(tmp, O_CREAT | O_WRONLY | O_EXCL,
+                   st.st_mode & 07777);
                if (outfd < 0) {
                        if (errno == EEXIST)
-                               goto tryagain;
-                       fprintf(stderr, "mrefile: %s: %s\n",
-                           tmp, strerror(errno));
-                       return -1;
+                               goto try_again;
+                       if (errno == ENOENT)
+                               fprintf(stderr, "mrefile: %s/tmp: %s\n",
+                                   targetdir, strerror(errno));
+                       else
+                               fprintf(stderr, "mrefile: %s: %s\n",
+                                   tmp, strerror(errno));
+                       goto fail;
                }
 
                outfile = fdopen(outfd, "w");
@@ -104,7 +150,7 @@
                        ssize_t rd = getdelim(&line, &linelen, '\n', infile);
                        if (rd == -1) {
                                if (errno != 0)
-                                       return -1;
+                                       goto fail;
                                break;
                        }
                        char *line_start = line;
@@ -142,14 +188,14 @@
                        }
 
                        if (fwrite(line_start, 1, rd, outfile) != (size_t)rd)
-                               return -1;
+                               goto fail;
                }
                if (fflush(outfile) == EOF)
-                       return -1;
+                       goto fail;
                if (fsync(outfd) < 0)
-                       return -1;
+                       goto fail;
                if (fclose(outfile) == EOF)
-                       return -1;
+                       goto fail;
 
                // compress flags
                int i, j;
@@ -173,18 +219,40 @@
                                        utimes(tmp, times);
                                }
                        }
+                       blaze822_free(msg);
+               }
+
+               if (preserve_mtime) {
+                       const struct timespec times[2] = {
+                               { tv.tv_sec, tv.tv_usec * 1000L },
+#if (defined(__APPLE__) && defined(__MACH__))
+                               st.st_mtimespec
+#else /* POSIX.1-2008 */
+                               st.st_mtim
+#endif
+                       };
+                       utimensat(AT_FDCWD, tmp, times, 0);
                }
 
                snprintf(dst, sizeof dst, "%s/%s/%s:2,%s",
                    targetdir, (cflag || is_old) ? "cur" : "new", id,
                    Xflag ? Xflag : statusflags);
                if (rename(tmp, dst) != 0)
-                       return -1;
+                       goto fail;
 
+success:
                if (vflag)
                        printf("%s\n", dst);
-       }
+       } while (Mflag && !feof(infile));
+
+       if (infile)
+               fclose(infile);
        return 0;
+
+fail:
+       if (infile)
+               fclose(infile);
+       return -1;
 }
 
 void
@@ -193,12 +261,6 @@
        while (*file == ' ' || *file == '\t')
                file++;
 
-       FILE *f = fopen(file, "r");
-       if (!f) {
-               fprintf(stderr, "mrefile: %s: %s\n", file, strerror(errno));
-               return;
-       }
-
        // keep flags
        char *flags = strstr(file, ":2,");
        if (flags)
@@ -206,13 +268,12 @@
        else
                Xflag = "";
 
-       if (deliver(f) < 0) {
+       if (deliver(file) < 0) {
                perror("mrefile");
                return;
        }
 
-       fclose(f);
-       if (!kflag)
+       if (!kflag && !try_rename)
                unlink(file);
 }
 
@@ -223,11 +284,13 @@
                // mrefile(1)
 
                cflag = 1;  // use cur/
+               preserve_mtime = 1;
+               try_rename = 1;
 
                int c;
                while ((c = getopt(argc, argv, "kv")) != -1)
                        switch (c) {
-                       case 'k': kflag = 1; break;
+                       case 'k': kflag = 1; try_rename = 0; break;
                        case 'v': vflag = 1; break;
                        default:
 usage:
@@ -274,7 +337,7 @@
 
        gethost();
 
-       if (deliver(stdin) < 0) {
+       if (deliver(0) < 0) {
                perror("mdeliver");
                return 2;
        }
diff -Nru mblaze-0.4/mdirs.c mblaze-0.5.1/mdirs.c
--- mblaze-0.4/mdirs.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mdirs.c        2019-03-03 17:12:56.000000000 +0100
@@ -9,12 +9,14 @@
 
 #include "blaze822.h"
 
+static char sep = '\n';
+
 void
 pwd()
 {
        char cwd[PATH_MAX];
        if (getcwd(cwd, sizeof cwd))
-               puts(cwd);
+               printf("%s%c", cwd, sep);
 }
 
 void
@@ -72,19 +74,31 @@
 main(int argc, char *argv[])
 {
        int c, i;
-       while ((c = getopt(argc, argv, "")) != -1)
+       while ((c = getopt(argc, argv, "0")) != -1)
                switch (c) {
+               case '0': sep = '\0'; break;
                default:
 usage:
-                       fprintf(stderr, "Usage: mdirs dirs...\n");
+                       fprintf(stderr, "Usage: mdirs [-0] dirs...\n");
                        exit(1);
                }
 
        if (argc == optind)
                goto usage;
 
-       for (i = 0; i < argc; i++)
+       char toplevel[PATH_MAX];
+       if (!getcwd(toplevel, sizeof toplevel)) {
+               perror("mdirs: getcwd");
+               exit(-1);
+       }
+
+       for (i = 0; i < argc; i++) {
                mdirs(argv[i]);
+               if (chdir(toplevel) < 0) {
+                       perror("mdirs: chdir");
+                       exit(-1);
+               }
+       }
 
        return 0;
 }
diff -Nru mblaze-0.4/mflow.c mblaze-0.5.1/mflow.c
--- mblaze-0.4/mflow.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mflow.c        2019-03-03 17:12:56.000000000 +0100
@@ -40,7 +40,7 @@
        if (column == 0) {
                for (; column < quotes; column++)
                        putchar('>');
-               if (quotes)
+               if (quotes && *line != ' ')
                        putchar(' ');
        }
 
@@ -60,7 +60,7 @@
                        for (; column < quotes; column++)
                                putchar('>');
                        column++;
-                       if (quotes)
+                       if (quotes && *line != ' ')
                                putchar(' ');
                }
 
diff -Nru mblaze-0.4/mgenmid.c mblaze-0.5.1/mgenmid.c
--- mblaze-0.4/mgenmid.c        2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mgenmid.c      2019-03-03 17:12:56.000000000 +0100
@@ -85,30 +85,35 @@
        struct timeval tp;
        gettimeofday(&tp, (struct timezone *)0);
 
-       uint64_t rnd;
+       uint64_t rnd1, rnd2;
 
        int rndfd = open("/dev/urandom", O_RDONLY);
        if (rndfd >= 0) {
-               unsigned char rndb[8];
+               unsigned char rndb[16];
                if (read(rndfd, rndb, sizeof rndb) != sizeof rndb)
                        goto fallback;
                close(rndfd);
 
                int i;
-               for (i = 0, rnd = 0; i < 8; i++)
-                       rnd = rnd*256 + rndb[i];
+               for (i = 0, rnd1 = 0; i < 8; i++)
+                       rnd1 = rnd1*256 + rndb[i];
+               for (i = 0, rnd2 = 0; i < 8; i++)
+                       rnd2 = rnd2*256 + rndb[i+8];
        } else {
 fallback:
                srand48(tp.tv_sec ^ tp.tv_usec ^ getpid());
-               rnd = ((uint64_t)lrand48() << 32) + lrand48();
+               rnd1 = ((uint64_t)lrand48() << 32) + lrand48();
+               rnd2 = ((uint64_t)lrand48() << 32) + lrand48();
        }
 
-       rnd |= (1ULL << 63);  // set highest bit to force full width
+       rnd1 ^= ((uint64_t)tp.tv_sec * 1000000LL + tp.tv_usec);
+       rnd1 |= (1ULL << 63);  // set highest bit to force full width
+       rnd2 |= (1ULL << 63);  // set highest bit to force full width
 
        putchar('<');
-       printb36(((uint64_t)tp.tv_sec * 1000000LL + tp.tv_usec));
+       printb36(rnd1);
        putchar('.');
-       printb36(rnd);
+       printb36(rnd2);
        putchar('@');
        fputs(host, stdout);
        putchar('>');
diff -Nru mblaze-0.4/mless mblaze-0.5.1/mless
--- mblaze-0.4/mless    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mless  2019-03-03 17:12:56.000000000 +0100
@@ -37,9 +37,9 @@
                        mshow "$2"
                fi | mcolor
        else
-               mseq -r $2
+               mseq -r "$2"
                echo
-               cat "$(mseq -r $2)"
+               cat "$(mseq -r "$2")"
        fi
        exit $?
 fi
@@ -53,11 +53,7 @@
        exec mseq :
 fi
 
-case "$0" in
-       *mnext) set -- +;;
-       *mprev) set -- -;;
-       *) [ "$#" -eq 1 ] && set -- ${1:-.};;
-esac
+[ "$#" -eq 1 ] && set -- ${1:-.}
 
 if [ "$#" -ge 1 ]; then
        mseq -C "$1"
@@ -68,12 +64,12 @@
 export MLESS_RAW=0
 export MLESS_HTML=0
 while :; do
-       if [ -f $MBLAZE/mless ]; then
-               export LESSKEY=$MBLAZE/mless
-       elif [ -f $HOME/.mblaze/mless ]; then
-               export LESSKEY=$HOME/.mblaze/mless
-       elif [ -f $HOME/.mless ]; then
-               export LESSKEY=$HOME/.mless
+       if [ -f "$MBLAZE/mless" ]; then
+               export LESSKEY="$MBLAZE/mless"
+       elif [ -f "$HOME/.mblaze/mless" ]; then
+               export LESSKEY="$HOME/.mblaze/mless"
+       elif [ -f "$HOME/.mless" ]; then
+               export LESSKEY="$HOME/.mless"
        fi
        LESSOPEN="|$0 --filter %s" \
                less -Ps"mless %f?m (message %i of %m).." -R \
diff -Nru mblaze-0.4/mmime.c mblaze-0.5.1/mmime.c
--- mblaze-0.4/mmime.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mmime.c        2019-03-03 17:12:56.000000000 +0100
@@ -282,6 +282,9 @@
        char *s, *e;
        size_t l = strlen(line);
 
+       if (l == 0)
+               return;
+
        if (line[l-1] == '\n')
                line[l-1] = 0;
 
@@ -299,7 +302,7 @@
 
        int prevq = 0;  // was the previous word encoded as qp?
 
-       size_t linelen = s - line;
+       ssize_t linelen = s - line;
 
        while (*s) {
                size_t highbit = 0;
diff -Nru mblaze-0.4/mmkdir mblaze-0.5.1/mmkdir
--- mblaze-0.4/mmkdir   2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mmkdir 2019-03-03 17:12:56.000000000 +0100
@@ -1,9 +1,11 @@
 #!/bin/sh
 # mmkdir DIRS... - create new maildirs
 
+umask 077
+
 r=0
 for dir; do
-       mkdir -p -m 0700 $dir/cur $dir/new $dir/tmp || r=1
+       mkdir -p "$dir"/cur "$dir"/new "$dir"/tmp || r=1
 done
 
 exit $r
diff -Nru mblaze-0.4/mnext mblaze-0.5.1/mnext
--- mblaze-0.4/mnext    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mnext  1970-01-01 01:00:00.000000000 +0100
@@ -1,107 +0,0 @@
-#!/bin/sh
-# mless [MSG] - less(1)-wrapper around mshow
-
-colorscan() {
-awk '
-function co(n, c) { e = ENVIRON["MCOLOR_" n]; return e ? e : c }
-function fg(c, s) { return sprintf("\033[38;5;%03dm%s\033[0m", c, s) }
-function so(s) { return sprintf("\033[1m%s\033[0m", s) }
-/^>/ { print so(fg(co("CUR",119), $0)); next }
-/^ *\\_/ { print fg(co("MISS",242), $0); next }
-{ print }'
-}
-
-if [ -n "${NO_COLOR+set}" ]; then
-       colorscan() { cat -; }
-fi
-
-if [ "$1" = --filter ]; then
-       if [ "$2" = //scan ]; then
-               mscan : 2>/dev/null | colorscan
-               exit $?
-       fi
-
-       mseq -C "$2"
-       mscan .-2:.+3 2>/dev/null | colorscan
-       echo
-
-       if ! [ -f "$(mseq -r "$2")" ]; then
-               mseq "$2"
-               exit
-       fi
-
-       if [ $MLESS_RAW -eq 0 ]; then
-               if [ $MLESS_HTML -eq 1 ]; then
-                       mshow -A text/html "$2"
-               else
-                       mshow "$2"
-               fi | mcolor
-       else
-               mseq -r $2
-               echo
-               cat "$(mseq -r $2)"
-       fi
-       exit $?
-fi
-
-if [ "$#" -eq 0 ] && ! [ -t 0 ]; then
-       mseq -S >/dev/null
-       set -- :
-fi
-
-if ! [ -t 1 ]; then
-       exec mseq :
-fi
-
-case "$0" in
-       *mnext) set -- +;;
-       *mprev) set -- -;;
-       *) [ "$#" -eq 1 ] && set -- ${1:-.};;
-esac
-
-if [ "$#" -ge 1 ]; then
-       mseq -C "$1"
-fi
-
-nl="
-"
-export MLESS_RAW=0
-export MLESS_HTML=0
-while :; do
-       if [ -f $MBLAZE/mless ]; then
-               export LESSKEY=$MBLAZE/mless
-       elif [ -f $HOME/.mblaze/mless ]; then
-               export LESSKEY=$HOME/.mblaze/mless
-       elif [ -f $HOME/.mless ]; then
-               export LESSKEY=$HOME/.mless
-       fi
-       LESSOPEN="|$0 --filter %s" \
-               less -Ps"mless %f?m (message %i of %m).." -R \
-                       "+:e $(mscan -n .)$nl" //scan $(mscan -n :)
-       case "$?" in
-       0|1) exit $?;;
-       36) # $ goto end
-               mseq -C '$' 2>/dev/null
-               ;;
-       78) # N go to next unseen message
-               nu=$(magrep -v -m1 :S .:) && mseq -C "$nu"
-               ;;
-       107) # k next thread
-               mseq -C "$(mseq .+1: | sed -n '/^[^ <]/{p;q;}')"
-               ;;
-       100) # d mark read
-               mflag -S .
-               mseq -f : | mseq -S
-               mseq -C +
-               ;;
-       82) # R toggle raw mode
-               MLESS_RAW=$((1-$MLESS_RAW))
-               ;;
-       72) # H toggle HTML mode
-               MLESS_HTML=$((1-$MLESS_HTML))
-               ;;
-       94) # ^ goto parent
-               mseq -C '.^' 2>/dev/null
-               ;;
-       esac
-done
diff -Nru mblaze-0.4/mpick.c mblaze-0.5.1/mpick.c
--- mblaze-0.4/mpick.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mpick.c        2019-03-03 17:12:56.000000000 +0100
@@ -284,7 +284,7 @@
                pos++;
                while (*pos &&
                    (*pos != '"' || (*pos == '"' && *(pos+1) == '"'))) {
-                       if (len >= bufsiz) {
+                       if (len+1 >= bufsiz) {
                                bufsiz = 2*bufsiz + 16;
                                buf = realloc(buf, bufsiz);
                                if (!buf)
@@ -809,7 +809,7 @@
        if (!m->msg || !(b = blaze822_chdr(m->msg, h)))
                goto err;
 
-       char buf[100];
+       char buf[4096];
        blaze822_decode_rfc2047(buf, b, sizeof buf - 1, "UTF-8");
        if (!*buf)
                goto err;
@@ -1142,17 +1142,20 @@
 {
        long i;
        int c;
+       int vflag;
 
        argv0 = argv[0];
        now = time(0);
        num = 1;
+       vflag = 0;
 
-       while ((c = getopt(argc, argv, "Tt:")) != -1)
+       while ((c = getopt(argc, argv, "Tt:v")) != -1)
                switch (c) {
                case 'T': Tflag = need_thr = 1; break;
                case 't': expr = chain(expr, EXPR_AND, parse_expr(optarg)); 
break;
+               case 'v': vflag = 1; break;
                default:
-                       fprintf(stderr, "Usage: %s [-T] [-t test] [msglist 
...]\n", argv0);
+                       fprintf(stderr, "Usage: %s [-Tv] [-t test] [msglist 
...]\n", argv0);
                        exit(1);
                }
 
@@ -1169,6 +1172,7 @@
        if (Tflag && thr)
                do_thr();
 
-       fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept);
+       if (vflag)
+               fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept);
        return 0;
 }
diff -Nru mblaze-0.4/mprev mblaze-0.5.1/mprev
--- mblaze-0.4/mprev    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mprev  1970-01-01 01:00:00.000000000 +0100
@@ -1,107 +0,0 @@
-#!/bin/sh
-# mless [MSG] - less(1)-wrapper around mshow
-
-colorscan() {
-awk '
-function co(n, c) { e = ENVIRON["MCOLOR_" n]; return e ? e : c }
-function fg(c, s) { return sprintf("\033[38;5;%03dm%s\033[0m", c, s) }
-function so(s) { return sprintf("\033[1m%s\033[0m", s) }
-/^>/ { print so(fg(co("CUR",119), $0)); next }
-/^ *\\_/ { print fg(co("MISS",242), $0); next }
-{ print }'
-}
-
-if [ -n "${NO_COLOR+set}" ]; then
-       colorscan() { cat -; }
-fi
-
-if [ "$1" = --filter ]; then
-       if [ "$2" = //scan ]; then
-               mscan : 2>/dev/null | colorscan
-               exit $?
-       fi
-
-       mseq -C "$2"
-       mscan .-2:.+3 2>/dev/null | colorscan
-       echo
-
-       if ! [ -f "$(mseq -r "$2")" ]; then
-               mseq "$2"
-               exit
-       fi
-
-       if [ $MLESS_RAW -eq 0 ]; then
-               if [ $MLESS_HTML -eq 1 ]; then
-                       mshow -A text/html "$2"
-               else
-                       mshow "$2"
-               fi | mcolor
-       else
-               mseq -r $2
-               echo
-               cat "$(mseq -r $2)"
-       fi
-       exit $?
-fi
-
-if [ "$#" -eq 0 ] && ! [ -t 0 ]; then
-       mseq -S >/dev/null
-       set -- :
-fi
-
-if ! [ -t 1 ]; then
-       exec mseq :
-fi
-
-case "$0" in
-       *mnext) set -- +;;
-       *mprev) set -- -;;
-       *) [ "$#" -eq 1 ] && set -- ${1:-.};;
-esac
-
-if [ "$#" -ge 1 ]; then
-       mseq -C "$1"
-fi
-
-nl="
-"
-export MLESS_RAW=0
-export MLESS_HTML=0
-while :; do
-       if [ -f $MBLAZE/mless ]; then
-               export LESSKEY=$MBLAZE/mless
-       elif [ -f $HOME/.mblaze/mless ]; then
-               export LESSKEY=$HOME/.mblaze/mless
-       elif [ -f $HOME/.mless ]; then
-               export LESSKEY=$HOME/.mless
-       fi
-       LESSOPEN="|$0 --filter %s" \
-               less -Ps"mless %f?m (message %i of %m).." -R \
-                       "+:e $(mscan -n .)$nl" //scan $(mscan -n :)
-       case "$?" in
-       0|1) exit $?;;
-       36) # $ goto end
-               mseq -C '$' 2>/dev/null
-               ;;
-       78) # N go to next unseen message
-               nu=$(magrep -v -m1 :S .:) && mseq -C "$nu"
-               ;;
-       107) # k next thread
-               mseq -C "$(mseq .+1: | sed -n '/^[^ <]/{p;q;}')"
-               ;;
-       100) # d mark read
-               mflag -S .
-               mseq -f : | mseq -S
-               mseq -C +
-               ;;
-       82) # R toggle raw mode
-               MLESS_RAW=$((1-$MLESS_RAW))
-               ;;
-       72) # H toggle HTML mode
-               MLESS_HTML=$((1-$MLESS_HTML))
-               ;;
-       94) # ^ goto parent
-               mseq -C '.^' 2>/dev/null
-               ;;
-       esac
-done
diff -Nru mblaze-0.4/mrep mblaze-0.5.1/mrep
--- mblaze-0.4/mrep     2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mrep   2019-03-03 17:12:56.000000000 +0100
@@ -11,7 +11,7 @@
 }
 
 notmine() {
-       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)"
+       mine="$(maddr -a -h local-mailbox:alternate-mailboxes: 
"$MBLAZE/profile")"
        grep -Fv -e "$mine"
 }
 
@@ -40,6 +40,27 @@
        fi
 }
 
+checksensible() {
+       awk '
+               /^$/ {
+                       seenheader=1
+                       exit
+               }
+               !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) {
+                       bad=1
+                       print "invalid header line: "$0 >"/dev/stderr"
+               }
+               END {
+                       if (!seenheader) {
+                               print "warning: message does not contain an 
empty line between headers and body." >"/dev/stderr"
+                               exit 1
+                       }
+                       if (bad)
+                               exit 1
+               }
+' "$1"
+}
+
 stripempty() {
        tmp=$(mktemp -t mcom.XXXXXX)
        msed 's/^[ \t]*$//d' "$1" >"$tmp"
@@ -55,13 +76,13 @@
        if needs_multipart "$draft"; then
                (
                        IFS=$NL
-                       msed '/attach/d' $draft
-                       for f in $(mhdr -M -h attach $draft); do
+                       msed '/attach/d' "$draft"
+                       for f in $(mhdr -M -h attach "$draft"); do
                                printf '#%s %s\n' \
-                                      "$(file -Lbi $f | sed 's/ //g')" \
+                                      "$(file -Lbi "$f" | sed 's/ //g')" \
                                       "$f"
                        done
-               ) | mmime >$draftmime
+               ) | mmime >"$draftmime"
        else
                mmime -r <"$draft" >"$draftmime"
        fi
@@ -74,8 +95,11 @@
 sendmail="${sendmail:-sendmail} ${sendmail_args:--t}"
 default_from=$(mhdr -h local-mailbox "$MBLAZE/profile")
 
+defaultc=e
+
 hdrs=
 resume=
+noquote=
 case "$0" in
 *mcom*)
        hdr=to
@@ -90,11 +114,22 @@
                        shift
                        resume=1
                        if [ "$#" -gt 0 ]; then
-                               echo "used draft $1"
-                               draft="$1"
+                               case "$1" in
+                                       /*|./*) draft="$1";;
+                                       *) draft="./$1";;
+                               esac
+                               if ! [ -f "$draft" ]; then
+                                       printf 'mcom: no such draft %s\n' \
+                                              "$draft" 1>&2
+                                       exit 1
+                               fi
+                               echo "using draft $draft"
                                shift
                        fi
                        ;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -118,6 +153,9 @@
                -r)
                        shift
                        raw=1;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -139,6 +177,9 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -160,6 +201,12 @@
                --)
                        shift
                        break;;
+               -send)
+                       defaultc=justsend
+                       shift;;
+               -noquote)
+                       noquote=1
+                       shift;;
                -??*)
                        hdr=${1#-}
                        shift;;
@@ -280,8 +327,8 @@
                if [ "$ng" ]; then
                        printf 'Newsgroups: %s\n' "$ng"
                else
-                       to=$(mhdr -h reply-to "$1")
-                       [ -z "$to" ] && to=$(mhdr -h from "$1")
+                       to=$(mhdr -d -h reply-to "$1")
+                       [ -z "$to" ] && to=$(mhdr -d -h from "$1")
                        printf 'To: %s\n' "$to"
                        printf 'Cc: %s\n' \
                               "$(mhdr -d -A -h to:cc: "$1" |
@@ -308,8 +355,10 @@
                cat "$MBLAZE/headers" 2>/dev/null
                printf '\n'
 
-               mquote "$1"
-               printf '\n'
+               if [ -z "$noquote" ]; then
+                       mquote "$1"
+                       printf '\n'
+               fi
                (
                        IFS=$NL
                        cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h 
body /dev/stdin)
@@ -332,10 +381,10 @@
                        cat "$SIGNATURE"
                fi
        esac
-} >$draft
+} >"$draft"
 
 automime=
-c=e
+c=$defaultc
 while :; do
        case "$c" in
        s|send)
@@ -352,15 +401,15 @@
                        ;;
                esac
 
-               if [ -e $draftmime ]; then
-                       if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; 
then
-                               stampdate $draftmime
-                               if $sendmail <$draftmime; then
+               if [ -e "$draftmime" ]; then
+                       if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 
]; then
+                               stampdate "$draftmime"
+                               if $sendmail <"$draftmime"; then
                                        if [ "$outbox" ]; then
-                                               mv $draftmime $draft
-                                               mflag -d -S $draft
+                                               mv "$draftmime" "$draft"
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft $draftmime
+                                               rm "$draft" "$draftmime"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -369,15 +418,16 @@
                        else
                                printf 'mcom: re-run mmime first.\n'
                                c=
+                               continue
                        fi
                else
-                       if mmime -c <$draft; then
-                               stampdate $draft
-                               if $sendmail <$draft; then
+                       if mmime -c <"$draft"; then
+                               stampdate "$draft"
+                               if $sendmail <"$draft"; then
                                        if [ "$outbox" ]; then
-                                               mflag -d -S $draft
+                                               mflag -d -S "$draft"
                                        else
-                                               rm $draft
+                                               rm "$draft"
                                        fi
                                else
                                        printf '%s\n' "mcom: $sendmail failed, 
kept draft $draft"
@@ -386,6 +436,7 @@
                        else
                                printf '%s\n' "mcom: message needs to be 
MIME-encoded first."
                                c=
+                               continue
                        fi
                fi
 
@@ -398,49 +449,64 @@
                exit 0
                ;;
        c|cancel)
-               stampdate $draft
+               stampdate "$draft"
                printf '%s\n' "mcom: cancelled draft $draft"
                exit 1
                ;;
        m|mime)
                do_mime
-               mshow -t $draftmime
+               mshow -t "$draftmime"
                c=
                ;;
        e|edit)
                c=
-               if ! ${EDITOR:-vi} $draft; then
-                       c=c
+               if ! ${EDITOR:-vi} "$draft"; then
+                       c=d
+               else
+                       if checksensible "$draft"; then
+                               stripempty "$draft"
+                               if mmime -c <"$draft" && ! needs_multipart 
"$draft"; then
+                                       automime=
+                               else
+                                       automime=1
+                                       do_mime
+                               fi
+                       else
+                               printf '\n'
+                       fi
                fi
-               stripempty $draft
-               if mmime -c <$draft && ! needs_multipart $draft; then
+               ;;
+       justsend)
+               stripempty "$draft"
+               if mmime -c <"$draft" && ! needs_multipart "$draft"; then
                        automime=
                else
                        automime=1
                        do_mime
                fi
+               c=send
                ;;
        d|delete)
-               rm -i $draft
-               if ! [ -f $draft ]; then
-                       rm -f $draftmime
+               rm -i "$draft"
+               if ! [ -f "$draft" ]; then
+                       rm -f "$draftmime"
                        printf '%s\n' "mcom: deleted draft $draft"
                        exit 0
                fi
                c=
                ;;
        sign)
-               msign $draft >$draftmime
-               mshow -t $draftmime
+               msign "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        encrypt)
-               mencrypt $draft >$draftmime
-               mshow -t $draftmime
+               mencrypt "$draft" >"$draftmime"
+               mshow -t "$draftmime"
                c=
                ;;
        show)
-               if [ -e $draftmime ]; then
+               if [ -e "$draftmime" ]; then
                        mshow "$draftmime"
                else
                        mshow "$draft"
diff -Nru mblaze-0.4/mscan.c mblaze-0.5.1/mscan.c
--- mblaze-0.4/mscan.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mscan.c        2019-03-03 17:12:56.000000000 +0100
@@ -29,6 +29,7 @@
 
 static int Iflag;
 static int nflag;
+static int vflag;
 static int curyear;
 static time_t now;
 static char default_fflag[] = "%c%u%r %-3n %10d %17f %t %2i%s";
@@ -52,6 +53,7 @@
                        int r = u8decode(s, &c);
                        if (r < 0) {
                                r = 1;
+                               l--;
                                fprintf(out, "%lc", (wint_t)replacement);
                        } else {
                                l -= wcwidth((wchar_t)c);
@@ -338,12 +340,12 @@
                        wleft--;
                        break;
                case 'u':  // unseen
-                       if (strchr(flags, 'F'))
+                       if (strchr(flags, 'T'))
+                               putchar('x');
+                       else if (strchr(flags, 'F'))
                                putchar('*');
                        else if (msg && !strchr(flags, 'S'))
                                putchar('.');
-                       else if (strchr(flags, 'T'))
-                               putchar('x');
                        else
                                putchar(' ');
                        wleft--;
@@ -489,16 +491,17 @@
 int
 main(int argc, char *argv[])
 {
-       pid_t pid1 = -1;
+       pid_t pager_pid = -1;
 
        int c;
-       while ((c = getopt(argc, argv, "If:n")) != -1)
+       while ((c = getopt(argc, argv, "If:nv")) != -1)
                switch (c) {
                case 'I': Iflag++; break;
                case 'f': fflag = optarg; break;
                case 'n': nflag = 1; break;
+               case 'v': vflag = 1; break;
                default:
-                       fprintf(stderr, "Usage: mscan [-n] [-f format] [-I] 
[msgs...]\n");
+                       fprintf(stderr, "Usage: mscan [-Inv] [-f format] 
[msgs...]\n");
                        exit(1);
                }
 
@@ -528,8 +531,8 @@
                if (!pg)
                        pg = getenv("PAGER");
                if (pg && *pg && strcmp(pg, "cat") != 0) {
-                       pid1 = pipeto(pg);
-                       if (pid1 < 0)
+                       pager_pid = pipeto(pg);
+                       if (pager_pid < 0)
                                fprintf(stderr,
                                    "mscan: spawning pager '%s': %s\n",
                                    pg, strerror(errno));
@@ -567,10 +570,12 @@
                i = blaze822_loop1(":", oneline);
        else
                i = blaze822_loop(argc-optind, argv+optind, oneline);
-       fprintf(stderr, "%ld mails scanned\n", i);
 
-       if (pid1 > 0)
-               pipeclose(pid1);
+       if (pager_pid > 0)
+               pipeclose(pager_pid);
+
+       if (vflag)
+               fprintf(stderr, "%ld mails scanned\n", i);
 
        return 0;
 }
diff -Nru mblaze-0.4/msed.c mblaze-0.5.1/msed.c
--- mblaze-0.4/msed.c   2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/msed.c 2019-03-03 17:12:56.000000000 +0100
@@ -28,7 +28,7 @@
 #define APPC(c) do { if (b >= bufe) return str; *b++ = c; } while (0)
 
        regex_t srchrx;
-       regmatch_t pmatch[10];
+       regmatch_t pmatch[10] = {{0}};
        if (regcomp(&srchrx, srch, iflag ? REG_ICASE : 0) != 0)
                return str;
 
@@ -218,6 +218,8 @@
                                        free(flags);
 
                                        break;
+                               case '\0':
+                                       break;
                                default:
                                        fprintf(stderr, "msed: unknown command: 
'%c'\n", *e);
                                        exit(1);
diff -Nru mblaze-0.4/mshow.c mblaze-0.5.1/mshow.c
--- mblaze-0.4/mshow.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mshow.c        2019-03-03 17:12:56.000000000 +0100
@@ -35,6 +35,7 @@
 struct message *filters;
 
 static int mimecount;
+static int extractcount;
 static int safe_output;
 
 static int reply_found;
@@ -224,6 +225,11 @@
                }
                setenv("PIPE_CONTENTTYPE", ct, 1);
 
+               char *messageid = blaze822_hdr(msg, "message-id");
+               if (messageid) {
+                       setenv("MESSAGE_ID", messageid, 1);
+               }
+
                char *output;
                size_t outlen;
                int e = filter(body, bodylen, cmd, &output, &outlen);
@@ -326,6 +332,10 @@
        struct message *imsg = 0;
        while (blaze822_multipart(msg, &imsg)) {
                m++;
+
+               if (blaze822_bodylen(imsg) == 0)
+                       continue;
+
                char *ict = blaze822_hdr(imsg, "content-type");
                if (!ict)
                        ict = fallback_ct;
@@ -521,6 +531,7 @@
                                        printf("%s\n", bufptr);
                                        writefile(bufptr, body, bodylen);
                                }
+                               extractcount++;
                        } else if (filename &&
                            fnmatch(a, filename, FNM_PATHNAME) == 0) {
                                // extract by name
@@ -541,6 +552,7 @@
                                        printf("\n");
                                        writefile(filename, body, bodylen);
                                }
+                               extractcount++;
                        }
                }
        }
@@ -551,6 +563,8 @@
 void
 extract_cb(char *file)
 {
+       while (*file == ' ' || *file == '\t')
+               file++;
        struct message *msg = blaze822_file(file);
        if (!msg)
                return;
@@ -833,5 +847,10 @@
        if (pid1 > 0)
                pipeclose(pid1);
 
+       if ((xflag || Oflag) && extractcount < argc-optind) {
+               fprintf(stderr, "mshow: could not extract all attachments\n");
+               return 1;
+       }
+
        return 0;
 }
diff -Nru mblaze-0.4/mthread.c mblaze-0.5.1/mthread.c
--- mblaze-0.4/mthread.c        2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/mthread.c      2019-03-03 17:12:56.000000000 +0100
@@ -64,7 +64,7 @@
        } else {
                // invent new message-id for internal tracking
                static long i;
-               char buf[32];
+               char buf[40];
                snprintf(buf, sizeof buf, "thread%08ld@localhost", ++i);
                return strdup(buf);
        }
@@ -307,7 +307,8 @@
                        c->mid = c->child->mid;
                        c->file = c->child->file;
                        c->msg = c->child->msg;
-                       c->date = c->child->date;
+                       if (c->child->date > c->date)
+                               c->date = c->child->date;
                        c->optional = c->child->optional;
                        c->child = c->child->child;
                }
diff -Nru mblaze-0.4/NEWS.md mblaze-0.5.1/NEWS.md
--- mblaze-0.4/NEWS.md  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/NEWS.md        2019-03-03 17:12:56.000000000 +0100
@@ -1,3 +1,29 @@
+## 0.5.1 (2019-03-03)
+
+* mdeliver: preserve mtime in mrefile
+* mdirs: add -0 to separate folders by NUL characters
+* Fixes for buffer-overflows, found by fuzzing.
+* Fixes for memleaks.
+
+## 0.5 (2019-02-09)
+
+* New tool msearch to wrap several mail indexers.
+* New zsh completion _mblaze.
+* mnext/mprev were removed (you can call `mless +`/`mless -`).
+* The GnuPG tools in contrib/ now use gpg2.
+* mshow exits with error if it could not extract all attachments
+* mrep: add -noquote to disable quoting the message replied to
+* mdeliver: keep permissions of messages
+* mcom: aborting the editor is now more like delete than cancel
+* mcom: add -send to send directly without editing
+* mcom: check if mail is formatted sensibly
+* mpick: new flag -v for statistics
+* mscan: new flag -v for statistics
+* magrep: add -h, which is like -p but doesn't print the file name
+* mscan: prioritize displaying trashed mail over other markers
+* mpick: fix off-by-one in expression parsing
+* Many bug fixes
+
 ## 0.4 (2018-08-15)
 
 * New tool mrefile to move or copy messages.
diff -Nru mblaze-0.4/README mblaze-0.5.1/README
--- mblaze-0.4/README   2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/README 2019-03-03 17:12:56.000000000 +0100
@@ -19,7 +19,7 @@
      mdeliver(1)  deliver messages or import mbox file
      mdirs(1)     list maildir folders, recursively
      mexport(1)   export messages as mbox file
-     mflag(1)     manipulate maildir flags
+     mflag(1)     manipulate maildir message flags
      mflow(1)     reflow format=flowed plain text messages
      mfwd(1)      forward messages
      mgenmid(1)   generate a Message-ID
@@ -128,6 +128,6 @@
      To the extent possible under law, the creator of this work has waived all
      copyright and related or neighboring rights to this work.
 
-           http://creativecommons.org/publicdomain/zero/1.0/
+     http://creativecommons.org/publicdomain/zero/1.0/
 
 Void Linux                      January 6, 2018                     Void Linux
diff -Nru mblaze-0.4/rfc2047.c mblaze-0.5.1/rfc2047.c
--- mblaze-0.4/rfc2047.c        2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/rfc2047.c      2019-03-03 17:12:56.000000000 +0100
@@ -130,6 +130,10 @@
        iconv_t ic = (iconv_t)-1;
        char *srcenc = 0;
 
+       // need space for trailing nul
+       if (dlen-- == 0)
+               return 0;
+
        char *startdst = dst;
        size_t startdlen = dlen;
 
diff -Nru mblaze-0.4/rfc2231.c mblaze-0.5.1/rfc2231.c
--- mblaze-0.4/rfc2231.c        2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/rfc2231.c      2019-03-03 17:12:56.000000000 +0100
@@ -54,8 +54,10 @@
                                if (!srcenc)
                                        return 0;
                                sbuf = strchr(sbuf+1, '\'');
-                               if (!sbuf)
+                               if (!sbuf) {
+                                       free(srcenc);
                                        return 0;
+                               }
                                sbuf++;
                        }
                        while (sbuf < ebuf && dst < dstend) {
diff -Nru mblaze-0.4/safe_u8putstr.c mblaze-0.5.1/safe_u8putstr.c
--- mblaze-0.4/safe_u8putstr.c  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/safe_u8putstr.c        2019-03-03 17:12:56.000000000 +0100
@@ -34,8 +34,11 @@
                                fputc(0xc0 | (*s >> 6), stream);
                                fputc(0x80 | (*s & 0x3f), stream);
                        }
-               } else if (c < 32 && 
+               } else if (c < 32 &&
                    *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r') {
+                       // NUL
+                       if (l == 0)
+                               l = 1;
                        // C0
                        fputc(0xe2, stream);
                        fputc(0x90, stream);
diff -Nru mblaze-0.4/seq.c mblaze-0.5.1/seq.c
--- mblaze-0.4/seq.c    2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/seq.c  2019-03-03 17:12:56.000000000 +0100
@@ -467,44 +467,53 @@
        return r;
 }
 
+int mystrverscmp(const char *, const char *);
+
+static int
+mailsort(const struct dirent **a, const struct dirent **b)
+{
+       return mystrverscmp((*a)->d_name, (*b)->d_name);
+}
+
 static long
 iterdir(char *dir, void (*cb)(char *))
 {
-       DIR *fd, *fd2;
-       struct dirent *d;
+       struct dirent **namelist;
 
-       long i = 0;
+       int n;
+
+       char sub[PATH_MAX];
+       snprintf(sub, sizeof sub, "%s/cur", dir);
 
-       fd = opendir(dir);
-       if (!fd) {
+       char *m = "/cur";
+
+       n = scandir(sub, &namelist, 0, mailsort);
+       if (n == -1 && (errno == ENOENT || errno == ENOTDIR)) {
+               m = "";
+               n = scandir(dir, &namelist, 0, mailsort);
+       }
+               
+       if (n == -1) {  
                if (errno == ENOTDIR)
                        cb(dir);
                return 1;
        }
 
-       char sub[PATH_MAX];
-       snprintf(sub, sizeof sub, "%s/cur", dir);
-       fd2 = opendir(sub);
-       if (fd2) {
-               closedir(fd);
-               fd = fd2;
-       }
-
-       while ((d = readdir(fd))) {
+       long i = 0;
+       for (i = 0; i < n; i++) {
+               if (namelist[i]->d_name[0] != '.')
 #if defined(DT_REG) && defined(DT_UNKNOWN)
-               if (d->d_type != DT_REG && d->d_type != DT_UNKNOWN)
-                       continue;
+               if (namelist[i]->d_type == DT_REG ||
+                   namelist[i]->d_type == DT_UNKNOWN)
 #endif
-               if (d->d_name[0] == '.')
-                       continue;
-               if (fd2)
-                       snprintf(sub, sizeof sub, "%s/cur/%s", dir, d->d_name);
-               else
-                       snprintf(sub, sizeof sub, "%s/%s", dir, d->d_name);
-               cb(sub);
-               i++;
+               {
+                       snprintf(sub, sizeof sub, "%s%s/%s",
+                           dir, m, namelist[i]->d_name);
+                       cb(sub);
+               }
+               free(namelist[i]);
        }
-       closedir(fd);
+       free(namelist);
 
        return i;
 }
diff -Nru mblaze-0.4/t/1000-mmime.t mblaze-0.5.1/t/1000-mmime.t
--- mblaze-0.4/t/1000-mmime.t   2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/t/1000-mmime.t 2019-03-03 17:12:56.000000000 +0100
@@ -9,7 +9,7 @@
 Body
 EOF
 
-# https://github.com/chneukirchen/mblaze/issues/20
+# https://github.com/leahneukirchen/mblaze/issues/20
 
 check 'mime -r runs' 'mmime -r <tmp >tmp2'
 check 'no overlong lines' 'awk "{if(length(\$0)>=80)exit 1}" <tmp2'
diff -Nru mblaze-0.4/VERSION mblaze-0.5.1/VERSION
--- mblaze-0.4/VERSION  2018-08-15 17:16:45.000000000 +0200
+++ mblaze-0.5.1/VERSION        2019-03-03 17:12:56.000000000 +0100
@@ -1 +1 @@
-0.4
+0.5.1

Reply via email to