]> granicus.if.org Git - neomutt/commitdiff
Convert rfc1524_expand_command() implementation to use struct Buffer
authorKevin McCarthy <kevin@8t8.us>
Sun, 14 Apr 2019 20:34:37 +0000 (13:34 -0700)
committerRichard Russon <rich@flatcap.org>
Mon, 24 Jun 2019 15:20:38 +0000 (16:20 +0100)
Add mutt_buffer_sanitize_filename() helper.

Add a few end-of-buffer checks while iterating over command.

Convert the parameter name, paramater value, and types to use struct Buffer
instead of fixed size strings.

mutt/file.c
mutt/file.h
muttlib.c
muttlib.h
rfc1524.c

index 76bd9fe25862d4f91877b7b321b3862846fda35c..620bd6fb3bd1d7b21095af97c153f7e5577095d0 100644 (file)
@@ -54,7 +54,7 @@ char *C_Tmpdir; ///< Config: Directory for temporary files
 /* these characters must be escaped in regular expressions */
 static const char rx_special_chars[] = "^.[$()|*+?{\\";
 
-static const char safe_chars[] =
+const char filename_safe_chars[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%/";
 
 #define MAX_LOCK_ATTEMPTS 5
@@ -618,7 +618,7 @@ void mutt_file_sanitize_filename(char *path, bool slash)
 
   for (; *path; path++)
   {
-    if ((slash && (*path == '/')) || !strchr(safe_chars, *path))
+    if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
       *path = '_';
   }
 }
index 79acb5ae8ee786fd09dbb851a4daaa7a40fcee61..e9fdc6718e85833fa8ac08ba7861f2c391ed336f 100644 (file)
@@ -32,6 +32,7 @@
 struct Buffer;
 struct stat;
 extern char *C_Tmpdir;
+extern const char filename_safe_chars[];
 
 /* Flags for mutt_file_read_line() */
 #define MUTT_CONT (1 << 0) /**< \-continuation */
index 9e2348cd46dcc22b781f3dc53cf7771e6b085d79..e8b87382169291cdff7c31a91bd3fb911132d991 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -97,7 +97,7 @@ void mutt_adv_mktemp(struct Buffer *buf)
   {
     struct Buffer *prefix = mutt_buffer_pool_get();
     mutt_buffer_strcpy(prefix, buf->data);
-    mutt_file_sanitize_filename(prefix->data, 1);
+    mutt_file_sanitize_filename(prefix->data, true);
     mutt_buffer_printf(buf, "%s/%s", NONULL(C_Tmpdir), mutt_b2s(prefix));
 
     struct stat sb;
@@ -1691,3 +1691,25 @@ int mutt_inbox_cmp(const char *a, const char *b)
 
   return 0;
 }
+
+/**
+ * mutt_buffer_sanitize_filename - Replace unsafe characters in a filename
+ * @param buf   Buffer for the result
+ * @param path  Filename to make safe
+ * @param slash Replace '/' characters too
+ */
+void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
+{
+  if (!buf || !path)
+    return;
+
+  mutt_buffer_reset(buf);
+
+  for (; *path; path++)
+  {
+    if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
+      mutt_buffer_addch(buf, '_');
+    else
+      mutt_buffer_addch(buf, *path);
+  }
+}
index ce09d711f5c7d982d94285d2f0c85c059edda47a..a6ec969d0342b72be3b2e1ba808ef1e546df38b8 100644 (file)
--- a/muttlib.h
+++ b/muttlib.h
@@ -48,6 +48,7 @@ void        mutt_buffer_mktemp_full(struct Buffer *buf, const char *prefix, cons
 void        mutt_buffer_expand_path(struct Buffer *buf);
 void        mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex);
 void        mutt_buffer_pretty_mailbox(struct Buffer *s);
+void        mutt_buffer_sanitize_filename (struct Buffer *buf, const char *path, short slash);
 int         mutt_check_overwrite(const char *attname, const char *path, char *fname, size_t flen, enum SaveAttach *opt, char **directory);
 void        mutt_encode_path(char *dest, size_t dlen, const char *src);
 void        mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags);
index e6d934632cad13b675c7ba5308b38cf40446f91b..4c4dabc655e1798e2ff4715c9f15d9be7a880560 100644 (file)
--- a/rfc1524.c
+++ b/rfc1524.c
 bool C_MailcapSanitize; ///< Config: Restrict the possible characters in mailcap expandos
 
 /**
- * rfc1524_expand_command - Expand expandos in a command
+ * mutt_buffer_rfc1524_expand_command - Expand expandos in a command
  * @param a        Email Body
  * @param filename File containing the email text
  * @param type     Type, e.g. "text/plain"
  * @param command  Buffer containing command
- * @param clen     Length of buffer
  * @retval 0 Command works on a file
  * @retval 1 Command works on a pipe
  *
@@ -69,99 +68,94 @@ bool C_MailcapSanitize; ///< Config: Restrict the possible characters in mailcap
  * %n is the integer number of sub-parts in the multipart
  * %F is "content-type filename" repeated for each sub-part
  */
-int rfc1524_expand_command(struct Body *a, const char *filename,
-                           const char *type, char *command, int clen)
+int mutt_buffer_rfc1524_expand_command(struct Body *a, const char *filename,
+                                       const char *type, struct Buffer *command)
 {
-  int x = 0;
   int needspipe = true;
-  char type2[1024];
   struct Buffer *buf = mutt_buffer_pool_get();
   struct Buffer *quoted = mutt_buffer_pool_get();
+  struct Buffer *param = NULL;
+  struct Buffer *type2 = NULL;
 
-  mutt_str_strfcpy(type2, type, sizeof(type2));
-
-  if (C_MailcapSanitize)
-    mutt_file_sanitize_filename(type2, false);
-
-  while ((x < clen - 1) && command[x])
+  const char *cptr = mutt_b2s(command);
+  while (*cptr)
   {
-    if (command[x] == '\\')
+    if (*cptr == '\\')
     {
-      x++;
-      mutt_buffer_addch(buf, command[x++]);
+      cptr++;
+      if (*cptr)
+        mutt_buffer_addch(buf, *cptr++);
     }
-    else if (command[x] == '%')
+    else if (*cptr == '%')
     {
-      x++;
-      if (command[x] == '{')
+      cptr++;
+      if (*cptr == '{')
       {
-        char param[256];
-        char pvalue[256];
-        char *pvalue2 = NULL;
-        int z = 0;
+        const char *pvalue2 = NULL;
+
+        if (!param)
+          param = mutt_buffer_pool_get();
+        else
+          mutt_buffer_reset(param);
 
-        x++;
-        while (command[x] && (command[x] != '}') && (z < sizeof(param) - 1))
-          param[z++] = command[x++];
-        param[z] = '\0';
+        /* Copy parameter name into param buffer */
+        cptr++;
+        while (*cptr && (*cptr != '}'))
+          mutt_buffer_addch(param, *cptr++);
 
         /* In send mode, use the current charset, since the message hasn't
          * been converted yet.   If noconv is set, then we assume the
          * charset parameter has the correct value instead. */
-        if ((mutt_str_strcasecmp(param, "charset") == 0) && a->charset && !a->noconv)
+        if ((mutt_str_strcasecmp(mutt_b2s(param), "charset") == 0) && a->charset && !a->noconv)
           pvalue2 = a->charset;
         else
-          pvalue2 = mutt_param_get(&a->parameter, param);
-        mutt_str_strfcpy(pvalue, pvalue2, sizeof(pvalue));
+          pvalue2 = mutt_param_get(&a->parameter, mutt_b2s(param));
+
+        /* Now copy the parameter value into param buffer */
         if (C_MailcapSanitize)
-          mutt_file_sanitize_filename(pvalue, false);
+          mutt_buffer_sanitize_filename(param, NONULL(pvalue2), false);
+        else
+          mutt_buffer_strcpy(param, NONULL(pvalue2));
 
-        mutt_buffer_quote_filename(quoted, pvalue, true);
+        mutt_buffer_quote_filename(quoted, mutt_b2s(param), true);
         mutt_buffer_addstr(buf, mutt_b2s(quoted));
       }
-      else if ((command[x] == 's') && filename)
+      else if ((*cptr == 's') && filename)
       {
         mutt_buffer_quote_filename(quoted, filename, true);
         mutt_buffer_addstr(buf, mutt_b2s(quoted));
         needspipe = false;
       }
-      else if (command[x] == 't')
+      else if (*cptr == 't')
       {
-        mutt_buffer_quote_filename(quoted, type, true);
+        if (!type2)
+        {
+          type2 = mutt_buffer_pool_get();
+          if (C_MailcapSanitize)
+            mutt_buffer_sanitize_filename(type2, type, false);
+          else
+            mutt_buffer_strcpy(type2, type);
+        }
+        mutt_buffer_quote_filename(quoted, mutt_b2s(type2), true);
         mutt_buffer_addstr(buf, mutt_b2s(quoted));
       }
-      x++;
+
+      if (*cptr)
+        cptr++;
     }
     else
-      mutt_buffer_addch(buf, command[x++]);
+      mutt_buffer_addch(buf, *cptr++);
   }
-  mutt_str_strfcpy(command, mutt_b2s(buf), clen);
+  mutt_buffer_strcpy(command, mutt_b2s(buf));
 
   mutt_buffer_pool_release(&buf);
   mutt_buffer_pool_release(&quoted);
+  mutt_buffer_pool_release(&param);
+  mutt_buffer_pool_release(&type2);
 
   return needspipe;
 }
 
-/**
- * mutt_buffer_rfc1524_expand_command - Expand expandos in a command
- * @param a        Email Body
- * @param filename File containing the email text
- * @param type     Type, e.g. "text/plain"
- * @param command  Buffer containing command
- * @retval 0 Command works on a file
- * @retval 1 Command works on a pipe
- */
-int mutt_buffer_rfc1524_expand_command(struct Body *a, const char *filename,
-                                       const char *type, struct Buffer *command)
-{
-  mutt_buffer_increase_size(command, PATH_MAX);
-  int rc = rfc1524_expand_command(a, filename, type, command->data, command->dsize);
-  mutt_buffer_fix_dptr(command);
-
-  return rc;
-}
-
 /**
  * get_field - NUL terminate a RFC1524 field
  * @param s String to alter