NeoMutt  2018-07-16 +952-a2da0a
Teaching an old dog new tricks
DOXYGEN
mutt_header.c File Reference

Manipulate an email's header. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include "mutt/mutt.h"
#include "email/lib.h"
#include "mutt.h"
#include "alias.h"
#include "context.h"
#include "curs_lib.h"
#include "globals.h"
#include "index.h"
#include "mailbox.h"
#include "muttlib.h"
#include "ncrypt/ncrypt.h"
#include "options.h"
#include "protos.h"
#include "sendlib.h"
+ Include dependency graph for mutt_header.c:

Go to the source code of this file.

Functions

static void label_ref_dec (struct Mailbox *m, char *label)
 Decrease the refcount of a label. More...
 
static void label_ref_inc (struct Mailbox *m, char *label)
 Increase the refcount of a label. More...
 
static bool label_message (struct Mailbox *m, struct Email *e, char *new)
 add an X-Label: field More...
 
int mutt_label_message (struct Email *e)
 Let the user label a message. More...
 
void mutt_edit_headers (const char *editor, const char *body, struct Email *msg, char *fcc, size_t fcclen)
 Let the user edit the message header and body. More...
 
void mutt_make_label_hash (struct Mailbox *m)
 Create a Hash Table to store the labels. More...
 
void mutt_label_hash_add (struct Mailbox *m, struct Email *e)
 Add a message's labels to the Hash Table. More...
 
void mutt_label_hash_remove (struct Mailbox *m, struct Email *e)
 Rmove a message's labels from the Hash Table. More...
 

Detailed Description

Manipulate an email's header.

Authors
  • Michael R. Elkins

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 mutt_header.c.

Function Documentation

static void label_ref_dec ( struct Mailbox m,
char *  label 
)
static

Decrease the refcount of a label.

Parameters
mMailbox
labelLabel

Definition at line 56 of file mutt_header.c.

57 {
58  struct HashElem *elem = mutt_hash_find_elem(m->label_hash, label);
59  if (!elem)
60  return;
61 
62  uintptr_t count = (uintptr_t) elem->data;
63  if (count <= 1)
64  {
65  mutt_hash_delete(m->label_hash, label, NULL);
66  return;
67  }
68 
69  count--;
70  elem->data = (void *) count;
71 }
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:434
struct HashElem * mutt_hash_find_elem(const struct Hash *table, const char *strkey)
Find the HashElem in a Hash table element using a key.
Definition: hash.c:387
void * data
Definition: hash.h:46
The item stored in a Hash Table.
Definition: hash.h:42
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void label_ref_inc ( struct Mailbox m,
char *  label 
)
static

Increase the refcount of a label.

Parameters
mMailbox
labelLabel

Definition at line 78 of file mutt_header.c.

79 {
80  uintptr_t count;
81 
82  struct HashElem *elem = mutt_hash_find_elem(m->label_hash, label);
83  if (!elem)
84  {
85  count = 1;
86  mutt_hash_insert(m->label_hash, label, (void *) count);
87  return;
88  }
89 
90  count = (uintptr_t) elem->data;
91  count++;
92  elem->data = (void *) count;
93 }
struct HashElem * mutt_hash_find_elem(const struct Hash *table, const char *strkey)
Find the HashElem in a Hash table element using a key.
Definition: hash.c:387
void * data
Definition: hash.h:46
The item stored in a Hash Table.
Definition: hash.h:42
struct HashElem * mutt_hash_insert(struct Hash *table, const char *strkey, void *data)
Add a new element to the Hash table (with string keys)
Definition: hash.c:349
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool label_message ( struct Mailbox m,
struct Email e,
char *  new 
)
static

add an X-Label: field

Parameters
[in]mMailbox
[in]eEmail
[out]newSet to true if this is a new label
Return values
trueIf the label was added

Definition at line 102 of file mutt_header.c.

103 {
104  if (!e)
105  return false;
106  if (mutt_str_strcmp(e->env->x_label, new) == 0)
107  return false;
108 
109  if (e->env->x_label)
110  label_ref_dec(m, e->env->x_label);
111  mutt_str_replace(&e->env->x_label, new);
112  if (e->env->x_label)
113  label_ref_inc(m, e->env->x_label);
114 
115  e->changed = true;
116  e->xlabel_changed = true;
117  return true;
118 }
bool xlabel_changed
editable - used for syncing
Definition: email.h:60
bool changed
Definition: email.h:46
struct Envelope * env
envelope information
Definition: email.h:91
static void label_ref_dec(struct Mailbox *m, char *label)
Decrease the refcount of a label.
Definition: mutt_header.c:56
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
char * x_label
Definition: envelope.h:50
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
static void label_ref_inc(struct Mailbox *m, char *label)
Increase the refcount of a label.
Definition: mutt_header.c:78

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_label_message ( struct Email e)

Let the user label a message.

Parameters
eEmail (OPTIONAL)
Return values
numNumber of messages changed

If e isn't given, then tagged messages will be labelled.

Definition at line 127 of file mutt_header.c.

128 {
129  char buf[LONG_STRING], *new = NULL;
130  int changed;
131 
132  if (!Context || !Context->mailbox->label_hash)
133  return 0;
134 
135  *buf = '\0';
136  if (e && e->env->x_label)
137  {
138  mutt_str_strfcpy(buf, e->env->x_label, sizeof(buf));
139  }
140 
141  if (mutt_get_field("Label: ", buf, sizeof(buf), MUTT_LABEL /* | MUTT_CLEAR */) != 0)
142  return 0;
143 
144  new = buf;
145  SKIPWS(new);
146  if (*new == '\0')
147  new = NULL;
148 
149  changed = 0;
150  if (e)
151  {
152  if (label_message(Context->mailbox, e, new))
153  {
154  changed++;
156  }
157  }
158  else
159  {
160  for (int i = 0; i < Context->mailbox->msg_count; ++i)
161  {
162  if (!message_is_tagged(Context, i))
163  continue;
164 
165  struct Email *e2 = Context->mailbox->hdrs[i];
166  if (label_message(Context->mailbox, e2, new))
167  {
168  changed++;
170  /* mutt_set_flag re-evals the header color */
171  }
172  }
173  }
174 
175  return changed;
176 }
The "current" mailbox.
Definition: context.h:36
int msg_count
total number of messages
Definition: mailbox.h:86
The envelope/body of an email.
Definition: email.h:35
#define MUTT_LABEL
do label completion
Definition: mutt.h:66
bool changed
Definition: email.h:46
void mutt_set_header_color(struct Mailbox *m, struct Email *curhdr)
Select a colour for a message.
Definition: index.c:3514
#define LONG_STRING
Definition: string2.h:36
struct Email ** hdrs
Definition: mailbox.h:93
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
envelope information
Definition: email.h:91
Tagged messages.
Definition: mutt.h:123
static bool label_message(struct Mailbox *m, struct Email *e, char *new)
add an X-Label: field
Definition: mutt_header.c:102
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
#define mutt_set_flag(a, b, c, d)
Definition: protos.h:54
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
char * x_label
Definition: envelope.h:50
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_edit_headers ( const char *  editor,
const char *  body,
struct Email msg,
char *  fcc,
size_t  fcclen 
)

Let the user edit the message header and body.

Parameters
editorEditor command
bodyFile containing message body
msgHeader of the message
fccBuffer for the fcc field
fcclenLength of buffer

Definition at line 186 of file mutt_header.c.

188 {
189  char path[PATH_MAX]; /* tempfile used to edit headers + body */
190  char buffer[LONG_STRING];
191  const char *p = NULL;
192  int i;
193  struct Envelope *n = NULL;
194  time_t mtime;
195  struct stat st;
196 
197  mutt_mktemp(path, sizeof(path));
198  FILE *ofp = mutt_file_fopen(path, "w");
199  if (!ofp)
200  {
201  mutt_perror(path);
202  return;
203  }
204 
205  mutt_env_to_local(msg->env);
206  mutt_rfc822_write_header(ofp, msg->env, NULL, 1, false);
207  fputc('\n', ofp); /* tie off the header. */
208 
209  /* now copy the body of the message. */
210  FILE *ifp = fopen(body, "r");
211  if (!ifp)
212  {
213  mutt_perror(body);
214  mutt_file_fclose(&ofp);
215  return;
216  }
217 
218  mutt_file_copy_stream(ifp, ofp);
219 
220  mutt_file_fclose(&ifp);
221  mutt_file_fclose(&ofp);
222 
223  if (stat(path, &st) == -1)
224  {
225  mutt_perror(path);
226  return;
227  }
228 
229  mtime = mutt_file_decrease_mtime(path, &st);
230 
231  mutt_edit_file(editor, path);
232  stat(path, &st);
233  if (mtime == st.st_mtime)
234  {
235  mutt_debug(1, "temp file was not modified.\n");
236  /* the file has not changed! */
237  mutt_file_unlink(path);
238  return;
239  }
240 
241  mutt_file_unlink(body);
242  mutt_list_free(&msg->env->userhdrs);
243 
244  /* Read the temp file back in */
245  ifp = fopen(path, "r");
246  if (!ifp)
247  {
248  mutt_perror(path);
249  return;
250  }
251 
252  ofp = mutt_file_fopen(body, "w");
253  if (!ofp)
254  {
255  /* intentionally leak a possible temporary file here */
256  mutt_file_fclose(&ifp);
257  mutt_perror(body);
258  return;
259  }
260 
261  n = mutt_rfc822_read_header(ifp, NULL, true, false);
262  while ((i = fread(buffer, 1, sizeof(buffer), ifp)) > 0)
263  fwrite(buffer, 1, i, ofp);
264  mutt_file_fclose(&ofp);
265  mutt_file_fclose(&ifp);
266  mutt_file_unlink(path);
267 
268  /* in case the user modifies/removes the In-Reply-To header with
269  * $edit_headers set, we remove References: as they're likely invalid;
270  * we can simply compare strings as we don't generate References for
271  * multiple Message-Ids in IRT anyways */
272 #ifdef USE_NNTP
273  if (!OptNewsSend)
274 #endif
275  {
276  if (!STAILQ_EMPTY(&msg->env->in_reply_to) &&
277  (STAILQ_EMPTY(&n->in_reply_to) ||
279  STAILQ_FIRST(&msg->env->in_reply_to)->data) != 0)))
280  {
281  mutt_list_free(&msg->env->references);
282  }
283  }
284 
285  /* restore old info. */
288 
289  mutt_env_free(&msg->env);
290  msg->env = n;
291  n = NULL;
292 
294 
295  /* search through the user defined headers added to see if
296  * fcc: or attach: or pgp: was specified
297  */
298 
299  struct ListNode *np, *tmp;
300  STAILQ_FOREACH_SAFE(np, &msg->env->userhdrs, entries, tmp)
301  {
302  bool keep = true;
303  size_t plen;
304 
305  if (fcc && (plen = mutt_str_startswith(np->data, "fcc:", CASE_IGNORE)))
306  {
307  p = mutt_str_skip_email_wsp(np->data + plen);
308  if (*p)
309  {
310  mutt_str_strfcpy(fcc, p, fcclen);
311  mutt_pretty_mailbox(fcc, fcclen);
312  }
313  keep = false;
314  }
315  else if ((plen = mutt_str_startswith(np->data, "attach:", CASE_IGNORE)))
316  {
317  struct Body *body2 = NULL;
318  struct Body *parts = NULL;
319 
320  p = mutt_str_skip_email_wsp(np->data + plen);
321  if (*p)
322  {
323  size_t l = 0;
324  for (; *p && *p != ' ' && *p != '\t'; p++)
325  {
326  if (*p == '\\')
327  {
328  if (!*(p + 1))
329  break;
330  p++;
331  }
332  if (l < sizeof(path) - 1)
333  path[l++] = *p;
334  }
336  path[l] = '\0';
337 
338  mutt_expand_path(path, sizeof(path));
339  body2 = mutt_make_file_attach(path);
340  if (body2)
341  {
342  body2->description = mutt_str_strdup(p);
343  for (parts = msg->content; parts->next; parts = parts->next)
344  ;
345  parts->next = body2;
346  }
347  else
348  {
349  mutt_pretty_mailbox(path, sizeof(path));
350  mutt_error(_("%s: unable to attach file"), path);
351  }
352  }
353  keep = false;
354  }
355  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
356  (plen = mutt_str_startswith(np->data, "pgp:", CASE_IGNORE)))
357  {
358  msg->security = mutt_parse_crypt_hdr(np->data + plen, 0, APPLICATION_PGP);
359  if (msg->security)
360  msg->security |= APPLICATION_PGP;
361  keep = false;
362  }
363 
364  if (!keep)
365  {
366  STAILQ_REMOVE(&msg->env->userhdrs, np, ListNode, entries);
367  FREE(&np->data);
368  FREE(&np);
369  }
370  }
371 }
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:400
#define mutt_perror(...)
Definition: logging.h:89
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:606
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:311
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
struct Body * content
list of MIME parts
Definition: email.h:92
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:192
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:57
#define LONG_STRING
Definition: string2.h:36
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:105
The body of an email.
Definition: body.h:33
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, int mode, bool privacy)
Write out one RFC822 header line.
Definition: sendlib.c:2212
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
struct Body * mutt_make_file_attach(const char *path)
Create a file attachment.
Definition: sendlib.c:1591
struct Envelope * env
envelope information
Definition: email.h:91
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:360
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
#define PATH_MAX
Definition: mutt.h:46
time_t mutt_file_decrease_mtime(const char *f, struct stat *st)
Decrease a file&#39;s modification time by 1 second.
Definition: file.c:884
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
Ignore case when comparing strings.
Definition: string2.h:70
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:768
char * description
content-description
Definition: body.h:39
#define APPLICATION_PGP
Definition: ncrypt.h:129
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:166
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:200
char * data
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_parse_crypt_hdr(const char *p, int set_empty_signas, int crypt_app)
Parse a crypto header string.
Definition: postpone.c:448
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_error(...)
Definition: logging.h:88
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:53
char * path
Definition: email.h:93
#define FREE(x)
Definition: memory.h:46
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct Envelope * mutt_rfc822_read_header(FILE *f, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:971
#define STAILQ_SWAP(head1, head2, type)
Definition: queue.h:426
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct ListHead references
message references (in reverse order)
Definition: envelope.h:59
A List node for strings.
Definition: list.h:33
#define STAILQ_FIRST(head)
Definition: queue.h:348
#define WithCrypto
Definition: ncrypt.h:154
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:308
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
The header of an email.
Definition: envelope.h:32

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_make_label_hash ( struct Mailbox m)

Create a Hash Table to store the labels.

Parameters
mMailbox

Definition at line 377 of file mutt_header.c.

378 {
379  /* 131 is just a rough prime estimate of how many distinct
380  * labels someone might have in a m.
381  */
383 }
struct Hash * mutt_hash_new(size_t nelem, int flags)
Create a new Hash table (with string keys)
Definition: hash.c:278
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:75
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_label_hash_add ( struct Mailbox m,
struct Email e 
)

Add a message's labels to the Hash Table.

Parameters
mMailbox
eEmail

Definition at line 390 of file mutt_header.c.

391 {
392  if (!m || !m->label_hash)
393  return;
394  if (e->env->x_label)
395  label_ref_inc(m, e->env->x_label);
396 }
struct Envelope * env
envelope information
Definition: email.h:91
char * x_label
Definition: envelope.h:50
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123
static void label_ref_inc(struct Mailbox *m, char *label)
Increase the refcount of a label.
Definition: mutt_header.c:78

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_label_hash_remove ( struct Mailbox m,
struct Email e 
)

Rmove a message's labels from the Hash Table.

Parameters
mMailbox
eEmail

Definition at line 403 of file mutt_header.c.

404 {
405  if (!m || !m->label_hash)
406  return;
407  if (e->env->x_label)
408  label_ref_dec(m, e->env->x_label);
409 }
struct Envelope * env
envelope information
Definition: email.h:91
static void label_ref_dec(struct Mailbox *m, char *label)
Decrease the refcount of a label.
Definition: mutt_header.c:56
char * x_label
Definition: envelope.h:50
struct Hash * label_hash
hash table for x-labels
Definition: mailbox.h:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function: