NeoMutt  2020-03-20-65-g141838
Teaching an old dog new tricks
DOXYGEN
mailcap.c File Reference

RFC1524 Mailcap routines. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "email/lib.h"
#include "mailcap.h"
#include "globals.h"
#include "mutt_attach.h"
#include "muttlib.h"
#include "protos.h"
+ Include dependency graph for mailcap.c:

Go to the source code of this file.

Functions

int mailcap_expand_command (struct Body *a, const char *filename, const char *type, struct Buffer *command)
 Expand expandos in a command. More...
 
static char * get_field (char *s)
 NUL terminate a RFC1524 field. More...
 
static int get_field_text (char *field, char **entry, const char *type, const char *filename, int line)
 Get the matching text from a mailcap. More...
 
static bool rfc1524_mailcap_parse (struct Body *a, const char *filename, const char *type, struct MailcapEntry *entry, enum MailcapLookup opt)
 Parse a mailcap entry. More...
 
struct MailcapEntrymailcap_entry_new (void)
 Allocate memory for a new rfc1524 entry. More...
 
void mailcap_entry_free (struct MailcapEntry **ptr)
 Deallocate an struct MailcapEntry. More...
 
bool mailcap_lookup (struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
 Find given type in the list of mailcap files. More...
 
void mailcap_expand_filename (const char *nametemplate, const char *oldfile, struct Buffer *newfile)
 Expand a new filename from a template or existing filename. More...
 

Variables

bool C_MailcapSanitize
 Config: Restrict the possible characters in mailcap expandos. More...
 

Detailed Description

RFC1524 Mailcap routines.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mailcap.c.

Function Documentation

◆ mailcap_expand_command()

int mailcap_expand_command ( struct Body a,
const char *  filename,
const char *  type,
struct Buffer command 
)

Expand expandos in a command.

Parameters
aEmail Body
filenameFile containing the email text
typeType, e.g. "text/plain"
commandBuffer containing command
Return values
0Command works on a file
1Command works on a pipe

The command semantics include the following: s is the filename that contains the mail body data t is the content type, like text/plain %{parameter} is replaced by the parameter value from the content-type field % is % Unsupported rfc1524 parameters: these would probably require some doing by neomutt, and can probably just be done by piping the message to metamail n is the integer number of sub-parts in the multipart F is "content-type filename" repeated for each sub-part

Definition at line 69 of file mailcap.c.

71 {
72  int needspipe = true;
73  struct Buffer *buf = mutt_buffer_pool_get();
74  struct Buffer *quoted = mutt_buffer_pool_get();
75  struct Buffer *param = NULL;
76  struct Buffer *type2 = NULL;
77 
78  const char *cptr = mutt_b2s(command);
79  while (*cptr)
80  {
81  if (*cptr == '\\')
82  {
83  cptr++;
84  if (*cptr)
85  mutt_buffer_addch(buf, *cptr++);
86  }
87  else if (*cptr == '%')
88  {
89  cptr++;
90  if (*cptr == '{')
91  {
92  const char *pvalue2 = NULL;
93 
94  if (param)
95  mutt_buffer_reset(param);
96  else
97  param = mutt_buffer_pool_get();
98 
99  /* Copy parameter name into param buffer */
100  cptr++;
101  while (*cptr && (*cptr != '}'))
102  mutt_buffer_addch(param, *cptr++);
103 
104  /* In send mode, use the current charset, since the message hasn't
105  * been converted yet. If noconv is set, then we assume the
106  * charset parameter has the correct value instead. */
107  if ((mutt_str_strcasecmp(mutt_b2s(param), "charset") == 0) && a->charset && !a->noconv)
108  pvalue2 = a->charset;
109  else
110  pvalue2 = mutt_param_get(&a->parameter, mutt_b2s(param));
111 
112  /* Now copy the parameter value into param buffer */
113  if (C_MailcapSanitize)
114  mutt_buffer_sanitize_filename(param, NONULL(pvalue2), false);
115  else
116  mutt_buffer_strcpy(param, NONULL(pvalue2));
117 
118  mutt_buffer_quote_filename(quoted, mutt_b2s(param), true);
119  mutt_buffer_addstr(buf, mutt_b2s(quoted));
120  }
121  else if ((*cptr == 's') && filename)
122  {
123  mutt_buffer_quote_filename(quoted, filename, true);
124  mutt_buffer_addstr(buf, mutt_b2s(quoted));
125  needspipe = false;
126  }
127  else if (*cptr == 't')
128  {
129  if (!type2)
130  {
131  type2 = mutt_buffer_pool_get();
132  if (C_MailcapSanitize)
133  mutt_buffer_sanitize_filename(type2, type, false);
134  else
135  mutt_buffer_strcpy(type2, type);
136  }
137  mutt_buffer_quote_filename(quoted, mutt_b2s(type2), true);
138  mutt_buffer_addstr(buf, mutt_b2s(quoted));
139  }
140 
141  if (*cptr)
142  cptr++;
143  }
144  else
145  mutt_buffer_addch(buf, *cptr++);
146  }
147  mutt_buffer_copy(command, buf);
148 
150  mutt_buffer_pool_release(&quoted);
151  mutt_buffer_pool_release(&param);
152  mutt_buffer_pool_release(&type2);
153 
154  return needspipe;
155 }
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell&#39;s quoting rules.
Definition: file.c:837
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:33
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define mutt_b2s(buf)
Definition: buffer.h:41
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
bool C_MailcapSanitize
Config: Restrict the possible characters in mailcap expandos.
Definition: mailcap.c:48
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
Definition: muttlib.c:1729
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_field()

static char* get_field ( char *  s)
static

NUL terminate a RFC1524 field.

Parameters
sString to alter
Return values
ptrStart of next field
NULLError

Definition at line 163 of file mailcap.c.

164 {
165  if (!s)
166  return NULL;
167 
168  char *ch = NULL;
169 
170  while ((ch = strpbrk(s, ";\\")))
171  {
172  if (*ch == '\\')
173  {
174  s = ch + 1;
175  if (*s)
176  s++;
177  }
178  else
179  {
180  *ch = '\0';
181  ch = mutt_str_skip_email_wsp(ch + 1);
182  break;
183  }
184  }
186  return ch;
187 }
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:757
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:799
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_field_text()

static int get_field_text ( char *  field,
char **  entry,
const char *  type,
const char *  filename,
int  line 
)
static

Get the matching text from a mailcap.

Parameters
fieldString to parse
entrySave the entry here
typeType, e.g. "text/plain"
filenameMailcap filename
lineMailcap line
Return values
1Success
0Failure

Definition at line 199 of file mailcap.c.

201 {
202  field = mutt_str_skip_whitespace(field);
203  if (*field == '=')
204  {
205  if (entry)
206  {
207  field++;
208  field = mutt_str_skip_whitespace(field);
209  mutt_str_replace(entry, field);
210  }
211  return 1;
212  }
213  else
214  {
215  mutt_error(_("Improperly formatted entry for type %s in \"%s\" line %d"),
216  type, filename, line);
217  return 0;
218  }
219 }
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:743
#define _(a)
Definition: message.h:28
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define mutt_error(...)
Definition: logging.h:84
int const char int line
Definition: acutest.h:602
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rfc1524_mailcap_parse()

static bool rfc1524_mailcap_parse ( struct Body a,
const char *  filename,
const char *  type,
struct MailcapEntry entry,
enum MailcapLookup  opt 
)
static

Parse a mailcap entry.

Parameters
aEmail Body
filenameFilename
typeType, e.g. "text/plain"
entryEntry, e.g. "compose"
optOption, see MailcapLookup
Return values
trueSuccess
falseFailure

Definition at line 231 of file mailcap.c.

233 {
234  char *buf = NULL;
235  bool found = false;
236  int line = 0;
237 
238  /* rfc1524 mailcap file is of the format:
239  * base/type; command; extradefs
240  * type can be * for matching all
241  * base with no /type is an implicit wild
242  * command contains a %s for the filename to pass, default to pipe on stdin
243  * extradefs are of the form:
244  * def1="definition"; def2="define \;";
245  * line wraps with a \ at the end of the line
246  * # for comments */
247 
248  /* find length of basetype */
249  char *ch = strchr(type, '/');
250  if (!ch)
251  return false;
252  const int btlen = ch - type;
253 
254  FILE *fp = fopen(filename, "r");
255  if (fp)
256  {
257  size_t buflen;
258  while (!found && (buf = mutt_file_read_line(buf, &buflen, fp, &line, MUTT_CONT)))
259  {
260  /* ignore comments */
261  if (*buf == '#')
262  continue;
263  mutt_debug(LL_DEBUG2, "mailcap entry: %s\n", buf);
264 
265  /* check type */
266  ch = get_field(buf);
267  if ((mutt_str_strcasecmp(buf, type) != 0) &&
268  ((mutt_str_strncasecmp(buf, type, btlen) != 0) ||
269  ((buf[btlen] != '\0') && /* implicit wild */
270  (mutt_str_strcmp(buf + btlen, "/*") != 0)))) /* wildsubtype */
271  {
272  continue;
273  }
274 
275  /* next field is the viewcommand */
276  char *field = ch;
277  ch = get_field(ch);
278  if (entry)
279  entry->command = mutt_str_strdup(field);
280 
281  /* parse the optional fields */
282  found = true;
283  bool copiousoutput = false;
284  bool composecommand = false;
285  bool editcommand = false;
286  bool printcommand = false;
287 
288  while (ch)
289  {
290  field = ch;
291  ch = get_field(ch);
292  mutt_debug(LL_DEBUG2, "field: %s\n", field);
293  size_t plen;
294 
295  if (mutt_str_strcasecmp(field, "needsterminal") == 0)
296  {
297  if (entry)
298  entry->needsterminal = true;
299  }
300  else if (mutt_str_strcasecmp(field, "copiousoutput") == 0)
301  {
302  copiousoutput = true;
303  if (entry)
304  entry->copiousoutput = true;
305  }
306  else if ((plen = mutt_str_startswith(field, "composetyped", CASE_IGNORE)))
307  {
308  /* this compare most occur before compose to match correctly */
309  if (get_field_text(field + plen, entry ? &entry->composetypecommand : NULL,
310  type, filename, line))
311  {
312  composecommand = true;
313  }
314  }
315  else if ((plen = mutt_str_startswith(field, "compose", CASE_IGNORE)))
316  {
317  if (get_field_text(field + plen, entry ? &entry->composecommand : NULL,
318  type, filename, line))
319  {
320  composecommand = true;
321  }
322  }
323  else if ((plen = mutt_str_startswith(field, "print", CASE_IGNORE)))
324  {
325  if (get_field_text(field + plen, entry ? &entry->printcommand : NULL,
326  type, filename, line))
327  {
328  printcommand = true;
329  }
330  }
331  else if ((plen = mutt_str_startswith(field, "edit", CASE_IGNORE)))
332  {
333  if (get_field_text(field + plen, entry ? &entry->editcommand : NULL,
334  type, filename, line))
335  editcommand = true;
336  }
337  else if ((plen = mutt_str_startswith(field, "nametemplate", CASE_IGNORE)))
338  {
339  get_field_text(field + plen, entry ? &entry->nametemplate : NULL,
340  type, filename, line);
341  }
342  else if ((plen = mutt_str_startswith(field, "x-convert", CASE_IGNORE)))
343  {
344  get_field_text(field + plen, entry ? &entry->convert : NULL, type, filename, line);
345  }
346  else if ((plen = mutt_str_startswith(field, "test", CASE_IGNORE)))
347  {
348  /* This routine executes the given test command to determine
349  * if this is the right entry. */
350  char *test_command = NULL;
351 
352  if (get_field_text(field + plen, &test_command, type, filename, line) && test_command)
353  {
354  struct Buffer *command = mutt_buffer_pool_get();
355  struct Buffer *afilename = mutt_buffer_pool_get();
356  mutt_buffer_strcpy(command, test_command);
357  if (C_MailcapSanitize)
358  mutt_buffer_sanitize_filename(afilename, NONULL(a->filename), true);
359  else
360  mutt_buffer_strcpy(afilename, NONULL(a->filename));
361  mailcap_expand_command(a, mutt_b2s(afilename), type, command);
362  if (mutt_system(mutt_b2s(command)))
363  {
364  /* a non-zero exit code means test failed */
365  found = false;
366  }
367  FREE(&test_command);
368  mutt_buffer_pool_release(&command);
369  mutt_buffer_pool_release(&afilename);
370  }
371  }
372  else if (mutt_str_startswith(field, "x-neomutt-keep", CASE_IGNORE))
373  {
374  if (entry)
375  entry->xneomuttkeep = true;
376  }
377  } /* while (ch) */
378 
379  if (opt == MUTT_MC_AUTOVIEW)
380  {
381  if (!copiousoutput)
382  found = false;
383  }
384  else if (opt == MUTT_MC_COMPOSE)
385  {
386  if (!composecommand)
387  found = false;
388  }
389  else if (opt == MUTT_MC_EDIT)
390  {
391  if (!editcommand)
392  found = false;
393  }
394  else if (opt == MUTT_MC_PRINT)
395  {
396  if (!printcommand)
397  found = false;
398  }
399 
400  if (!found)
401  {
402  /* reset */
403  if (entry)
404  {
405  FREE(&entry->command);
406  FREE(&entry->composecommand);
407  FREE(&entry->composetypecommand);
408  FREE(&entry->editcommand);
409  FREE(&entry->printcommand);
410  FREE(&entry->nametemplate);
411  FREE(&entry->convert);
412  entry->needsterminal = false;
413  entry->copiousoutput = false;
414  entry->xneomuttkeep = false;
415  }
416  }
417  } /* while (!found && (buf = mutt_file_read_line ())) */
418  mutt_file_fclose(&fp);
419  } /* if ((fp = fopen ())) */
420  FREE(&buf);
421  return found;
422 }
bool xneomuttkeep
do not remove the file on command exit
Definition: mailcap.h:50
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * convert
Definition: mailcap.h:47
Mailcap autoview field.
Definition: mailcap.h:62
char * composetypecommand
Definition: mailcap.h:43
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
#define MUTT_CONT
-continuation
Definition: file.h:38
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
Mailcap compose field.
Definition: mailcap.h:60
Log at debug level 2.
Definition: logging.h:41
Mailcap print field.
Definition: mailcap.h:61
bool copiousoutput
needs pager, basically
Definition: mailcap.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * editcommand
Definition: mailcap.h:44
char * command
Definition: mailcap.h:40
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:679
static int get_field_text(char *field, char **entry, const char *type, const char *filename, int line)
Get the matching text from a mailcap.
Definition: mailcap.c:199
Ignore case when comparing strings.
Definition: string2.h:68
bool C_MailcapSanitize
Config: Restrict the possible characters in mailcap expandos.
Definition: mailcap.c:48
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
char * printcommand
Definition: mailcap.h:45
char * nametemplate
Definition: mailcap.h:46
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
Definition: muttlib.c:1729
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
char * composecommand
Definition: mailcap.h:42
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:602
Mailcap edit field.
Definition: mailcap.h:59
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
bool needsterminal
endwin() and system
Definition: mailcap.h:48
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
static char * get_field(char *s)
NUL terminate a RFC1524 field.
Definition: mailcap.c:163
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mailcap_entry_new()

struct MailcapEntry* mailcap_entry_new ( void  )

Allocate memory for a new rfc1524 entry.

Return values
ptrAn un-initialized struct MailcapEntry

Definition at line 428 of file mailcap.c.

429 {
430  return mutt_mem_calloc(1, sizeof(struct MailcapEntry));
431 }
A mailcap entry.
Definition: mailcap.h:38
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mailcap_entry_free()

void mailcap_entry_free ( struct MailcapEntry **  ptr)

Deallocate an struct MailcapEntry.

Parameters
[out]ptrMailcapEntry to deallocate

Definition at line 437 of file mailcap.c.

438 {
439  if (!ptr || !*ptr)
440  return;
441 
442  struct MailcapEntry *me = *ptr;
443 
444  FREE(&me->command);
445  FREE(&me->testcommand);
446  FREE(&me->composecommand);
447  FREE(&me->composetypecommand);
448  FREE(&me->editcommand);
449  FREE(&me->printcommand);
450  FREE(&me->nametemplate);
451  FREE(ptr);
452 }
A mailcap entry.
Definition: mailcap.h:38
char * composetypecommand
Definition: mailcap.h:43
char * editcommand
Definition: mailcap.h:44
char * command
Definition: mailcap.h:40
char * printcommand
Definition: mailcap.h:45
char * nametemplate
Definition: mailcap.h:46
char * composecommand
Definition: mailcap.h:42
#define FREE(x)
Definition: memory.h:40
char * testcommand
Definition: mailcap.h:41
+ Here is the caller graph for this function:

◆ mailcap_lookup()

bool mailcap_lookup ( struct Body a,
char *  type,
size_t  typelen,
struct MailcapEntry entry,
enum MailcapLookup  opt 
)

Find given type in the list of mailcap files.

Parameters
aMessage body
typeText type in "type/subtype" format
typelenLength of the type
entrystruct MailcapEntry to populate with results
optType of mailcap entry to lookup, see MailcapLookup
Return values
trueIf *entry is not NULL it populates it with the mailcap entry
falseNo matching entry is found

Find the given type in the list of mailcap files.

Definition at line 466 of file mailcap.c.

468 {
469  /* rfc1524 specifies that a path of mailcap files should be searched.
470  * joy. They say
471  * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
472  * and overridden by the MAILCAPS environment variable, and, just to be nice,
473  * we'll make it specifiable in .neomuttrc */
474  if (!C_MailcapPath || (C_MailcapPath->count == 0))
475  {
476  mutt_error(_("No mailcap path specified"));
477  return false;
478  }
479 
480  mutt_check_lookup_list(a, type, typelen);
481 
482  struct Buffer *path = mutt_buffer_pool_get();
483  bool found = false;
484 
485  struct ListNode *np = NULL;
486  STAILQ_FOREACH(np, &C_MailcapPath->head, entries)
487  {
488  mutt_buffer_strcpy(path, np->data);
490 
491  mutt_debug(LL_DEBUG2, "Checking mailcap file: %s\n", mutt_b2s(path));
492  found = rfc1524_mailcap_parse(a, mutt_b2s(path), type, entry, opt);
493  if (found)
494  break;
495  }
496 
498 
499  if (entry && !found)
500  mutt_error(_("mailcap entry for type %s not found"), type);
501 
502  return found;
503 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Log at debug level 2.
Definition: logging.h:41
struct ListHead head
Definition: slist.h:45
size_t count
Definition: slist.h:46
#define mutt_b2s(buf)
Definition: buffer.h:41
WHERE struct Slist * C_MailcapPath
Config: Colon-separated list of mailcap files.
Definition: globals.h:120
static bool rfc1524_mailcap_parse(struct Body *a, const char *filename, const char *type, struct MailcapEntry *entry, enum MailcapLookup opt)
Parse a mailcap entry.
Definition: mailcap.c:231
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * data
String.
Definition: list.h:35
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:328
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
Definition: mutt_attach.c:332
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
A List node for strings.
Definition: list.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mailcap_expand_filename()

void mailcap_expand_filename ( const char *  nametemplate,
const char *  oldfile,
struct Buffer newfile 
)

Expand a new filename from a template or existing filename.

Parameters
nametemplateTemplate
oldfileOriginal filename
newfileBuffer for new filename

If there is no nametemplate, the stripped oldfile name is used as the template for newfile.

If there is no oldfile, the stripped nametemplate name is used as the template for newfile.

If both a nametemplate and oldfile are specified, the template is checked for a "%s". If none is found, the nametemplate is used as the template for newfile. The first path component of the nametemplate and oldfile are ignored.

Definition at line 521 of file mailcap.c.

523 {
524  int i, j, k;
525  char *s = NULL;
526  bool lmatch = false, rmatch = false;
527 
528  mutt_buffer_reset(newfile);
529 
530  /* first, ignore leading path components */
531 
532  if (nametemplate && (s = strrchr(nametemplate, '/')))
533  nametemplate = s + 1;
534 
535  if (oldfile && (s = strrchr(oldfile, '/')))
536  oldfile = s + 1;
537 
538  if (!nametemplate)
539  {
540  if (oldfile)
541  mutt_buffer_strcpy(newfile, oldfile);
542  }
543  else if (!oldfile)
544  {
545  mutt_file_expand_fmt(newfile, nametemplate, "neomutt");
546  }
547  else /* oldfile && nametemplate */
548  {
549  /* first, compare everything left from the "%s"
550  * (if there is one). */
551 
552  lmatch = true;
553  bool ps = false;
554  for (i = 0; nametemplate[i]; i++)
555  {
556  if ((nametemplate[i] == '%') && (nametemplate[i + 1] == 's'))
557  {
558  ps = true;
559  break;
560  }
561 
562  /* note that the following will _not_ read beyond oldfile's end. */
563 
564  if (lmatch && (nametemplate[i] != oldfile[i]))
565  lmatch = false;
566  }
567 
568  if (ps)
569  {
570  /* If we had a "%s", check the rest. */
571 
572  /* now, for the right part: compare everything right from
573  * the "%s" to the final part of oldfile.
574  *
575  * The logic here is as follows:
576  *
577  * - We start reading from the end.
578  * - There must be a match _right_ from the "%s",
579  * thus the i + 2.
580  * - If there was a left hand match, this stuff
581  * must not be counted again. That's done by the
582  * condition (j >= (lmatch ? i : 0)). */
583 
584  rmatch = true;
585 
586  for (j = mutt_str_strlen(oldfile) - 1, k = mutt_str_strlen(nametemplate) - 1;
587  (j >= (lmatch ? i : 0)) && (k >= (i + 2)); j--, k--)
588  {
589  if (nametemplate[k] != oldfile[j])
590  {
591  rmatch = false;
592  break;
593  }
594  }
595 
596  /* Now, check if we had a full match. */
597 
598  if (k >= i + 2)
599  rmatch = false;
600 
601  struct Buffer *left = mutt_buffer_pool_get();
602  struct Buffer *right = mutt_buffer_pool_get();
603 
604  if (!lmatch)
605  mutt_buffer_strcpy_n(left, nametemplate, i);
606  if (!rmatch)
607  mutt_buffer_strcpy(right, nametemplate + i + 2);
608  mutt_buffer_printf(newfile, "%s%s%s", mutt_b2s(left), oldfile, mutt_b2s(right));
609 
611  mutt_buffer_pool_release(&right);
612  }
613  else
614  {
615  /* no "%s" in the name template. */
616  mutt_buffer_strcpy(newfile, nametemplate);
617  }
618  }
619 
620  mutt_adv_mktemp(newfile);
621 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:327
void mutt_file_expand_fmt(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1441
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:95
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_MailcapSanitize

bool C_MailcapSanitize

Config: Restrict the possible characters in mailcap expandos.

Definition at line 48 of file mailcap.c.