NeoMutt  2020-04-24
Teaching an old dog new tricks
DOXYGEN
protos.h File Reference

Prototypes for many functions. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include "mutt.h"
#include "keymap.h"
#include "ncrypt/lib.h"
#include "mutt/regex3.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, struct Buffer *buf)
 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 263 of file editmsg.c.

264 {
265  struct EmailNode *en = NULL;
266  STAILQ_FOREACH(en, el, entries)
267  {
268  if (ev_message(action, m, en->email) == -1)
269  return -1;
270  }
271 
272  return 0;
273 }
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 51 of file system.c.

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

Find an XDG path or its fallback.

Parameters
typeType of XDG variable, e.g. XDG_CONFIG_HOME
bufBuffer to save path
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 1588 of file muttlib.c.

1589 {
1590  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1591  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1592  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1593  char *token = NULL;
1594  int rc = 0;
1595 
1596  while ((token = strsep(&xdg, ":")))
1597  {
1598  if (mutt_buffer_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1599  continue;
1601  if (access(mutt_b2s(buf), F_OK) == 0)
1602  {
1603  rc = 1;
1604  break;
1605  }
1606 
1607  if (mutt_buffer_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1608  continue;
1610  if (access(mutt_b2s(buf), F_OK) == 0)
1611  {
1612  rc = 1;
1613  break;
1614  }
1615  }
1616 
1617  FREE(&x);
1618  return rc;
1619 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * xdg_env_vars[]
Definition: muttlib.c:76
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1074
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:327
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:81
+ 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 444 of file help.c.

445 {
446  char buf[128];
447  FILE *fp = NULL;
448 
449  /* We don't use the buffer pool because of the extended lifetime of t */
450  struct Buffer t = mutt_buffer_make(PATH_MAX);
451  mutt_buffer_mktemp(&t);
452 
453  const struct Binding *funcs = km_get_table(menu);
454  const char *desc = mutt_map_get_name(menu, Menus);
455  if (!desc)
456  desc = _("<UNKNOWN>");
457 
458  do
459  {
460  fp = mutt_file_fopen(mutt_b2s(&t), "w");
461  if (!fp)
462  {
463  mutt_perror(mutt_b2s(&t));
464  goto cleanup;
465  }
466 
467  dump_menu(fp, menu, wraplen);
468  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
469  {
470  fprintf(fp, "\n%s\n\n", _("Generic bindings:"));
471  dump_menu(fp, MENU_GENERIC, wraplen);
472  }
473 
474  fprintf(fp, "\n%s\n\n", _("Unbound functions:"));
475  if (funcs)
476  dump_unbound(fp, funcs, Keymaps[menu], NULL, wraplen);
477  if (menu != MENU_PAGER)
478  dump_unbound(fp, OpGeneric, Keymaps[MENU_GENERIC], Keymaps[menu], wraplen);
479 
480  mutt_file_fclose(&fp);
481 
482  snprintf(buf, sizeof(buf), _("Help for %s"), desc);
483  } while (mutt_do_pager(buf, mutt_b2s(&t),
485  NULL) == OP_REFORMAT_WINCH);
486 
487 cleanup:
489 }
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:429
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
#define mutt_perror(...)
Definition: logging.h:85
struct Keymap * Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:149
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:153
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:55
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:61
#define PATH_MAX
Definition: mutt.h:44
static void dump_menu(FILE *fp, enum MenuType menu, int wraplen)
Write all the key bindings to a file.
Definition: help.c:377
#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:665
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1264
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:588
Mapping between a user key and a function.
Definition: keymap.h:117
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 93 of file help.c.

94 {
95  char tmp[128];
96 
97  if (km_expand_key(tmp, sizeof(tmp), km_find_func(menu, op)) ||
98  km_expand_key(tmp, sizeof(tmp), km_find_func(MENU_GENERIC, op)))
99  {
100  snprintf(buf, buflen, "%s:%s", tmp, txt);
101  }
102  else
103  {
104  buf[0] = '\0';
105  }
106 }
int op
function id number
Definition: keymap.h:120
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:898
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:870
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->type == 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->type == 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->type == 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 }
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
Flagged messages.
Definition: mutt.h:100
bool changed
Email has been edited.
Definition: email.h:48
Messages to be purged (bypass trash)
Definition: mutt.h:98
bool searched
Email has been searched.
Definition: email.h:67
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Messages that have been replied to.
Definition: mutt.h:93
#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
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:60
Old messages.
Definition: mutt.h:92
Messages to be deleted.
Definition: mutt.h:96
Tagged messages.
Definition: mutt.h:101
New messages.
Definition: mutt.h:91
Messages that have been read.
Definition: mutt.h:94
bool purge
Skip trash folder when deleting.
Definition: email.h:46
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3955
bool flagged
Marked important?
Definition: email.h:43
int msg_new
Number of new messages.
Definition: mailbox.h:95
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:73
WHERE bool C_FlagSafe
Config: Protect flagged messages from deletion.
Definition: globals.h:213
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ 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 132 of file mutt_signal.c.

133 {
135 
136 #ifdef USE_SLANG_CURSES
137  /* This bit of code is required because of the implementation of
138  * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
139  * are in blocking mode, SLsys_getkey() will not return an error unless
140  * a handler function is defined and it returns -1. This is needed so
141  * that if the user resizes the screen while at a prompt, it will just
142  * abort and go back to the main-menu. */
143  SLang_getkey_intr_hook = mutt_intr_hook;
144 #endif
145 }
static void curses_signal_handler(int sig)
Catch signals and relay the info to the main program - Implements sig_handler_t.
Definition: mutt_signal.c:46
static void curses_exit_handler(int sig)
Notify the user and shutdown gracefully - Implements sig_handler_t.
Definition: mutt_signal.c:86
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 - Implements sig_handler_t.
Definition: mutt_signal.c:98
+ 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:134
Flagged messages.
Definition: mutt.h:100
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:98
Messages that have been replied to.
Definition: mutt.h:93
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:112
Old messages.
Definition: mutt.h:92
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:106
Messages to be deleted.
Definition: mutt.h:96
Tagged messages.
Definition: mutt.h:101
New messages.
Definition: mutt.h:91
Messages that have been read.
Definition: mutt.h:94
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:311
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:46
+ 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:2524
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:121
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:776
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:1455
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:327
Log at debug level 1.
Definition: logging.h:40
WHERE char * C_Spoolfile
Config: Inbox.
Definition: globals.h:145
int mutt_str_strncmp(const char *a, const char *b, size_t l)
Compare two strings (to a maximum), safely.
Definition: string.c:668
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:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:46
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
+ 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 655 of file postpone.c.

657 {
658  struct Message *msg = NULL;
659  struct Body *b = NULL;
660  FILE *fp_body = NULL;
661  int rc = -1;
662  struct State s = { 0 };
663  SecurityFlags sec_type;
664  struct Envelope *protected_headers = NULL;
665 
666  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
667  return -1;
668 
669  if (!fp)
670  fp = msg->fp;
671 
672  fp_body = fp;
673 
674  /* parse the message header and MIME structure */
675 
676  fseeko(fp, e->offset, SEEK_SET);
677  e_new->offset = e->offset;
678  /* enable header weeding for resent messages */
679  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
680  e_new->content->length = e->content->length;
681  mutt_parse_part(fp, e_new->content);
682 
683  /* If resending a message, don't keep message_id or mail_followup_to.
684  * Otherwise, we are resuming a postponed message, and want to keep those
685  * headers if they exist. */
686  if (resend)
687  {
688  FREE(&e_new->env->message_id);
689  FREE(&e_new->env->mail_followup_to);
690  }
691 
692  /* decrypt pgp/mime encoded messages */
693 
694  if (((WithCrypto & APPLICATION_PGP) != 0) &&
695  (sec_type = mutt_is_multipart_encrypted(e_new->content)))
696  {
697  e_new->security |= sec_type;
698  if (!crypt_valid_passphrase(sec_type))
699  goto bail;
700 
701  mutt_message(_("Decrypting message..."));
702  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->content, &b) == -1) || !b)
703  {
704  goto bail;
705  }
706 
707  mutt_body_free(&e_new->content);
708  e_new->content = b;
709 
710  if (b->mime_headers)
711  {
712  protected_headers = b->mime_headers;
713  b->mime_headers = NULL;
714  }
715 
717  }
718 
719  /* remove a potential multipart/signed layer - useful when
720  * resending messages */
721  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->content))
722  {
723  e_new->security |= SEC_SIGN;
724  if (((WithCrypto & APPLICATION_PGP) != 0) &&
726  mutt_param_get(&e_new->content->parameter, "protocol"),
727  "application/pgp-signature") == 0))
728  {
729  e_new->security |= APPLICATION_PGP;
730  }
731  else if (WithCrypto & APPLICATION_SMIME)
732  e_new->security |= APPLICATION_SMIME;
733 
734  /* destroy the signature */
735  mutt_body_free(&e_new->content->parts->next);
736  e_new->content = mutt_remove_multipart(e_new->content);
737 
738  if (e_new->content->mime_headers)
739  {
740  mutt_env_free(&protected_headers);
741  protected_headers = e_new->content->mime_headers;
742  e_new->content->mime_headers = NULL;
743  }
744  }
745 
746  /* We don't need no primary multipart.
747  * Note: We _do_ preserve messages!
748  *
749  * XXX - we don't handle multipart/alternative in any
750  * smart way when sending messages. However, one may
751  * consider this a feature. */
752  if (e_new->content->type == TYPE_MULTIPART)
753  e_new->content = mutt_remove_multipart(e_new->content);
754 
755  s.fp_in = fp_body;
756 
757  struct Buffer *file = mutt_buffer_pool_get();
758 
759  /* create temporary files for all attachments */
760  for (b = e_new->content; b; b = b->next)
761  {
762  /* what follows is roughly a receive-mode variant of
763  * mutt_get_tmp_attachment () from muttlib.c */
764 
765  mutt_buffer_reset(file);
766  if (b->filename)
767  {
768  mutt_buffer_strcpy(file, b->filename);
770  }
771  else
772  {
773  /* avoid Content-Disposition: header with temporary filename */
774  b->use_disp = false;
775  }
776 
777  /* set up state flags */
778 
779  s.flags = 0;
780 
781  if (b->type == TYPE_TEXT)
782  {
783  if (mutt_str_strcasecmp("yes",
784  mutt_param_get(&b->parameter, "x-mutt-noconv")) == 0)
785  {
786  b->noconv = true;
787  }
788  else
789  {
790  s.flags |= MUTT_CHARCONV;
791  b->noconv = false;
792  }
793 
794  mutt_param_delete(&b->parameter, "x-mutt-noconv");
795  }
796 
797  mutt_adv_mktemp(file);
798  s.fp_out = mutt_file_fopen(mutt_b2s(file), "w");
799  if (!s.fp_out)
800  goto bail;
801 
802  if (((WithCrypto & APPLICATION_PGP) != 0) &&
803  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
804  {
805  if (sec_type & SEC_ENCRYPT)
806  {
807  if (!crypt_valid_passphrase(APPLICATION_PGP))
808  goto bail;
809  mutt_message(_("Decrypting message..."));
810  }
811 
812  if (mutt_body_handler(b, &s) < 0)
813  {
814  mutt_error(_("Decryption failed"));
815  goto bail;
816  }
817 
818  if ((b == e_new->content) && !protected_headers)
819  {
820  protected_headers = b->mime_headers;
821  b->mime_headers = NULL;
822  }
823 
824  e_new->security |= sec_type;
825  b->type = TYPE_TEXT;
826  mutt_str_replace(&b->subtype, "plain");
827  mutt_param_delete(&b->parameter, "x-action");
828  }
829  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
830  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
831  {
832  if (sec_type & SEC_ENCRYPT)
833  {
834  if (!crypt_valid_passphrase(APPLICATION_SMIME))
835  goto bail;
836  crypt_smime_getkeys(e_new->env);
837  mutt_message(_("Decrypting message..."));
838  }
839 
840  if (mutt_body_handler(b, &s) < 0)
841  {
842  mutt_error(_("Decryption failed"));
843  goto bail;
844  }
845 
846  e_new->security |= sec_type;
847  b->type = TYPE_TEXT;
848  mutt_str_replace(&b->subtype, "plain");
849  }
850  else
851  mutt_decode_attachment(b, &s);
852 
853  if (mutt_file_fclose(&s.fp_out) != 0)
854  goto bail;
855 
856  mutt_str_replace(&b->filename, mutt_b2s(file));
857  b->unlink = true;
858 
860 
861  mutt_body_free(&b->parts);
862  if (b->email)
863  b->email->content = NULL; /* avoid dangling pointer */
864  }
865 
866  if (C_CryptProtectedHeadersRead && protected_headers && protected_headers->subject &&
867  (mutt_str_strcmp(e_new->env->subject, protected_headers->subject) != 0))
868  {
869  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
870  }
871  mutt_env_free(&protected_headers);
872 
873  /* Fix encryption flags. */
874 
875  /* No inline if multipart. */
876  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->content->next)
877  e_new->security &= ~SEC_INLINE;
878 
879  /* Do we even support multiple mechanisms? */
880  e_new->security &= WithCrypto | ~(APPLICATION_PGP | APPLICATION_SMIME);
881 
882  /* Theoretically, both could be set. Take the one the user wants to set by default. */
883  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
884  {
885  if (C_SmimeIsDefault)
886  e_new->security &= ~APPLICATION_PGP;
887  else
888  e_new->security &= ~APPLICATION_SMIME;
889  }
890 
892 
893  rc = 0;
894 
895 bail:
896 
897  /* that's it. */
899  if (fp_body != fp)
900  mutt_file_fclose(&fp_body);
901  if (msg)
902  mx_msg_close(m, &msg);
903 
904  if (rc == -1)
905  {
906  mutt_env_free(&e_new->env);
907  mutt_body_free(&e_new->content);
908  }
909 
910  return rc;
911 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1803
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1443
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
#define WithCrypto
Definition: lib.h:163
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
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
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
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:123
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:132
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:1171
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:146
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:459
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:89
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:418
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:481
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
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:565
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
A local copy of an email.
Definition: mx.h:83
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:460
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:624
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
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:455
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 SEC_SIGN
Email is signed.
Definition: lib.h:126
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1407
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:212
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:654
FILE * fp
pointer to the message data
Definition: mx.h:85
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:94
#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:1550
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
int const char * file
Definition: acutest.h:617
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1137
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1123
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:86
+ 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 145 of file enter.c.

146 {
147  int rc;
148  struct EnterState *es = mutt_enter_state_new();
149  do
150  {
151  if (SigWinch)
152  {
153  SigWinch = 0;
155  clearok(stdscr, true);
156  }
157  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
158  } while (rc == 1);
160  return rc;
161 }
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:101
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:177
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:821
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:126
+ 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 177 of file enter.c.

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

333 {
334  if (!C_Postponed)
335  return -1;
336 
337  struct Email *e = NULL;
338  int rc = SEND_POSTPONED;
339  const char *p = NULL;
340  struct Context *ctx_post = NULL;
341 
342  struct Mailbox *m = mx_path_resolve(C_Postponed);
343  if (ctx && (ctx->mailbox == m))
344  ctx_post = ctx;
345  else
346  ctx_post = mx_mbox_open(m, MUTT_NOSORT);
347 
348  if (!ctx_post)
349  {
350  PostCount = 0;
351  mutt_error(_("No postponed messages"));
352  mailbox_free(&m);
353  return -1;
354  }
355 
356  /* TODO:
357  * mx_mbox_open() for IMAP leaves IMAP_REOPEN_ALLOW set. For the
358  * index this is papered-over because it calls mx_check_mailbox()
359  * every event loop(which resets that flag).
360  *
361  * For a stable-branch fix, I'm doing the same here, to prevent
362  * context changes from occuring behind the scenes and causing
363  * segvs, but probably the flag needs to be reset after downloading
364  * headers in imap_open_mailbox().
365  */
366  mx_mbox_check(ctx_post->mailbox, NULL);
367 
368  if (ctx_post->mailbox->msg_count == 0)
369  {
370  PostCount = 0;
371  if (ctx_post == ctx)
372  ctx_post = NULL;
373  else
374  mx_mbox_close(&ctx_post);
375  mutt_error(_("No postponed messages"));
376  return -1;
377  }
378 
379  if (ctx_post->mailbox->msg_count == 1)
380  {
381  /* only one message, so just use that one. */
382  e = ctx_post->mailbox->emails[0];
383  }
384  else if (!(e = select_msg(ctx_post)))
385  {
386  if (ctx_post == ctx)
387  ctx_post = NULL;
388  else
389  mx_mbox_close(&ctx_post);
390  return -1;
391  }
392 
393  if (mutt_prepare_template(NULL, ctx_post->mailbox, hdr, e, false) < 0)
394  {
395  if (ctx_post != ctx)
396  {
397  mx_fastclose_mailbox(ctx_post->mailbox);
398  FREE(&ctx_post);
399  }
400  return -1;
401  }
402 
403  /* finished with this message, so delete it. */
404  mutt_set_flag(ctx_post->mailbox, e, MUTT_DELETE, true);
405  mutt_set_flag(ctx_post->mailbox, e, MUTT_PURGE, true);
406 
407  /* update the count for the status display */
408  PostCount = ctx_post->mailbox->msg_count - ctx_post->mailbox->msg_deleted;
409 
410  /* avoid the "purge deleted messages" prompt */
411  int opt_delete = C_Delete;
412  C_Delete = MUTT_YES;
413  if (ctx_post == ctx)
414  ctx_post = NULL;
415  else
416  mx_mbox_close(&ctx_post);
417  C_Delete = opt_delete;
418 
419  struct ListNode *np = NULL, *tmp = NULL;
420  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
421  {
422  size_t plen = mutt_str_startswith(np->data, "X-Mutt-References:", CASE_IGNORE);
423  if (plen)
424  {
425  /* if a mailbox is currently open, look to see if the original message
426  * the user attempted to reply to is in this mailbox */
427  p = mutt_str_skip_email_wsp(np->data + plen);
428  if (!ctx->mailbox->id_hash)
430  *cur = mutt_hash_find(ctx->mailbox->id_hash, p);
431 
432  if (*cur)
433  rc |= SEND_REPLY;
434  }
435  else if ((plen = mutt_str_startswith(np->data, "X-Mutt-Fcc:", CASE_IGNORE)))
436  {
437  p = mutt_str_skip_email_wsp(np->data + plen);
438  mutt_buffer_strcpy(fcc, p);
440 
441  /* note that x-mutt-fcc was present. we do this because we want to add a
442  * default fcc if the header was missing, but preserve the request of the
443  * user to not make a copy if the header field is present, but empty.
444  * see http://dev.mutt.org/trac/ticket/3653 */
445  rc |= SEND_POSTPONED_FCC;
446  }
447  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
448  /* this is generated by old neomutt versions */
449  (mutt_str_startswith(np->data, "Pgp:", CASE_MATCH) ||
450  /* this is the new way */
451  mutt_str_startswith(np->data, "X-Mutt-PGP:", CASE_MATCH)))
452  {
453  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
454  hdr->security |= APPLICATION_PGP;
455  }
456  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
457  mutt_str_startswith(np->data, "X-Mutt-SMIME:", CASE_MATCH))
458  {
459  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
460  hdr->security |= APPLICATION_SMIME;
461  }
462 #ifdef MIXMASTER
463  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:", CASE_MATCH))
464  {
465  mutt_list_free(&hdr->chain);
466 
467  char *t = strtok(np->data + 11, " \t\n");
468  while (t)
469  {
471  t = strtok(NULL, " \t\n");
472  }
473  }
474 #endif
475  else
476  {
477  // skip header removal
478  continue;
479  }
480 
481  // remove the header
482  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
483  FREE(&np->data);
484  FREE(&np);
485  }
486 
489 
490  return rc;
491 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:37
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:70
#define WithCrypto
Definition: lib.h:163
#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 mx_mbox_check(struct Mailbox *m, int *index_hint)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1104
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:593
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:181
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:255
Messages to be purged (bypass trash)
Definition: mutt.h:98
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:688
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
struct Mailbox * mailbox
Definition: context.h:51
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:414
#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
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:268
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
Messages to be deleted.
Definition: mutt.h:96
A mailbox.
Definition: mailbox.h:81
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:53
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:802
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
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
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:500
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1036
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:1655
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:135
A List node for strings.
Definition: list.h:33
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:655
struct Hash * id_hash
Hash table by msg id.
Definition: mailbox.h:127
+ 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 500 of file postpone.c.

501 {
502  char smime_cryptalg[1024] = { 0 };
503  char sign_as[1024] = { 0 };
504  char *q = NULL;
505  SecurityFlags flags = SEC_NO_FLAGS;
506 
507  if (!WithCrypto)
508  return SEC_NO_FLAGS;
509 
511  for (; p[0] != '\0'; p++)
512  {
513  switch (p[0])
514  {
515  case 'c':
516  case 'C':
517  q = smime_cryptalg;
518 
519  if (p[1] == '<')
520  {
521  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
522  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
523  *q++ = *p++)
524  {
525  }
526 
527  if (p[0] != '>')
528  {
529  mutt_error(_("Illegal S/MIME header"));
530  return SEC_NO_FLAGS;
531  }
532  }
533 
534  *q = '\0';
535  break;
536 
537  case 'e':
538  case 'E':
539  flags |= SEC_ENCRYPT;
540  break;
541 
542  case 'i':
543  case 'I':
544  flags |= SEC_INLINE;
545  break;
546 
547  /* This used to be the micalg parameter.
548  *
549  * It's no longer needed, so we just skip the parameter in order
550  * to be able to recall old messages. */
551  case 'm':
552  case 'M':
553  if (p[1] != '<')
554  break;
555 
556  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
557  ;
558  if (p[0] != '>')
559  {
560  mutt_error(_("Illegal crypto header"));
561  return SEC_NO_FLAGS;
562  }
563  break;
564 
565  case 'o':
566  case 'O':
567  flags |= SEC_OPPENCRYPT;
568  break;
569 
570  case 'a':
571  case 'A':
572 #ifdef USE_AUTOCRYPT
573  flags |= SEC_AUTOCRYPT;
574 #endif
575  break;
576 
577  case 'z':
578  case 'Z':
579 #ifdef USE_AUTOCRYPT
580  flags |= SEC_AUTOCRYPT_OVERRIDE;
581 #endif
582  break;
583 
584  case 's':
585  case 'S':
586  flags |= SEC_SIGN;
587  q = sign_as;
588 
589  if (p[1] == '<')
590  {
591  for (p += 2;
592  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
593  *q++ = *p++)
594  {
595  }
596 
597  if (p[0] != '>')
598  {
599  mutt_error(_("Illegal crypto header"));
600  return SEC_NO_FLAGS;
601  }
602  }
603 
604  q[0] = '\0';
605  break;
606 
607  default:
608  mutt_error(_("Illegal crypto header"));
609  return SEC_NO_FLAGS;
610  }
611  }
612 
613  /* the cryptalg field must not be empty */
614  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
615  {
616  struct Buffer errmsg = mutt_buffer_make(0);
617  int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
618  smime_cryptalg, &errmsg);
619 
620  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
621  mutt_error("%s", mutt_b2s(&errmsg));
622 
623  mutt_buffer_dealloc(&errmsg);
624  }
625 
626  /* Set {Smime,Pgp}SignAs, if desired. */
627 
628  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
629  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
630  {
631  mutt_str_replace(&C_PgpSignAs, sign_as);
632  }
633 
634  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
635  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
636  {
637  mutt_str_replace(&C_SmimeSignAs, sign_as);
638  }
639 
640  return flags;
641 }
#define WithCrypto
Definition: lib.h:163
#define CSR_RESULT(x)
Definition: set.h:52
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:124
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
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 SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:134
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:123
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:395
Container for Accounts, Notifications.
Definition: neomutt.h:35
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:132
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:36
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:135
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:802
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:455
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:133
#define SEC_SIGN
Email is signed.
Definition: lib.h:126
#define mutt_error(...)
Definition: logging.h:84
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:38
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:161
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:165
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
+ 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:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
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:1319
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2524
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
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:255
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:51
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:414
#define mutt_b2s(buf)
Definition: buffer.h:41
A mailbox.
Definition: mailbox.h:81
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:53
static short PostCount
Definition: postpone.c:75
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:56
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:1655
static bool UpdateNumPostponed
Definition: postpone.c:76
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:48
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:135
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:46
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
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:37
#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:51
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
WHERE struct Regex * C_QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: globals.h:175
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:593
int const char int line
Definition: acutest.h:617
+ 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 3978 of file index.c.

3979 {
3980  if (!nc->event_data)
3981  return -1;
3982  if (nc->event_type != NT_CONFIG)
3983  return 0;
3984 
3985  struct EventConfig *ec = nc->event_data;
3986 
3987  if (mutt_str_strcmp(ec->name, "reply_regex") != 0)
3988  return 0;
3989 
3990  if (!Context || !Context->mailbox)
3991  return 0;
3992 
3993  regmatch_t pmatch[1];
3994  struct Mailbox *m = Context->mailbox;
3995 
3996  for (int i = 0; i < m->msg_count; i++)
3997  {
3998  struct Email *e = m->emails[i];
3999  if (!e)
4000  break;
4001  struct Envelope *env = e->env;
4002  if (!env || !env->subject)
4003  continue;
4004 
4005  if (mutt_regex_capture(C_ReplyRegex, env->subject, 1, pmatch))
4006  {
4007  env->real_subj = env->subject + pmatch[0].rm_eo;
4008  continue;
4009  }
4010 
4011  env->real_subj = env->subject;
4012  }
4013 
4014  OptResortInit = true; /* trigger a redraw of the index */
4015  return 0;
4016 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
A config-change event.
Definition: subset.h:70
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:41
struct Mailbox * mailbox
Definition: context.h:51
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:81
WHERE bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:52
void * event_data
Data from notify_send()
Definition: observer.h:43
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:593
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:73
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
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: