NeoMutt  2021-10-29-33-g41675a
Teaching an old dog new tricks
DOXYGEN
mailcap.h File Reference

RFC1524 Mailcap routines. More...

#include <stddef.h>
#include <stdbool.h>
+ Include dependency graph for mailcap.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MailcapEntry
 A mailcap entry. More...
 

Enumerations

enum  MailcapLookup {
  MUTT_MC_NO_FLAGS = 0 , MUTT_MC_EDIT , MUTT_MC_COMPOSE , MUTT_MC_PRINT ,
  MUTT_MC_AUTOVIEW
}
 Mailcap actions. More...
 

Functions

void mailcap_entry_free (struct MailcapEntry **ptr)
 Deallocate an struct MailcapEntry. More...
 
struct MailcapEntrymailcap_entry_new (void)
 Allocate memory for a new rfc1524 entry. More...
 
int mailcap_expand_command (struct Body *a, const char *filename, const char *type, struct Buffer *command)
 Expand expandos in a command. 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...
 
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...
 

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.h.

Enumeration Type Documentation

◆ MailcapLookup

Mailcap actions.

Enumerator
MUTT_MC_NO_FLAGS 

No flags set.

MUTT_MC_EDIT 

Mailcap edit field.

MUTT_MC_COMPOSE 

Mailcap compose field.

MUTT_MC_PRINT 

Mailcap print field.

MUTT_MC_AUTOVIEW 

Mailcap autoview field.

Definition at line 54 of file mailcap.h.

55 {
56  MUTT_MC_NO_FLAGS = 0,
57  MUTT_MC_EDIT,
61 };
@ MUTT_MC_PRINT
Mailcap print field.
Definition: mailcap.h:59
@ MUTT_MC_EDIT
Mailcap edit field.
Definition: mailcap.h:57
@ MUTT_MC_AUTOVIEW
Mailcap autoview field.
Definition: mailcap.h:60
@ MUTT_MC_NO_FLAGS
No flags set.
Definition: mailcap.h:56
@ MUTT_MC_COMPOSE
Mailcap compose field.
Definition: mailcap.h:58

Function Documentation

◆ mailcap_entry_free()

void mailcap_entry_free ( struct MailcapEntry **  ptr)

Deallocate an struct MailcapEntry.

Parameters
[out]ptrMailcapEntry to deallocate

Definition at line 446 of file mailcap.c.

447 {
448  if (!ptr || !*ptr)
449  return;
450 
451  struct MailcapEntry *me = *ptr;
452 
453  FREE(&me->command);
454  FREE(&me->testcommand);
455  FREE(&me->composecommand);
456  FREE(&me->composetypecommand);
457  FREE(&me->editcommand);
458  FREE(&me->printcommand);
459  FREE(&me->nametemplate);
460  FREE(ptr);
461 }
#define FREE(x)
Definition: memory.h:40
A mailcap entry.
Definition: mailcap.h:36
char * composecommand
Definition: mailcap.h:39
char * testcommand
Definition: mailcap.h:38
char * nametemplate
Definition: mailcap.h:43
char * printcommand
Definition: mailcap.h:42
char * composetypecommand
Definition: mailcap.h:40
char * editcommand
Definition: mailcap.h:41
char * command
Definition: mailcap.h:37
+ 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 437 of file mailcap.c.

438 {
439  return mutt_mem_calloc(1, sizeof(struct MailcapEntry));
440 }
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_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 67 of file mailcap.c.

69 {
70  int needspipe = true;
71  struct Buffer *buf = mutt_buffer_pool_get();
72  struct Buffer *quoted = mutt_buffer_pool_get();
73  struct Buffer *param = NULL;
74  struct Buffer *type2 = NULL;
75 
76  const bool c_mailcap_sanitize =
77  cs_subset_bool(NeoMutt->sub, "mailcap_sanitize");
78  const char *cptr = mutt_buffer_string(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_istr_equal(mutt_buffer_string(param), "charset") && a->charset && !a->noconv)
108  pvalue2 = a->charset;
109  else
110  pvalue2 = mutt_param_get(&a->parameter, mutt_buffer_string(param));
111 
112  /* Now copy the parameter value into param buffer */
113  if (c_mailcap_sanitize)
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_buffer_string(param), true);
120  }
121  else if ((*cptr == 's') && filename)
122  {
123  mutt_buffer_quote_filename(quoted, filename, true);
125  needspipe = false;
126  }
127  else if (*cptr == 't')
128  {
129  if (!type2)
130  {
131  type2 = mutt_buffer_pool_get();
132  if (c_mailcap_sanitize)
133  mutt_buffer_sanitize_filename(type2, type, false);
134  else
135  mutt_buffer_strcpy(type2, type);
136  }
137  mutt_buffer_quote_filename(quoted, mutt_buffer_string(type2), true);
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 }
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
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_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:866
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
Definition: muttlib.c:1657
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define NONULL(x)
Definition: string2.h:37
bool noconv
Don't do character set conversion.
Definition: body.h:45
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:77
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:61
String manipulation buffer.
Definition: buffer.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 545 of file mailcap.c.

547 {
548  int i, j, k;
549  char *s = NULL;
550  bool lmatch = false, rmatch = false;
551 
552  mutt_buffer_reset(newfile);
553 
554  /* first, ignore leading path components */
555 
556  if (nametemplate && (s = strrchr(nametemplate, '/')))
557  nametemplate = s + 1;
558 
559  if (oldfile && (s = strrchr(oldfile, '/')))
560  oldfile = s + 1;
561 
562  if (!nametemplate)
563  {
564  if (oldfile)
565  mutt_buffer_strcpy(newfile, oldfile);
566  }
567  else if (!oldfile)
568  {
569  mutt_file_expand_fmt(newfile, nametemplate, "neomutt");
570  }
571  else /* oldfile && nametemplate */
572  {
573  /* first, compare everything left from the "%s"
574  * (if there is one). */
575 
576  lmatch = true;
577  bool ps = false;
578  for (i = 0; nametemplate[i]; i++)
579  {
580  if ((nametemplate[i] == '%') && (nametemplate[i + 1] == 's'))
581  {
582  ps = true;
583  break;
584  }
585 
586  /* note that the following will _not_ read beyond oldfile's end. */
587 
588  if (lmatch && (nametemplate[i] != oldfile[i]))
589  lmatch = false;
590  }
591 
592  if (ps)
593  {
594  /* If we had a "%s", check the rest. */
595 
596  /* now, for the right part: compare everything right from
597  * the "%s" to the final part of oldfile.
598  *
599  * The logic here is as follows:
600  *
601  * - We start reading from the end.
602  * - There must be a match _right_ from the "%s",
603  * thus the i + 2.
604  * - If there was a left hand match, this stuff
605  * must not be counted again. That's done by the
606  * condition (j >= (lmatch ? i : 0)). */
607 
608  rmatch = true;
609 
610  for (j = mutt_str_len(oldfile) - 1, k = mutt_str_len(nametemplate) - 1;
611  (j >= (lmatch ? i : 0)) && (k >= (i + 2)); j--, k--)
612  {
613  if (nametemplate[k] != oldfile[j])
614  {
615  rmatch = false;
616  break;
617  }
618  }
619 
620  /* Now, check if we had a full match. */
621 
622  if (k >= i + 2)
623  rmatch = false;
624 
625  struct Buffer *left = mutt_buffer_pool_get();
626  struct Buffer *right = mutt_buffer_pool_get();
627 
628  if (!lmatch)
629  mutt_buffer_strcpy_n(left, nametemplate, i);
630  if (!rmatch)
631  mutt_buffer_strcpy(right, nametemplate + i + 2);
632  mutt_buffer_printf(newfile, "%s%s%s", mutt_buffer_string(left), oldfile,
633  mutt_buffer_string(right));
634 
636  mutt_buffer_pool_release(&right);
637  }
638  else
639  {
640  /* no "%s" in the name template. */
641  mutt_buffer_strcpy(newfile, nametemplate);
642  }
643  }
644 
645  mutt_adv_mktemp(newfile);
646 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
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:1478
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:83
+ Here is the call graph for this function:
+ 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 475 of file mailcap.c.

477 {
478  /* rfc1524 specifies that a path of mailcap files should be searched.
479  * joy. They say
480  * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
481  * and overridden by the MAILCAPS environment variable, and, just to be nice,
482  * we'll make it specifiable in .neomuttrc */
483  const struct Slist *c_mailcap_path =
484  cs_subset_slist(NeoMutt->sub, "mailcap_path");
485  if (!c_mailcap_path || (c_mailcap_path->count == 0))
486  {
487  /* L10N:
488  Mutt is trying to look up a mailcap value, but $mailcap_path is empty.
489  We added a reference to the MAILCAPS environment variable as a hint too.
490 
491  Because the variable is automatically populated by Mutt, this
492  should only occur if the user deliberately runs in their shell:
493  export MAILCAPS=
494 
495  or deliberately runs inside Mutt or their .muttrc:
496  set mailcap_path=""
497  -or-
498  unset mailcap_path
499  */
500  mutt_error(_("Neither mailcap_path nor MAILCAPS specified"));
501  return false;
502  }
503 
504  mutt_check_lookup_list(a, type, typelen);
505 
506  struct Buffer *path = mutt_buffer_pool_get();
507  bool found = false;
508 
509  struct ListNode *np = NULL;
510  STAILQ_FOREACH(np, &c_mailcap_path->head, entries)
511  {
512  mutt_buffer_strcpy(path, np->data);
514 
515  mutt_debug(LL_DEBUG2, "Checking mailcap file: %s\n", mutt_buffer_string(path));
516  found = rfc1524_mailcap_parse(a, mutt_buffer_string(path), type, entry, opt);
517  if (found)
518  break;
519  }
520 
522 
523  if (entry && !found)
524  mutt_error(_("mailcap entry for type %s not found"), type);
525 
526  return found;
527 }
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:268
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
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 _(a)
Definition: message.h:28
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
Definition: mutt_attach.c:340
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
String list.
Definition: slist.h:47
struct ListHead head
List containing values.
Definition: slist.h:48
size_t count
Number of values in list.
Definition: slist.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function: