NeoMutt  2019-12-07-60-g0cfa53
Teaching an old dog new tricks
DOXYGEN
protos.h File Reference

Prototypes for many functions. More...

#include "config.h"
#include <stddef.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include "mutt.h"
#include "keymap.h"
#include "ncrypt/ncrypt.h"
+ Include dependency graph for protos.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define mutt_set_flag(m, e, flag, bf)   mutt_set_flag_update(m, e, flag, bf, true)
 

Enumerations

enum  XdgType { XDG_CONFIG_HOME, XDG_CONFIG_DIRS }
 XDG variable types. More...
 
enum  EvMessage { EVM_VIEW, EVM_EDIT }
 Edit or View a message. More...
 

Functions

int mutt_ev_message (struct Mailbox *m, struct EmailList *el, enum EvMessage action)
 Edit or view a message. More...
 
int mutt_system (const char *cmd)
 Run an external command. More...
 
int mutt_set_xdg_path (enum XdgType type, char *buf, size_t bufsize)
 Find an XDG path or its fallback. More...
 
void mutt_help (enum MenuType menu, int wraplan)
 Display the help menu. More...
 
void mutt_make_help (char *d, size_t dlen, const char *txt, enum MenuType menu, int op)
 Create one entry for the help bar. More...
 
void mutt_set_flag_update (struct Mailbox *m, struct Email *e, int flag, bool bf, bool upd_mbox)
 Set a flag on an email. More...
 
void mutt_signal_init (void)
 Initialise the signal handling. More...
 
void mutt_emails_set_flag (struct Mailbox *m, struct EmailList *el, int flag, bool bf)
 Set flag on messages. More...
 
int mutt_change_flag (struct Mailbox *m, struct EmailList *el, bool bf)
 Change the flag on a Message. More...
 
int mutt_complete (char *buf, size_t buflen)
 Attempt to complete a partial pathname. More...
 
int mutt_prepare_template (FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
 Prepare a message template. More...
 
int mutt_enter_string (char *buf, size_t buflen, int col, CompletionFlags flags)
 Ask the user for a string. More...
 
int mutt_enter_string_full (char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, char ***files, int *numfiles, struct EnterState *state)
 Ask the user for a string. More...
 
int mutt_get_postponed (struct Context *ctx, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
 Recall a postponed message. More...
 
SecurityFlags mutt_parse_crypt_hdr (const char *p, bool set_empty_signas, SecurityFlags crypt_app)
 Parse a crypto header string. More...
 
int mutt_num_postponed (struct Mailbox *m, bool force)
 Return the number of postponed messages. More...
 
int mutt_thread_set_flag (struct Email *e, int flag, bool bf, bool subthread)
 Set a flag on an entire thread. More...
 
void mutt_update_num_postponed (void)
 Force the update of the number of postponed messages. More...
 
int mutt_is_quote_line (char *buf, regmatch_t *pmatch)
 Is a line of message text a quote? More...
 
int wcscasecmp (const wchar_t *a, const wchar_t *b)
 Compare two wide-character strings, ignoring case. More...
 
int mutt_reply_observer (struct NotifyCallback *nc)
 Listen for config changes to "reply_regex" - Implements observer_t() More...
 

Detailed Description

Prototypes for many functions.

Authors
  • Michael R. Elkins
  • Karel Zak

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

Macro Definition Documentation

◆ mutt_set_flag

#define mutt_set_flag (   m,
  e,
  flag,
  bf 
)    mutt_set_flag_update(m, e, flag, bf, true)

Definition at line 70 of file protos.h.

Enumeration Type Documentation

◆ XdgType

enum XdgType

XDG variable types.

Enumerator
XDG_CONFIG_HOME 

XDG home dir: ~/.config.

XDG_CONFIG_DIRS 

XDG system dir: /etc/xdg.

Definition at line 47 of file protos.h.

48 {
51 };
XDG home dir: ~/.config.
Definition: protos.h:49
XDG system dir: /etc/xdg.
Definition: protos.h:50

◆ EvMessage

enum EvMessage

Edit or View a message.

Enumerator
EVM_VIEW 

View the message.

EVM_EDIT 

Edit the message.

Definition at line 56 of file protos.h.

57 {
58  EVM_VIEW,
59  EVM_EDIT,
60 };
View the message.
Definition: protos.h:58
Edit the message.
Definition: protos.h:59

Function Documentation

◆ mutt_ev_message()

int mutt_ev_message ( struct Mailbox m,
struct EmailList *  el,
enum EvMessage  action 
)

Edit or view a message.

Parameters
mMailbox
elList of Emails
actionAction to perform, e.g. EVM_EDIT
Return values
1Message not modified
0Message edited successfully
-1Error

Definition at line 264 of file editmsg.c.

265 {
266  struct EmailNode *en = NULL;
267  STAILQ_FOREACH(en, el, entries)
268  {
269  if (ev_message(action, m, en->email) == -1)
270  return -1;
271  }
272 
273  return 0;
274 }
static int ev_message(enum EvMessage action, struct Mailbox *m, struct Email *e)
Edit an email or view it in an external editor.
Definition: editmsg.c:58
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Email * email
Email in the list.
Definition: email.h:116
List of Emails.
Definition: email.h:114
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_system()

int mutt_system ( const char *  cmd)

Run an external command.

Parameters
cmdCommand and arguments
Return values
-1Error
>=0Success (command's return code)

Fork and run an external command with arguments.

Note
This function won't return until the command finishes.

Definition at line 52 of file system.c.

53 {
54  int rc = -1;
55  struct sigaction act;
56  struct sigaction oldtstp;
57  struct sigaction oldcont;
58  pid_t pid;
59 
60  if (!cmd || !*cmd)
61  return 0;
62 
63  /* must ignore SIGINT and SIGQUIT */
64 
66 
67  act.sa_handler = SIG_DFL;
68 /* we want to restart the waitpid() below */
69 #ifdef SA_RESTART
70  act.sa_flags = SA_RESTART;
71 #endif
72  sigemptyset(&act.sa_mask);
73  sigaction(SIGTSTP, &act, &oldtstp);
74  sigaction(SIGCONT, &act, &oldcont);
75 
76  pid = fork();
77  if (pid == 0)
78  {
79  act.sa_flags = 0;
80 
81  /* reset signals for the child; not really needed, but... */
83  act.sa_handler = SIG_DFL;
84  act.sa_flags = 0;
85  sigemptyset(&act.sa_mask);
86  sigaction(SIGTERM, &act, NULL);
87  sigaction(SIGTSTP, &act, NULL);
88  sigaction(SIGCONT, &act, NULL);
89 
90  execle(EXEC_SHELL, "sh", "-c", cmd, NULL, mutt_envlist_getlist());
91  _exit(127); /* execl error */
92  }
93  else if (pid != -1)
94  {
95 #ifdef USE_IMAP
96  rc = imap_wait_keepalive(pid);
97 #endif
98  }
99 
100  sigaction(SIGCONT, &oldcont, NULL);
101  sigaction(SIGTSTP, &oldtstp, NULL);
102 
103  /* reset SIGINT, SIGQUIT and SIGCHLD */
105 
106  rc = (pid != -1) ? (WIFEXITED(rc) ? WEXITSTATUS(rc) : -1) : -1;
107 
108  return rc;
109 }
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:183
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
#define EXEC_SHELL
Definition: mutt.h:124
int imap_wait_keepalive(pid_t pid)
Wait for a process to change state.
Definition: util.c:1090
char ** mutt_envlist_getlist(void)
Get the private environment.
Definition: envlist.c:169
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_xdg_path()

int mutt_set_xdg_path ( enum XdgType  type,
char *  buf,
size_t  bufsize 
)

Find an XDG path or its fallback.

Parameters
typeType of XDG variable, e.g. XDG_CONFIG_HOME
bufBuffer to save path
bufsizeBuffer length
Return values
1if an entry was found that actually exists on disk and 0 otherwise

Process an XDG environment variable or its fallback.

Definition at line 1616 of file muttlib.c.

1617 {
1618  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1619  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1620  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1621  char *token = NULL;
1622  int rc = 0;
1623 
1624  while ((token = strsep(&xdg, ":")))
1625  {
1626  if (snprintf(buf, bufsize, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1627  continue;
1628  mutt_expand_path(buf, bufsize);
1629  if (access(buf, F_OK) == 0)
1630  {
1631  rc = 1;
1632  break;
1633  }
1634 
1635  if (snprintf(buf, bufsize, "%s/%s/Muttrc", token, PACKAGE) < 0)
1636  continue;
1637  mutt_expand_path(buf, bufsize);
1638  if (access(buf, F_OK) == 0)
1639  {
1640  rc = 1;
1641  break;
1642  }
1643  }
1644 
1645  FREE(&x);
1646  return rc;
1647 }
static const char * xdg_env_vars[]
Definition: muttlib.c:77
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1048
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:133
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
static const char * xdg_defaults[]
Definition: muttlib.c:82
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_help()

void mutt_help ( enum MenuType  menu,
int  wraplen 
)

Display the help menu.

Parameters
menuCurrent Menu
wraplenWidth to wrap to

Definition at line 443 of file help.c.

444 {
445  char buf[128];
446  FILE *fp = NULL;
447 
448  /* We don't use the buffer pool because of the extended lifetime of t */
449  struct Buffer t = mutt_buffer_make(PATH_MAX);
450  mutt_buffer_mktemp(&t);
451 
452  const struct Binding *funcs = km_get_table(menu);
453  const char *desc = mutt_map_get_name(menu, Menus);
454  if (!desc)
455  desc = _("<UNKNOWN>");
456 
457  do
458  {
459  fp = mutt_file_fopen(mutt_b2s(&t), "w");
460  if (!fp)
461  {
462  mutt_perror(mutt_b2s(&t));
463  goto cleanup;
464  }
465 
466  dump_menu(fp, menu, wraplen);
467  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
468  {
469  fprintf(fp, "\n%s\n\n", _("Generic bindings:"));
470  dump_menu(fp, MENU_GENERIC, wraplen);
471  }
472 
473  fprintf(fp, "\n%s\n\n", _("Unbound functions:"));
474  if (funcs)
475  dump_unbound(fp, funcs, Keymaps[menu], NULL, wraplen);
476  if (menu != MENU_PAGER)
477  dump_unbound(fp, OpGeneric, Keymaps[MENU_GENERIC], Keymaps[menu], wraplen);
478 
479  mutt_file_fclose(&fp);
480 
481  snprintf(buf, sizeof(buf), _("Help for %s"), desc);
482  } while (mutt_do_pager(buf, mutt_b2s(&t),
484  NULL) == OP_REFORMAT_WINCH);
485 
486 cleanup:
488 }
static void dump_unbound(FILE *fp, const struct Binding *funcs, struct Keymap *map, struct Keymap *aux, int wraplen)
Write out all the operations with no key bindings.
Definition: help.c:428
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
#define mutt_perror(...)
Definition: logging.h:85
struct Keymap * Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:147
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: pager.h:56
Pager pager (email viewer)
Definition: keymap.h:78
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define MUTT_PAGER_NSKIP
Preserve whitespace with smartwrap.
Definition: pager.h:52
#define mutt_b2s(buf)
Definition: buffer.h:41
const struct Mapping Menus[]
Menu name lookup table.
Definition: keymap.c:60
#define PATH_MAX
Definition: mutt.h:50
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.h:54
static void dump_menu(FILE *fp, enum MenuType menu, int wraplen)
Write all the key bindings to a file.
Definition: help.c:376
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: pager.h:54
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:664
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1221
Text entry area.
Definition: keymap.h:74
#define MUTT_PAGER_MARKER
Use markers if option is set.
Definition: pager.h:53
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
Mapping between a user key and a function.
Definition: keymap.h:114
Generic selection list.
Definition: keymap.h:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_help()

void mutt_make_help ( char *  buf,
size_t  buflen,
const char *  txt,
enum MenuType  menu,
int  op 
)

Create one entry for the help bar.

Parameters
bufBuffer for the result
buflenLength of buffer
txtText part, e.g. "delete"
menuCurrent Menu, e.g. MENU_PAGER
opOperation, e.g. OP_DELETE

This will return something like: "d:delete"

Definition at line 92 of file help.c.

93 {
94  char tmp[128];
95 
96  if (km_expand_key(tmp, sizeof(tmp), km_find_func(menu, op)) ||
97  km_expand_key(tmp, sizeof(tmp), km_find_func(MENU_GENERIC, op)))
98  {
99  snprintf(buf, buflen, "%s:%s", tmp, txt);
100  }
101  else
102  {
103  buf[0] = '\0';
104  }
105 }
int op
function id number
Definition: keymap.h:117
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:854
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:826
Generic selection list.
Definition: keymap.h:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_flag_update()

void mutt_set_flag_update ( struct Mailbox m,
struct Email e,
int  flag,
bool  bf,
bool  upd_mbox 
)

Set a flag on an email.

Parameters
mMailbox
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
upd_mboxtrue: update the Mailbox

Definition at line 54 of file flags.c.

55 {
56  if (!m || !e)
57  return;
58 
59  bool changed = e->changed;
60  int deleted = m->msg_deleted;
61  int tagged = m->msg_tagged;
62  int flagged = m->msg_flagged;
63  int update = false;
64 
65  if (m->readonly && (flag != MUTT_TAG))
66  return; /* don't modify anything if we are read-only */
67 
68  switch (flag)
69  {
70  case MUTT_DELETE:
71 
72  if (!(m->rights & MUTT_ACL_DELETE))
73  return;
74 
75  if (bf)
76  {
77  if (!e->deleted && !m->readonly && (!e->flagged || !C_FlagSafe))
78  {
79  e->deleted = true;
80  update = true;
81  if (upd_mbox)
82  m->msg_deleted++;
83 #ifdef USE_IMAP
84  /* deleted messages aren't treated as changed elsewhere so that the
85  * purge-on-sync option works correctly. This isn't applicable here */
86  if (m->magic == MUTT_IMAP)
87  {
88  e->changed = true;
89  if (upd_mbox)
90  m->changed = true;
91  }
92 #endif
93  }
94  }
95  else if (e->deleted)
96  {
97  e->deleted = false;
98  update = true;
99  if (upd_mbox)
100  m->msg_deleted--;
101 #ifdef USE_IMAP
102  /* see my comment above */
103  if (m->magic == MUTT_IMAP)
104  {
105  e->changed = true;
106  if (upd_mbox)
107  m->changed = true;
108  }
109 #endif
110  /* If the user undeletes a message which is marked as
111  * "trash" in the maildir folder on disk, the folder has
112  * been changed, and is marked accordingly. However, we do
113  * _not_ mark the message itself changed, because trashing
114  * is checked in specific code in the maildir folder
115  * driver. */
116  if ((m->magic == MUTT_MAILDIR) && upd_mbox && e->trash)
117  m->changed = true;
118  }
119  break;
120 
121  case MUTT_PURGE:
122 
123  if (!(m->rights & MUTT_ACL_DELETE))
124  return;
125 
126  if (bf)
127  {
128  if (!e->purge && !m->readonly)
129  e->purge = true;
130  }
131  else if (e->purge)
132  e->purge = false;
133  break;
134 
135  case MUTT_NEW:
136 
137  if (!(m->rights & MUTT_ACL_SEEN))
138  return;
139 
140  if (bf)
141  {
142  if (e->read || e->old)
143  {
144  update = true;
145  e->old = false;
146  if (upd_mbox)
147  m->msg_new++;
148  if (e->read)
149  {
150  e->read = false;
151  if (upd_mbox)
152  m->msg_unread++;
153  }
154  e->changed = true;
155  if (upd_mbox)
156  m->changed = true;
157  }
158  }
159  else if (!e->read)
160  {
161  update = true;
162  if (!e->old)
163  if (upd_mbox)
164  m->msg_new--;
165  e->read = true;
166  if (upd_mbox)
167  m->msg_unread--;
168  e->changed = true;
169  if (upd_mbox)
170  m->changed = true;
171  }
172  break;
173 
174  case MUTT_OLD:
175 
176  if (!(m->rights & MUTT_ACL_SEEN))
177  return;
178 
179  if (bf)
180  {
181  if (!e->old)
182  {
183  update = true;
184  e->old = true;
185  if (!e->read)
186  if (upd_mbox)
187  m->msg_new--;
188  e->changed = true;
189  if (upd_mbox)
190  m->changed = true;
191  }
192  }
193  else if (e->old)
194  {
195  update = true;
196  e->old = false;
197  if (!e->read)
198  if (upd_mbox)
199  m->msg_new++;
200  e->changed = true;
201  if (upd_mbox)
202  m->changed = true;
203  }
204  break;
205 
206  case MUTT_READ:
207 
208  if (!(m->rights & MUTT_ACL_SEEN))
209  return;
210 
211  if (bf)
212  {
213  if (!e->read)
214  {
215  update = true;
216  e->read = true;
217  if (upd_mbox)
218  m->msg_unread--;
219  if (!e->old)
220  if (upd_mbox)
221  m->msg_new--;
222  e->changed = true;
223  if (upd_mbox)
224  m->changed = true;
225  }
226  }
227  else if (e->read)
228  {
229  update = true;
230  e->read = false;
231  if (upd_mbox)
232  m->msg_unread++;
233  if (!e->old)
234  if (upd_mbox)
235  m->msg_new++;
236  e->changed = true;
237  if (upd_mbox)
238  m->changed = true;
239  }
240  break;
241 
242  case MUTT_REPLIED:
243 
244  if (!(m->rights & MUTT_ACL_WRITE))
245  return;
246 
247  if (bf)
248  {
249  if (!e->replied)
250  {
251  update = true;
252  e->replied = true;
253  if (!e->read)
254  {
255  e->read = true;
256  if (upd_mbox)
257  m->msg_unread--;
258  if (!e->old)
259  if (upd_mbox)
260  m->msg_new--;
261  }
262  e->changed = true;
263  if (upd_mbox)
264  m->changed = true;
265  }
266  }
267  else if (e->replied)
268  {
269  update = true;
270  e->replied = false;
271  e->changed = true;
272  if (upd_mbox)
273  m->changed = true;
274  }
275  break;
276 
277  case MUTT_FLAG:
278 
279  if (!(m->rights & MUTT_ACL_WRITE))
280  return;
281 
282  if (bf)
283  {
284  if (!e->flagged)
285  {
286  update = true;
287  e->flagged = bf;
288  if (upd_mbox)
289  m->msg_flagged++;
290  e->changed = true;
291  if (upd_mbox)
292  m->changed = true;
293  }
294  }
295  else if (e->flagged)
296  {
297  update = true;
298  e->flagged = false;
299  if (upd_mbox)
300  m->msg_flagged--;
301  e->changed = true;
302  if (upd_mbox)
303  m->changed = true;
304  }
305  break;
306 
307  case MUTT_TAG:
308  if (bf)
309  {
310  if (!e->tagged)
311  {
312  update = true;
313  e->tagged = true;
314  if (upd_mbox)
315  m->msg_tagged++;
316  }
317  }
318  else if (e->tagged)
319  {
320  update = true;
321  e->tagged = false;
322  if (upd_mbox)
323  m->msg_tagged--;
324  }
325  break;
326  }
327 
328  if (update)
329  {
330  mutt_set_header_color(m, e);
331 #ifdef USE_SIDEBAR
333 #endif
334  }
335 
336  /* if the message status has changed, we need to invalidate the cached
337  * search results so that any future search will match the current status
338  * of this message and not what it was at the time it was last searched. */
339  if (e->searched && ((changed != e->changed) || (deleted != m->msg_deleted) ||
340  (tagged != m->msg_tagged) || (flagged != m->msg_flagged)))
341  {
342  e->searched = false;
343  }
344 }
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:95
int msg_unread
Number of unread messages.
Definition: mailbox.h:91
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:92
Flagged messages.
Definition: mutt.h:106
bool changed
Email has been edited.
Definition: email.h:48
Messages to be purged (bypass trash)
Definition: mutt.h:104
bool searched
Email has been searched.
Definition: email.h:67
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:65
Messages that have been replied to.
Definition: mutt.h:99
#define REDRAW_SIDEBAR
Redraw the sidebar.
Definition: mutt_menu.h:51
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:104
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:118
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:73
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:50
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:60
Old messages.
Definition: mutt.h:98
Messages to be deleted.
Definition: mutt.h:102
Tagged messages.
Definition: mutt.h:107
New messages.
Definition: mutt.h:97
Messages that have been read.
Definition: mutt.h:100
bool purge
Skip trash folder when deleting.
Definition: email.h:46
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:96
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:120
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3921
bool flagged
Marked important?
Definition: email.h:43
int msg_new
Number of new messages.
Definition: mailbox.h:94
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:72
WHERE bool C_FlagSafe
Config: Protect flagged messages from deletion.
Definition: globals.h:211
bool changed
Mailbox has been modified.
Definition: mailbox.h:113
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_signal_init()

void mutt_signal_init ( void  )

Initialise the signal handling.

Definition at line 131 of file mutt_signal.c.

132 {
134 
135 #ifdef USE_SLANG_CURSES
136  /* This bit of code is required because of the implementation of
137  * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
138  * are in blocking mode, SLsys_getkey() will not return an error unless
139  * a handler function is defined and it returns -1. This is needed so
140  * that if the user resizes the screen while at a prompt, it will just
141  * abort and go back to the main-menu. */
142  SLang_getkey_intr_hook = mutt_intr_hook;
143 #endif
144 }
static void curses_signal_handler(int sig)
Catch signals and relay the info to the main program.
Definition: mutt_signal.c:48
static void curses_exit_handler(int sig)
Notify the user and shutdown gracefully.
Definition: mutt_signal.c:88
void mutt_sig_init(sig_handler_t sig_fn, sig_handler_t exit_fn, sig_handler_t segv_fn)
Initialise the signal handling.
Definition: signal.c:88
static void curses_segv_handler(int sig)
Catch a segfault and print a backtrace.
Definition: mutt_signal.c:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_emails_set_flag()

void mutt_emails_set_flag ( struct Mailbox m,
struct EmailList *  el,
int  flag,
bool  bf 
)

Set flag on messages.

Parameters
mMailbox
elList of Emails to flag
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag

Definition at line 353 of file flags.c.

354 {
355  if (!m || !el || STAILQ_EMPTY(el))
356  return;
357 
358  struct EmailNode *en = NULL;
359  STAILQ_FOREACH(en, el, entries)
360  {
361  mutt_set_flag(m, en->email, flag, bf);
362  }
363 }
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:70
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Email * email
Email in the list.
Definition: email.h:116
#define STAILQ_EMPTY(head)
Definition: queue.h:345
List of Emails.
Definition: email.h:114
+ Here is the caller graph for this function:

◆ mutt_change_flag()

int mutt_change_flag ( struct Mailbox m,
struct EmailList *  el,
bool  bf 
)

Change the flag on a Message.

Parameters
mMailbox
elList of Emails to change
bftrue: set the flag; false: clear the flag
Return values
0Success
-1Failure

Definition at line 432 of file flags.c.

433 {
434  if (!m || !el || STAILQ_EMPTY(el))
435  return -1;
436 
437  int flag;
438  struct KeyEvent event;
439 
441  "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
443  mutt_refresh();
444 
445  do
446  {
447  event = mutt_getch();
448  } while (event.ch == -2);
449  int i = event.ch;
450  if (i < 0)
451  {
453  return -1;
454  }
455 
457 
458  switch (i)
459  {
460  case 'd':
461  case 'D':
462  if (!bf)
463  mutt_emails_set_flag(m, el, MUTT_PURGE, bf);
464  flag = MUTT_DELETE;
465  break;
466 
467  case 'N':
468  case 'n':
469  flag = MUTT_NEW;
470  break;
471 
472  case 'o':
473  case 'O':
474  mutt_emails_set_flag(m, el, MUTT_READ, !bf);
475  flag = MUTT_OLD;
476  break;
477 
478  case 'r':
479  case 'R':
480  flag = MUTT_REPLIED;
481  break;
482 
483  case '*':
484  flag = MUTT_TAG;
485  break;
486 
487  case '!':
488  flag = MUTT_FLAG;
489  break;
490 
491  default:
492  mutt_beep(false);
493  return -1;
494  }
495 
496  mutt_emails_set_flag(m, el, flag, bf);
497  return 0;
498 }
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, int flag, bool bf)
Set flag on messages.
Definition: flags.c:353
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:135
Flagged messages.
Definition: mutt.h:106
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:104
Messages that have been replied to.
Definition: mutt.h:99
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:97
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:113
Old messages.
Definition: mutt.h:98
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:106
Messages to be deleted.
Definition: mutt.h:102
Tagged messages.
Definition: mutt.h:107
New messages.
Definition: mutt.h:97
Messages that have been read.
Definition: mutt.h:100
An event such as a keypress.
Definition: keymap.h:60
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:187
#define STAILQ_EMPTY(head)
Definition: queue.h:345
int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:312
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_complete()

int mutt_complete ( char *  buf,
size_t  buflen 
)

Attempt to complete a partial pathname.

Parameters
bufBuffer containing pathname
buflenLength of buffer
Return values
0if ok
-1if no matches

Given a partial pathname, fill in as much of the rest of the path as is unique.

Definition at line 57 of file complete.c.

58 {
59  char *p = NULL;
60  DIR *dirp = NULL;
61  struct dirent *de = NULL;
62  int init = 0;
63  size_t len;
64  struct Buffer *dirpart = NULL;
65  struct Buffer *exp_dirpart = NULL;
66  struct Buffer *filepart = NULL;
67  struct Buffer *tmp = NULL;
68 #ifdef USE_IMAP
69  struct Buffer *imap_path = NULL;
70  int rc;
71 #endif
72 
73  mutt_debug(LL_DEBUG2, "completing %s\n", buf);
74 
75 #ifdef USE_NNTP
76  if (OptNews)
77  return nntp_complete(buf, buflen);
78 #endif
79 
80 #ifdef USE_IMAP
81  imap_path = mutt_buffer_pool_get();
82  /* we can use '/' as a delimiter, imap_complete rewrites it */
83  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
84  {
85  if (*buf == '!')
86  p = NONULL(C_Spoolfile);
87  else
88  p = NONULL(C_Folder);
89 
90  mutt_buffer_concat_path(imap_path, p, buf + 1);
91  }
92  else
93  mutt_buffer_strcpy(imap_path, buf);
94 
95  if (imap_path_probe(mutt_b2s(imap_path), NULL) == MUTT_IMAP)
96  {
97  rc = imap_complete(buf, buflen, mutt_b2s(imap_path));
98  mutt_buffer_pool_release(&imap_path);
99  return rc;
100  }
101 
102  mutt_buffer_pool_release(&imap_path);
103 #endif
104 
105  dirpart = mutt_buffer_pool_get();
106  exp_dirpart = mutt_buffer_pool_get();
107  filepart = mutt_buffer_pool_get();
108  tmp = mutt_buffer_pool_get();
109 
110  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
111  {
112  mutt_buffer_addch(dirpart, *buf);
113  if (*buf == '!')
114  mutt_buffer_strcpy(exp_dirpart, NONULL(C_Spoolfile));
115  else
116  mutt_buffer_strcpy(exp_dirpart, NONULL(C_Folder));
117  p = strrchr(buf, '/');
118  if (p)
119  {
120  mutt_buffer_concatn_path(tmp, mutt_b2s(exp_dirpart), mutt_buffer_len(exp_dirpart),
121  buf + 1, (size_t)(p - buf - 1));
122  mutt_buffer_copy(exp_dirpart, tmp);
123  mutt_buffer_substrcpy(dirpart, buf, p + 1);
124  mutt_buffer_strcpy(filepart, p + 1);
125  }
126  else
127  mutt_buffer_strcpy(filepart, buf + 1);
128  dirp = opendir(mutt_b2s(exp_dirpart));
129  }
130  else
131  {
132  p = strrchr(buf, '/');
133  if (p)
134  {
135  if (p == buf) /* absolute path */
136  {
137  p = buf + 1;
138  mutt_buffer_strcpy(dirpart, "/");
139  mutt_buffer_strcpy(filepart, p);
140  dirp = opendir(mutt_b2s(dirpart));
141  }
142  else
143  {
144  mutt_buffer_substrcpy(dirpart, buf, p);
145  mutt_buffer_strcpy(filepart, p + 1);
146  mutt_buffer_copy(exp_dirpart, dirpart);
147  mutt_buffer_expand_path(exp_dirpart);
148  dirp = opendir(mutt_b2s(exp_dirpart));
149  }
150  }
151  else
152  {
153  /* no directory name, so assume current directory. */
154  mutt_buffer_strcpy(filepart, buf);
155  dirp = opendir(".");
156  }
157  }
158 
159  if (!dirp)
160  {
161  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", mutt_b2s(exp_dirpart),
162  strerror(errno), errno);
163  goto cleanup;
164  }
165 
166  /* special case to handle when there is no filepart yet. find the first
167  * file/directory which is not "." or ".." */
168  len = mutt_buffer_len(filepart);
169  if (len == 0)
170  {
171  while ((de = readdir(dirp)))
172  {
173  if ((mutt_str_strcmp(".", de->d_name) != 0) &&
174  (mutt_str_strcmp("..", de->d_name) != 0))
175  {
176  mutt_buffer_strcpy(filepart, de->d_name);
177  init++;
178  break;
179  }
180  }
181  }
182 
183  while ((de = readdir(dirp)))
184  {
185  if (mutt_str_strncmp(de->d_name, mutt_b2s(filepart), len) == 0)
186  {
187  if (init)
188  {
189  char *cp = filepart->data;
190 
191  for (int i = 0; (*cp != '\0') && (de->d_name[i] != '\0'); i++, cp++)
192  {
193  if (*cp != de->d_name[i])
194  break;
195  }
196  *cp = '\0';
197  mutt_buffer_fix_dptr(filepart);
198  }
199  else
200  {
201  struct stat st;
202 
203  mutt_buffer_strcpy(filepart, de->d_name);
204 
205  /* check to see if it is a directory */
206  if (mutt_buffer_is_empty(dirpart))
207  {
208  mutt_buffer_reset(tmp);
209  }
210  else
211  {
212  mutt_buffer_copy(tmp, exp_dirpart);
213  mutt_buffer_addch(tmp, '/');
214  }
215  mutt_buffer_addstr(tmp, mutt_b2s(filepart));
216  if ((stat(mutt_b2s(tmp), &st) != -1) && (st.st_mode & S_IFDIR))
217  mutt_buffer_addch(filepart, '/');
218  init = 1;
219  }
220  }
221  }
222  closedir(dirp);
223 
224  if (!mutt_buffer_is_empty(dirpart))
225  {
226  mutt_str_strfcpy(buf, mutt_b2s(dirpart), buflen);
227  if ((mutt_str_strcmp("/", mutt_b2s(dirpart)) != 0) &&
228  (mutt_b2s(dirpart)[0] != '=') && (mutt_b2s(dirpart)[0] != '+'))
229  {
230  mutt_str_strfcpy(buf + strlen(buf), "/", buflen - strlen(buf));
231  }
232  mutt_str_strfcpy(buf + strlen(buf), mutt_b2s(filepart), buflen - strlen(buf));
233  }
234  else
235  mutt_str_strfcpy(buf, mutt_b2s(filepart), buflen);
236 
237 cleanup:
238  mutt_buffer_pool_release(&dirpart);
239  mutt_buffer_pool_release(&exp_dirpart);
240  mutt_buffer_pool_release(&filepart);
242 
243  return init ? 0 : -1;
244 }
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2474
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
size_t mutt_buffer_substrcpy(struct Buffer *buf, const char *beg, const char *end)
Copy a partial string into a Buffer.
Definition: buffer.c:342
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
Log at debug level 2.
Definition: logging.h:41
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define mutt_b2s(buf)
Definition: buffer.h:41
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:119
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * data
Pointer to data.
Definition: buffer.h:35
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:750
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_concatn_path(struct Buffer *buf, const char *dir, size_t dirlen, const char *fname, size_t fnamelen)
Join a directory name and a filename.
Definition: buffer.c:411
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int nntp_complete(char *buf, size_t buflen)
Auto-complete NNTP newsgroups.
Definition: complete.c:45
int imap_complete(char *buf, size_t buflen, const char *path)
Try to complete an IMAP folder path.
Definition: imap.c:1448
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:342
Log at debug level 1.
Definition: logging.h:40
WHERE char * C_Spoolfile
Config: Inbox.
Definition: globals.h:144
int mutt_str_strncmp(const char *a, const char *b, size_t l)
Compare two strings (to a maximum), safely.
Definition: string.c:642
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prepare_template()

int mutt_prepare_template ( FILE *  fp,
struct Mailbox m,
struct Email e_new,
struct Email e,
bool  resend 
)

Prepare a message template.

Parameters
fpIf not NULL, file containing the template
mIf fp is NULL, the Mailbox containing the header with the template
e_newThe template is read into this Header
eEmail to recall/resend
resendSet if resending (as opposed to recalling a postponed msg) Resent messages enable header weeding, and also discard any existing Message-ID and Mail-Followup-To
Return values
0Success
-1Error

Definition at line 632 of file postpone.c.

634 {
635  struct Message *msg = NULL;
636  struct Body *b = NULL;
637  FILE *fp_body = NULL;
638  int rc = -1;
639  struct State s = { 0 };
640  SecurityFlags sec_type;
641  struct Envelope *protected_headers = NULL;
642 
643  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
644  return -1;
645 
646  if (!fp)
647  fp = msg->fp;
648 
649  fp_body = fp;
650 
651  /* parse the message header and MIME structure */
652 
653  fseeko(fp, e->offset, SEEK_SET);
654  e_new->offset = e->offset;
655  /* enable header weeding for resent messages */
656  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
657  e_new->content->length = e->content->length;
658  mutt_parse_part(fp, e_new->content);
659 
660  /* If resending a message, don't keep message_id or mail_followup_to.
661  * Otherwise, we are resuming a postponed message, and want to keep those
662  * headers if they exist. */
663  if (resend)
664  {
665  FREE(&e_new->env->message_id);
666  FREE(&e_new->env->mail_followup_to);
667  }
668 
669  /* decrypt pgp/mime encoded messages */
670 
671  if (((WithCrypto & APPLICATION_PGP) != 0) &&
672  (sec_type = mutt_is_multipart_encrypted(e_new->content)))
673  {
674  e_new->security |= sec_type;
675  if (!crypt_valid_passphrase(sec_type))
676  goto bail;
677 
678  mutt_message(_("Decrypting message..."));
679  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->content, &b) == -1) || !b)
680  {
681  goto bail;
682  }
683 
684  mutt_body_free(&e_new->content);
685  e_new->content = b;
686 
687  if (b->mime_headers)
688  {
689  protected_headers = b->mime_headers;
690  b->mime_headers = NULL;
691  }
692 
694  }
695 
696  /* remove a potential multipart/signed layer - useful when
697  * resending messages */
698  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->content))
699  {
700  e_new->security |= SEC_SIGN;
701  if (((WithCrypto & APPLICATION_PGP) != 0) &&
703  mutt_param_get(&e_new->content->parameter, "protocol"),
704  "application/pgp-signature") == 0))
705  {
706  e_new->security |= APPLICATION_PGP;
707  }
708  else if (WithCrypto & APPLICATION_SMIME)
709  e_new->security |= APPLICATION_SMIME;
710 
711  /* destroy the signature */
712  mutt_body_free(&e_new->content->parts->next);
713  e_new->content = mutt_remove_multipart(e_new->content);
714 
715  if (e_new->content->mime_headers)
716  {
717  mutt_env_free(&protected_headers);
718  protected_headers = e_new->content->mime_headers;
719  e_new->content->mime_headers = NULL;
720  }
721  }
722 
723  /* We don't need no primary multipart.
724  * Note: We _do_ preserve messages!
725  *
726  * XXX - we don't handle multipart/alternative in any
727  * smart way when sending messages. However, one may
728  * consider this a feature. */
729  if (e_new->content->type == TYPE_MULTIPART)
730  e_new->content = mutt_remove_multipart(e_new->content);
731 
732  s.fp_in = fp_body;
733 
734  struct Buffer *file = mutt_buffer_pool_get();
735 
736  /* create temporary files for all attachments */
737  for (b = e_new->content; b; b = b->next)
738  {
739  /* what follows is roughly a receive-mode variant of
740  * mutt_get_tmp_attachment () from muttlib.c */
741 
742  mutt_buffer_reset(file);
743  if (b->filename)
744  {
745  mutt_buffer_strcpy(file, b->filename);
747  }
748  else
749  {
750  /* avoid Content-Disposition: header with temporary filename */
751  b->use_disp = false;
752  }
753 
754  /* set up state flags */
755 
756  s.flags = 0;
757 
758  if (b->type == TYPE_TEXT)
759  {
760  if (mutt_str_strcasecmp("yes",
761  mutt_param_get(&b->parameter, "x-mutt-noconv")) == 0)
762  {
763  b->noconv = true;
764  }
765  else
766  {
767  s.flags |= MUTT_CHARCONV;
768  b->noconv = false;
769  }
770 
771  mutt_param_delete(&b->parameter, "x-mutt-noconv");
772  }
773 
774  mutt_adv_mktemp(file);
775  s.fp_out = mutt_file_fopen(mutt_b2s(file), "w");
776  if (!s.fp_out)
777  goto bail;
778 
779  if (((WithCrypto & APPLICATION_PGP) != 0) &&
780  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
781  {
782  if (sec_type & SEC_ENCRYPT)
783  {
784  if (!crypt_valid_passphrase(APPLICATION_PGP))
785  goto bail;
786  mutt_message(_("Decrypting message..."));
787  }
788 
789  if (mutt_body_handler(b, &s) < 0)
790  {
791  mutt_error(_("Decryption failed"));
792  goto bail;
793  }
794 
795  if ((b == e_new->content) && !protected_headers)
796  {
797  protected_headers = b->mime_headers;
798  b->mime_headers = NULL;
799  }
800 
801  e_new->security |= sec_type;
802  b->type = TYPE_TEXT;
803  mutt_str_replace(&b->subtype, "plain");
804  mutt_param_delete(&b->parameter, "x-action");
805  }
806  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
807  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
808  {
809  if (sec_type & SEC_ENCRYPT)
810  {
811  if (!crypt_valid_passphrase(APPLICATION_SMIME))
812  goto bail;
813  crypt_smime_getkeys(e_new->env);
814  mutt_message(_("Decrypting message..."));
815  }
816 
817  if (mutt_body_handler(b, &s) < 0)
818  {
819  mutt_error(_("Decryption failed"));
820  goto bail;
821  }
822 
823  e_new->security |= sec_type;
824  b->type = TYPE_TEXT;
825  mutt_str_replace(&b->subtype, "plain");
826  }
827  else
828  mutt_decode_attachment(b, &s);
829 
830  if (mutt_file_fclose(&s.fp_out) != 0)
831  goto bail;
832 
833  mutt_str_replace(&b->filename, mutt_b2s(file));
834  b->unlink = true;
835 
837 
838  mutt_body_free(&b->parts);
839  if (b->email)
840  b->email->content = NULL; /* avoid dangling pointer */
841  }
842 
843  if (C_CryptProtectedHeadersRead && protected_headers && protected_headers->subject &&
844  (mutt_str_strcmp(e_new->env->subject, protected_headers->subject) != 0))
845  {
846  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
847  }
848  mutt_env_free(&protected_headers);
849 
850  /* Fix encryption flags. */
851 
852  /* No inline if multipart. */
853  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->content->next)
854  e_new->security &= ~SEC_INLINE;
855 
856  /* Do we even support multiple mechanisms? */
857  e_new->security &= WithCrypto | ~(APPLICATION_PGP | APPLICATION_SMIME);
858 
859  /* Theoretically, both could be set. Take the one the user wants to set by default. */
860  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
861  {
862  if (C_SmimeIsDefault)
863  e_new->security &= ~APPLICATION_PGP;
864  else
865  e_new->security &= ~APPLICATION_SMIME;
866  }
867 
869 
870  rc = 0;
871 
872 bail:
873 
874  /* that's it. */
876  if (fp_body != fp)
877  mutt_file_fclose(&fp_body);
878  if (msg)
879  mx_msg_close(m, &msg);
880 
881  if (rc == -1)
882  {
883  mutt_env_free(&e_new->env);
884  mutt_body_free(&e_new->content);
885  }
886 
887  return rc;
888 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1795
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1448
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1772
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define mutt_message(...)
Definition: logging.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Body * content
List of MIME parts.
Definition: email.h:90
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_out
File to write to.
Definition: state.h:47
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:129
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
WHERE bool C_SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:273
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1140
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:145
char * message_id
Message ID.
Definition: envelope.h:69
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:451
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
struct Envelope * env
Envelope information.
Definition: email.h:89
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:410
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:485
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
char * subtype
content-type subtype
Definition: body.h:37
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
#define mutt_b2s(buf)
Definition: buffer.h:41
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:557
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:123
A local copy of an email.
Definition: mx.h:81
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:451
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:616
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:39
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:270
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type
Definition: body.h:65
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:83
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1406
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:203
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
FILE * fp
pointer to the message data
Definition: mx.h:83
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:95
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1551
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:120
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1136
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
#define WithCrypto
Definition: ncrypt.h:160
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1092
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:86
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string()

int mutt_enter_string ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags 
)

Ask the user for a string.

Parameters
bufBuffer to store the string
buflenBuffer length
colInitial cursor position
flagsFlags, see CompletionFlags
Return values
0if input was given
-1if abort

This function is for very basic input, currently used only by the built-in editor. It does not handle screen redrawing on resizes well, because there is no active menu for the built-in editor. Most callers should prefer mutt_get_field() instead.

Definition at line 144 of file enter.c.

145 {
146  int rc;
147  struct EnterState *es = mutt_enter_state_new();
148  do
149  {
150  if (SigWinch)
151  {
152  SigWinch = 0;
154  clearok(stdscr, true);
155  }
156  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
157  } while (rc == 1);
159  return rc;
160 }
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:100
int mutt_enter_string_full(char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, char ***files, int *numfiles, struct EnterState *state)
Ask the user for a string.
Definition: enter.c:176
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.h:80
Keep our place when entering a string.
Definition: enter_state.h:32
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: enter.c:820
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:125
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string_full()

int mutt_enter_string_full ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags,
bool  multiple,
char ***  files,
int *  numfiles,
struct EnterState state 
)

Ask the user for a string.

Parameters
[in]bufBuffer to store the string
[in]buflenBuffer length
[in]colInitial cursor position
[in]flagsFlags, see CompletionFlags
[in]multipleAllow multiple matches
[out]filesList of files selected
[out]numfilesNumber of files selected
[out]stateCurrent state (if function is called repeatedly)
Return values
1Redraw the screen and call the function again
0Selection made
-1Aborted

Definition at line 176 of file enter.c.

179 {
180  int width = MuttMessageWindow->state.cols - col - 1;
181  enum EnterRedrawFlags redraw = ENTER_REDRAW_NONE;
182  bool pass = (flags & MUTT_PASS);
183  bool first = true;
184  int ch;
185  wchar_t *tempbuf = NULL;
186  size_t templen = 0;
187  enum HistoryClass hclass;
188  int rc = 0;
189  mbstate_t mbstate;
190  memset(&mbstate, 0, sizeof(mbstate));
191 
192  if (state->wbuf)
193  {
194  /* Coming back after return 1 */
195  redraw = ENTER_REDRAW_LINE;
196  first = false;
197  }
198  else
199  {
200  /* Initialise wbuf from buf */
201  state->wbuflen = 0;
202  state->lastchar = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
203  redraw = ENTER_REDRAW_INIT;
204  }
205 
206  if (flags & MUTT_FILE)
207  hclass = HC_FILE;
208  else if (flags & MUTT_EFILE)
209  hclass = HC_MBOX;
210  else if (flags & MUTT_CMD)
211  hclass = HC_CMD;
212  else if (flags & MUTT_ALIAS)
213  hclass = HC_ALIAS;
214  else if (flags & MUTT_COMMAND)
215  hclass = HC_COMMAND;
216  else if (flags & MUTT_PATTERN)
217  hclass = HC_PATTERN;
218  else
219  hclass = HC_OTHER;
220 
221  while (true)
222  {
223  if (!pass)
224  {
225  if (redraw == ENTER_REDRAW_INIT)
226  {
227  /* Go to end of line */
228  state->curpos = state->lastchar;
229  state->begin = mutt_mb_width_ceiling(
230  state->wbuf, state->lastchar,
231  mutt_mb_wcswidth(state->wbuf, state->lastchar) - width + 1);
232  }
233  if ((state->curpos < state->begin) ||
234  (mutt_mb_wcswidth(state->wbuf + state->begin, state->curpos - state->begin) >= width))
235  {
236  state->begin = mutt_mb_width_ceiling(
237  state->wbuf, state->lastchar,
238  mutt_mb_wcswidth(state->wbuf, state->curpos) - (width / 2));
239  }
241  int w = 0;
242  for (size_t i = state->begin; i < state->lastchar; i++)
243  {
244  w += mutt_mb_wcwidth(state->wbuf[i]);
245  if (w > width)
246  break;
247  my_addwch(state->wbuf[i]);
248  }
251  col + mutt_mb_wcswidth(state->wbuf + state->begin,
252  state->curpos - state->begin));
253  }
254  mutt_refresh();
255 
256  ch = km_dokey(MENU_EDITOR);
257  if (ch < 0)
258  {
259  rc = (SigWinch && (ch == -2)) ? 1 : -1;
260  goto bye;
261  }
262 
263  if (ch != OP_NULL)
264  {
265  first = false;
266  if ((ch != OP_EDITOR_COMPLETE) && (ch != OP_EDITOR_COMPLETE_QUERY))
267  state->tabs = 0;
268  redraw = ENTER_REDRAW_LINE;
269  switch (ch)
270  {
271  case OP_EDITOR_HISTORY_UP:
272  state->curpos = state->lastchar;
273  if (mutt_hist_at_scratch(hclass))
274  {
275  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
276  mutt_hist_save_scratch(hclass, buf);
277  }
278  replace_part(state, 0, mutt_hist_prev(hclass));
279  redraw = ENTER_REDRAW_INIT;
280  break;
281 
282  case OP_EDITOR_HISTORY_DOWN:
283  state->curpos = state->lastchar;
284  if (mutt_hist_at_scratch(hclass))
285  {
286  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
287  mutt_hist_save_scratch(hclass, buf);
288  }
289  replace_part(state, 0, mutt_hist_next(hclass));
290  redraw = ENTER_REDRAW_INIT;
291  break;
292 
293  case OP_EDITOR_HISTORY_SEARCH:
294  state->curpos = state->lastchar;
295  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
296  mutt_hist_complete(buf, buflen, hclass);
297  replace_part(state, 0, buf);
298  rc = 1;
299  goto bye;
300  break;
301 
302  case OP_EDITOR_BACKSPACE:
303  if (state->curpos == 0)
304  {
305  // Pressing backspace when no text is in the command prompt should exit the prompt
306  if (state->lastchar == 0)
307  goto bye;
308  // Pressing backspace with text in the command prompt should just beep
309  mutt_beep(false);
310  }
311  else
312  {
313  size_t i = state->curpos;
314  while ((i > 0) && COMB_CHAR(state->wbuf[i - 1]))
315  i--;
316  if (i > 0)
317  i--;
318  memmove(state->wbuf + i, state->wbuf + state->curpos,
319  (state->lastchar - state->curpos) * sizeof(wchar_t));
320  state->lastchar -= state->curpos - i;
321  state->curpos = i;
322  }
323  break;
324 
325  case OP_EDITOR_BOL:
326  state->curpos = 0;
327  break;
328 
329  case OP_EDITOR_EOL:
330  redraw = ENTER_REDRAW_INIT;
331  break;
332 
333  case OP_EDITOR_KILL_LINE:
334  state->curpos = 0;
335  state->lastchar = 0;
336  break;
337 
338  case OP_EDITOR_KILL_EOL:
339  state->lastchar = state->curpos;
340  break;
341 
342  case OP_EDITOR_BACKWARD_CHAR:
343  if (state->curpos == 0)
344  mutt_beep(false);
345  else
346  {
347  while (state->curpos && COMB_CHAR(state->wbuf[state->curpos - 1]))
348  state->curpos--;
349  if (state->curpos)
350  state->curpos--;
351  }
352  break;
353 
354  case OP_EDITOR_FORWARD_CHAR:
355  if (state->curpos == state->lastchar)
356  mutt_beep(false);
357  else
358  {
359  state->curpos++;
360  while ((state->curpos < state->lastchar) &&
361  COMB_CHAR(state->wbuf[state->curpos]))
362  {
363  state->curpos++;
364  }
365  }
366  break;
367 
368  case OP_EDITOR_BACKWARD_WORD:
369  if (state->curpos == 0)
370  mutt_beep(false);
371  else
372  {
373  while (state->curpos && iswspace(state->wbuf[state->curpos - 1]))
374  state->curpos--;
375  while (state->curpos && !iswspace(state->wbuf[state->curpos - 1]))
376  state->curpos--;
377  }
378  break;
379 
380  case OP_EDITOR_FORWARD_WORD:
381  if (state->curpos == state->lastchar)
382  mutt_beep(false);
383  else
384  {
385  while ((state->curpos < state->lastchar) &&
386  iswspace(state->wbuf[state->curpos]))
387  {
388  state->curpos++;
389  }
390  while ((state->curpos < state->lastchar) &&
391  !iswspace(state->wbuf[state->curpos]))
392  {
393  state->curpos++;
394  }
395  }
396  break;
397 
398  case OP_EDITOR_CAPITALIZE_WORD:
399  case OP_EDITOR_UPCASE_WORD:
400  case OP_EDITOR_DOWNCASE_WORD:
401  if (state->curpos == state->lastchar)
402  {
403  mutt_beep(false);
404  break;
405  }
406  while (state->curpos && !iswspace(state->wbuf[state->curpos]))
407  state->curpos--;
408  while ((state->curpos < state->lastchar) && iswspace(state->wbuf[state->curpos]))
409  state->curpos++;
410  while ((state->curpos < state->lastchar) &&
411  !iswspace(state->wbuf[state->curpos]))
412  {
413  if (ch == OP_EDITOR_DOWNCASE_WORD)
414  state->wbuf[state->curpos] = towlower(state->wbuf[state->curpos]);
415  else
416  {
417  state->wbuf[state->curpos] = towupper(state->wbuf[state->curpos]);
418  if (ch == OP_EDITOR_CAPITALIZE_WORD)
419  ch = OP_EDITOR_DOWNCASE_WORD;
420  }
421  state->curpos++;
422  }
423  break;
424 
425  case OP_EDITOR_DELETE_CHAR:
426  if (state->curpos == state->lastchar)
427  mutt_beep(false);
428  else
429  {
430  size_t i = state->curpos;
431  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
432  i++;
433  if (i < state->lastchar)
434  i++;
435  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
436  i++;
437  memmove(state->wbuf + state->curpos, state->wbuf + i,
438  (state->lastchar - i) * sizeof(wchar_t));
439  state->lastchar -= i - state->curpos;
440  }
441  break;
442 
443  case OP_EDITOR_KILL_WORD:
444  /* delete to beginning of word */
445  if (state->curpos != 0)
446  {
447  size_t i = state->curpos;
448  while (i && iswspace(state->wbuf[i - 1]))
449  i--;
450  if (i > 0)
451  {
452  if (iswalnum(state->wbuf[i - 1]))
453  {
454  for (--i; (i > 0) && iswalnum(state->wbuf[i - 1]); i--)
455  ;
456  }
457  else
458  i--;
459  }
460  memmove(state->wbuf + i, state->wbuf + state->curpos,
461  (state->lastchar - state->curpos) * sizeof(wchar_t));
462  state->lastchar += i - state->curpos;
463  state->curpos = i;
464  }
465  break;
466 
467  case OP_EDITOR_KILL_EOW:
468  {
469  /* delete to end of word */
470 
471  /* first skip over whitespace */
472  size_t i;
473  for (i = state->curpos; (i < state->lastchar) && iswspace(state->wbuf[i]); i++)
474  ;
475 
476  /* if there are any characters left.. */
477  if (i < state->lastchar)
478  {
479  /* if the current character is alphanumeric.. */
480  if (iswalnum(state->wbuf[i]))
481  {
482  /* skip over the rest of the word consistent of only alphanumerics */
483  for (; (i < state->lastchar) && iswalnum(state->wbuf[i]); i++)
484  ;
485  }
486  else
487  {
488  /* skip over one non-alphanumeric character */
489  i++;
490  }
491  }
492 
493  memmove(state->wbuf + state->curpos, state->wbuf + i,
494  (state->lastchar - i) * sizeof(wchar_t));
495  state->lastchar += state->curpos - i;
496  break;
497  }
498 
499  case OP_EDITOR_MAILBOX_CYCLE:
500  if (flags & MUTT_EFILE)
501  {
502  first = true; /* clear input if user types a real key later */
503  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
504  mutt_mailbox_next(Context ? Context->mailbox : NULL, buf, buflen);
505  state->curpos = state->lastchar =
506  mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
507  break;
508  }
509  else if (!(flags & MUTT_FILE))
510  {
511  goto self_insert;
512  }
513  /* fallthrough */
514 
515  case OP_EDITOR_COMPLETE:
516  case OP_EDITOR_COMPLETE_QUERY:
517  state->tabs++;
518  if (flags & MUTT_CMD)
519  {
520  size_t i;
521  for (i = state->curpos;
522  (i > 0) && !mutt_mb_is_shell_char(state->wbuf[i - 1]); i--)
523  {
524  }
525  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
526  if (tempbuf && (templen == (state->lastchar - i)) &&
527  (memcmp(tempbuf, state->wbuf + i, (state->lastchar - i) * sizeof(wchar_t)) == 0))
528  {
529  mutt_select_file(buf, buflen, (flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : MUTT_SEL_NO_FLAGS,
530  NULL, NULL);
531  if (buf[0] != '\0')
532  replace_part(state, i, buf);
533  rc = 1;
534  goto bye;
535  }
536  if (mutt_complete(buf, buflen) == 0)
537  {
538  templen = state->lastchar - i;
539  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
540  }
541  else
542  mutt_beep(false);
543 
544  replace_part(state, i, buf);
545  }
546  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE))
547  {
548  /* invoke the alias-menu to get more addresses */
549  size_t i;
550  for (i = state->curpos;
551  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
552  {
553  }
554  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
555  ;
556  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
557  int rc2 = mutt_alias_complete(buf, buflen);
558  replace_part(state, i, buf);
559  if (rc2 != 1)
560  {
561  rc = 1;
562  goto bye;
563  }
564  break;
565  }
566  else if ((flags & MUTT_LABEL) && (ch == OP_EDITOR_COMPLETE))
567  {
568  size_t i;
569  for (i = state->curpos;
570  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
571  {
572  }
573  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
574  ;
575  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
576  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
577  replace_part(state, i, buf);
578  if (rc2 != 1)
579  {
580  rc = 1;
581  goto bye;
582  }
583  break;
584  }
585  else if ((flags & MUTT_PATTERN) && (ch == OP_EDITOR_COMPLETE))
586  {
587  size_t i;
588  for (i = state->curpos; (i > 0) && (state->wbuf[i - 1] != '~'); i--)
589  ;
590  if ((i > 0) && (i < state->curpos) && (state->wbuf[i - 1] == '~') &&
591  (state->wbuf[i] == 'y'))
592  {
593  i++;
594  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
595  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
596  replace_part(state, i, buf);
597  if (rc2 != 1)
598  {
599  rc = 1;
600  goto bye;
601  }
602  }
603  else
604  goto self_insert;
605  break;
606  }
607  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE_QUERY))
608  {
609  size_t i = state->curpos;
610  if (i != 0)
611  {
612  for (; (i > 0) && (state->wbuf[i - 1] != ','); i--)
613  ;
614  for (; (i < state->curpos) && (state->wbuf[i] == ' '); i++)
615  ;
616  }
617 
618  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
619  mutt_query_complete(buf, buflen);
620  replace_part(state, i, buf);
621 
622  rc = 1;
623  goto bye;
624  }
625  else if (flags & MUTT_COMMAND)
626  {
627  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
628  size_t i = strlen(buf);
629  if ((i != 0) && (buf[i - 1] == '=') &&
630  (mutt_var_value_complete(buf, buflen, i) != 0))
631  {
632  state->tabs = 0;
633  }
634  else if (mutt_command_complete(buf, buflen, i, state->tabs) == 0)
635  mutt_beep(false);
636  replace_part(state, 0, buf);
637  }
638  else if (flags & (MUTT_FILE | MUTT_EFILE))
639  {
640  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
641 
642  /* see if the path has changed from the last time */
643  if ((!tempbuf && !state->lastchar) ||
644  (tempbuf && (templen == state->lastchar) &&
645  (memcmp(tempbuf, state->wbuf, state->lastchar * sizeof(wchar_t)) == 0)))
646  {
647  mutt_select_file(buf, buflen,
648  ((flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : MUTT_SEL_NO_FLAGS) |
649  (multiple ? MUTT_SEL_MULTI : MUTT_SEL_NO_FLAGS),
650  files, numfiles);
651  if (buf[0] != '\0')
652  {
653  mutt_pretty_mailbox(buf, buflen);
654  if (!pass)
655  mutt_hist_add(hclass, buf, true);
656  rc = 0;
657  goto bye;
658  }
659 
660  /* file selection cancelled */
661  rc = 1;
662  goto bye;
663  }
664 
665  if (mutt_complete(buf, buflen) == 0)
666  {
667  templen = state->lastchar;
668  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
669  memcpy(tempbuf, state->wbuf, templen * sizeof(wchar_t));
670  }
671  else
672  mutt_beep(false); /* let the user know that nothing matched */
673  replace_part(state, 0, buf);
674  }
675 #ifdef USE_NOTMUCH
676  else if (flags & MUTT_NM_QUERY)
677  {
678  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
679  size_t len = strlen(buf);
680  if (!mutt_nm_query_complete(buf, buflen, len, state->tabs))
681  mutt_beep(false);
682 
683  replace_part(state, 0, buf);
684  }
685  else if (flags & MUTT_NM_TAG)
686  {
687  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
688  if (!mutt_nm_tag_complete(buf, buflen, state->tabs))
689  mutt_beep(false);
690 
691  replace_part(state, 0, buf);
692  }
693 #endif
694  else
695  goto self_insert;
696  break;
697 
698  case OP_EDITOR_QUOTE_CHAR:
699  {
700  struct KeyEvent event;
701  do
702  {
703  event = mutt_getch();
704  } while (event.ch == -2);
705  if (event.ch >= 0)
706  {
707  LastKey = event.ch;
708  goto self_insert;
709  }
710  break;
711  }
712 
713  case OP_EDITOR_TRANSPOSE_CHARS:
714  if (state->lastchar < 2)
715  mutt_beep(false);
716  else
717  {
718  wchar_t t;
719 
720  if (state->curpos == 0)
721  state->curpos = 2;
722  else if (state->curpos < state->lastchar)
723  state->curpos++;
724 
725  t = state->wbuf[state->curpos - 2];
726  state->wbuf[state->curpos - 2] = state->wbuf[state->curpos - 1];
727  state->wbuf[state->curpos - 1] = t;
728  }
729  break;
730 
731  default:
732  mutt_beep(false);
733  }
734  }
735  else
736  {
737  self_insert:
738  state->tabs = 0;
739  wchar_t wc;
740  /* use the raw keypress */
741  ch = LastKey;
742 
743  /* quietly ignore all other function keys */
744  if (ch & ~0xff)
745  continue;
746 
747  /* gather the octets into a wide character */
748  {
749  char c = ch;
750  size_t k = mbrtowc(&wc, &c, 1, &mbstate);
751  if (k == (size_t)(-2))
752  continue;
753  else if ((k != 0) && (k != 1))
754  {
755  memset(&mbstate, 0, sizeof(mbstate));
756  continue;
757  }
758  }
759 
760  if (first && (flags & MUTT_CLEAR))
761  {
762  first = false;
763  if (IsWPrint(wc)) /* why? */
764  {
765  state->curpos = 0;
766  state->lastchar = 0;
767  }
768  }
769 
770  if ((wc == '\r') || (wc == '\n'))
771  {
772  /* Convert from wide characters */
773  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->lastchar);
774  if (!pass)
775  mutt_hist_add(hclass, buf, true);
776 
777  if (multiple)
778  {
779  char **tfiles = NULL;
780  *numfiles = 1;
781  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
782  mutt_expand_path(buf, buflen);
783  tfiles[0] = mutt_str_strdup(buf);
784  *files = tfiles;
785  }
786  rc = 0;
787  goto bye;
788  }
789  else if (wc && ((wc < ' ') || IsWPrint(wc))) /* why? */
790  {
791  if (state->lastchar >= state->wbuflen)
792  {
793  state->wbuflen = state->lastchar + 20;
794  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
795  }
796  memmove(state->wbuf + state->curpos + 1, state->wbuf + state->curpos,
797  (state->lastchar - state->curpos) * sizeof(wchar_t));
798  state->wbuf[state->curpos++] = wc;
799  state->lastchar++;
800  }
801  else
802  {
803  mutt_flushinp();
804  mutt_beep(false);
805  }
806  }
807  }
808 
809 bye:
810 
811  mutt_hist_reset_state(hclass);
812  FREE(&tempbuf);
813  return rc;
814 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:617
The "current" mailbox.
Definition: context.h:36
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
wchar_t * wbuf
Definition: enter_state.h:34
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:68
Miscellaneous strings.
Definition: history.h:46
char * mutt_hist_next(enum HistoryClass hclass)
Get the next string in a History.
Definition: history.c:516
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:63
#define IsWPrint(wc)
Definition: mbyte.h:40
NeoMutt commands.
Definition: history.h:43
HistoryClass
Type to differentiate different histories.
Definition: history.h:39
void mutt_hist_complete(char *buf, size_t buflen, enum HistoryClass hclass)
Complete a string from a history list.
Definition: mutt_history.c:167
int mutt_label_complete(char *buf, size_t buflen, int numtabs)
Complete a label name.
Definition: init.c:3556
#define MUTT_LABEL
Do label completion.
Definition: mutt.h:71
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:919
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:135
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:479
size_t wbuflen
Definition: enter_state.h:35
bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:3677
#define MUTT_NM_QUERY
Notmuch query mode.
Definition: mutt.h:72
Mailboxes.
Definition: history.h:47
int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete a command name.
Definition: init.c:3386
int ch
raw key pressed
Definition: keymap.h:62
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:44
size_t mutt_mb_width_ceiling(const wchar_t *s, size_t n, int w1)
Keep the end of the string on-screen.
Definition: mbyte.c:217
bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:3620
External commands.
Definition: history.h:41
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:70
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:47
void mutt_mb_wcstombs(char *dest, size_t dlen, const wchar_t *src, size_t slen)
Convert a string from wide to multibyte characters.
Definition: mbyte.c:237
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:97
Aliases.
Definition: history.h:42
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:133
struct Mailbox * mailbox
Definition: context.h:50
#define MUTT_NM_TAG
Notmuch tag +/- mode.
Definition: mutt.h:73
int LastKey
contains the last key the user pressed
Definition: keymap.c:145
int mutt_mb_wcswidth(const wchar_t *s, size_t n)
Measure the screen width of a string.
Definition: mbyte.c:196
#define MUTT_COMMAND
Do command completion.
Definition: mutt.h:69
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.h:80
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:56
Patterns.
Definition: history.h:45
#define MUTT_CMD
Do completion on previous word.
Definition: mutt.h:66
size_t begin
Definition: enter_state.h:38
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:106
Nothing to redraw.
Definition: enter.c:57
#define MUTT_PASS
Password mode (no echo)
Definition: mutt.h:67
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
bool mutt_hist_at_scratch(enum HistoryClass hclass)
Is the current History position at the &#39;scratch&#39; place?
Definition: history.c:634
void mutt_select_file(char *file, size_t filelen, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:2255
void mutt_hist_save_scratch(enum HistoryClass hclass, const char *str)
Save a temporary string to the History.
Definition: history.c:651
void mutt_mailbox_next(struct Mailbox *m_cur, char *s, size_t slen)
incoming folders completion routine
Definition: mutt_mailbox.c:335
int mutt_query_complete(char *buf, size_t buflen)
Perform auto-complete using an Address Query.
Definition: query.c:652
static int my_addwch(wchar_t wc)
Display one wide character on screen.
Definition: enter.c:71
An event such as a keypress.
Definition: keymap.h:60
size_t curpos
Definition: enter_state.h:37
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:627
int mutt_alias_complete(char *buf, size_t buflen)
alias completion routine
Definition: alias.c:603
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:187
#define COMB_CHAR(wc)
Definition: enter.c:63
static void replace_part(struct EnterState *state, size_t from, char *buf)
Search and replace on a buffer.
Definition: enter.c:89
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:46
#define MUTT_FILE
Do file completion.
Definition: mutt.h:64
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:279
char * mutt_hist_prev(enum HistoryClass hclass)
Get the previous string in a History.
Definition: history.c:543
int mutt_complete(char *buf, size_t buflen)
Attempt to complete a partial pathname.
Definition: complete.c:57
EnterRedrawFlags
redraw flags for mutt_enter_string_full()
Definition: enter.c:55
bool mutt_mb_is_shell_char(wchar_t ch)
Is character not typically part of a pathname.
Definition: mbyte.c:344
size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf)
Convert a string from multibyte to wide characters.
Definition: mbyte.c:295
Go to end of line and redraw.
Definition: enter.c:58
#define MUTT_EFILE
Do file completion, plus incoming folders.
Definition: mutt.h:65
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
Redraw entire line.
Definition: enter.c:59
#define FREE(x)
Definition: memory.h:40
int mutt_mb_wcwidth(wchar_t wc)
Measure the screen width of a character.
Definition: mbyte.c:178
Text entry area.
Definition: keymap.h:74
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:47
void mutt_hist_reset_state(enum HistoryClass hclass)
Move the &#39;current&#39; position to the end of the History.
Definition: history.c:570
size_t lastchar
Definition: enter_state.h:36
Files.
Definition: history.h:44
int mutt_var_value_complete(char *buf, size_t buflen, int pos)
Complete a variable/value.
Definition: init.c:3730
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_postponed()

int mutt_get_postponed ( struct Context ctx,
struct Email hdr,
struct Email **  cur,
struct Buffer fcc 
)

Recall a postponed message.

Parameters
[in]ctxContext info, used when recalling a message to which we reply
[in]hdrenvelope/attachment info for recalled message
[out]curif message was a reply, 'cur' is set to the message which 'hdr' is in reply to
[in]fccfcc for the recalled message
Return values
-1Error/no messages
0Normal exit
SEND_REPLYRecalled message is a reply

Definition at line 328 of file postpone.c.

330 {
331  if (!C_Postponed)
332  return -1;
333 
334  struct Email *e = NULL;
335  int rc = SEND_POSTPONED;
336  const char *p = NULL;
337  struct Context *ctx_post = NULL;
338 
339  struct Mailbox *m = mx_path_resolve(C_Postponed);
340  if (ctx && (ctx->mailbox == m))
341  ctx_post = ctx;
342  else
343  ctx_post = mx_mbox_open(m, MUTT_NOSORT);
344 
345  if (!ctx_post)
346  {
347  PostCount = 0;
348  mutt_error(_("No postponed messages"));
349  mailbox_free(&m);
350  return -1;
351  }
352 
353  if (ctx_post->mailbox->msg_count == 0)
354  {
355  PostCount = 0;
356  if (ctx_post == ctx)
357  ctx_post = NULL;
358  else
359  mx_mbox_close(&ctx_post);
360  mutt_error(_("No postponed messages"));
361  return -1;
362  }
363 
364  if (ctx_post->mailbox->msg_count == 1)
365  {
366  /* only one message, so just use that one. */
367  e = ctx_post->mailbox->emails[0];
368  }
369  else if (!(e = select_msg(ctx_post)))
370  {
371  if (ctx_post == ctx)
372  ctx_post = NULL;
373  else
374  mx_mbox_close(&ctx_post);
375  return -1;
376  }
377 
378  if (mutt_prepare_template(NULL, ctx_post->mailbox, hdr, e, false) < 0)
379  {
380  if (ctx_post != ctx)
381  {
382  mx_fastclose_mailbox(ctx_post->mailbox);
383  FREE(&ctx_post);
384  }
385  return -1;
386  }
387 
388  /* finished with this message, so delete it. */
389  mutt_set_flag(ctx_post->mailbox, e, MUTT_DELETE, true);
390  mutt_set_flag(ctx_post->mailbox, e, MUTT_PURGE, true);
391 
392  /* update the count for the status display */
393  PostCount = ctx_post->mailbox->msg_count - ctx_post->mailbox->msg_deleted;
394 
395  /* avoid the "purge deleted messages" prompt */
396  int opt_delete = C_Delete;
397  C_Delete = MUTT_YES;
398  if (ctx_post == ctx)
399  ctx_post = NULL;
400  else
401  mx_mbox_close(&ctx_post);
402  C_Delete = opt_delete;
403 
404  struct ListNode *np = NULL, *tmp = NULL;
405  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
406  {
407  size_t plen = mutt_str_startswith(np->data, "X-Mutt-References:", CASE_IGNORE);
408  if (plen)
409  {
410  /* if a mailbox is currently open, look to see if the original message
411  * the user attempted to reply to is in this mailbox */
412  p = mutt_str_skip_email_wsp(np->data + plen);
413  if (!ctx->mailbox->id_hash)
415  *cur = mutt_hash_find(ctx->mailbox->id_hash, p);
416 
417  if (*cur)
418  rc |= SEND_REPLY;
419  }
420  else if ((plen = mutt_str_startswith(np->data, "X-Mutt-Fcc:", CASE_IGNORE)))
421  {
422  p = mutt_str_skip_email_wsp(np->data + plen);
423  mutt_buffer_strcpy(fcc, p);
425 
426  /* note that x-mutt-fcc was present. we do this because we want to add a
427  * default fcc if the header was missing, but preserve the request of the
428  * user to not make a copy if the header field is present, but empty.
429  * see http://dev.mutt.org/trac/ticket/3653 */
430  rc |= SEND_POSTPONED_FCC;
431  }
432  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
433  /* this is generated by old neomutt versions */
434  (mutt_str_startswith(np->data, "Pgp:", CASE_MATCH) ||
435  /* this is the new way */
436  mutt_str_startswith(np->data, "X-Mutt-PGP:", CASE_MATCH)))
437  {
438  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
439  hdr->security |= APPLICATION_PGP;
440  }
441  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
442  mutt_str_startswith(np->data, "X-Mutt-SMIME:", CASE_MATCH))
443  {
444  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
445  hdr->security |= APPLICATION_SMIME;
446  }
447 #ifdef MIXMASTER
448  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:", CASE_MATCH))
449  {
450  mutt_list_free(&hdr->chain);
451 
452  char *t = strtok(np->data + 11, " \t\n");
453  while (t)
454  {
455  mutt_list_insert_tail(&hdr->chain, mutt_str_strdup(t));
456  t = strtok(NULL, " \t\n");
457  }
458  }
459 #endif
460  else
461  {
462  // skip header removal
463  continue;
464  }
465 
466  // remove the header
467  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
468  FREE(&np->data);
469  FREE(&np);
470  }
471 
474 
475  return rc;
476 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:98
The "current" mailbox.
Definition: context.h:36
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
int msg_count
Total number of messages.
Definition: mailbox.h:90
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:70
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:97
The envelope/body of an email.
Definition: email.h:37
static struct Email * select_msg(struct Context *ctx)
Create a Menu to select a postponed message.
Definition: postpone.c:221
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:95
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:583
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:378
WHERE unsigned char C_Delete
Config: Really delete messages, when the mailbox is closed.
Definition: globals.h:180
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
#define _(a)
Definition: message.h:28
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:253
Messages to be purged (bypass trash)
Definition: mutt.h:104
Match case when comparing strings.
Definition: string2.h:67
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:92
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:703
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
struct Envelope * env
Envelope information.
Definition: email.h:89
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:412
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:269
Messages to be deleted.
Definition: mutt.h:102
A mailbox.
Definition: mailbox.h:80
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:51
static short PostCount
Definition: postpone.c:75
Ignore case when comparing strings.
Definition: string2.h:68
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:39
#define SEND_REPLY
Reply to sender.
Definition: send.h:88
struct Hash * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1456
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
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:168
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition: postpone.c:485
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1028
char * data
String.
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1603
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:134
A List node for strings.
Definition: list.h:33
#define WithCrypto
Definition: ncrypt.h:160
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:632
struct Hash * id_hash
Hash table by msg id.
Definition: mailbox.h:126
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_crypt_hdr()

SecurityFlags mutt_parse_crypt_hdr ( const char *  p,
bool  set_empty_signas,
SecurityFlags  crypt_app 
)

Parse a crypto header string.

Parameters
pHeader string to parse
set_empty_signasAllow an empty "Sign as"
crypt_appApp, e.g. APPLICATION_PGP
Return values
numSecurityFlags, see SecurityFlags

Definition at line 485 of file postpone.c.

486 {
487  char smime_cryptalg[1024] = { 0 };
488  char sign_as[1024] = { 0 };
489  char *q = NULL;
490  SecurityFlags flags = SEC_NO_FLAGS;
491 
492  if (!WithCrypto)
493  return SEC_NO_FLAGS;
494 
496  for (; p[0] != '\0'; p++)
497  {
498  switch (p[0])
499  {
500  case 'c':
501  case 'C':
502  q = smime_cryptalg;
503 
504  if (p[1] == '<')
505  {
506  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
507  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
508  *q++ = *p++)
509  {
510  }
511 
512  if (p[0] != '>')
513  {
514  mutt_error(_("Illegal S/MIME header"));
515  return SEC_NO_FLAGS;
516  }
517  }
518 
519  *q = '\0';
520  break;
521 
522  case 'e':
523  case 'E':
524  flags |= SEC_ENCRYPT;
525  break;
526 
527  case 'i':
528  case 'I':
529  flags |= SEC_INLINE;
530  break;
531 
532  /* This used to be the micalg parameter.
533  *
534  * It's no longer needed, so we just skip the parameter in order
535  * to be able to recall old messages. */
536  case 'm':
537  case 'M':
538  if (p[1] == '<')
539  {
540  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
541  ;
542  if (p[0] != '>')
543  {
544  mutt_error(_("Illegal crypto header"));
545  return SEC_NO_FLAGS;
546  }
547  }
548 
549  break;
550 
551  case 'o':
552  case 'O':
553  flags |= SEC_OPPENCRYPT;
554  break;
555 
556  case 'a':
557  case 'A':
558 #ifdef USE_AUTOCRYPT
559  flags |= SEC_AUTOCRYPT;
560 #endif
561  break;
562 
563  case 'z':
564  case 'Z':
565 #ifdef USE_AUTOCRYPT
566  flags |= SEC_AUTOCRYPT_OVERRIDE;
567 #endif
568  break;
569 
570  case 's':
571  case 'S':
572  flags |= SEC_SIGN;
573  q = sign_as;
574 
575  if (p[1] == '<')
576  {
577  for (p += 2;
578  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
579  *q++ = *p++)
580  {
581  }
582 
583  if (p[0] != '>')
584  {
585  mutt_error(_("Illegal crypto header"));
586  return SEC_NO_FLAGS;
587  }
588  }
589 
590  q[0] = '\0';
591  break;
592 
593  default:
594  mutt_error(_("Illegal crypto header"));
595  return SEC_NO_FLAGS;
596  }
597  }
598 
599  /* the cryptalg field must not be empty */
600  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
601  mutt_str_replace(&C_SmimeEncryptWith, smime_cryptalg);
602 
603  /* Set {Smime,Pgp}SignAs, if desired. */
604 
605  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
606  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
607  {
608  mutt_str_replace(&C_PgpSignAs, sign_as);
609  }
610 
611  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
612  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
613  {
614  mutt_str_replace(&C_SmimeSignAs, sign_as);
615  }
616 
617  return flags;
618 }
#define SEC_AUTOCRYPT
Message will be, or was Autocrypt encrypt+signed.
Definition: ncrypt.h:131
#define SEC_AUTOCRYPT_OVERRIDE
Indicates manual set/unset of encryption.
Definition: ncrypt.h:132
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:121
#define _(a)
Definition: message.h:28
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:129
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:123
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:165
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:130
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
#define mutt_error(...)
Definition: logging.h:84
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:120
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:160
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:164
#define WithCrypto
Definition: ncrypt.h:160
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_num_postponed()

int mutt_num_postponed ( struct Mailbox m,
bool  force 
)

Return the number of postponed messages.

Parameters
mcurrently selected mailbox
force
  • false Use a cached value if costly to get a fresh count (IMAP)
  • true Force check
Return values
numPostponed messages

Definition at line 86 of file postpone.c.

87 {
88  struct stat st;
89 
90  static time_t LastModify = 0;
91  static char *OldPostponed = NULL;
92 
94  {
95  UpdateNumPostponed = false;
96  force = true;
97  }
98 
99  if (mutt_str_strcmp(C_Postponed, OldPostponed) != 0)
100  {
101  FREE(&OldPostponed);
102  OldPostponed = mutt_str_strdup(C_Postponed);
103  LastModify = 0;
104  force = true;
105  }
106 
107  if (!C_Postponed)
108  return 0;
109 
110  // We currently are in the C_Postponed mailbox so just pick the current status
111  if (m && (mutt_str_strcmp(C_Postponed, m->realpath) == 0))
112  {
113  PostCount = m->msg_count - m->msg_deleted;
114  return PostCount;
115  }
116 
117 #ifdef USE_IMAP
118  /* LastModify is useless for IMAP */
119  if (imap_path_probe(C_Postponed, NULL) == MUTT_IMAP)
120  {
121  if (force)
122  {
123  short newpc;
124 
125  newpc = imap_path_status(C_Postponed, false);
126  if (newpc >= 0)
127  {
128  PostCount = newpc;
129  mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", PostCount);
130  }
131  else
132  mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
133  }
134  return PostCount;
135  }
136 #endif
137 
138  if (stat(C_Postponed, &st) == -1)
139  {
140  PostCount = 0;
141  LastModify = 0;
142  return 0;
143  }
144 
145  if (S_ISDIR(st.st_mode))
146  {
147  /* if we have a maildir mailbox, we need to stat the "new" dir */
148  struct Buffer *buf = mutt_buffer_pool_get();
149 
150  mutt_buffer_printf(buf, "%s/new", C_Postponed);
151  if ((access(mutt_b2s(buf), F_OK) == 0) && (stat(mutt_b2s(buf), &st) == -1))
152  {
153  PostCount = 0;
154  LastModify = 0;
156  return 0;
157  }
159  }
160 
161  if (LastModify < st.st_mtime)
162  {
163 #ifdef USE_NNTP
164  int optnews = OptNews;
165 #endif
166  LastModify = st.st_mtime;
167 
168  if (access(C_Postponed, R_OK | F_OK) != 0)
169  return PostCount = 0;
170 #ifdef USE_NNTP
171  if (optnews)
172  OptNews = false;
173 #endif
174  struct Mailbox *m_post = mx_path_resolve(C_Postponed);
175  struct Context *ctx = mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET);
176  if (ctx)
177  {
178  PostCount = ctx->mailbox->msg_count;
179  }
180  else
181  {
182  mailbox_free(&m_post);
183  PostCount = 0;
184  }
185  mx_fastclose_mailbox(m_post);
186  ctx_free(&ctx);
187 #ifdef USE_NNTP
188  if (optnews)
189  OptNews = true;
190 #endif
191  }
192 
193  return PostCount;
194 }
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:90
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1310
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2474
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:95
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:253
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:412
#define mutt_b2s(buf)
Definition: buffer.h:41
A mailbox.
Definition: mailbox.h:80
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:51
static short PostCount
Definition: postpone.c:75
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:54
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1603
static bool UpdateNumPostponed
Definition: postpone.c:76
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:134
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_set_flag()

int mutt_thread_set_flag ( struct Email e,
int  flag,
bool  bf,
bool  subthread 
)

Set a flag on an entire thread.

Parameters
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
subthreadIf true apply to all of the thread
Return values
0Success
-1Failure

Definition at line 374 of file flags.c.

375 {
376  struct MuttThread *start = NULL;
377  struct MuttThread *cur = e->thread;
378 
379  if ((C_Sort & SORT_MASK) != SORT_THREADS)
380  {
381  mutt_error(_("Threading is not enabled"));
382  return -1;
383  }
384 
385  if (!subthread)
386  while (cur->parent)
387  cur = cur->parent;
388  start = cur;
389 
390  if (cur->message && (cur != e->thread))
391  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
392 
393  cur = cur->child;
394  if (!cur)
395  goto done;
396 
397  while (true)
398  {
399  if (cur->message && (cur != e->thread))
400  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
401 
402  if (cur->child)
403  cur = cur->child;
404  else if (cur->next)
405  cur = cur->next;
406  else
407  {
408  while (!cur->next)
409  {
410  cur = cur->parent;
411  if (cur == start)
412  goto done;
413  }
414  cur = cur->next;
415  }
416  }
417 done:
418  cur = e->thread;
419  if (cur->message)
420  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
421  return 0;
422 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The "current" mailbox.
Definition: context.h:36
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:70
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
#define _(a)
Definition: message.h:28
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct Mailbox * mailbox
Definition: context.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
Sort by email threads.
Definition: sort2.h:56
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
An Email conversation.
Definition: thread.h:34
#define mutt_error(...)
Definition: logging.h:84
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:85
+ Here is the caller graph for this function:

◆ mutt_update_num_postponed()

void mutt_update_num_postponed ( void  )

Force the update of the number of postponed messages.

Definition at line 199 of file postpone.c.

200 {
201  UpdateNumPostponed = true;
202 }
static bool UpdateNumPostponed
Definition: postpone.c:76
+ Here is the caller graph for this function:

◆ mutt_is_quote_line()

int mutt_is_quote_line ( char *  line,
regmatch_t *  pmatch 
)

Is a line of message text a quote?

Parameters
[in]lineLine to test
[out]pmatchRegex sub-matches
Return values
trueLine is quoted

Checks if line matches the C_QuoteRegex and doesn't match C_Smileys. This is used by the pager for calling classify_quote.

Definition at line 937 of file pager.c.

938 {
939  bool is_quote = false;
940  regmatch_t pmatch_internal[1], smatch[1];
941 
942  if (!pmatch)
943  pmatch = pmatch_internal;
944 
945  if (mutt_regex_capture(C_QuoteRegex, line, 1, pmatch))
946  {
947  if (mutt_regex_capture(C_Smileys, line, 1, smatch))
948  {
949  if (smatch[0].rm_so > 0)
950  {
951  char c = line[smatch[0].rm_so];
952  line[smatch[0].rm_so] = 0;
953 
954  if (mutt_regex_capture(C_QuoteRegex, line, 1, pmatch))
955  is_quote = true;
956 
957  line[smatch[0].rm_so] = c;
958  }
959  }
960  else
961  is_quote = true;
962  }
963 
964  return is_quote;
965 }
struct Regex * C_Smileys
Config: Regex to match smileys to prevent mistakes when quoting text.
Definition: pager.c:92
const char * line
Definition: common.c:36
WHERE struct Regex * C_QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: globals.h:174
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:594
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ wcscasecmp()

int wcscasecmp ( const wchar_t *  a,
const wchar_t *  b 
)

Compare two wide-character strings, ignoring case.

Parameters
aFirst string
bSecond string
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 41 of file wcscasecmp.c.

42 {
43  if (!a && !b)
44  return 0;
45  if (!a && b)
46  return -1;
47  if (a && !b)
48  return 1;
49 
50  for (; *a || *b; a++, b++)
51  {
52  int i = towlower(*a);
53  if ((i - towlower(*b)) != 0)
54  return i;
55  }
56  return 0;
57 }
+ Here is the caller graph for this function:

◆ mutt_reply_observer()

int mutt_reply_observer ( struct NotifyCallback nc)

Listen for config changes to "reply_regex" - Implements observer_t()

Definition at line 3944 of file index.c.

3945 {
3946  if (!nc->event_data)
3947  return -1;
3948  if (nc->event_type != NT_CONFIG)
3949  return 0;
3950 
3951  struct EventConfig *ec = nc->event_data;
3952 
3953  if (mutt_str_strcmp(ec->name, "reply_regex") != 0)
3954  return 0;
3955 
3956  if (!Context || !Context->mailbox)
3957  return 0;
3958 
3959  regmatch_t pmatch[1];
3960  struct Mailbox *m = Context->mailbox;
3961 
3962  for (int i = 0; i < m->msg_count; i++)
3963  {
3964  struct Email *e = m->emails[i];
3965  if (!e)
3966  break;
3967  struct Envelope *env = e->env;
3968  if (!env || !env->subject)
3969  continue;
3970 
3971  if (mutt_regex_capture(C_ReplyRegex, env->subject, 1, pmatch))
3972  {
3973  env->real_subj = env->subject + pmatch[0].rm_eo;
3974  continue;
3975  }
3976 
3977  env->real_subj = env->subject;
3978  }
3979 
3980  OptResortInit = true; /* trigger a redraw of the index */
3981  return 0;
3982 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:98
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:90
The envelope/body of an email.
Definition: email.h:37
A config-change event.
Definition: subset.h:68
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Regex * C_ReplyRegex
Config: Regex to match message reply subjects like "re: ".
Definition: email_globals.c:37
A mailbox.
Definition: mailbox.h:80
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:49
void * event_data
Data from notify_send()
Definition: observer.h:44
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:594
Config has changed.
Definition: notify_type.h:34
char * subject
Email&#39;s subject.
Definition: envelope.h:66
const char * name
Name of config item that changed.
Definition: subset.h:71
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
The header of an Email.
Definition: envelope.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function: