NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
header.h File Reference

Convenience wrapper for the send headers. More...

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

Go to the source code of this file.

Enumerations

enum  MuttWriteHeaderMode {
  MUTT_WRITE_HEADER_NORMAL , MUTT_WRITE_HEADER_FCC , MUTT_WRITE_HEADER_POSTPONE , MUTT_WRITE_HEADER_EDITHDRS ,
  MUTT_WRITE_HEADER_MIME
}
 Modes for mutt_rfc822_write_header() More...
 

Functions

int mutt_rfc822_write_header (FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
 Write out one RFC822 header line. More...
 
int mutt_write_mime_header (struct Body *a, FILE *fp, struct ConfigSubset *sub)
 Create a MIME header. More...
 
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. More...
 
void mutt_write_references (const struct ListHead *r, FILE *fp, size_t trim)
 Add the message references to a list. More...
 

Detailed Description

Convenience wrapper for the send headers.

Authors
  • Richard Russon

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

Enumeration Type Documentation

◆ MuttWriteHeaderMode

Modes for mutt_rfc822_write_header()

Enumerator
MUTT_WRITE_HEADER_NORMAL 

A normal Email, write full header + MIME headers.

MUTT_WRITE_HEADER_FCC 

fcc mode, like normal mode but for Bcc header

MUTT_WRITE_HEADER_POSTPONE 

A postponed Email, just the envelope info.

MUTT_WRITE_HEADER_EDITHDRS 

"light" mode (used for edit_hdrs)

MUTT_WRITE_HEADER_MIME 

Write protected headers.

Definition at line 38 of file header.h.

39{
45};
@ MUTT_WRITE_HEADER_FCC
fcc mode, like normal mode but for Bcc header
Definition: header.h:41
@ MUTT_WRITE_HEADER_MIME
Write protected headers.
Definition: header.h:44
@ MUTT_WRITE_HEADER_NORMAL
A normal Email, write full header + MIME headers.
Definition: header.h:40
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition: header.h:42
@ MUTT_WRITE_HEADER_EDITHDRS
"light" mode (used for edit_hdrs)
Definition: header.h:43

Function Documentation

◆ mutt_rfc822_write_header()

int mutt_rfc822_write_header ( FILE *  fp,
struct Envelope env,
struct Body attach,
enum MuttWriteHeaderMode  mode,
bool  privacy,
bool  hide_protected_subject,
struct ConfigSubset sub 
)

Write out one RFC822 header line.

Parameters
fpFile to write to
envEnvelope of email
attachAttachment
modeMode, see MuttWriteHeaderMode
privacyIf true, remove headers that might identify the user
hide_protected_subjectIf true, replace subject header
subConfig Subset
Return values
0Success
-1Failure
Note
All RFC2047 encoding should be done outside of this routine, except for the "real name." This will allow this routine to be used more than once, if necessary.

Likewise, all IDN processing should happen outside of this routine.

privacy true => will omit any headers which may identify the user. Output generated is suitable for being sent through anonymous remailer chains.

hide_protected_subject: replaces the Subject header with $crypt_protected_headers_subject in NORMAL or POSTPONE mode.

Definition at line 575 of file header.c.

578{
579 if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
580 (mode == MUTT_WRITE_HEADER_POSTPONE)) &&
581 !privacy)
582 {
583 struct Buffer *date = buf_pool_get();
584 mutt_date_make_date(date, cs_subset_bool(sub, "local_date_header"));
585 fprintf(fp, "Date: %s\n", buf_string(date));
586 buf_pool_release(&date);
587 }
588
589 /* UseFrom is not consulted here so that we can still write a From:
590 * field if the user sets it with the 'my_hdr' command */
591 if (!TAILQ_EMPTY(&env->from) && !privacy)
592 {
593 mutt_addrlist_write_file(&env->from, fp, "From");
594 }
595
596 if (!TAILQ_EMPTY(&env->sender) && !privacy)
597 {
598 mutt_addrlist_write_file(&env->sender, fp, "Sender");
599 }
600
601 if (!TAILQ_EMPTY(&env->to))
602 {
603 mutt_addrlist_write_file(&env->to, fp, "To");
604 }
605 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
606#ifdef USE_NNTP
607 if (!OptNewsSend)
608#endif
609 fputs("To:\n", fp);
610
611 if (!TAILQ_EMPTY(&env->cc))
612 {
613 mutt_addrlist_write_file(&env->cc, fp, "Cc");
614 }
615 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
616#ifdef USE_NNTP
617 if (!OptNewsSend)
618#endif
619 fputs("Cc:\n", fp);
620
621 if (!TAILQ_EMPTY(&env->bcc))
622 {
623 const bool c_write_bcc = cs_subset_bool(sub, "write_bcc");
624
625 if ((mode == MUTT_WRITE_HEADER_POSTPONE) ||
626 (mode == MUTT_WRITE_HEADER_EDITHDRS) || (mode == MUTT_WRITE_HEADER_FCC) ||
627 ((mode == MUTT_WRITE_HEADER_NORMAL) && c_write_bcc))
628 {
629 mutt_addrlist_write_file(&env->bcc, fp, "Bcc");
630 }
631 }
632 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
633#ifdef USE_NNTP
634 if (!OptNewsSend)
635#endif
636 fputs("Bcc:\n", fp);
637
638#ifdef USE_NNTP
639 if (env->newsgroups)
640 fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
641 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
642 fputs("Newsgroups:\n", fp);
643
644 if (env->followup_to)
645 fprintf(fp, "Followup-To: %s\n", env->followup_to);
646 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
647 fputs("Followup-To:\n", fp);
648
649 const bool c_x_comment_to = cs_subset_bool(sub, "x_comment_to");
650 if (env->x_comment_to)
651 fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
652 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && c_x_comment_to)
653 fputs("X-Comment-To:\n", fp);
654#endif
655
656 if (env->subject)
657 {
658 if (hide_protected_subject &&
659 ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
661 {
662 const char *const c_crypt_protected_headers_subject = cs_subset_string(sub, "crypt_protected_headers_subject");
663 mutt_write_one_header(fp, "Subject", c_crypt_protected_headers_subject,
664 NULL, 0, CH_NO_FLAGS, sub);
665 }
666 else
667 {
668 mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS, sub);
669 }
670 }
671 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
672 {
673 fputs("Subject:\n", fp);
674 }
675
676 /* save message id if the user has set it */
677 if (env->message_id && !privacy)
678 fprintf(fp, "Message-ID: %s\n", env->message_id);
679
680 if (!TAILQ_EMPTY(&env->reply_to))
681 {
682 mutt_addrlist_write_file(&env->reply_to, fp, "Reply-To");
683 }
684 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
685 {
686 fputs("Reply-To:\n", fp);
687 }
688
689 if (!TAILQ_EMPTY(&env->mail_followup_to))
690 {
691#ifdef USE_NNTP
692 if (!OptNewsSend)
693#endif
694 {
695 mutt_addrlist_write_file(&env->mail_followup_to, fp, "Mail-Followup-To");
696 }
697 }
698
699 /* Add any user defined headers */
700 struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs,
701 privacy, sub);
702
703 if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
705 {
706 if (!STAILQ_EMPTY(&env->references))
707 {
708 fputs("References:", fp);
709 mutt_write_references(&env->references, fp, 10);
710 fputc('\n', fp);
711 }
712
713 /* Add the MIME headers */
714 if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
715 {
716 fputs("MIME-Version: 1.0\n", fp);
717 mutt_write_mime_header(attach, fp, sub);
718 }
719 }
720
721 if (!STAILQ_EMPTY(&env->in_reply_to))
722 {
723 fputs("In-Reply-To:", fp);
725 fputc('\n', fp);
726 }
727
728#ifdef USE_AUTOCRYPT
729 const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
730 if (c_autocrypt)
731 {
732 if (mode == MUTT_WRITE_HEADER_NORMAL || mode == MUTT_WRITE_HEADER_FCC)
734 if (mode == MUTT_WRITE_HEADER_MIME)
736 }
737#endif
738
739 const bool c_user_agent = cs_subset_bool(sub, "user_agent");
740 if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy &&
741 c_user_agent && !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
742 {
743 /* Add a vanity header */
744 fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
745 }
746
747 return (ferror(fp) == 0) ? 0 : -1;
748}
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, const char *header)
Wrapper for mutt_write_address()
Definition: address.c:1237
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:807
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:769
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: globals.c:80
const char * GitVer
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:758
static struct UserHdrsOverride write_userhdrs(FILE *fp, const struct ListHead *userhdrs, bool privacy, struct ConfigSubset *sub)
Write user-defined headers and keep track of the interesting ones.
Definition: header.c:362
@ USERHDRS_OVERRIDE_CONTENT_TYPE
Override the "Content-Type".
Definition: header.c:59
@ USERHDRS_OVERRIDE_USER_AGENT
Override the "User-Agent".
Definition: header.c:60
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: header.c:517
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:421
void mutt_date_make_date(struct Buffer *buf, bool local)
Write a date in RFC822 format to a buffer.
Definition: date.c:387
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 STAILQ_EMPTY(head)
Definition: queue.h:348
#define TAILQ_EMPTY(head)
Definition: queue.h:721
String manipulation buffer.
Definition: buffer.h:34
struct ListHead userhdrs
user defined headers
Definition: envelope.h:87
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:81
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:64
char * message_id
Message ID.
Definition: envelope.h:73
char * x_comment_to
List of 'X-comment-to' fields.
Definition: envelope.h:82
char * newsgroups
List of newsgroups.
Definition: envelope.h:79
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:65
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList sender
Email's sender.
Definition: envelope.h:63
struct ListHead references
message references (in reverse order)
Definition: envelope.h:85
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:86
char * subject
Email's subject.
Definition: envelope.h:70
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
Which headers have been overridden.
Definition: header.c:67
bool is_overridden[mutt_array_size(UserhdrsOverrideHeaders)]
Which email headers have been overridden.
Definition: header.c:69
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_mime_header()

int mutt_write_mime_header ( struct Body a,
FILE *  fp,
struct ConfigSubset sub 
)

Create a MIME header.

Parameters
aBody part
fpFile to write to
subConfig Subset
Return values
0Success
-1Failure

Definition at line 758 of file header.c.

759{
760 if (!a || !fp)
761 return -1;
762
763 int len;
764 int tmplen;
765 char buf[256] = { 0 };
766
767 char *id = NULL;
768
769 fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
770
771 if (!TAILQ_EMPTY(&a->parameter))
772 {
773 len = 25 + mutt_str_len(a->subtype); /* approximate len. of content-type */
774
775 struct Parameter *np = NULL;
776 TAILQ_FOREACH(np, &a->parameter, entries)
777 {
778 if (!np->attribute || !np->value)
779 continue;
780
781 struct ParameterList pl_conts = TAILQ_HEAD_INITIALIZER(pl_conts);
782 rfc2231_encode_string(&pl_conts, np->attribute, np->value);
783 struct Parameter *cont = NULL;
784 TAILQ_FOREACH(cont, &pl_conts, entries)
785 {
786 if (mutt_istr_equal(cont->attribute, "content-id"))
787 {
788 // Content-ID: gets its own header
789 mutt_str_replace(&id, cont->value);
790 break;
791 }
792
793 fputc(';', fp);
794
795 buf[0] = 0;
796 mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
797
798 /* Dirty hack to make messages readable by Outlook Express
799 * for the Mac: force quotes around the boundary parameter
800 * even when they aren't needed. */
801 if (mutt_istr_equal(cont->attribute, "boundary") && mutt_str_equal(buf, cont->value))
802 snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
803
804 tmplen = mutt_str_len(buf) + mutt_str_len(cont->attribute) + 1;
805 if (len + tmplen + 2 > 76)
806 {
807 fputs("\n\t", fp);
808 len = tmplen + 1;
809 }
810 else
811 {
812 fputc(' ', fp);
813 len += tmplen + 1;
814 }
815
816 fprintf(fp, "%s=%s", cont->attribute, buf);
817 }
818
819 mutt_param_free(&pl_conts);
820 }
821 }
822
823 fputc('\n', fp);
824
825 if (id)
826 {
827 fprintf(fp, "Content-ID: <%s>\n", id);
828 mutt_mem_free(&id);
829 }
830
831 if (a->language)
832 fprintf(fp, "Content-Language: %s\n", a->language);
833
834 if (a->description)
835 fprintf(fp, "Content-Description: %s\n", a->description);
836
837 if (a->disposition != DISP_NONE)
838 {
839 const char *dispstr[] = { "inline", "attachment", "form-data" };
840
841 if (a->disposition < sizeof(dispstr) / sizeof(char *))
842 {
843 fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
844 len = 21 + mutt_str_len(dispstr[a->disposition]);
845
846 if (a->use_disp && ((a->disposition != DISP_INLINE) || a->d_filename))
847 {
848 char *fn = a->d_filename;
849 if (!fn)
850 fn = a->filename;
851
852 if (fn)
853 {
854 /* Strip off the leading path... */
855 char *t = strrchr(fn, '/');
856 if (t)
857 t++;
858 else
859 t = fn;
860
861 struct ParameterList pl_conts = TAILQ_HEAD_INITIALIZER(pl_conts);
862 rfc2231_encode_string(&pl_conts, "filename", t);
863 struct Parameter *cont = NULL;
864 TAILQ_FOREACH(cont, &pl_conts, entries)
865 {
866 fputc(';', fp);
867 buf[0] = 0;
868 mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
869
870 tmplen = mutt_str_len(buf) + mutt_str_len(cont->attribute) + 1;
871 if (len + tmplen + 2 > 76)
872 {
873 fputs("\n\t", fp);
874 len = tmplen + 1;
875 }
876 else
877 {
878 fputc(' ', fp);
879 len += tmplen + 1;
880 }
881
882 fprintf(fp, "%s=%s", cont->attribute, buf);
883 }
884
885 mutt_param_free(&pl_conts);
886 }
887 }
888
889 fputc('\n', fp);
890 }
891 else
892 {
893 mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
894 }
895 }
896
897 if (a->encoding != ENC_7BIT)
898 fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
899
900 const bool c_crypt_protected_headers_write = cs_subset_bool(sub, "crypt_protected_headers_write");
901 bool c_autocrypt = false;
902#ifdef USE_AUTOCRYPT
903 c_autocrypt = cs_subset_bool(sub, "autocrypt");
904#endif
905
906 if ((c_crypt_protected_headers_write || c_autocrypt) && a->mime_headers)
907 {
909 false, false, sub);
910 }
911
912 /* Do NOT add the terminator here!!! */
913 return ferror(fp) ? -1 : 0;
914}
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:693
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:575
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
void mutt_mem_free(void *ptr)
Release memory allocated on the heap.
Definition: memory.c:68
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
@ DISP_NONE
No preferred disposition.
Definition: mime.h:65
#define ENCODING(x)
Definition: mime.h:92
#define TYPE(body)
Definition: mime.h:89
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
size_t rfc2231_encode_string(struct ParameterList *head, const char *attribute, char *value)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:351
char * language
content-language (RFC8255)
Definition: body.h:77
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:47
char * description
content-description
Definition: body.h:55
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
Attribute associated with a MIME part.
Definition: parameter.h:33
char * attribute
Parameter name.
Definition: parameter.h:34
char * value
Parameter value.
Definition: parameter.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_one_header()

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.

Parameters
fpFile to write to
tagHeader key, e.g. "From"
valueHeader value
pfxPrefix for header
wraplenColumn to wrap at
chflagsFlags, see CopyHeaderFlags
subConfig Subset
Return values
0Success
-1Failure

split several headers into individual ones and call write_one_header for each one

Definition at line 421 of file header.c.

424{
425 char *last = NULL, *line = NULL;
426 int max = 0, w, rc = -1;
427 int pfxw = mutt_strwidth(pfx);
428 char *v = mutt_str_dup(value);
429 bool display = (chflags & CH_DISPLAY);
430
431 const bool c_weed = cs_subset_bool(sub, "weed");
432 if (!display || c_weed)
433 v = unfold_header(v);
434
435 /* when not displaying, use sane wrap value */
436 if (!display)
437 {
438 const short c_wrap_headers = cs_subset_number(sub, "wrap_headers");
439 if ((c_wrap_headers < 78) || (c_wrap_headers > 998))
440 wraplen = 78;
441 else
442 wraplen = c_wrap_headers;
443 }
444 else if (wraplen <= 0)
445 {
446 wraplen = 78;
447 }
448
449 const size_t vlen = mutt_str_len(v);
450 if (tag)
451 {
452 /* if header is short enough, simply print it */
453 if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strnwidth(v, vlen) <= wraplen))
454 {
455 mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
456 if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
457 goto out;
458 rc = 0;
459 goto out;
460 }
461 else
462 {
463 rc = fold_one_header(fp, tag, v, vlen, pfx, wraplen, chflags);
464 goto out;
465 }
466 }
467
468 char *p = v;
469 last = v;
470 line = v;
471 while (p && *p)
472 {
473 p = strchr(p, '\n');
474
475 /* find maximum line width in current header */
476 if (p)
477 *p = '\0';
478 w = mutt_mb_width(line, 0, display);
479 if (w > max)
480 max = w;
481 if (p)
482 *p = '\n';
483
484 if (!p)
485 break;
486
487 line = ++p;
488 if ((*p != ' ') && (*p != '\t'))
489 {
490 if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
491 goto out;
492 last = p;
493 max = 0;
494 }
495 }
496
497 if (last && *last)
498 if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
499 goto out;
500
501 rc = 0;
502
503out:
504 FREE(&v);
505 return rc;
506}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define CH_DISPLAY
Display result to user.
Definition: copy.h:70
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:927
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:914
static int fold_one_header(FILE *fp, const char *tag, const char *value, size_t vlen, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: header.c:129
static int write_one_header(FILE *fp, int pfxw, int max, int wraplen, const char *pfx, const char *start, const char *end, CopyHeaderFlags chflags)
Write out one header line.
Definition: header.c:293
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: header.c:236
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
int mutt_mb_width(const char *str, int col, bool display)
Measure a string's display width (in screen columns)
Definition: mbyte.c:137
#define FREE(x)
Definition: memory.h:43
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_references()

void mutt_write_references ( const struct ListHead *  r,
FILE *  fp,
size_t  trim 
)

Add the message references to a list.

Parameters
rString List of references
fpFile to write to
trimTrim the list to at most this many items

Write the list in reverse because they are stored in reverse order when parsed to speed up threading.

Definition at line 517 of file header.c.

518{
519 struct ListNode *np = NULL;
520 size_t length = 0;
521
522 STAILQ_FOREACH(np, r, entries)
523 {
524 if (++length == trim)
525 break;
526 }
527
528 struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
529
530 // store in reverse order
531 size_t tmp = length;
532 STAILQ_FOREACH(np, r, entries)
533 {
534 ref[--tmp] = np;
535 if (tmp == 0)
536 break;
537 }
538
539 for (size_t i = 0; i < length; i++)
540 {
541 fputc(' ', fp);
542 fputs(ref[i]->data, fp);
543 if (i != length - 1)
544 fputc('\n', fp);
545 }
546
547 FREE(&ref);
548}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#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
+ Here is the call graph for this function:
+ Here is the caller graph for this function: