NeoMutt  2022-04-29-247-gc6aae8
Teaching an old dog new tricks
cid.c File Reference

Attachment Content-ID header functions. More...

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

Go to the source code of this file.


void cid_map_free (struct CidMap **ptr)
 Free a CidMap. More...
struct CidMapcid_map_new (const char *cid, const char *filename)
 Initialise a new CidMap. More...
void cid_map_list_clear (struct CidMapList *cid_map_list)
 Empty a CidMapList. More...
static void cid_save_attachment (struct Body *body, struct CidMapList *cid_map_list)
 Save attachment if it has a Content-ID. More...
void cid_save_attachments (struct Body *body, struct CidMapList *cid_map_list)
 Save all attachments in a "multipart/related" group with a Content-ID. More...
void cid_to_filename (struct Buffer *filename, const struct CidMapList *cid_map_list)
 Replace Content-IDs with filenames. More...

Detailed Description

Attachment Content-ID header functions.

  • David Purton

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

Definition in file cid.c.

Function Documentation

◆ cid_map_free()

void cid_map_free ( struct CidMap **  ptr)

Free a CidMap.

[out]ptrCidMap to free

Definition at line 45 of file cid.c.

47 if (!ptr)
48 return;
50 struct CidMap *cid_map = *ptr;
52 FREE(&cid_map->cid);
53 FREE(&cid_map->fname);
55 FREE(ptr);
#define FREE(x)
Definition: memory.h:43
List of Content-ID to filename mappings.
Definition: cid.h:35
char * fname
Definition: cid.h:37
char * cid
Definition: cid.h:36
+ Here is the caller graph for this function:

◆ cid_map_new()

struct CidMap * cid_map_new ( const char *  cid,
const char *  filename 

Initialise a new CidMap.

cidContent-ID to replace including "cid:" prefix
filenamePath to file to replace Content-ID with
Return values
ptrNewly allocated CidMap

Definition at line 64 of file cid.c.

66 if (!cid || !filename)
67 return NULL;
69 struct CidMap *cid_map = mutt_mem_calloc(1, sizeof(struct CidMap));
71 cid_map->cid = mutt_str_dup(cid);
72 cid_map->fname = mutt_str_dup(filename);
74 return cid_map;
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cid_map_list_clear()

void cid_map_list_clear ( struct CidMapList *  cid_map_list)

Empty a CidMapList.

cid_map_listList of Content-ID to filename mappings

Definition at line 81 of file cid.c.

83 if (!cid_map_list)
84 return;
86 while (!STAILQ_EMPTY(cid_map_list))
87 {
88 struct CidMap *cid_map = STAILQ_FIRST(cid_map_list);
89 STAILQ_REMOVE_HEAD(cid_map_list, entries);
90 cid_map_free(&cid_map);
91 }
void cid_map_free(struct CidMap **ptr)
Free a CidMap.
Definition: cid.c:45
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_EMPTY(head)
Definition: queue.h:348
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cid_save_attachment()

static void cid_save_attachment ( struct Body body,
struct CidMapList *  cid_map_list 

Save attachment if it has a Content-ID.

[in]bodyBody to check and save
[out]cid_map_listList of Content-ID to filename mappings

If body has a Content-ID, it is saved to disk and a new Content-ID to filename mapping is added to cid_map_list.

Definition at line 102 of file cid.c.

104 if (!body || !cid_map_list)
105 return;
107 char *id = mutt_param_get(&body->parameter, "content-id");
108 if (!id)
109 return;
111 struct Buffer *tmpfile = mutt_buffer_pool_get();
112 struct Buffer *cid = mutt_buffer_pool_get();
113 bool has_tempfile = false;
114 FILE *fp = NULL;
116 mutt_debug(LL_DEBUG2, "attachment found with \"Content-ID: %s\"\n", id);
117 /* get filename */
118 char *fname = mutt_str_dup(body->filename);
119 if (body->aptr)
120 fp = body->aptr->fp;
121 mutt_file_sanitize_filename(fname, fp ? true : false);
122 mailcap_expand_filename("%s", fname, tmpfile);
123 FREE(&fname);
125 /* save attachment */
126 if (mutt_save_attachment(fp, body, mutt_buffer_string(tmpfile), 0, NULL) == -1)
127 goto bail;
128 has_tempfile = true;
129 mutt_debug(LL_DEBUG2, "attachment with \"Content-ID: %s\" saved to file \"%s\"\n",
130 id, mutt_buffer_string(tmpfile));
132 /* add Content-ID to filename mapping to list */
133 mutt_buffer_printf(cid, "cid:%s", id);
134 struct CidMap *cid_map = cid_map_new(mutt_buffer_string(cid), mutt_buffer_string(tmpfile));
135 STAILQ_INSERT_TAIL(cid_map_list, cid_map, entries);
139 if ((fp && !mutt_buffer_is_empty(tmpfile)) || has_tempfile)
141 mutt_buffer_pool_release(&tmpfile);
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct CidMap * cid_map_new(const char *cid, const char *filename)
Initialise a new CidMap.
Definition: cid.c:64
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:647
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
Log at debug level 2.
Definition: logging.h:41
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:542
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1292
int mutt_save_attachment(FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:896
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 STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:74
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cid_save_attachments()

void cid_save_attachments ( struct Body body,
struct CidMapList *  cid_map_list 

Save all attachments in a "multipart/related" group with a Content-ID.

[in]bodyFirst body in "multipart/related" group
[out]cid_map_listList of Content-ID to filename mappings

Definition at line 150 of file cid.c.

152 if (!body || !cid_map_list)
153 return;
155 for (struct Body *b = body; b; b = b->next)
156 {
157 if (b->parts)
158 cid_save_attachments(b->parts, cid_map_list);
159 else
160 cid_save_attachment(b, cid_map_list);
161 }
static void cid_save_attachment(struct Body *body, struct CidMapList *cid_map_list)
Save attachment if it has a Content-ID.
Definition: cid.c:102
void cid_save_attachments(struct Body *body, struct CidMapList *cid_map_list)
Save all attachments in a "multipart/related" group with a Content-ID.
Definition: cid.c:150
The body of an email.
Definition: body.h:36
struct Body * next
next attachment in the list
Definition: body.h:71
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cid_to_filename()

void cid_to_filename ( struct Buffer filename,
const struct CidMapList *  cid_map_list 

Replace Content-IDs with filenames.

filenamePath to file to replace Content-IDs with filenames
cid_map_listList of Content-ID to filename mappings

Definition at line 169 of file cid.c.

171 if (!filename || !cid_map_list)
172 return;
174 FILE *fp_out = NULL;
175 char *pbuf = NULL;
176 char *searchbuf = NULL;
177 char *buf = NULL;
178 char *cid = NULL;
179 size_t blen = 0;
180 struct CidMap *cid_map = NULL;
182 struct Buffer *tmpfile = mutt_buffer_pool_get();
183 struct Buffer *tmpbuf = mutt_buffer_pool_get();
185 FILE *fp_in = mutt_file_fopen(mutt_buffer_string(filename), "r");
186 if (!fp_in)
187 goto bail;
189 /* ensure tmpfile has the same file extension as filename otherwise an
190 * HTML file may be opened as plain text by the viewer */
191 const char *suffix = mutt_strn_rfind(mutt_buffer_string(filename),
192 mutt_buffer_len(filename), ".");
193 if (suffix && *(suffix++))
194 mutt_buffer_mktemp_pfx_sfx(tmpfile, "neomutt", suffix);
195 else
196 mutt_buffer_mktemp(tmpfile);
197 fp_out = mutt_file_fopen(mutt_buffer_string(tmpfile), "w+");
198 if (!fp_out)
199 goto bail;
201 /* Read in lines from filename into buf */
202 while ((buf = mutt_file_read_line(buf, &blen, fp_in, NULL, MUTT_RL_NO_FLAGS)) != NULL)
203 {
204 if (mutt_str_len(buf) == 0)
205 {
206 fputs(buf, fp_out);
207 continue;
208 }
210 /* copy buf to searchbuf because we need to edit multiple times */
211 searchbuf = mutt_str_dup(buf);
212 mutt_buffer_reset(tmpbuf);
214 /* loop through Content-ID to filename mappings and do search and replace */
215 STAILQ_FOREACH(cid_map, cid_map_list, entries)
216 {
217 pbuf = searchbuf;
218 while ((cid = strstr(pbuf, cid_map->cid)) != NULL)
219 {
220 mutt_buffer_addstr_n(tmpbuf, pbuf, cid - pbuf);
221 mutt_buffer_addstr(tmpbuf, cid_map->fname);
222 pbuf = cid + mutt_str_len(cid_map->cid);
223 mutt_debug(LL_DEBUG2, "replaced \"%s\" with \"%s\" in file \"%s\"\n",
224 cid_map->cid, cid_map->fname, mutt_buffer_string(filename));
225 }
226 mutt_buffer_addstr(tmpbuf, pbuf);
227 FREE(&searchbuf);
228 searchbuf = mutt_buffer_strdup(tmpbuf);
229 mutt_buffer_reset(tmpbuf);
230 }
232 /* write edited line to output file */
233 fputs(searchbuf, fp_out);
234 fputs("\n", fp_out);
235 FREE(&searchbuf);
236 }
240 /* add filename to TempAtachmentsList so it doesn't get left lying around */
242 /* update filename to point to new file */
243 mutt_buffer_copy(filename, tmpfile);
246 FREE(&buf);
247 mutt_file_fclose(&fp_in);
248 mutt_file_fclose(&fp_out);
249 mutt_buffer_pool_release(&tmpfile);
size_t mutt_buffer_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition: buffer.c:105
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void mutt_file_set_mtime(const char *from, const char *to)
Set the modification time of one file from another.
Definition: file.c:1059
No flags are set.
Definition: file.h:38
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
const char * mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:856
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:75
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
static unsigned char * pbuf
Cached PGP data packet.
Definition: pgppacket.c:38
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
+ Here is the call graph for this function:
+ Here is the caller graph for this function: