Re: [PATCH] Add filename filters when saving attachments.
Alejandro Colomar via Mutt-dev <[email protected]> Sat, 9 May 2026 14:02:54 +0200
| Newsgroups | gmane.mail.mutt.devel |
|---|---|
| Message-ID | <af8guf6an9ZhO6vM@devuan> |
Hi Kevin,
On 2026-05-09T18:59:22+0800, Kevin J. McCarthy wrote:
> In send mode (the compose menu), simply take the basename, since it's
> attached by the user already.
>
> In receive mode, try to keep the whole filename, even if it orginally
> contained path characters. Filter "/" and non-printables into an
> underscore "_".
> ---
>
> This is an early v2 patch, sent out to solicit feedback.
>
> The attachment saving code is a bit of a maze, so there isn't a need to
> understand it all.
>
> Suffice to say I've swapped out the various places in it that directly
> reference the attachment name to use a version that has been filtered by
> safe_attachment_filename() just below.
>
> Right now, in receive mode, this filters "/" and unprintables into "_".
> I could use a stricter sanitizer function, but I think that would be too
> strict and irritate users.
>
> I could also simply filter only "/" -> "_", which might be all we need
> to do. Comments?
I think I'd do the simplest change. And if we want to do more, maybe
split that into its own commit, with a different justification in the
commit message.
>
> muttlib.c | 11 ++++++++---
> recvattach.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 50 insertions(+), 12 deletions(-)
>
> diff --git a/muttlib.c b/muttlib.c
> index 6eabdec2..858a4bcf 100644
> --- a/muttlib.c
> +++ b/muttlib.c
> @@ -1277,8 +1277,13 @@ void mutt_expand_fmt(BUFFER *dest, const char *fmt, const char *src)
> }
> }
>
> -/* return 0 on success, -1 on abort, 1 on error */
> -int mutt_check_overwrite(const char *attname, const char *path,
> +/* return 0 on success, -1 on abort, 1 on error
> + *
> + * safe_attname should have been filtered through safe_attachment_filename()
> + * in recvattach.c to either get the basename in sendmode,
> + * or to filter '/' and unsafe characters in recvmode.
> + * */
> +int mutt_check_overwrite(const char *safe_attname, const char *path,
> BUFFER *fname, int *append, char **directory)
> {
> int rc = 0;
> @@ -1321,7 +1326,7 @@ int mutt_check_overwrite(const char *attname, const char *path,
> return (rc == MUTT_NO) ? 1 : -1;
>
> tmp = mutt_buffer_pool_get();
> - mutt_buffer_strcpy(tmp, mutt_basename(NONULL(attname)));
> + mutt_buffer_strcpy(tmp, safe_attname);
> if ((mutt_buffer_get_field(_("File under directory: "), tmp,
> MUTT_FILE | MUTT_CLEAR) != 0) ||
> !mutt_buffer_len(tmp))
> diff --git a/recvattach.c b/recvattach.c
> index 3b172e4c..f64a0008 100644
> --- a/recvattach.c
> +++ b/recvattach.c
> @@ -518,23 +518,49 @@ static int save_attachment_helper(FILE *fp, BODY *m, const char *path,
> return rc;
> }
>
> +static void safe_attachment_filename(BUFFER *safe_filename, const char *filename,
> + int sendmode)
> +{
> + if (sendmode)
> + mutt_buffer_strcpy(safe_filename, mutt_basename(filename));
> + else
> + {
> + /* Alternatively, we could use
> + * mutt_buffer_sanitize_filename(safe_filename, filename, MUTT_SANITIZE_ALLOW_8BIT);
> + * Comments?
> + */
> + mutt_buffer_clear(safe_filename);
> +
> + for (; *filename; filename++)
> + {
> + if (*filename == '/' || !IsPrint((unsigned char) *filename))
AFAICS, IsPrint() already does the necessary cast.
alx@devuan:~/src/mutt/mutt/master$ grepc -B1 -A3 -n IsPrint .
./protos.h-452-#ifdef LOCALES_HACK
./protos.h:453:#define IsPrint(c) (isprint((unsigned char)(c)) || \
((unsigned char)(c) >= 0xa0))
./protos.h-455-#define IsWPrint(wc) (iswprint(wc) || wc >= 0xa0)
./protos.h-456-#else
./protos.h:457:#define IsPrint(c) (isprint((unsigned char)(c)) || \
(option(OPTLOCALES) ? 0 : \
((unsigned char)(c) >= 0xa0)))
./protos.h-460-#define IsWPrint(wc) (iswprint(wc) || \
./protos.h-461- (option(OPTLOCALES) ? 0 : (wc >= 0xa0)))
./protos.h-462-#endif
> + mutt_buffer_addch(safe_filename, '_');
> + else
> + mutt_buffer_addch(safe_filename, *filename);
> + }
> + }
> +}
Have a lovely day!
Alex
--
<https://www.alejandro-colomar.es>
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmn/ImgACgkQ64mZXMKQ wqngphAAoe4r+I3p4/08/2h1MksgzZB6eFoSZtZUfBPQCrt8pSo3Nt0LunbiPIl8 pqdCYq7Qw/uVR9UYGB60x8WLCBC8SyLAbIJI/J63jPpOlK3KKpKf2UuDhGEF6F6r a7HOCPYjuyl2oZ9/DLaTe28gTbYn38VAevuk1wblyl0SO4UVhFZDLZWuIL4ehp/i jk4neZmq+3e50dAcj/G+Sj36uBf8Mz47ufVLRqFsOw5Wd5QzsPgXtWLPSu6dUnyF p1KFGbBlEFPc3K1ij+mYK5W6D7xdD3d3wdd7duZzuU3g42WndNDQrmpaMss2I6uG 1AUyaFKUKaEl+4He2kwx528S10MK3T4/yt43RB3SM5zhix83xy59Ytj2tz0VER9C pADEdC6Vo5pa9FbRSdARPlyxrS28NnVbD0l4E7p8QE8v5AjQibpJFFczTG19aWQz pYcZCnp9h0Ue9QXhw2aEi1mEXnC2ehWCYvjE4ZKrVsaMRiovZ4jNtMKbM/PUG+ca ne2813oWDRs/0GfauKsR8WnyLDoGdkBMh2Bku8BVXs8OXlpFv3oGBbErbOJaCIqS uhgPrSJH/6l9tPaWdT161be9nLYtApSs2Hjthjy1YBiTsTj23XOMh+sal3avbmnw 5EEEAXhpbclsZb2D9ZazyAIWzyvJxrrkt7ORurXSbJa7JrNF2/M= =tuBD -----END PGP SIGNATURE-----