NeoMutt  2025-01-09-41-g086358
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
copy.h File Reference

Duplicate the structure of an entire email. More...

#include "config.h"
#include <stdint.h>
#include <stdio.h>
+ Include dependency graph for copy.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_CM_NO_FLAGS   0
 No flags are set.
 
#define MUTT_CM_NOHEADER   (1 << 0)
 Don't copy the message header.
 
#define MUTT_CM_PREFIX   (1 << 1)
 Quote the header and body.
 
#define MUTT_CM_DECODE   (1 << 2)
 Decode the message body into text/plain.
 
#define MUTT_CM_DISPLAY   (1 << 3)
 Output is displayed to the user.
 
#define MUTT_CM_UPDATE   (1 << 4)
 Update structs on sync.
 
#define MUTT_CM_WEED   (1 << 5)
 Weed message/rfc822 attachment headers.
 
#define MUTT_CM_CHARCONV   (1 << 6)
 Perform character set conversions.
 
#define MUTT_CM_PRINTING   (1 << 7)
 Printing the message - display light.
 
#define MUTT_CM_REPLYING   (1 << 8)
 Replying the message.
 
#define MUTT_CM_DECODE_PGP   (1 << 9)
 Used for decoding PGP messages.
 
#define MUTT_CM_DECODE_SMIME   (1 << 10)
 Used for decoding S/MIME messages.
 
#define MUTT_CM_VERIFY   (1 << 11)
 Do signature verification.
 
#define MUTT_CM_DECODE_CRYPT   (MUTT_CM_DECODE_PGP | MUTT_CM_DECODE_SMIME)
 
#define CH_NO_FLAGS   0
 No flags are set.
 
#define CH_UPDATE   (1 << 0)
 Update the status and x-status fields?
 
#define CH_WEED   (1 << 1)
 Weed the headers?
 
#define CH_DECODE   (1 << 2)
 Do RFC2047 header decoding.
 
#define CH_XMIT   (1 << 3)
 Transmitting this message? (Ignore Lines: and Content-Length:)
 
#define CH_FROM   (1 << 4)
 Retain the "From " message separator?
 
#define CH_PREFIX   (1 << 5)
 Quote header using $indent_string string?
 
#define CH_NOSTATUS   (1 << 6)
 Suppress the status and x-status fields.
 
#define CH_REORDER   (1 << 7)
 Re-order output of headers (specified by 'hdr_order')
 
#define CH_NONEWLINE   (1 << 8)
 Don't output terminating newline after the header.
 
#define CH_MIME   (1 << 9)
 Ignore MIME fields.
 
#define CH_UPDATE_LEN   (1 << 10)
 Update Lines: and Content-Length:
 
#define CH_TXTPLAIN   (1 << 11)
 Generate text/plain MIME headers.
 
#define CH_NOLEN   (1 << 12)
 Don't write Content-Length: and Lines:
 
#define CH_WEED_DELIVERED   (1 << 13)
 Weed eventual Delivered-To headers.
 
#define CH_FORCE_FROM   (1 << 14)
 Give CH_FROM precedence over CH_WEED?
 
#define CH_NOQFROM   (1 << 15)
 Ignore ">From " line.
 
#define CH_UPDATE_IRT   (1 << 16)
 Update In-Reply-To:
 
#define CH_UPDATE_REFS   (1 << 17)
 Update References:
 
#define CH_DISPLAY   (1 << 18)
 Display result to user.
 
#define CH_UPDATE_LABEL   (1 << 19)
 Update X-Label: from email->env->x_label?
 
#define CH_UPDATE_SUBJECT   (1 << 20)
 Update Subject: protected header update.
 
#define CH_VIRTUAL   (1 << 21)
 Write virtual header lines too.
 

Typedefs

typedef uint16_t CopyMessageFlags
 Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
 
typedef uint32_t CopyHeaderFlags
 Flags for mutt_copy_header(), e.g. CH_UPDATE.
 

Functions

int mutt_copy_hdr (FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
 Copy header from one file to another.
 
int mutt_copy_header (FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
 Copy Email header.
 
int mutt_copy_message_fp (FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
 Make a copy of a message from a FILE pointer.
 
int mutt_copy_message (FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
 Copy a message from a Mailbox.
 
int mutt_append_message (struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
 Append a message.
 

Detailed Description

Duplicate the structure of an entire email.

Authors
  • Michael R. Elkins
  • 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 copy.h.

Macro Definition Documentation

◆ MUTT_CM_NO_FLAGS

#define MUTT_CM_NO_FLAGS   0

No flags are set.

Definition at line 37 of file copy.h.

◆ MUTT_CM_NOHEADER

#define MUTT_CM_NOHEADER   (1 << 0)

Don't copy the message header.

Definition at line 38 of file copy.h.

◆ MUTT_CM_PREFIX

#define MUTT_CM_PREFIX   (1 << 1)

Quote the header and body.

Definition at line 39 of file copy.h.

◆ MUTT_CM_DECODE

#define MUTT_CM_DECODE   (1 << 2)

Decode the message body into text/plain.

Definition at line 40 of file copy.h.

◆ MUTT_CM_DISPLAY

#define MUTT_CM_DISPLAY   (1 << 3)

Output is displayed to the user.

Definition at line 41 of file copy.h.

◆ MUTT_CM_UPDATE

#define MUTT_CM_UPDATE   (1 << 4)

Update structs on sync.

Definition at line 42 of file copy.h.

◆ MUTT_CM_WEED

#define MUTT_CM_WEED   (1 << 5)

Weed message/rfc822 attachment headers.

Definition at line 43 of file copy.h.

◆ MUTT_CM_CHARCONV

#define MUTT_CM_CHARCONV   (1 << 6)

Perform character set conversions.

Definition at line 44 of file copy.h.

◆ MUTT_CM_PRINTING

#define MUTT_CM_PRINTING   (1 << 7)

Printing the message - display light.

Definition at line 45 of file copy.h.

◆ MUTT_CM_REPLYING

#define MUTT_CM_REPLYING   (1 << 8)

Replying the message.

Definition at line 46 of file copy.h.

◆ MUTT_CM_DECODE_PGP

#define MUTT_CM_DECODE_PGP   (1 << 9)

Used for decoding PGP messages.

Definition at line 47 of file copy.h.

◆ MUTT_CM_DECODE_SMIME

#define MUTT_CM_DECODE_SMIME   (1 << 10)

Used for decoding S/MIME messages.

Definition at line 48 of file copy.h.

◆ MUTT_CM_VERIFY

#define MUTT_CM_VERIFY   (1 << 11)

Do signature verification.

Definition at line 49 of file copy.h.

◆ MUTT_CM_DECODE_CRYPT

#define MUTT_CM_DECODE_CRYPT   (MUTT_CM_DECODE_PGP | MUTT_CM_DECODE_SMIME)

Definition at line 50 of file copy.h.

◆ CH_NO_FLAGS

#define CH_NO_FLAGS   0

No flags are set.

Definition at line 53 of file copy.h.

◆ CH_UPDATE

#define CH_UPDATE   (1 << 0)

Update the status and x-status fields?

Definition at line 54 of file copy.h.

◆ CH_WEED

#define CH_WEED   (1 << 1)

Weed the headers?

Definition at line 55 of file copy.h.

◆ CH_DECODE

#define CH_DECODE   (1 << 2)

Do RFC2047 header decoding.

Definition at line 56 of file copy.h.

◆ CH_XMIT

#define CH_XMIT   (1 << 3)

Transmitting this message? (Ignore Lines: and Content-Length:)

Definition at line 57 of file copy.h.

◆ CH_FROM

#define CH_FROM   (1 << 4)

Retain the "From " message separator?

Definition at line 58 of file copy.h.

◆ CH_PREFIX

#define CH_PREFIX   (1 << 5)

Quote header using $indent_string string?

Definition at line 59 of file copy.h.

◆ CH_NOSTATUS

#define CH_NOSTATUS   (1 << 6)

Suppress the status and x-status fields.

Definition at line 60 of file copy.h.

◆ CH_REORDER

#define CH_REORDER   (1 << 7)

Re-order output of headers (specified by 'hdr_order')

Definition at line 61 of file copy.h.

◆ CH_NONEWLINE

#define CH_NONEWLINE   (1 << 8)

Don't output terminating newline after the header.

Definition at line 62 of file copy.h.

◆ CH_MIME

#define CH_MIME   (1 << 9)

Ignore MIME fields.

Definition at line 63 of file copy.h.

◆ CH_UPDATE_LEN

#define CH_UPDATE_LEN   (1 << 10)

Update Lines: and Content-Length:

Definition at line 64 of file copy.h.

◆ CH_TXTPLAIN

#define CH_TXTPLAIN   (1 << 11)

Generate text/plain MIME headers.

Definition at line 65 of file copy.h.

◆ CH_NOLEN

#define CH_NOLEN   (1 << 12)

Don't write Content-Length: and Lines:

Definition at line 66 of file copy.h.

◆ CH_WEED_DELIVERED

#define CH_WEED_DELIVERED   (1 << 13)

Weed eventual Delivered-To headers.

Definition at line 67 of file copy.h.

◆ CH_FORCE_FROM

#define CH_FORCE_FROM   (1 << 14)

Give CH_FROM precedence over CH_WEED?

Definition at line 68 of file copy.h.

◆ CH_NOQFROM

#define CH_NOQFROM   (1 << 15)

Ignore ">From " line.

Definition at line 69 of file copy.h.

◆ CH_UPDATE_IRT

#define CH_UPDATE_IRT   (1 << 16)

Update In-Reply-To:

Definition at line 70 of file copy.h.

◆ CH_UPDATE_REFS

#define CH_UPDATE_REFS   (1 << 17)

Update References:

Definition at line 71 of file copy.h.

◆ CH_DISPLAY

#define CH_DISPLAY   (1 << 18)

Display result to user.

Definition at line 72 of file copy.h.

◆ CH_UPDATE_LABEL

#define CH_UPDATE_LABEL   (1 << 19)

Update X-Label: from email->env->x_label?

Definition at line 73 of file copy.h.

◆ CH_UPDATE_SUBJECT

#define CH_UPDATE_SUBJECT   (1 << 20)

Update Subject: protected header update.

Definition at line 74 of file copy.h.

◆ CH_VIRTUAL

#define CH_VIRTUAL   (1 << 21)

Write virtual header lines too.

Definition at line 75 of file copy.h.

Typedef Documentation

◆ CopyMessageFlags

typedef uint16_t CopyMessageFlags

Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.

Definition at line 36 of file copy.h.

◆ CopyHeaderFlags

typedef uint32_t CopyHeaderFlags

Flags for mutt_copy_header(), e.g. CH_UPDATE.

Definition at line 52 of file copy.h.

Function Documentation

◆ mutt_copy_hdr()

int mutt_copy_hdr ( FILE *  fp_in,
FILE *  fp_out,
LOFF_T  off_start,
LOFF_T  off_end,
CopyHeaderFlags  chflags,
const char *  prefix,
int  wraplen 
)

Copy header from one file to another.

Parameters
fp_inFILE pointer to read from
fp_outFILE pointer to write to
off_startOffset to start from
off_endOffset to finish at
chflagsFlags, see CopyHeaderFlags
prefixPrefix for quoting headers
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Ok, the only reason for not merging this with mutt_copy_header() below is to avoid creating a Email structure in message_handler(). Also, this one will wrap headers much more aggressively than the other one.

Definition at line 107 of file copy.c.

109{
110 bool from = false;
111 bool this_is_from = false;
112 bool ignore = false;
113 char buf[1024] = { 0 }; /* should be long enough to get most fields in one pass */
114 char *nl = NULL;
115 struct HeaderArray headers = ARRAY_HEAD_INITIALIZER;
116 int hdr_count;
117 int x;
118 char *this_one = NULL;
119 size_t this_one_len = 0;
120
121 if (off_start < 0)
122 return -1;
123
124 if (ftello(fp_in) != off_start)
125 if (!mutt_file_seek(fp_in, off_start, SEEK_SET))
126 return -1;
127
128 buf[0] = '\n';
129 buf[1] = '\0';
130
131 if ((chflags & (CH_REORDER | CH_WEED | CH_MIME | CH_DECODE | CH_PREFIX | CH_WEED_DELIVERED)) == 0)
132 {
133 /* Without these flags to complicate things
134 * we can do a more efficient line to line copying */
135 while (ftello(fp_in) < off_end)
136 {
137 nl = strchr(buf, '\n');
138
139 if (!fgets(buf, sizeof(buf), fp_in))
140 break;
141
142 /* Is it the beginning of a header? */
143 if (nl && (buf[0] != ' ') && (buf[0] != '\t'))
144 {
145 ignore = true;
146 if (!from && mutt_str_startswith(buf, "From "))
147 {
148 if ((chflags & CH_FROM) == 0)
149 continue;
150 from = true;
151 }
152 else if ((chflags & CH_NOQFROM) && mutt_istr_startswith(buf, ">From "))
153 {
154 continue;
155 }
156 else if ((buf[0] == '\n') || ((buf[0] == '\r') && (buf[1] == '\n')))
157 {
158 break; /* end of header */
159 }
160
161 if ((chflags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
162 (mutt_istr_startswith(buf, "Status:") || mutt_istr_startswith(buf, "X-Status:")))
163 {
164 continue;
165 }
166 if ((chflags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
167 (mutt_istr_startswith(buf, "Content-Length:") ||
168 mutt_istr_startswith(buf, "Lines:")))
169 {
170 continue;
171 }
172 if ((chflags & CH_UPDATE_REFS) && mutt_istr_startswith(buf, "References:"))
173 {
174 continue;
175 }
176 if ((chflags & CH_UPDATE_IRT) && mutt_istr_startswith(buf, "In-Reply-To:"))
177 {
178 continue;
179 }
180 if (chflags & CH_UPDATE_LABEL && mutt_istr_startswith(buf, "X-Label:"))
181 continue;
182 if ((chflags & CH_UPDATE_SUBJECT) && mutt_istr_startswith(buf, "Subject:"))
183 {
184 continue;
185 }
186
187 ignore = false;
188 }
189
190 if (!ignore && (fputs(buf, fp_out) == EOF))
191 return -1;
192 }
193 return 0;
194 }
195
196 hdr_count = 1;
197 x = 0;
198
199 /* We are going to read and collect the headers in an array
200 * so we are able to do re-ordering.
201 * First count the number of entries in the array */
202 if (chflags & CH_REORDER)
203 {
204 struct ListNode *np = NULL;
205 STAILQ_FOREACH(np, &HeaderOrderList, entries)
206 {
207 mutt_debug(LL_DEBUG3, "Reorder list: %s\n", np->data);
208 hdr_count++;
209 }
210 }
211
212 mutt_debug(LL_DEBUG1, "WEED is %sset\n", (chflags & CH_WEED) ? "" : "not ");
213
214 ARRAY_RESERVE(&headers, hdr_count);
215
216 /* Read all the headers into the array */
217 while (ftello(fp_in) < off_end)
218 {
219 nl = strchr(buf, '\n');
220
221 /* Read a line */
222 if (!fgets(buf, sizeof(buf), fp_in))
223 break;
224
225 /* Is it the beginning of a header? */
226 if (nl && (buf[0] != ' ') && (buf[0] != '\t'))
227 {
228 /* Do we have anything pending? */
229 if (this_one)
230 {
231 if (chflags & CH_DECODE)
232 {
233 if (address_header_decode(&this_one) == 0)
234 rfc2047_decode(&this_one);
235 this_one_len = mutt_str_len(this_one);
236
237 /* Convert CRLF line endings to LF */
238 if ((this_one_len > 2) && (this_one[this_one_len - 2] == '\r') &&
239 (this_one[this_one_len - 1] == '\n'))
240 {
241 this_one[this_one_len - 2] = '\n';
242 this_one[this_one_len - 1] = '\0';
243 }
244 }
245
246 add_one_header(&headers, x, this_one);
247 this_one = NULL;
248 }
249
250 ignore = true;
251 this_is_from = false;
252 if (!from && mutt_str_startswith(buf, "From "))
253 {
254 if ((chflags & CH_FROM) == 0)
255 continue;
256 this_is_from = true;
257 from = true;
258 }
259 else if ((buf[0] == '\n') || ((buf[0] == '\r') && (buf[1] == '\n')))
260 {
261 break; /* end of header */
262 }
263
264 /* note: CH_FROM takes precedence over header weeding. */
265 if (!((chflags & CH_FROM) && (chflags & CH_FORCE_FROM) && this_is_from) &&
266 (chflags & CH_WEED) && mutt_matches_ignore(buf))
267 {
268 continue;
269 }
270 if ((chflags & CH_WEED_DELIVERED) && mutt_istr_startswith(buf, "Delivered-To:"))
271 {
272 continue;
273 }
274 if ((chflags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
275 (mutt_istr_startswith(buf, "Status:") || mutt_istr_startswith(buf, "X-Status:")))
276 {
277 continue;
278 }
279 if ((chflags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
280 (mutt_istr_startswith(buf, "Content-Length:") || mutt_istr_startswith(buf, "Lines:")))
281 {
282 continue;
283 }
284 if ((chflags & CH_MIME))
285 {
286 if (mutt_istr_startswith(buf, "mime-version:"))
287 {
288 continue;
289 }
290 size_t plen = mutt_istr_startswith(buf, "content-");
291 if ((plen != 0) && (mutt_istr_startswith(buf + plen, "transfer-encoding:") ||
292 mutt_istr_startswith(buf + plen, "type:")))
293 {
294 continue;
295 }
296 }
297 if ((chflags & CH_UPDATE_REFS) && mutt_istr_startswith(buf, "References:"))
298 {
299 continue;
300 }
301 if ((chflags & CH_UPDATE_IRT) && mutt_istr_startswith(buf, "In-Reply-To:"))
302 {
303 continue;
304 }
305 if ((chflags & CH_UPDATE_LABEL) && mutt_istr_startswith(buf, "X-Label:"))
306 continue;
307 if ((chflags & CH_UPDATE_SUBJECT) && mutt_istr_startswith(buf, "Subject:"))
308 {
309 continue;
310 }
311
312 /* Find x -- the array entry where this header is to be saved */
313 if (chflags & CH_REORDER)
314 {
315 struct ListNode *np = NULL;
316 x = 0;
317 int match = -1;
318 size_t match_len = 0;
319
320 STAILQ_FOREACH(np, &HeaderOrderList, entries)
321 {
322 size_t hdr_order_len = mutt_str_len(np->data);
323 if (mutt_istrn_equal(buf, np->data, hdr_order_len))
324 {
325 if ((match == -1) || (hdr_order_len > match_len))
326 {
327 match = x;
328 match_len = hdr_order_len;
329 }
330 mutt_debug(LL_DEBUG2, "Reorder: %s matches %s", np->data, buf);
331 }
332 x++;
333 }
334 if (match != -1)
335 x = match;
336 }
337
338 ignore = false;
339 } /* If beginning of header */
340
341 if (!ignore)
342 {
343 mutt_debug(LL_DEBUG2, "Reorder: x = %d; hdr_count = %d\n", x, hdr_count);
344 if (this_one)
345 {
346 size_t blen = mutt_str_len(buf);
347
348 MUTT_MEM_REALLOC(&this_one, this_one_len + blen + 1, char);
349 mutt_strn_copy(this_one + this_one_len, buf, blen, blen + 1);
350 this_one_len += blen;
351 }
352 else
353 {
354 this_one = mutt_str_dup(buf);
355 this_one_len = mutt_str_len(this_one);
356 }
357 }
358 } /* while (ftello (fp_in) < off_end) */
359
360 /* Do we have anything pending? -- XXX, same code as in above in the loop. */
361 if (this_one)
362 {
363 if (chflags & CH_DECODE)
364 {
365 if (address_header_decode(&this_one) == 0)
366 rfc2047_decode(&this_one);
367 this_one_len = mutt_str_len(this_one);
368 }
369
370 add_one_header(&headers, x, this_one);
371 this_one = NULL;
372 }
373
374 /* Now output the headers in order */
375 bool error = false;
376 char **hp = NULL;
377 const short c_wrap = cs_subset_number(NeoMutt->sub, "wrap");
378
379 ARRAY_FOREACH(hp, &headers)
380 {
381 if (!error && hp && *hp)
382 {
383 /* We couldn't do the prefixing when reading because RFC2047
384 * decoding may have concatenated lines. */
385 if (chflags & (CH_DECODE | CH_PREFIX))
386 {
387 const char *pre = (chflags & CH_PREFIX) ? prefix : NULL;
388 wraplen = mutt_window_wrap_cols(wraplen, c_wrap);
389
390 if (mutt_write_one_header(fp_out, 0, *hp, pre, wraplen, chflags, NeoMutt->sub) == -1)
391 {
392 error = true;
393 }
394 }
395 else
396 {
397 if (fputs(*hp, fp_out) == EOF)
398 {
399 error = true;
400 }
401 }
402 }
403
404 FREE(hp);
405 }
406 ARRAY_FREE(&headers);
407
408 if (error)
409 return -1;
410 return 0;
411}
#define ARRAY_RESERVE(head, num)
Reserve memory for the array.
Definition: array.h:189
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
static int address_header_decode(char **h)
Parse an email's headers.
Definition: copy.c:1082
static void add_one_header(struct HeaderArray *headers, size_t pos, char *value)
Add a header to a Headers array.
Definition: copy.c:77
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:56
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:57
#define CH_PREFIX
Quote header using $indent_string string?
Definition: copy.h:59
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:54
#define CH_NOSTATUS
Suppress the status and x-status fields.
Definition: copy.h:60
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:58
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:67
#define CH_UPDATE_LABEL
Update X-Label: from email->env->x_label?
Definition: copy.h:73
#define CH_WEED
Weed the headers?
Definition: copy.h:55
#define CH_REORDER
Re-order output of headers (specified by 'hdr_order')
Definition: copy.h:61
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:63
#define CH_UPDATE_REFS
Update References:
Definition: copy.h:71
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:69
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:64
#define CH_UPDATE_IRT
Update In-Reply-To:
Definition: copy.h:70
#define CH_FORCE_FROM
Give CH_FROM precedence over CH_WEED?
Definition: copy.h:68
#define CH_UPDATE_SUBJECT
Update Subject: protected header update.
Definition: copy.h:74
#define CH_NOLEN
Don't write Content-Length: and Lines:
Definition: copy.h:66
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:356
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:655
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: globals.c:49
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags, struct ConfigSubset *sub)
Write one header line to a file.
Definition: header.c:423
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition: memory.h:43
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition: string.c:360
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:242
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:453
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:334
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:661
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
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:

◆ mutt_copy_header()

int mutt_copy_header ( FILE *  fp_in,
struct Email e,
FILE *  fp_out,
CopyHeaderFlags  chflags,
const char *  prefix,
int  wraplen 
)

Copy Email header.

Parameters
fp_inFILE pointer to read from
eEmail
fp_outFILE pointer to write to
chflagsSee CopyHeaderFlags
prefixPrefix for quoting headers (if CH_PREFIX is set)
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Definition at line 424 of file copy.c.

426{
427 char *temp_hdr = NULL;
428 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
429
430 if (e->env)
431 {
432 chflags |= ((e->env->changed & MUTT_ENV_CHANGED_IRT) ? CH_UPDATE_IRT : 0) |
436 }
437
438 if (mutt_copy_hdr(fp_in, fp_out, e->offset, e->body->offset, chflags, prefix, wraplen) == -1)
439 return -1;
440
441 if (chflags & CH_TXTPLAIN)
442 {
443 char chsbuf[128] = { 0 };
444 char buf[128] = { 0 };
445 fputs("MIME-Version: 1.0\n", fp_out);
446 fputs("Content-Transfer-Encoding: 8bit\n", fp_out);
447 fputs("Content-Type: text/plain; charset=", fp_out);
448 const char *const c_charset = cc_charset();
449 mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), c_charset ? c_charset : "us-ascii");
450 mutt_addr_cat(buf, sizeof(buf), chsbuf, MimeSpecials);
451 fputs(buf, fp_out);
452 fputc('\n', fp_out);
453 }
454
455 if ((chflags & CH_UPDATE_IRT) && !STAILQ_EMPTY(&e->env->in_reply_to) &&
456 !(c_weed && mutt_matches_ignore("In-Reply-To")))
457 {
458 fputs("In-Reply-To:", fp_out);
459 struct ListNode *np = NULL;
460 STAILQ_FOREACH(np, &e->env->in_reply_to, entries)
461 {
462 fputc(' ', fp_out);
463 fputs(np->data, fp_out);
464 }
465 fputc('\n', fp_out);
466 }
467
468 if ((chflags & CH_UPDATE_REFS) && !STAILQ_EMPTY(&e->env->references) &&
469 !(c_weed && mutt_matches_ignore("References")))
470 {
471 fputs("References:", fp_out);
472 mutt_write_references(&e->env->references, fp_out, 0);
473 fputc('\n', fp_out);
474 }
475
476 if ((chflags & CH_UPDATE) && ((chflags & CH_NOSTATUS) == 0))
477 {
478 if ((e->old || e->read) && !(c_weed && mutt_matches_ignore("Status")))
479 {
480 fputs("Status: ", fp_out);
481 if (e->read)
482 fputs("RO", fp_out);
483 else if (e->old)
484 fputc('O', fp_out);
485 fputc('\n', fp_out);
486 }
487
488 if ((e->flagged || e->replied) && !(c_weed && mutt_matches_ignore("X-Status")))
489 {
490 fputs("X-Status: ", fp_out);
491 if (e->replied)
492 fputc('A', fp_out);
493 if (e->flagged)
494 fputc('F', fp_out);
495 fputc('\n', fp_out);
496 }
497 }
498
499 if (chflags & CH_UPDATE_LEN && ((chflags & CH_NOLEN) == 0) &&
500 !(c_weed && mutt_matches_ignore("Content-Length")))
501 {
502 fprintf(fp_out, "Content-Length: " OFF_T_FMT "\n", e->body->length);
503 if ((e->lines != 0) || (e->body->length == 0))
504 fprintf(fp_out, "Lines: %d\n", e->lines);
505 }
506
507#ifdef USE_NOTMUCH
508 if (chflags & CH_VIRTUAL)
509 {
510 /* Add some fake headers based on notmuch data */
511 char *folder = nm_email_get_folder(e);
512 if (folder && !(c_weed && mutt_matches_ignore("Folder")))
513 {
514 char buf[1024] = { 0 };
515 mutt_str_copy(buf, folder, sizeof(buf));
516 mutt_pretty_mailbox(buf, sizeof(buf));
517
518 fputs("Folder: ", fp_out);
519 fputs(buf, fp_out);
520 fputc('\n', fp_out);
521 }
522 }
523#endif
524
525 struct Buffer *tags = buf_pool_get();
526 driver_tags_get(&e->tags, tags);
527 if (!buf_is_empty(tags) && !(c_weed && mutt_matches_ignore("Tags")))
528 {
529 fputs("Tags: ", fp_out);
530 fputs(buf_string(tags), fp_out);
531 fputc('\n', fp_out);
532 }
533 buf_pool_release(&tags);
534
535 const struct Slist *const c_send_charset = cs_subset_slist(NeoMutt->sub, "send_charset");
536 const short c_wrap = cs_subset_number(NeoMutt->sub, "wrap");
537 if ((chflags & CH_UPDATE_LABEL) && e->env->x_label &&
538 !(c_weed && mutt_matches_ignore("X-Label")))
539 {
540 temp_hdr = e->env->x_label;
541 /* env->x_label isn't currently stored with direct references elsewhere.
542 * Mailbox->label_hash strdups the keys. But to be safe, encode a copy */
543 if (!(chflags & CH_DECODE))
544 {
545 temp_hdr = mutt_str_dup(temp_hdr);
546 rfc2047_encode(&temp_hdr, NULL, sizeof("X-Label:"), c_send_charset);
547 }
548 if (mutt_write_one_header(fp_out, "X-Label", temp_hdr, (chflags & CH_PREFIX) ? prefix : 0,
549 mutt_window_wrap_cols(wraplen, c_wrap), chflags,
550 NeoMutt->sub) == -1)
551 {
552 return -1;
553 }
554 if (!(chflags & CH_DECODE))
555 FREE(&temp_hdr);
556 }
557
558 if ((chflags & CH_UPDATE_SUBJECT) && e->env->subject &&
559 !(c_weed && mutt_matches_ignore("Subject")))
560 {
561 temp_hdr = e->env->subject;
562 /* env->subject is directly referenced in Mailbox->subj_hash, so we
563 * have to be careful not to encode (and thus free) that memory. */
564 if (!(chflags & CH_DECODE))
565 {
566 temp_hdr = mutt_str_dup(temp_hdr);
567 rfc2047_encode(&temp_hdr, NULL, sizeof("Subject:"), c_send_charset);
568 }
569 if (mutt_write_one_header(fp_out, "Subject", temp_hdr, (chflags & CH_PREFIX) ? prefix : 0,
570 mutt_window_wrap_cols(wraplen, c_wrap), chflags,
571 NeoMutt->sub) == -1)
572 {
573 return -1;
574 }
575 if (!(chflags & CH_DECODE))
576 FREE(&temp_hdr);
577 }
578
579 if ((chflags & CH_NONEWLINE) == 0)
580 {
581 if (chflags & CH_PREFIX)
582 fputs(prefix, fp_out);
583 fputc('\n', fp_out); /* add header terminator */
584 }
585
586 if (ferror(fp_out) || feof(fp_out))
587 return -1;
588
589 return 0;
590}
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition: address.c:708
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:440
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition: copy.c:107
#define CH_NONEWLINE
Don't output terminating newline after the header.
Definition: copy.h:62
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:65
#define CH_VIRTUAL
Write virtual header lines too.
Definition: copy.h:75
#define MUTT_ENV_CHANGED_SUBJECT
Protected header update.
Definition: envelope.h:37
#define MUTT_ENV_CHANGED_XLABEL
X-Label edited.
Definition: envelope.h:36
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:34
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:35
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: header.c:519
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:374
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:581
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1488
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 STAILQ_EMPTY(head)
Definition: queue.h:382
void rfc2047_encode(char **pd, const char *specials, int col, const struct Slist *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:628
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
String manipulation buffer.
Definition: buffer.h:36
bool read
Email is read.
Definition: email.h:50
struct Envelope * env
Envelope information.
Definition: email.h:68
int lines
How many lines in the body of this message?
Definition: email.h:62
struct Body * body
List of MIME parts.
Definition: email.h:69
bool old
Email is seen, but unread.
Definition: email.h:49
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:71
bool flagged
Marked important?
Definition: email.h:47
bool replied
Email has been replied to.
Definition: email.h:51
struct TagList tags
For drivers that support server tagging.
Definition: email.h:72
char *const subject
Email's subject.
Definition: envelope.h:70
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:90
struct ListHead references
message references (in reverse order)
Definition: envelope.h:83
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
char * x_label
X-Label.
Definition: envelope.h:76
String list.
Definition: slist.h:37
void driver_tags_get(struct TagList *tl, struct Buffer *tags)
Get tags all tags separated by space.
Definition: tags.c:164
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_copy_message_fp()

int mutt_copy_message_fp ( FILE *  fp_out,
FILE *  fp_in,
struct Email e,
CopyMessageFlags  cmflags,
CopyHeaderFlags  chflags,
int  wraplen 
)

Make a copy of a message from a FILE pointer.

Parameters
fp_outWhere to write output
fp_inWhere to get input
eEmail being copied
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Definition at line 657 of file copy.c.

659{
660 struct Body *body = e->body;
661 struct Buffer *prefix = buf_pool_get();
662 LOFF_T new_offset = -1;
663 int rc = 0;
664
665 if (cmflags & MUTT_CM_PREFIX)
666 {
667 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
668 if (c_text_flowed)
669 {
670 buf_strcpy(prefix, ">");
671 }
672 else
673 {
674 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
675 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
676 struct Mailbox *m_cur = get_current_mailbox();
677 setlocale(LC_TIME, NONULL(c_attribution_locale));
678 mutt_make_string(prefix, -1, c_indent_string, m_cur, -1, e, MUTT_FORMAT_NO_FLAGS, NULL);
679 setlocale(LC_TIME, "");
680 }
681 }
682
683 if ((cmflags & MUTT_CM_NOHEADER) == 0)
684 {
685 if (cmflags & MUTT_CM_PREFIX)
686 {
687 chflags |= CH_PREFIX;
688 }
689 else if (e->attach_del && (chflags & CH_UPDATE_LEN))
690 {
691 int new_lines;
692 int rc_attach_del = -1;
693 LOFF_T new_length = body->length;
694 struct Buffer *quoted_date = NULL;
695
696 quoted_date = buf_pool_get();
697 buf_addch(quoted_date, '"');
698 mutt_date_make_date(quoted_date, cs_subset_bool(NeoMutt->sub, "local_date_header"));
699 buf_addch(quoted_date, '"');
700
701 /* Count the number of lines and bytes to be deleted */
702 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
703 {
704 goto attach_del_cleanup;
705 }
706 const int del = count_delete_lines(fp_in, body, &new_length, buf_len(quoted_date));
707 if (del == -1)
708 {
709 goto attach_del_cleanup;
710 }
711 new_lines = e->lines - del;
712
713 /* Copy the headers */
714 if (mutt_copy_header(fp_in, e, fp_out, chflags | CH_NOLEN | CH_NONEWLINE, NULL, wraplen))
715 goto attach_del_cleanup;
716 fprintf(fp_out, "Content-Length: " OFF_T_FMT "\n", new_length);
717 if (new_lines <= 0)
718 new_lines = 0;
719 else
720 fprintf(fp_out, "Lines: %d\n", new_lines);
721
722 putc('\n', fp_out);
723 if (ferror(fp_out) || feof(fp_out))
724 goto attach_del_cleanup;
725 new_offset = ftello(fp_out);
726
727 /* Copy the body */
728 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
729 goto attach_del_cleanup;
730 if (copy_delete_attach(body, fp_in, fp_out, buf_string(quoted_date)))
731 goto attach_del_cleanup;
732
733 buf_pool_release(&quoted_date);
734
735 LOFF_T fail = ((ftello(fp_out) - new_offset) - new_length);
736 if (fail)
737 {
738 mutt_error(ngettext("The length calculation was wrong by %ld byte",
739 "The length calculation was wrong by %ld bytes", fail),
740 (long) fail);
741 new_length += fail;
742 }
743
744 /* Update original message if we are sync'ing a mailfolder */
745 if (cmflags & MUTT_CM_UPDATE)
746 {
747 e->attach_del = false;
748 e->lines = new_lines;
749 body->offset = new_offset;
750
751 body->length = new_length;
752 mutt_body_free(&body->parts);
753 }
754
755 rc_attach_del = 0;
756
757 attach_del_cleanup:
758 buf_pool_release(&quoted_date);
759 rc = rc_attach_del;
760 goto done;
761 }
762
763 if (mutt_copy_header(fp_in, e, fp_out, chflags,
764 (chflags & CH_PREFIX) ? buf_string(prefix) : NULL, wraplen) == -1)
765 {
766 rc = -1;
767 goto done;
768 }
769
770 new_offset = ftello(fp_out);
771 }
772
773 if (cmflags & MUTT_CM_DECODE)
774 {
775 /* now make a text/plain version of the message */
776 struct State state = { 0 };
777 state.fp_in = fp_in;
778 state.fp_out = fp_out;
779 if (cmflags & MUTT_CM_PREFIX)
780 state.prefix = buf_string(prefix);
781 if (cmflags & MUTT_CM_DISPLAY)
782 {
783 state.flags |= STATE_DISPLAY;
784 state.wraplen = wraplen;
785 const char *const c_pager = pager_get_pager(NeoMutt->sub);
786 if (!c_pager)
787 state.flags |= STATE_PAGER;
788 }
789 if (cmflags & MUTT_CM_PRINTING)
790 state.flags |= STATE_PRINTING;
791 if (cmflags & MUTT_CM_WEED)
792 state.flags |= STATE_WEED;
793 if (cmflags & MUTT_CM_CHARCONV)
794 state.flags |= STATE_CHARCONV;
795 if (cmflags & MUTT_CM_REPLYING)
796 state.flags |= STATE_REPLYING;
797
798 if ((WithCrypto != 0) && cmflags & MUTT_CM_VERIFY)
799 state.flags |= STATE_VERIFY;
800
801 rc = mutt_body_handler(body, &state);
802 }
803 else if ((WithCrypto != 0) && (cmflags & MUTT_CM_DECODE_CRYPT) && (e->security & SEC_ENCRYPT))
804 {
805 struct Body *cur = NULL;
806 FILE *fp = NULL;
807
808 if (((WithCrypto & APPLICATION_PGP) != 0) && (cmflags & MUTT_CM_DECODE_PGP) &&
810 {
811 if (crypt_pgp_decrypt_mime(fp_in, &fp, e->body, &cur))
812 {
813 rc = 1;
814 goto done;
815 }
816 fputs("MIME-Version: 1.0\n", fp_out);
817 }
818
819 if (((WithCrypto & APPLICATION_SMIME) != 0) && (cmflags & MUTT_CM_DECODE_SMIME) &&
821 {
822 if (crypt_smime_decrypt_mime(fp_in, &fp, e->body, &cur))
823 {
824 rc = 1;
825 goto done;
826 }
827 }
828
829 if (!cur)
830 {
831 mutt_error(_("No decryption engine available for message"));
832 rc = 1;
833 goto done;
834 }
835
836 mutt_write_mime_header(cur, fp_out, NeoMutt->sub);
837 fputc('\n', fp_out);
838
839 if (!mutt_file_seek(fp, cur->offset, SEEK_SET))
840 {
841 rc = 1;
842 goto done;
843 }
844
845 if (mutt_file_copy_bytes(fp, fp_out, cur->length) == -1)
846 {
847 mutt_file_fclose(&fp);
848 mutt_body_free(&cur);
849 rc = 1;
850 goto done;
851 }
852 mutt_body_free(&cur);
853 mutt_file_fclose(&fp);
854 }
855 else
856 {
857 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
858 {
859 rc = 1;
860 goto done;
861 }
862 if (cmflags & MUTT_CM_PREFIX)
863 {
864 int c;
865 size_t bytes = body->length;
866
867 fputs(buf_string(prefix), fp_out);
868
869 while (((c = fgetc(fp_in)) != EOF) && bytes--)
870 {
871 fputc(c, fp_out);
872 if (c == '\n')
873 {
874 fputs(buf_string(prefix), fp_out);
875 }
876 }
877 }
878 else if (mutt_file_copy_bytes(fp_in, fp_out, body->length) == -1)
879 {
880 rc = 1;
881 goto done;
882 }
883 }
884
885 if ((cmflags & MUTT_CM_UPDATE) && ((cmflags & MUTT_CM_NOHEADER) == 0) &&
886 (new_offset != -1))
887 {
888 body->offset = new_offset;
889 mutt_body_free(&body->parts);
890 }
891
892done:
893 buf_pool_release(&prefix);
894 return rc;
895}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:357
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c:424
static int count_delete_lines(FILE *fp, struct Body *b, LOFF_T *length, size_t datelen)
Count lines to be deleted in this email body.
Definition: copy.c:603
static int copy_delete_attach(struct Body *b, FILE *fp_in, FILE *fp_out, const char *quoted_date)
Copy a message, deleting marked attachments.
Definition: copy.c:1020
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:43
#define MUTT_CM_REPLYING
Replying the message.
Definition: copy.h:46
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:39
#define MUTT_CM_UPDATE
Update structs on sync.
Definition: copy.h:42
#define MUTT_CM_VERIFY
Do signature verification.
Definition: copy.h:49
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:47
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:40
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:44
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:48
#define MUTT_CM_PRINTING
Printing the message - display light.
Definition: copy.h:45
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:50
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition: copy.h:38
#define MUTT_CM_DISPLAY
Output is displayed to the user.
Definition: copy.h:41
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:210
int crypt_smime_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:432
int mutt_make_string(struct Buffer *buf, size_t max_cols, const struct Expando *exp, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: dlg_index.c:803
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:58
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:195
#define mutt_file_fclose(FP)
Definition: file.h:139
#define mutt_error(...)
Definition: logging2.h:92
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1632
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:756
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:715
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
void mutt_date_make_date(struct Buffer *buf, bool local)
Write a date in RFC822 format to a buffer.
Definition: date.c:397
#define _(a)
Definition: message.h:28
#define STATE_PAGER
Output will be displayed in the Pager.
Definition: state.h:42
#define STATE_WEED
Weed headers even when not in display mode.
Definition: state.h:36
#define STATE_DISPLAY
Output is displayed to the user.
Definition: state.h:33
#define STATE_REPLYING
Are we replying?
Definition: state.h:39
#define STATE_VERIFY
Perform signature verification.
Definition: state.h:34
#define STATE_CHARCONV
Do character set conversions.
Definition: state.h:37
#define STATE_PRINTING
Are we printing? - STATE_DISPLAY "light".
Definition: state.h:38
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:96
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:97
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:84
#define WithCrypto
Definition: lib.h:122
const char * pager_get_pager(struct ConfigSubset *sub)
Get the value of $pager.
Definition: config.c:111
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
#define NONULL(x)
Definition: string2.h:37
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:73
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:99
Parsed Expando trees.
Definition: expando.h:41
A mailbox.
Definition: mailbox.h:79
Keep track when processing files.
Definition: state.h:48
int wraplen
Width to wrap lines to (when flags & STATE_DISPLAY)
Definition: state.h:53
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:52
FILE * fp_out
File to write to.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:49
const char * prefix
String to add to the beginning of each output line.
Definition: state.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_copy_message()

int mutt_copy_message ( FILE *  fp_out,
struct Email e,
struct Message msg,
CopyMessageFlags  cmflags,
CopyHeaderFlags  chflags,
int  wraplen 
)

Copy a message from a Mailbox.

Parameters
fp_outFILE pointer to write to
eEmail
msgMessage
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

should be made to return -1 on fatal errors, and 1 on non-fatal errors like partial decode, where it is worth displaying as much as possible

Definition at line 911 of file copy.c.

913{
914 if (!msg || !e->body)
915 {
916 return -1;
917 }
918 if (fp_out == msg->fp)
919 {
920 mutt_debug(LL_DEBUG1, "trying to read/write from/to the same FILE*!\n");
921 return -1;
922 }
923
924 int rc = mutt_copy_message_fp(fp_out, msg->fp, e, cmflags, chflags, wraplen);
925 if ((rc == 0) && (ferror(fp_out) || feof(fp_out)))
926 {
927 mutt_debug(LL_DEBUG1, "failed to detect EOF!\n");
928 rc = -1;
929 }
930 return rc;
931}
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Make a copy of a message from a FILE pointer.
Definition: copy.c:657
FILE * fp
pointer to the message data
Definition: message.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_append_message()

int mutt_append_message ( struct Mailbox m_dst,
struct Mailbox m_src,
struct Email e,
struct Message msg,
CopyMessageFlags  cmflags,
CopyHeaderFlags  chflags 
)

Append a message.

Parameters
m_dstDestination Mailbox
m_srcSource Mailbox
eEmail
msgMessage
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
Return values
0Success
-1Failure

Definition at line 986 of file copy.c.

989{
990 if (!e)
991 return -1;
992
993 const bool own_msg = !msg;
994 if (own_msg && !(msg = mx_msg_open(m_src, e)))
995 {
996 return -1;
997 }
998
999 int rc = append_message(m_dst, msg->fp, m_src, e, cmflags, chflags);
1000 if (own_msg)
1001 {
1002 mx_msg_close(m_src, &msg);
1003 }
1004 return rc;
1005}
static int append_message(struct Mailbox *dest, FILE *fp_in, struct Mailbox *src, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Appends a copy of the given message to a mailbox.
Definition: copy.c:944
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1184
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1138
+ Here is the call graph for this function:
+ Here is the caller graph for this function: