NeoMutt  2024-03-23-142-g2b2e76
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 *b, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
 Write out one RFC822 header line.
 
int mutt_write_mime_header (struct Body *b, FILE *fp, struct ConfigSubset *sub)
 Create a MIME 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.
 
void mutt_write_references (const struct ListHead *r, FILE *fp, size_t trim)
 Add the message references to a list.
 

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 b,
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
bAttachment
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 577 of file header.c.

580{
581 if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
582 (mode == MUTT_WRITE_HEADER_POSTPONE)) &&
583 !privacy)
584 {
585 struct Buffer *date = buf_pool_get();
586 mutt_date_make_date(date, cs_subset_bool(sub, "local_date_header"));
587 fprintf(fp, "Date: %s\n", buf_string(date));
588 buf_pool_release(&date);
589 }
590
591 /* UseFrom is not consulted here so that we can still write a From:
592 * field if the user sets it with the 'my_hdr' command */
593 if (!TAILQ_EMPTY(&env->from) && !privacy)
594 {
595 mutt_addrlist_write_file(&env->from, fp, "From");
596 }
597
598 if (!TAILQ_EMPTY(&env->sender) && !privacy)
599 {
600 mutt_addrlist_write_file(&env->sender, fp, "Sender");
601 }
602
603 if (!TAILQ_EMPTY(&env->to))
604 {
605 mutt_addrlist_write_file(&env->to, fp, "To");
606 }
607 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
608 {
609 if (!OptNewsSend)
610 fputs("To:\n", fp);
611 }
612
613 if (!TAILQ_EMPTY(&env->cc))
614 {
615 mutt_addrlist_write_file(&env->cc, fp, "Cc");
616 }
617 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
618 {
619 if (!OptNewsSend)
620 fputs("Cc:\n", fp);
621 }
622
623 if (!TAILQ_EMPTY(&env->bcc))
624 {
625 const bool c_write_bcc = cs_subset_bool(sub, "write_bcc");
626
627 if ((mode == MUTT_WRITE_HEADER_POSTPONE) ||
628 (mode == MUTT_WRITE_HEADER_EDITHDRS) || (mode == MUTT_WRITE_HEADER_FCC) ||
629 ((mode == MUTT_WRITE_HEADER_NORMAL) && c_write_bcc))
630 {
631 mutt_addrlist_write_file(&env->bcc, fp, "Bcc");
632 }
633 }
634 else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
635 {
636 if (!OptNewsSend)
637 fputs("Bcc:\n", fp);
638 }
639
640 if (env->newsgroups)
641 fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
642 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
643 fputs("Newsgroups:\n", fp);
644
645 if (env->followup_to)
646 fprintf(fp, "Followup-To: %s\n", env->followup_to);
647 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
648 fputs("Followup-To:\n", fp);
649
650 const bool c_x_comment_to = cs_subset_bool(sub, "x_comment_to");
651 if (env->x_comment_to)
652 fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
653 else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && c_x_comment_to)
654 fputs("X-Comment-To:\n", fp);
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 if (!OptNewsSend)
692 {
693 mutt_addrlist_write_file(&env->mail_followup_to, fp, "Mail-Followup-To");
694 }
695 }
696
697 /* Add any user defined headers */
698 struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs,
699 privacy, sub);
700
701 if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
703 {
704 if (!STAILQ_EMPTY(&env->references))
705 {
706 fputs("References:", fp);
707 mutt_write_references(&env->references, fp, 10);
708 fputc('\n', fp);
709 }
710
711 /* Add the MIME headers */
712 if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
713 {
714 fputs("MIME-Version: 1.0\n", fp);
715 mutt_write_mime_header(b, fp, sub);
716 }
717 }
718
719 if (!STAILQ_EMPTY(&env->in_reply_to))
720 {
721 fputs("In-Reply-To:", fp);
723 fputc('\n', fp);
724 }
725
726#ifdef USE_AUTOCRYPT
727 const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
728 if (c_autocrypt)
729 {
730 if (mode == MUTT_WRITE_HEADER_NORMAL || mode == MUTT_WRITE_HEADER_FCC)
732 if (mode == MUTT_WRITE_HEADER_MIME)
734 }
735#endif
736
737 const bool c_user_agent = cs_subset_bool(sub, "user_agent");
738 if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy &&
739 c_user_agent && !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
740 {
741 /* Add a vanity header */
742 fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
743 }
744
745 return (ferror(fp) == 0) ? 0 : -1;
746}
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, const char *header)
Wrapper for mutt_write_address()
Definition: address.c:1252
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:803
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:765
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:53
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: globals.c:71
const char * GitVer
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:364
@ USERHDRS_OVERRIDE_CONTENT_TYPE
Override the "Content-Type".
Definition: header.c:61
@ USERHDRS_OVERRIDE_USER_AGENT
Override the "User-Agent".
Definition: header.c:62
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:756
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: header.c:519
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
void mutt_date_make_date(struct Buffer *buf, bool local)
Write a date in RFC822 format to a buffer.
Definition: date.c:396
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:36
struct ListHead userhdrs
user defined headers
Definition: envelope.h:85
char *const subject
Email's subject.
Definition: envelope.h:70
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:80
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:81
char * newsgroups
List of newsgroups.
Definition: envelope.h:78
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:83
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
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:69
bool is_overridden[mutt_array_size(UserhdrsOverrideHeaders)]
Which email headers have been overridden.
Definition: header.c:71
+ 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 b,
FILE *  fp,
struct ConfigSubset sub 
)

Create a MIME header.

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

Definition at line 756 of file header.c.

757{
758 if (!b || !fp)
759 return -1;
760
761 int len;
762 int tmplen;
763 char buf[256] = { 0 };
764
765 char *id = NULL;
766
767 fprintf(fp, "Content-Type: %s/%s", TYPE(b), b->subtype);
768
769 if (!TAILQ_EMPTY(&b->parameter))
770 {
771 len = 25 + mutt_str_len(b->subtype); /* approximate len. of content-type */
772
773 struct Parameter *np = NULL;
774 TAILQ_FOREACH(np, &b->parameter, entries)
775 {
776 if (!np->attribute || !np->value)
777 continue;
778
779 struct ParameterList pl_conts = TAILQ_HEAD_INITIALIZER(pl_conts);
780 rfc2231_encode_string(&pl_conts, np->attribute, np->value);
781 struct Parameter *cont = NULL;
782 TAILQ_FOREACH(cont, &pl_conts, entries)
783 {
784 if (mutt_istr_equal(cont->attribute, "content-id"))
785 {
786 // Content-ID: gets its own header
787 mutt_str_replace(&id, cont->value);
788 break;
789 }
790
791 fputc(';', fp);
792
793 buf[0] = 0;
794 mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
795
796 /* Dirty hack to make messages readable by Outlook Express
797 * for the Mac: force quotes around the boundary parameter
798 * even when they aren't needed. */
799 if (mutt_istr_equal(cont->attribute, "boundary") && mutt_str_equal(buf, cont->value))
800 snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
801
802 tmplen = mutt_str_len(buf) + mutt_str_len(cont->attribute) + 1;
803 if ((len + tmplen + 2) > 76)
804 {
805 fputs("\n\t", fp);
806 len = tmplen + 1;
807 }
808 else
809 {
810 fputc(' ', fp);
811 len += tmplen + 1;
812 }
813
814 fprintf(fp, "%s=%s", cont->attribute, buf);
815 }
816
817 mutt_param_free(&pl_conts);
818 }
819 }
820
821 fputc('\n', fp);
822
823 if (id)
824 {
825 fprintf(fp, "Content-ID: <%s>\n", id);
826 mutt_mem_free(&id);
827 }
828
829 if (b->language)
830 fprintf(fp, "Content-Language: %s\n", b->language);
831
832 if (b->description)
833 fprintf(fp, "Content-Description: %s\n", b->description);
834
835 if (b->disposition != DISP_NONE)
836 {
837 const char *dispstr[] = { "inline", "attachment", "form-data" };
838
839 if (b->disposition < sizeof(dispstr) / sizeof(char *))
840 {
841 fprintf(fp, "Content-Disposition: %s", dispstr[b->disposition]);
842 len = 21 + mutt_str_len(dispstr[b->disposition]);
843
844 if (b->use_disp && ((b->disposition != DISP_INLINE) || b->d_filename))
845 {
846 char *fn = b->d_filename;
847 if (!fn)
848 fn = b->filename;
849
850 if (fn)
851 {
852 /* Strip off the leading path... */
853 char *t = strrchr(fn, '/');
854 if (t)
855 t++;
856 else
857 t = fn;
858
859 struct ParameterList pl_conts = TAILQ_HEAD_INITIALIZER(pl_conts);
860 rfc2231_encode_string(&pl_conts, "filename", t);
861 struct Parameter *cont = NULL;
862 TAILQ_FOREACH(cont, &pl_conts, entries)
863 {
864 fputc(';', fp);
865 buf[0] = 0;
866 mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
867
868 tmplen = mutt_str_len(buf) + mutt_str_len(cont->attribute) + 1;
869 if ((len + tmplen + 2) > 76)
870 {
871 fputs("\n\t", fp);
872 len = tmplen + 1;
873 }
874 else
875 {
876 fputc(' ', fp);
877 len += tmplen + 1;
878 }
879
880 fprintf(fp, "%s=%s", cont->attribute, buf);
881 }
882
883 mutt_param_free(&pl_conts);
884 }
885 }
886
887 fputc('\n', fp);
888 }
889 else
890 {
891 mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", b->disposition);
892 }
893 }
894
895 if (b->encoding != ENC_7BIT)
896 fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(b->encoding));
897
898 const bool c_crypt_protected_headers_write = cs_subset_bool(sub, "crypt_protected_headers_write");
899 bool c_autocrypt = false;
900#ifdef USE_AUTOCRYPT
901 c_autocrypt = cs_subset_bool(sub, "autocrypt");
902#endif
903
904 if ((c_crypt_protected_headers_write || c_autocrypt) && b->mime_headers)
905 {
907 false, false, sub);
908 }
909
910 /* Do NOT add the terminator here!!! */
911 return ferror(fp) ? -1 : 0;
912}
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
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *b, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:577
@ 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:721
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:545
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:62
#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:355
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 423 of file header.c.

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

520{
521 struct ListNode *np = NULL;
522 size_t length = 0;
523
524 STAILQ_FOREACH(np, r, entries)
525 {
526 if (++length == trim)
527 break;
528 }
529
530 struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
531
532 // store in reverse order
533 size_t tmp = length;
534 STAILQ_FOREACH(np, r, entries)
535 {
536 ref[--tmp] = np;
537 if (tmp == 0)
538 break;
539 }
540
541 for (size_t i = 0; i < length; i++)
542 {
543 fputc(' ', fp);
544 fputs(ref[i]->data, fp);
545 if (i != length - 1)
546 fputc('\n', fp);
547 }
548
549 FREE(&ref);
550}
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: