NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mailcap.h File Reference

RFC1524 Mailcap routines. More...

#include <stdbool.h>
#include <stddef.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.
 
struct MailcapEntrymailcap_entry_new (void)
 Allocate memory for a new rfc1524 entry.
 
int mailcap_expand_command (struct Body *b, const char *filename, const char *type, struct Buffer *command)
 Expand expandos in a command.
 
void mailcap_expand_filename (const char *nametemplate, const char *oldfile, struct Buffer *newfile)
 Expand a new filename from a template or existing filename.
 
bool mailcap_lookup (struct Body *b, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
 Find given type in the list of mailcap files.
 

Detailed Description

RFC1524 Mailcap routines.

Authors
  • Richard Russon
  • Pietro Cerutti

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 55 of file mailcap.h.

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

Function Documentation

◆ mailcap_entry_free()

void mailcap_entry_free ( struct MailcapEntry **  ptr)

Deallocate an struct MailcapEntry.

Parameters
[out]ptrMailcapEntry to deallocate

Definition at line 454 of file mailcap.c.

455{
456 if (!ptr || !*ptr)
457 return;
458
459 struct MailcapEntry *me = *ptr;
460
461 FREE(&me->command);
462 FREE(&me->testcommand);
463 FREE(&me->composecommand);
465 FREE(&me->editcommand);
466 FREE(&me->printcommand);
467 FREE(&me->nametemplate);
468 FREE(ptr);
469}
#define FREE(x)
Definition: memory.h:55
A mailcap entry.
Definition: mailcap.h:37
char * composecommand
Definition: mailcap.h:40
char * testcommand
Definition: mailcap.h:39
char * nametemplate
Definition: mailcap.h:44
char * printcommand
Definition: mailcap.h:43
char * composetypecommand
Definition: mailcap.h:41
char * editcommand
Definition: mailcap.h:42
char * command
Definition: mailcap.h:38
+ 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 445 of file mailcap.c.

446{
447 return MUTT_MEM_CALLOC(1, struct MailcapEntry);
448}
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ mailcap_expand_command()

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

Expand expandos in a command.

Parameters
bEmail 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 = buf_pool_get();
74 struct Buffer *quoted = buf_pool_get();
75 struct Buffer *param = NULL;
76 struct Buffer *type2 = NULL;
77
78 const bool c_mailcap_sanitize = cs_subset_bool(NeoMutt->sub, "mailcap_sanitize");
79 const char *cptr = buf_string(command);
80 while (*cptr)
81 {
82 if (*cptr == '\\')
83 {
84 cptr++;
85 if (*cptr)
86 buf_addch(buf, *cptr++);
87 }
88 else if (*cptr == '%')
89 {
90 cptr++;
91 if (*cptr == '{')
92 {
93 const char *pvalue2 = NULL;
94
95 if (param)
96 buf_reset(param);
97 else
98 param = buf_pool_get();
99
100 /* Copy parameter name into param buffer */
101 cptr++;
102 while (*cptr && (*cptr != '}'))
103 buf_addch(param, *cptr++);
104
105 /* In send mode, use the current charset, since the message hasn't
106 * been converted yet. If noconv is set, then we assume the
107 * charset parameter has the correct value instead. */
108 if (mutt_istr_equal(buf_string(param), "charset") && b->charset && !b->noconv)
109 pvalue2 = b->charset;
110 else
111 pvalue2 = mutt_param_get(&b->parameter, buf_string(param));
112
113 /* Now copy the parameter value into param buffer */
114 if (c_mailcap_sanitize)
115 buf_sanitize_filename(param, NONULL(pvalue2), false);
116 else
117 buf_strcpy(param, pvalue2);
118
119 buf_quote_filename(quoted, buf_string(param), true);
120 buf_addstr(buf, buf_string(quoted));
121 }
122 else if ((*cptr == 's') && filename)
123 {
124 buf_quote_filename(quoted, filename, true);
125 buf_addstr(buf, buf_string(quoted));
126 needspipe = false;
127 }
128 else if (*cptr == 't')
129 {
130 if (!type2)
131 {
132 type2 = buf_pool_get();
133 if (c_mailcap_sanitize)
134 buf_sanitize_filename(type2, type, false);
135 else
136 buf_strcpy(type2, type);
137 }
138 buf_quote_filename(quoted, buf_string(type2), true);
139 buf_addstr(buf, buf_string(quoted));
140 }
141
142 if (*cptr)
143 cptr++;
144 }
145 else
146 {
147 buf_addch(buf, *cptr++);
148 }
149 }
150 buf_copy(command, buf);
151
152 buf_pool_release(&buf);
153 buf_pool_release(&quoted);
154 buf_pool_release(&param);
155 buf_pool_release(&type2);
156
157 return needspipe;
158}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:601
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:933
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
void buf_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
Definition: muttlib.c:982
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:85
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
#define NONULL(x)
Definition: string2.h:37
bool noconv
Don't do character set conversion.
Definition: body.h:46
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:79
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:63
String manipulation buffer.
Definition: buffer.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ 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 552 of file mailcap.c.

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

◆ mailcap_lookup()

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

Find given type in the list of mailcap files.

Parameters
bMessage 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 483 of file mailcap.c.

485{
486 /* rfc1524 specifies that a path of mailcap files should be searched.
487 * joy. They say
488 * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
489 * and overridden by the MAILCAPS environment variable, and, just to be nice,
490 * we'll make it specifiable in .neomuttrc */
491 const struct Slist *c_mailcap_path = cs_subset_slist(NeoMutt->sub, "mailcap_path");
492 if (!c_mailcap_path || (c_mailcap_path->count == 0))
493 {
494 /* L10N:
495 Mutt is trying to look up a mailcap value, but $mailcap_path is empty.
496 We added a reference to the MAILCAPS environment variable as a hint too.
497
498 Because the variable is automatically populated by Mutt, this
499 should only occur if the user deliberately runs in their shell:
500 export MAILCAPS=
501
502 or deliberately runs inside Mutt or their .muttrc:
503 set mailcap_path=""
504 -or-
505 unset mailcap_path
506 */
507 mutt_error(_("Neither mailcap_path nor MAILCAPS specified"));
508 return false;
509 }
510
511 mutt_check_lookup_list(b, type, typelen);
512
513 struct Buffer *path = buf_pool_get();
514 bool found = false;
515
516 struct ListNode *np = NULL;
517 STAILQ_FOREACH(np, &c_mailcap_path->head, entries)
518 {
519 buf_strcpy(path, np->data);
520 buf_expand_path(path);
521
522 mutt_debug(LL_DEBUG2, "Checking mailcap file: %s\n", buf_string(path));
523 found = rfc1524_mailcap_parse(b, buf_string(path), type, entry, opt);
524 if (found)
525 break;
526 }
527
528 buf_pool_release(&path);
529
530 if (entry && !found)
531 mutt_error(_("mailcap entry for type %s not found"), type);
532
533 return found;
534}
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:242
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
static bool rfc1524_mailcap_parse(struct Body *b, const char *filename, const char *type, struct MailcapEntry *entry, enum MailcapLookup opt)
Parse a mailcap entry.
Definition: mailcap.c:234
#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:343
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:315
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
String list.
Definition: slist.h:37
struct ListHead head
List containing values.
Definition: slist.h:38
size_t count
Number of values in list.
Definition: slist.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function: