NeoMutt  2019-12-07
Teaching an old dog new tricks
DOXYGEN
envelope.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdbool.h>
33 #include <string.h>
34 #include "mutt/mutt.h"
35 #include "address/lib.h"
36 #include "envelope.h"
37 
42 struct Envelope *mutt_env_new(void)
43 {
44  struct Envelope *e = mutt_mem_calloc(1, sizeof(struct Envelope));
46  TAILQ_INIT(&e->from);
47  TAILQ_INIT(&e->to);
48  TAILQ_INIT(&e->cc);
49  TAILQ_INIT(&e->bcc);
50  TAILQ_INIT(&e->sender);
51  TAILQ_INIT(&e->reply_to);
56  STAILQ_INIT(&e->userhdrs);
57  return e;
58 }
59 
60 #ifdef USE_AUTOCRYPT
61 
66 {
67  return mutt_mem_calloc(1, sizeof(struct AutocryptHeader));
68 }
69 
75 {
76  if (!p)
77  return;
78 
79  struct AutocryptHeader *cur = NULL;
80 
81  while (*p)
82  {
83  cur = *p;
84  *p = (*p)->next;
85  FREE(&cur->addr);
86  FREE(&cur->keydata);
87  FREE(&cur);
88  }
89 }
90 #endif
91 
96 void mutt_env_free(struct Envelope **ptr)
97 {
98  if (!ptr || !*ptr)
99  return;
100 
101  struct Envelope *env = *ptr;
102 
104  mutt_addrlist_clear(&env->from);
105  mutt_addrlist_clear(&env->to);
106  mutt_addrlist_clear(&env->cc);
107  mutt_addrlist_clear(&env->bcc);
112 
113  FREE(&env->list_post);
114  FREE(&env->subject);
115  /* real_subj is just an offset to subject and shouldn't be freed */
116  FREE(&env->disp_subj);
117  FREE(&env->message_id);
118  FREE(&env->supersedes);
119  FREE(&env->date);
120  FREE(&env->x_label);
121  FREE(&env->organization);
122 #ifdef USE_NNTP
123  FREE(&env->newsgroups);
124  FREE(&env->xref);
125  FREE(&env->followup_to);
126  FREE(&env->x_comment_to);
127 #endif
128 
129  mutt_buffer_dealloc(&env->spam);
130 
131  mutt_list_free(&env->references);
133  mutt_list_free(&env->userhdrs);
134 
135 #ifdef USE_AUTOCRYPT
138 #endif
139 
140  FREE(ptr);
141 }
142 
151 void mutt_env_merge(struct Envelope *base, struct Envelope **extra)
152 {
153  if (!base || !extra || !*extra)
154  return;
155 
156 /* copies each existing element if necessary, and sets the element
157  * to NULL in the source so that mutt_env_free doesn't leave us
158  * with dangling pointers. */
159 #define MOVE_ELEM(member) \
160  if (!base->member) \
161  { \
162  base->member = (*extra)->member; \
163  (*extra)->member = NULL; \
164  }
165 
166 #define MOVE_STAILQ(member) \
167  if (STAILQ_EMPTY(&base->member)) \
168  { \
169  STAILQ_SWAP(&base->member, &(*extra)->member, ListNode); \
170  }
171 
172 #define MOVE_ADDRESSLIST(member) \
173  if (TAILQ_EMPTY(&base->member)) \
174  { \
175  TAILQ_SWAP(&base->member, &(*extra)->member, Address, entries); \
176  }
177 
178 #define MOVE_BUFFER(member) \
179  if (mutt_buffer_is_empty(&base->member)) \
180  { \
181  memcpy(&base->member, &(*extra)->member, sizeof(struct Buffer)); \
182  mutt_buffer_init(&(*extra)->member); \
183  }
184 
196  MOVE_ELEM(date);
198  if (!(base->changed & MUTT_ENV_CHANGED_XLABEL))
199  {
201  }
202  if (!(base->changed & MUTT_ENV_CHANGED_REFS))
203  {
205  }
206  if (!(base->changed & MUTT_ENV_CHANGED_IRT))
207  {
209  }
210 
211  /* real_subj is subordinate to subject */
212  if (!base->subject)
213  {
214  base->subject = (*extra)->subject;
215  base->real_subj = (*extra)->real_subj;
216  base->disp_subj = (*extra)->disp_subj;
217  (*extra)->subject = NULL;
218  (*extra)->real_subj = NULL;
219  (*extra)->disp_subj = NULL;
220  }
221  /* spam and user headers should never be hashed, and the new envelope may
222  * have better values. Use new versions regardless. */
223  mutt_buffer_dealloc(&base->spam);
224  mutt_list_free(&base->userhdrs);
225  MOVE_BUFFER(spam);
227 #undef MOVE_ELEM
228 #undef MOVE_STAILQ
229 #undef MOVE_ADDRESSLIST
230 #undef MOVE_BUFFER
231 
232  mutt_env_free(extra);
233 }
234 
241 bool mutt_env_cmp_strict(const struct Envelope *e1, const struct Envelope *e2)
242 {
243  if (e1 && e2)
244  {
245  if ((mutt_str_strcmp(e1->message_id, e2->message_id) != 0) ||
246  (mutt_str_strcmp(e1->subject, e2->subject) != 0) ||
247  !mutt_list_compare(&e1->references, &e2->references) ||
248  !mutt_addrlist_equal(&e1->from, &e2->from) ||
249  !mutt_addrlist_equal(&e1->sender, &e2->sender) ||
250  !mutt_addrlist_equal(&e1->reply_to, &e2->reply_to) ||
251  !mutt_addrlist_equal(&e1->to, &e2->to) || !mutt_addrlist_equal(&e1->cc, &e2->cc) ||
253  {
254  return false;
255  }
256  else
257  return true;
258  }
259  else
260  {
261  return (!e1 && !e2);
262  }
263 }
264 
271 void mutt_env_to_local(struct Envelope *env)
272 {
273  if (!env)
274  return;
275 
278  mutt_addrlist_to_local(&env->to);
279  mutt_addrlist_to_local(&env->cc);
283 }
284 
285 /* Note that 'member' in the 'env->member' expression is macro argument, not
286  * "real" name of an 'env' compound member. Real name will be substituted by
287  * preprocessor at the macro-expansion time.
288  * Note that #member escapes and double quotes the argument.
289  */
290 #define H_TO_INTL(member) \
291  if (mutt_addrlist_to_intl(&env->member, err) && !e) \
292  { \
293  if (tag) \
294  *tag = #member; \
295  e = 1; \
296  err = NULL; \
297  }
298 
309 int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
310 {
311  if (!env)
312  return 1;
313 
314  int e = 0;
316  H_TO_INTL(from);
317  H_TO_INTL(to);
318  H_TO_INTL(cc);
319  H_TO_INTL(bcc);
322  return e;
323 }
324 
325 #undef H_TO_INTL
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AutocryptHeader * autocrypt_gossip
Definition: envelope.h:86
void mutt_env_merge(struct Envelope *base, struct Envelope **extra)
Merge the headers of two Envelopes.
Definition: envelope.c:151
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
char * supersedes
Supersedes header.
Definition: envelope.h:70
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1298
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1381
char * xref
List of cross-references.
Definition: envelope.h:76
char * disp_subj
Display subject (modified copy of subject)
Definition: envelope.h:68
char * date
Sent date.
Definition: envelope.h:71
#define MOVE_ELEM(member)
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
struct AutocryptHeader * mutt_autocrypthdr_new(void)
Create a new AutocryptHeader.
Definition: envelope.c:65
struct AutocryptHeader * autocrypt
Definition: envelope.h:85
bool mutt_addrlist_equal(const struct AddressList *ala, const struct AddressList *alb)
Compare two Address lists for equality.
Definition: address.c:802
bool mutt_env_cmp_strict(const struct Envelope *e1, const struct Envelope *e2)
Strictly compare two Envelopes.
Definition: envelope.c:241
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:309
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
Email Address Handling.
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
char * keydata
Definition: envelope.h:44
#define STAILQ_INIT(head)
Definition: queue.h:370
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define TAILQ_INIT(head)
Definition: queue.h:759
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define MOVE_BUFFER(member)
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
#define MUTT_ENV_CHANGED_XLABEL
X-Label edited.
Definition: envelope.h:34
Representation of an email header (envelope)
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct AutocryptHeader * next
Definition: envelope.h:47
#define MOVE_STAILQ(member)
char * addr
Definition: envelope.h:43
Parse Autocrypt header info.
Definition: envelope.h:41
char * list_post
This stores a mailto URL, or nothing.
Definition: envelope.h:65
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:271
char * subject
Email&#39;s subject.
Definition: envelope.h:66
struct AddressList return_path
Return path for the Email.
Definition: envelope.h:56
void mutt_autocrypthdr_free(struct AutocryptHeader **p)
Free an AutocryptHeader.
Definition: envelope.c:74
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
#define FREE(x)
Definition: memory.h:40
char * organization
Organisation header.
Definition: envelope.h:73
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:33
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:32
bool mutt_list_compare(const struct ListHead *ah, const struct ListHead *bh)
Compare two string lists.
Definition: list.c:219
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
struct AddressList x_original_to
Email&#39;s &#39;X-Orig-to&#39;.
Definition: envelope.h:64
char * x_label
X-Label.
Definition: envelope.h:72
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
#define H_TO_INTL(member)
Definition: envelope.c:290
The header of an Email.
Definition: envelope.h:54
struct Buffer spam
Spam header.
Definition: envelope.h:80
#define MOVE_ADDRESSLIST(member)