NeoMutt  2023-11-03-107-g582dc1
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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.
 
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
  • 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{
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 451 of file mailcap.c.

452{
453 if (!ptr || !*ptr)
454 return;
455
456 struct MailcapEntry *me = *ptr;
457
458 FREE(&me->command);
459 FREE(&me->testcommand);
460 FREE(&me->composecommand);
462 FREE(&me->editcommand);
463 FREE(&me->printcommand);
464 FREE(&me->nametemplate);
465 FREE(ptr);
466}
#define FREE(x)
Definition: memory.h:45
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 442 of file mailcap.c.

443{
444 return mutt_mem_calloc(1, sizeof(struct MailcapEntry));
445}
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 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 67 of file mailcap.c.

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

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

482{
483 /* rfc1524 specifies that a path of mailcap files should be searched.
484 * joy. They say
485 * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
486 * and overridden by the MAILCAPS environment variable, and, just to be nice,
487 * we'll make it specifiable in .neomuttrc */
488 const struct Slist *c_mailcap_path = cs_subset_slist(NeoMutt->sub, "mailcap_path");
489 if (!c_mailcap_path || (c_mailcap_path->count == 0))
490 {
491 /* L10N:
492 Mutt is trying to look up a mailcap value, but $mailcap_path is empty.
493 We added a reference to the MAILCAPS environment variable as a hint too.
494
495 Because the variable is automatically populated by Mutt, this
496 should only occur if the user deliberately runs in their shell:
497 export MAILCAPS=
498
499 or deliberately runs inside Mutt or their .muttrc:
500 set mailcap_path=""
501 -or-
502 unset mailcap_path
503 */
504 mutt_error(_("Neither mailcap_path nor MAILCAPS specified"));
505 return false;
506 }
507
508 mutt_check_lookup_list(b, type, typelen);
509
510 struct Buffer *path = buf_pool_get();
511 bool found = false;
512
513 struct ListNode *np = NULL;
514 STAILQ_FOREACH(np, &c_mailcap_path->head, entries)
515 {
516 buf_strcpy(path, np->data);
517 buf_expand_path(path);
518
519 mutt_debug(LL_DEBUG2, "Checking mailcap file: %s\n", buf_string(path));
520 found = rfc1524_mailcap_parse(b, buf_string(path), type, entry, opt);
521 if (found)
522 break;
523 }
524
525 buf_pool_release(&path);
526
527 if (entry && !found)
528 mutt_error(_("mailcap entry for type %s not found"), type);
529
530 return found;
531}
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:243
#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:232
#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:339
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:329
#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: