NeoMutt  2021-02-05-666-ge300cd
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/lib.h"
#include "mutt.h"
#include "menu/lib.h"
#include "ncrypt/lib.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)
 Display the help menu. More...
 
void mutt_set_flag_update (struct Mailbox *m, struct Email *e, enum MessageType 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, enum MessageType 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_full (char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, struct Mailbox *m, char ***files, int *numfiles, struct EnterState *state)
 Ask the user for a string. More...
 
int mutt_get_postponed (struct Mailbox *m_cur, 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 Mailbox *m, struct Email *e, enum MessageType 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)
 

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 66 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 44 of file protos.h.

45 {
48 };
XDG home dir: ~/.config.
Definition: protos.h:46
XDG system dir: /etc/xdg.
Definition: protos.h:47

◆ EvMessage

enum EvMessage

Edit or View a message.

Enumerator
EVM_VIEW 

View the message.

EVM_EDIT 

Edit the message.

Definition at line 53 of file protos.h.

54 {
55  EVM_VIEW,
56  EVM_EDIT,
57 };
View the message.
Definition: protos.h:55
Edit the message.
Definition: protos.h:56

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 276 of file editmsg.c.

277 {
278  struct EmailNode *en = NULL;
279  STAILQ_FOREACH(en, el, entries)
280  {
281  if (ev_message(action, m, en->email) == -1)
282  return -1;
283  }
284 
285  return 0;
286 }
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:57
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct Email * email
Email in the list.
Definition: email.h:131
List of Emails.
Definition: email.h:129
+ 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 == '\0'))
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:973
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
1An entry was found that actually exists on disk and 0 otherwise

Process an XDG environment variable or its fallback.

Definition at line 1516 of file muttlib.c.

1517 {
1518  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1519  char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(xdg_defaults[type]);
1520  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1521  char *token = NULL;
1522  int rc = 0;
1523 
1524  while ((token = strsep(&xdg, ":")))
1525  {
1526  if (mutt_buffer_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1527  continue;
1529  if (access(mutt_buffer_string(buf), F_OK) == 0)
1530  {
1531  rc = 1;
1532  break;
1533  }
1534 
1535  if (mutt_buffer_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1536  continue;
1538  if (access(mutt_buffer_string(buf), F_OK) == 0)
1539  {
1540  rc = 1;
1541  break;
1542  }
1543  }
1544 
1545  FREE(&x);
1546  return rc;
1547 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
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:65
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
#define FREE(x)
Definition: memory.h:40
static const char * xdg_defaults[]
Definition: muttlib.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_help()

void mutt_help ( enum MenuType  menu)

Display the help menu.

Parameters
menuCurrent Menu

Definition at line 389 of file help.c.

390 {
391  const int wraplen = AllDialogsWindow->state.cols;
392  char banner[128];
393  FILE *fp = NULL;
394 
395  /* We don't use the buffer pool because of the extended lifetime of t */
396  struct Buffer t = mutt_buffer_make(PATH_MAX);
397  mutt_buffer_mktemp(&t);
398 
399  const struct Binding *funcs = km_get_table(menu);
400  const char *desc = mutt_map_get_name(menu, MenuNames);
401  if (!desc)
402  desc = _("<UNKNOWN>");
403 
404  struct PagerData pdata = { 0 };
405  struct PagerView pview = { &pdata };
406 
407  pview.mode = PAGER_MODE_HELP;
409 
410  do
411  {
412  fp = mutt_file_fopen(mutt_buffer_string(&t), "w");
413  if (!fp)
414  {
416  goto cleanup;
417  }
418 
419  dump_menu(fp, menu, wraplen);
420  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
421  {
422  fprintf(fp, "\n%s\n\n", _("Generic bindings:"));
423  dump_menu(fp, MENU_GENERIC, wraplen);
424  }
425 
426  fprintf(fp, "\n%s\n\n", _("Unbound functions:"));
427  if (funcs)
428  dump_unbound(fp, funcs, &Keymaps[menu], NULL, wraplen);
429  if (menu != MENU_PAGER)
430  dump_unbound(fp, OpGeneric, &Keymaps[MENU_GENERIC], &Keymaps[menu], wraplen);
431 
432  mutt_file_fclose(&fp);
433 
434  snprintf(banner, sizeof(banner), _("Help for %s"), desc);
435  pdata.fname = mutt_buffer_string(&t);
436  pview.banner = banner;
437  } while (mutt_do_pager(&pview, NULL) == OP_REFORMAT_WINCH);
438 
439 cleanup:
441 }
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: lib.h:65
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
static void dump_unbound(FILE *fp, const struct Binding *funcs, struct KeymapList *km_list, struct KeymapList *aux, int wraplen)
Write out all the operations with no key bindings.
Definition: help.c:375
#define MUTT_PAGER_NSKIP
Preserve whitespace with smartwrap.
Definition: lib.h:63
struct KeymapList Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:126
Generic selection list.
Definition: type.h:45
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
Paged view into some data.
Definition: lib.h:154
#define _(a)
Definition: message.h:28
#define mutt_perror(...)
Definition: logging.h:89
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Pager pager (email viewer)
Definition: type.h:54
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
Data to be displayed by PagerView.
Definition: lib.h:143
Text entry area.
Definition: type.h:43
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:53
#define MUTT_PAGER_MARKER
Use markers if option is set.
Definition: lib.h:64
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
Pager is invoked via 3rd path to show help.
Definition: lib.h:134
enum PagerMode mode
Pager mode.
Definition: lib.h:157
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
#define PATH_MAX
Definition: mutt.h:40
static void dump_menu(FILE *fp, enum MenuType menu, int wraplen)
Write all the key bindings to a file.
Definition: help.c:321
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:120
struct MuttWindow * AllDialogsWindow
Parent of all Dialogs.
Definition: dialog.c:76
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
const struct Binding * km_get_table(enum MenuType mtype)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1313
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:31
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:67
const char * fname
Name of the file to read.
Definition: lib.h:148
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
const char * banner
Title to display in status bar.
Definition: lib.h:159
Mapping between a user key and a function.
Definition: keymap.h:91
+ 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,
enum MessageType  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 51 of file flags.c.

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

141 {
143 
144 #ifdef USE_SLANG_CURSES
145  /* This bit of code is required because of the implementation of
146  * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
147  * are in blocking mode, SLsys_getkey() will not return an error unless
148  * a handler function is defined and it returns -1. This is needed so
149  * that if the user resizes the screen while at a prompt, it will just
150  * abort and go back to the main-menu. */
151  SLang_getkey_intr_hook = mutt_intr_hook;
152 #endif
153 }
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:51
static void curses_exit_handler(int sig)
Notify the user and shutdown gracefully - Implements sig_handler_t.
Definition: mutt_signal.c:94
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:106
+ 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,
enum MessageType  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 352 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:66
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct Email * email
Email in the list.
Definition: email.h:131
#define STAILQ_EMPTY(head)
Definition: queue.h:348
List of Emails.
Definition: email.h:129
+ 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 434 of file flags.c.

435 {
436  struct MuttWindow *win = msgwin_get_window();
437  if (!win)
438  return -1;
439 
440  if (!m || !el || STAILQ_EMPTY(el))
441  return -1;
442 
443  enum MessageType flag = MUTT_NONE;
444  struct KeyEvent event;
445 
446  struct MuttWindow *old_focus = window_set_focus(win);
447 
448  mutt_window_mvprintw(win, 0, 0, "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
450  window_redraw(NULL);
451 
452  do
453  {
454  event = mutt_getch();
455  } while (event.ch == -2); // Timeout
456 
458  window_set_focus(old_focus);
459 
460  if (event.ch < 0) // SIGINT, Abort key (Ctrl-G)
461  return -1;
462 
463  switch (event.ch)
464  {
465  case 'd':
466  case 'D':
467  if (!bf)
468  mutt_emails_set_flag(m, el, MUTT_PURGE, bf);
469  flag = MUTT_DELETE;
470  break;
471 
472  case 'N':
473  case 'n':
474  flag = MUTT_NEW;
475  break;
476 
477  case 'o':
478  case 'O':
479  mutt_emails_set_flag(m, el, MUTT_READ, !bf);
480  flag = MUTT_OLD;
481  break;
482 
483  case 'r':
484  case 'R':
485  flag = MUTT_REPLIED;
486  break;
487 
488  case '*':
489  flag = MUTT_TAG;
490  break;
491 
492  case '!':
493  flag = MUTT_FLAG;
494  break;
495 
496  default:
497  mutt_beep(false);
498  return -1;
499  }
500 
501  mutt_emails_set_flag(m, el, flag, bf);
502  return 0;
503 }
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:352
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:259
struct MuttWindow * window_set_focus(struct MuttWindow *win)
Set the Window focus.
Definition: mutt_window.c:680
Flagged messages.
Definition: mutt.h:98
#define _(a)
Definition: message.h:28
No messages.
Definition: mutt.h:88
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:632
Messages to be purged (bypass trash)
Definition: mutt.h:96
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:242
Messages that have been replied to.
Definition: mutt.h:91
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:105
MessageType
To set flags or match patterns.
Definition: mutt.h:85
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:253
Old messages.
Definition: mutt.h:90
Messages to be deleted.
Definition: mutt.h:94
Tagged messages.
Definition: mutt.h:99
New messages.
Definition: mutt.h:89
Messages that have been read.
Definition: mutt.h:92
An event such as a keypress.
Definition: keymap.h:64
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:196
#define STAILQ_EMPTY(head)
Definition: queue.h:348
int mutt_window_mvprintw(struct MuttWindow *win, int col, int row, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:343
+ 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
0Ok
-1No 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  const 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  const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
81  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
82 #ifdef USE_IMAP
83  imap_path = mutt_buffer_pool_get();
84  /* we can use '/' as a delimiter, imap_complete rewrites it */
85  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
86  {
87  if (*buf == '!')
88  p = NONULL(c_spool_file);
89  else
90  p = NONULL(c_folder);
91 
92  mutt_buffer_concat_path(imap_path, p, buf + 1);
93  }
94  else
95  mutt_buffer_strcpy(imap_path, buf);
96 
97  if (imap_path_probe(mutt_buffer_string(imap_path), NULL) == MUTT_IMAP)
98  {
99  rc = imap_complete(buf, buflen, mutt_buffer_string(imap_path));
100  mutt_buffer_pool_release(&imap_path);
101  return rc;
102  }
103 
104  mutt_buffer_pool_release(&imap_path);
105 #endif
106 
107  dirpart = mutt_buffer_pool_get();
108  exp_dirpart = mutt_buffer_pool_get();
109  filepart = mutt_buffer_pool_get();
110  tmp = mutt_buffer_pool_get();
111 
112  if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
113  {
114  mutt_buffer_addch(dirpart, *buf);
115  if (*buf == '!')
116  mutt_buffer_strcpy(exp_dirpart, NONULL(c_spool_file));
117  else
118  mutt_buffer_strcpy(exp_dirpart, NONULL(c_folder));
119  p = strrchr(buf, '/');
120  if (p)
121  {
123  mutt_buffer_len(exp_dirpart), buf + 1,
124  (size_t) (p - buf - 1));
125  mutt_buffer_copy(exp_dirpart, tmp);
126  mutt_buffer_substrcpy(dirpart, buf, p + 1);
127  mutt_buffer_strcpy(filepart, p + 1);
128  }
129  else
130  mutt_buffer_strcpy(filepart, buf + 1);
131  dirp = opendir(mutt_buffer_string(exp_dirpart));
132  }
133  else
134  {
135  p = strrchr(buf, '/');
136  if (p)
137  {
138  if (p == buf) /* absolute path */
139  {
140  p = buf + 1;
141  mutt_buffer_strcpy(dirpart, "/");
142  mutt_buffer_strcpy(filepart, p);
143  dirp = opendir(mutt_buffer_string(dirpart));
144  }
145  else
146  {
147  mutt_buffer_substrcpy(dirpart, buf, p);
148  mutt_buffer_strcpy(filepart, p + 1);
149  mutt_buffer_copy(exp_dirpart, dirpart);
150  mutt_buffer_expand_path(exp_dirpart);
151  dirp = opendir(mutt_buffer_string(exp_dirpart));
152  }
153  }
154  else
155  {
156  /* no directory name, so assume current directory. */
157  mutt_buffer_strcpy(filepart, buf);
158  dirp = opendir(".");
159  }
160  }
161 
162  if (!dirp)
163  {
164  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n",
165  mutt_buffer_string(exp_dirpart), strerror(errno), errno);
166  goto cleanup;
167  }
168 
169  /* special case to handle when there is no filepart yet. find the first
170  * file/directory which is not "." or ".." */
171  len = mutt_buffer_len(filepart);
172  if (len == 0)
173  {
174  while ((de = readdir(dirp)))
175  {
176  if (!mutt_str_equal(".", de->d_name) && !mutt_str_equal("..", de->d_name))
177  {
178  mutt_buffer_strcpy(filepart, de->d_name);
179  init++;
180  break;
181  }
182  }
183  }
184 
185  while ((de = readdir(dirp)))
186  {
187  if (mutt_strn_equal(de->d_name, mutt_buffer_string(filepart), len))
188  {
189  if (init)
190  {
191  char *cp = filepart->data;
192 
193  for (int i = 0; (*cp != '\0') && (de->d_name[i] != '\0'); i++, cp++)
194  {
195  if (*cp != de->d_name[i])
196  break;
197  }
198  *cp = '\0';
199  mutt_buffer_fix_dptr(filepart);
200  }
201  else
202  {
203  struct stat st;
204 
205  mutt_buffer_strcpy(filepart, de->d_name);
206 
207  /* check to see if it is a directory */
208  if (mutt_buffer_is_empty(dirpart))
209  {
210  mutt_buffer_reset(tmp);
211  }
212  else
213  {
214  mutt_buffer_copy(tmp, exp_dirpart);
215  mutt_buffer_addch(tmp, '/');
216  }
217  mutt_buffer_addstr(tmp, mutt_buffer_string(filepart));
218  if ((stat(mutt_buffer_string(tmp), &st) != -1) && (st.st_mode & S_IFDIR))
219  mutt_buffer_addch(filepart, '/');
220  init = 1;
221  }
222  }
223  }
224  closedir(dirp);
225 
226  if (!mutt_buffer_is_empty(dirpart))
227  {
228  mutt_str_copy(buf, mutt_buffer_string(dirpart), buflen);
229  if (!mutt_str_equal("/", mutt_buffer_string(dirpart)) &&
230  (mutt_buffer_string(dirpart)[0] != '=') && (mutt_buffer_string(dirpart)[0] != '+'))
231  {
232  mutt_str_copy(buf + strlen(buf), "/", buflen - strlen(buf));
233  }
234  mutt_str_copy(buf + strlen(buf), mutt_buffer_string(filepart), buflen - strlen(buf));
235  }
236  else
237  mutt_str_copy(buf, mutt_buffer_string(filepart), buflen);
238 
239 cleanup:
240  mutt_buffer_pool_release(&dirpart);
241  mutt_buffer_pool_release(&exp_dirpart);
242  mutt_buffer_pool_release(&filepart);
244 
245  return init ? 0 : -1;
246 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
#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
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
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Log at debug level 2.
Definition: logging.h:41
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
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
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
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:47
int imap_complete(char *buf, size_t buflen, const char *path)
Try to complete an IMAP folder path.
Definition: imap.c:1343
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
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
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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:44
+ 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 736 of file postpone.c.

738 {
739  struct Message *msg = NULL;
740  struct Body *b = NULL;
741  FILE *fp_body = NULL;
742  int rc = -1;
743  struct State s = { 0 };
744  SecurityFlags sec_type;
745  struct Envelope *protected_headers = NULL;
746  struct Buffer *file = NULL;
747 
748  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
749  return -1;
750 
751  if (!fp)
752  fp = msg->fp;
753 
754  fp_body = fp;
755 
756  /* parse the message header and MIME structure */
757 
758  fseeko(fp, e->offset, SEEK_SET);
759  e_new->offset = e->offset;
760  /* enable header weeding for resent messages */
761  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
762  e_new->body->length = e->body->length;
763  mutt_parse_part(fp, e_new->body);
764 
765  /* If resending a message, don't keep message_id or mail_followup_to.
766  * Otherwise, we are resuming a postponed message, and want to keep those
767  * headers if they exist. */
768  if (resend)
769  {
770  FREE(&e_new->env->message_id);
771  FREE(&e_new->env->mail_followup_to);
772  }
773 
774  /* decrypt pgp/mime encoded messages */
775 
776  if (((WithCrypto & APPLICATION_PGP) != 0) &&
777  (sec_type = mutt_is_multipart_encrypted(e_new->body)))
778  {
779  e_new->security |= sec_type;
780  if (!crypt_valid_passphrase(sec_type))
781  goto bail;
782 
783  mutt_message(_("Decrypting message..."));
784  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->body, &b) == -1) || !b)
785  {
786  mutt_error(_("Could not decrypt PGP message"));
787  goto bail;
788  }
789 
790  mutt_body_free(&e_new->body);
791  e_new->body = b;
792 
793  if (b->mime_headers)
794  {
795  protected_headers = b->mime_headers;
796  b->mime_headers = NULL;
797  }
798 
800  }
801 
802  /* remove a potential multipart/signed layer - useful when
803  * resending messages */
804  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->body))
805  {
806  e_new->security |= SEC_SIGN;
807  if (((WithCrypto & APPLICATION_PGP) != 0) &&
808  mutt_istr_equal(mutt_param_get(&e_new->body->parameter, "protocol"),
809  "application/pgp-signature"))
810  {
811  e_new->security |= APPLICATION_PGP;
812  }
813  else if (WithCrypto & APPLICATION_SMIME)
814  e_new->security |= APPLICATION_SMIME;
815 
816  /* destroy the signature */
817  mutt_body_free(&e_new->body->parts->next);
818  e_new->body = mutt_remove_multipart(e_new->body);
819 
820  if (e_new->body->mime_headers)
821  {
822  mutt_env_free(&protected_headers);
823  protected_headers = e_new->body->mime_headers;
824  e_new->body->mime_headers = NULL;
825  }
826  }
827 
828  /* We don't need no primary multipart.
829  * Note: We _do_ preserve messages!
830  *
831  * XXX - we don't handle multipart/alternative in any
832  * smart way when sending messages. However, one may
833  * consider this a feature. */
834  if (e_new->body->type == TYPE_MULTIPART)
835  e_new->body = mutt_remove_multipart(e_new->body);
836 
837  s.fp_in = fp_body;
838 
839  file = mutt_buffer_pool_get();
840 
841  /* create temporary files for all attachments */
842  for (b = e_new->body; b; b = b->next)
843  {
844  /* what follows is roughly a receive-mode variant of
845  * mutt_get_tmp_attachment () from muttlib.c */
846 
847  mutt_buffer_reset(file);
848  if (b->filename)
849  {
850  mutt_buffer_strcpy(file, b->filename);
852  }
853  else
854  {
855  /* avoid Content-Disposition: header with temporary filename */
856  b->use_disp = false;
857  }
858 
859  /* set up state flags */
860 
861  s.flags = 0;
862 
863  if (b->type == TYPE_TEXT)
864  {
865  if (mutt_istr_equal("yes",
866  mutt_param_get(&b->parameter, "x-mutt-noconv")))
867  {
868  b->noconv = true;
869  }
870  else
871  {
872  s.flags |= MUTT_CHARCONV;
873  b->noconv = false;
874  }
875 
876  mutt_param_delete(&b->parameter, "x-mutt-noconv");
877  }
878 
879  mutt_adv_mktemp(file);
880  s.fp_out = mutt_file_fopen(mutt_buffer_string(file), "w");
881  if (!s.fp_out)
882  goto bail;
883 
884  if (((WithCrypto & APPLICATION_PGP) != 0) &&
885  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
886  {
887  if (sec_type & SEC_ENCRYPT)
888  {
889  if (!crypt_valid_passphrase(APPLICATION_PGP))
890  goto bail;
891  mutt_message(_("Decrypting message..."));
892  }
893 
894  if (mutt_body_handler(b, &s) < 0)
895  {
896  mutt_error(_("Decryption failed"));
897  goto bail;
898  }
899 
900  if ((b == e_new->body) && !protected_headers)
901  {
902  protected_headers = b->mime_headers;
903  b->mime_headers = NULL;
904  }
905 
906  e_new->security |= sec_type;
907  b->type = TYPE_TEXT;
908  mutt_str_replace(&b->subtype, "plain");
909  mutt_param_delete(&b->parameter, "x-action");
910  }
911  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
912  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
913  {
914  if (sec_type & SEC_ENCRYPT)
915  {
916  if (!crypt_valid_passphrase(APPLICATION_SMIME))
917  goto bail;
918  crypt_smime_getkeys(e_new->env);
919  mutt_message(_("Decrypting message..."));
920  }
921 
922  if (mutt_body_handler(b, &s) < 0)
923  {
924  mutt_error(_("Decryption failed"));
925  goto bail;
926  }
927 
928  e_new->security |= sec_type;
929  b->type = TYPE_TEXT;
930  mutt_str_replace(&b->subtype, "plain");
931  }
932  else
933  mutt_decode_attachment(b, &s);
934 
935  if (mutt_file_fclose(&s.fp_out) != 0)
936  goto bail;
937 
939  b->unlink = true;
940 
942 
943  mutt_body_free(&b->parts);
944  if (b->email)
945  b->email->body = NULL; /* avoid dangling pointer */
946  }
947 
948  const bool c_crypt_protected_headers_read =
949  cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
950  if (c_crypt_protected_headers_read && protected_headers && protected_headers->subject &&
951  !mutt_str_equal(e_new->env->subject, protected_headers->subject))
952  {
953  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
954  }
955  mutt_env_free(&protected_headers);
956 
957  /* Fix encryption flags. */
958 
959  /* No inline if multipart. */
960  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->body->next)
961  e_new->security &= ~SEC_INLINE;
962 
963  /* Do we even support multiple mechanisms? */
964  e_new->security &= WithCrypto | ~(APPLICATION_PGP | APPLICATION_SMIME);
965 
966  /* Theoretically, both could be set. Take the one the user wants to set by default. */
967  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
968  {
969  const bool c_smime_is_default =
970  cs_subset_bool(NeoMutt->sub, "smime_is_default");
971  if (c_smime_is_default)
972  e_new->security &= ~APPLICATION_PGP;
973  else
974  e_new->security &= ~APPLICATION_SMIME;
975  }
976 
978 
979  rc = 0;
980 
981 bail:
982 
983  /* that's it. */
985  if (fp_body != fp)
986  mutt_file_fclose(&fp_body);
987  if (msg)
988  mx_msg_close(m, &msg);
989 
990  if (rc == -1)
991  {
992  mutt_env_free(&e_new->env);
993  mutt_body_free(&e_new->body);
994  }
995 
996  return rc;
997 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1861
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:892
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define WithCrypto
Definition: lib.h:113
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
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
struct Body * body
List of MIME parts.
Definition: email.h:91
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define mutt_error(...)
Definition: logging.h:88
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#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:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:82
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
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:1186
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
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:460
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:90
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:420
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:496
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
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 APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:126
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
A local copy of an email.
Definition: mxapi.h:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Type: &#39;text/*&#39;.
Definition: mime.h:38
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:463
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
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, ContentType
Definition: body.h:65
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1678
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_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
FILE * fp
pointer to the message data
Definition: mxapi.h:43
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:83
#define mutt_message(...)
Definition: logging.h:87
#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:1604
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1140
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:87
+ 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,
struct Mailbox m,
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
[in]mMailbox
[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 150 of file enter.c.

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

Recall a postponed message.

Parameters
[in]m_curCurrent mailbox
[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 424 of file postpone.c.

426 {
427  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
428  if (!c_postponed)
429  return -1;
430 
431  struct Email *e = NULL;
432  int rc = SEND_POSTPONED;
433  const char *p = NULL;
434 
435  struct Mailbox *m = mx_path_resolve(c_postponed);
436  if (m_cur != m)
437  {
438  if (!mx_mbox_open(m, MUTT_NOSORT))
439  {
440  PostCount = 0;
441  mutt_error(_("No postponed messages"));
442  mailbox_free(&m);
443  return -1;
444  }
445  }
446 
447  mx_mbox_check(m);
448 
449  if (m->msg_count == 0)
450  {
451  PostCount = 0;
452  mutt_error(_("No postponed messages"));
453  if (m_cur != m)
454  {
456  }
457  return -1;
458  }
459 
460  /* avoid the "purge deleted messages" prompt */
461  const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
462  cs_subset_str_native_set(NeoMutt->sub, "delete", MUTT_YES, NULL);
463 
464  struct Context *ctx = (m_cur != m) ? ctx_new(m) : NULL;
465  if (m->msg_count == 1)
466  {
467  /* only one message, so just use that one. */
468  e = m->emails[0];
469  }
470  else if (!(e = dlg_select_postponed_email(m)))
471  {
472  rc = -1;
473  goto cleanup;
474  }
475 
476  if (mutt_prepare_template(NULL, m, hdr, e, false) < 0)
477  {
478  rc = -1;
479  goto cleanup;
480  }
481 
482  /* finished with this message, so delete it. */
483  mutt_set_flag(m, e, MUTT_DELETE, true);
484  mutt_set_flag(m, e, MUTT_PURGE, true);
485 
486  /* update the count for the status display */
487  PostCount = m->msg_count - m->msg_deleted;
488 
489  struct ListNode *np = NULL, *tmp = NULL;
490  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
491  {
492  size_t plen = mutt_istr_startswith(np->data, "X-Mutt-References:");
493  if (plen)
494  {
495  /* if a mailbox is currently open, look to see if the original message
496  * the user attempted to reply to is in this mailbox */
497  p = mutt_str_skip_email_wsp(np->data + plen);
498  if (!m_cur->id_hash)
499  m_cur->id_hash = mutt_make_id_hash(m_cur);
500  *cur = mutt_hash_find(m_cur->id_hash, p);
501 
502  if (*cur)
503  rc |= SEND_REPLY;
504  }
505  else if ((plen = mutt_istr_startswith(np->data, "X-Mutt-Fcc:")))
506  {
507  p = mutt_str_skip_email_wsp(np->data + plen);
508  mutt_buffer_strcpy(fcc, p);
510 
511  /* note that x-mutt-fcc was present. we do this because we want to add a
512  * default fcc if the header was missing, but preserve the request of the
513  * user to not make a copy if the header field is present, but empty.
514  * see http://dev.mutt.org/trac/ticket/3653 */
515  rc |= SEND_POSTPONED_FCC;
516  }
517  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
518  /* this is generated by old neomutt versions */
519  (mutt_str_startswith(np->data, "Pgp:") ||
520  /* this is the new way */
521  mutt_str_startswith(np->data, "X-Mutt-PGP:")))
522  {
523  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
524  hdr->security |= APPLICATION_PGP;
525  }
526  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
527  mutt_str_startswith(np->data, "X-Mutt-SMIME:"))
528  {
529  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
530  hdr->security |= APPLICATION_SMIME;
531  }
532 #ifdef MIXMASTER
533  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:"))
534  {
535  mutt_list_free(&hdr->chain);
536 
537  char *t = strtok(np->data + 11, " \t\n");
538  while (t)
539  {
541  t = strtok(NULL, " \t\n");
542  }
543  }
544 #endif
545  else
546  {
547  // skip header removal
548  continue;
549  }
550 
551  // remove the header
552  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
553  FREE(&np->data);
554  FREE(&np);
555  }
556 
557  const bool c_crypt_opportunistic_encrypt =
558  cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
559  if (c_crypt_opportunistic_encrypt)
560  crypt_opportunistic_encrypt(m_cur, hdr);
561 
562 cleanup:
563  if (m_cur != m)
564  {
565  hardclose(m);
566  ctx_free(&ctx);
567  }
568 
569  cs_subset_str_native_set(NeoMutt->sub, "delete", c_delete, NULL);
570  return rc;
571 }
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
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:402
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define WithCrypto
Definition: lib.h:113
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:48
The envelope/body of an email.
Definition: email.h:37
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
#define mutt_error(...)
Definition: logging.h:88
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1658
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:96
static void hardclose(struct Mailbox *m)
try hard to close a mailbox
Definition: postpone.c:403
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:44
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:603
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
enum MxStatus mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1119
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
void crypt_opportunistic_encrypt(struct Mailbox *m, struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1054
struct Envelope * env
Envelope information.
Definition: email.h:90
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:429
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
struct Context * ctx_new(struct Mailbox *m)
Create a new Context.
Definition: context.c:77
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
Messages to be deleted.
Definition: mutt.h:94
A mailbox.
Definition: mailbox.h:81
static short PostCount
Definition: postpone.c:116
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
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:40
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition: postpone.c:580
char * data
String.
Definition: list.h:36
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:49
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:61
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:736
static struct Email * dlg_select_postponed_email(struct Mailbox *m)
Create a Menu to select a postponed message.
Definition: postpone.c:314
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ 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 580 of file postpone.c.

581 {
582  char smime_cryptalg[1024] = { 0 };
583  char sign_as[1024] = { 0 };
584  char *q = NULL;
585  SecurityFlags flags = SEC_NO_FLAGS;
586 
587  if (!WithCrypto)
588  return SEC_NO_FLAGS;
589 
591  for (; p[0] != '\0'; p++)
592  {
593  switch (p[0])
594  {
595  case 'c':
596  case 'C':
597  q = smime_cryptalg;
598 
599  if (p[1] == '<')
600  {
601  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
602  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
603  *q++ = *p++)
604  {
605  }
606 
607  if (p[0] != '>')
608  {
609  mutt_error(_("Illegal S/MIME header"));
610  return SEC_NO_FLAGS;
611  }
612  }
613 
614  *q = '\0';
615  break;
616 
617  case 'e':
618  case 'E':
619  flags |= SEC_ENCRYPT;
620  break;
621 
622  case 'i':
623  case 'I':
624  flags |= SEC_INLINE;
625  break;
626 
627  /* This used to be the micalg parameter.
628  *
629  * It's no longer needed, so we just skip the parameter in order
630  * to be able to recall old messages. */
631  case 'm':
632  case 'M':
633  if (p[1] != '<')
634  break;
635 
636  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
637  ; // do nothing
638 
639  if (p[0] != '>')
640  {
641  mutt_error(_("Illegal crypto header"));
642  return SEC_NO_FLAGS;
643  }
644  break;
645 
646  case 'o':
647  case 'O':
648  flags |= SEC_OPPENCRYPT;
649  break;
650 
651  case 'a':
652  case 'A':
653 #ifdef USE_AUTOCRYPT
654  flags |= SEC_AUTOCRYPT;
655 #endif
656  break;
657 
658  case 'z':
659  case 'Z':
660 #ifdef USE_AUTOCRYPT
661  flags |= SEC_AUTOCRYPT_OVERRIDE;
662 #endif
663  break;
664 
665  case 's':
666  case 'S':
667  flags |= SEC_SIGN;
668  q = sign_as;
669 
670  if (p[1] == '<')
671  {
672  for (p += 2;
673  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
674  *q++ = *p++)
675  {
676  }
677 
678  if (p[0] != '>')
679  {
680  mutt_error(_("Illegal crypto header"));
681  return SEC_NO_FLAGS;
682  }
683  }
684 
685  q[0] = '\0';
686  break;
687 
688  default:
689  mutt_error(_("Illegal crypto header"));
690  return SEC_NO_FLAGS;
691  }
692  }
693 
694  /* the cryptalg field must not be empty */
695  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
696  {
697  struct Buffer errmsg = mutt_buffer_make(0);
698  int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
699  smime_cryptalg, &errmsg);
700 
701  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
702  mutt_error("%s", mutt_buffer_string(&errmsg));
703 
704  mutt_buffer_dealloc(&errmsg);
705  }
706 
707  /* Set {Smime,Pgp}SignAs, if desired. */
708 
709  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
710  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
711  {
712  cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", sign_as, NULL);
713  }
714 
715  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
716  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
717  {
718  cs_subset_str_string_set(NeoMutt->sub, "smime_sign_as", sign_as, NULL);
719  }
720 
721  return flags;
722 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define WithCrypto
Definition: lib.h:113
#define mutt_error(...)
Definition: logging.h:88
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:74
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
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:84
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:82
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
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:408
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:85
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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 127 of file postpone.c.

128 {
129  struct stat st;
130 
131  static time_t LastModify = 0;
132  static char *OldPostponed = NULL;
133 
134  if (UpdateNumPostponed)
135  {
136  UpdateNumPostponed = false;
137  force = true;
138  }
139 
140  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
141  if (!mutt_str_equal(c_postponed, OldPostponed))
142  {
143  FREE(&OldPostponed);
144  OldPostponed = mutt_str_dup(c_postponed);
145  LastModify = 0;
146  force = true;
147  }
148 
149  if (!c_postponed)
150  return 0;
151 
152  // We currently are in the `$postponed` mailbox so just pick the current status
153  if (m && mutt_str_equal(c_postponed, m->realpath))
154  {
155  PostCount = m->msg_count - m->msg_deleted;
156  return PostCount;
157  }
158 
159 #ifdef USE_IMAP
160  /* LastModify is useless for IMAP */
161  if (imap_path_probe(c_postponed, NULL) == MUTT_IMAP)
162  {
163  if (force)
164  {
165  short newpc;
166 
167  newpc = imap_path_status(c_postponed, false);
168  if (newpc >= 0)
169  {
170  PostCount = newpc;
171  mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", PostCount);
172  }
173  else
174  mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
175  }
176  return PostCount;
177  }
178 #endif
179 
180  if (stat(c_postponed, &st) == -1)
181  {
182  PostCount = 0;
183  LastModify = 0;
184  return 0;
185  }
186 
187  if (S_ISDIR(st.st_mode))
188  {
189  /* if we have a maildir mailbox, we need to stat the "new" dir */
190  struct Buffer *buf = mutt_buffer_pool_get();
191 
192  mutt_buffer_printf(buf, "%s/new", c_postponed);
193  if ((access(mutt_buffer_string(buf), F_OK) == 0) &&
194  (stat(mutt_buffer_string(buf), &st) == -1))
195  {
196  PostCount = 0;
197  LastModify = 0;
199  return 0;
200  }
202  }
203 
204  if (LastModify < st.st_mtime)
205  {
206 #ifdef USE_NNTP
207  int optnews = OptNews;
208 #endif
209  LastModify = st.st_mtime;
210 
211  if (access(c_postponed, R_OK | F_OK) != 0)
212  return PostCount = 0;
213 #ifdef USE_NNTP
214  if (optnews)
215  OptNews = false;
216 #endif
217  struct Mailbox *m_post = mx_path_resolve(c_postponed);
218  if (mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET))
219  {
220  PostCount = m_post->msg_count;
221  }
222  else
223  {
224  mailbox_free(&m_post);
225  PostCount = 0;
226  }
227  mx_fastclose_mailbox(m_post);
228 #ifdef USE_NNTP
229  if (optnews)
230  OptNews = true;
231 #endif
232  }
233 
234  return PostCount;
235 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
int msg_count
Total number of messages.
Definition: mailbox.h:91
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
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:1235
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
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:429
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
A mailbox.
Definition: mailbox.h:81
static short PostCount
Definition: postpone.c:116
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:64
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
static bool UpdateNumPostponed
Definition: postpone.c:117
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:61
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:44
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 Mailbox m,
struct Email e,
enum MessageType  flag,
bool  bf,
bool  subthread 
)

Set a flag on an entire thread.

Parameters
mMailbox
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 375 of file flags.c.

377 {
378  struct MuttThread *start = NULL;
379  struct MuttThread *cur = e->thread;
380 
381  if (!mutt_using_threads())
382  {
383  mutt_error(_("Threading is not enabled"));
384  return -1;
385  }
386 
387  if (!subthread)
388  while (cur->parent)
389  cur = cur->parent;
390  start = cur;
391 
392  if (cur->message && (cur != e->thread))
393  mutt_set_flag(m, cur->message, flag, bf);
394 
395  cur = cur->child;
396  if (!cur)
397  goto done;
398 
399  while (true)
400  {
401  if (cur->message && (cur != e->thread))
402  mutt_set_flag(m, cur->message, flag, bf);
403 
404  if (cur->child)
405  cur = cur->child;
406  else if (cur->next)
407  cur = cur->next;
408  else
409  {
410  while (!cur->next)
411  {
412  cur = cur->parent;
413  if (cur == start)
414  goto done;
415  }
416  cur = cur->next;
417  }
418  }
419 done:
420  cur = e->thread;
421  if (cur->message)
422  mutt_set_flag(m, cur->message, flag, bf);
423  return 0;
424 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
#define mutt_error(...)
Definition: logging.h:88
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
#define _(a)
Definition: message.h:28
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
#define mutt_using_threads()
Definition: mutt_thread.h:95
An Email conversation.
Definition: thread.h:34
+ 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 240 of file postpone.c.

241 {
242  UpdateNumPostponed = true;
243 }
static bool UpdateNumPostponed
Definition: postpone.c:117
+ 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 $quote_regex and doesn't match $smileys. This is used by the pager for calling classify_quote.

Definition at line 968 of file dlg_pager.c.

969 {
970  bool is_quote = false;
971  const struct Regex *c_smileys = cs_subset_regex(NeoMutt->sub, "smileys");
972  regmatch_t pmatch_internal[1], smatch[1];
973 
974  if (!pmatch)
975  pmatch = pmatch_internal;
976 
977  const struct Regex *c_quote_regex =
978  cs_subset_regex(NeoMutt->sub, "quote_regex");
979  if (mutt_regex_capture(c_quote_regex, line, 1, pmatch))
980  {
981  if (mutt_regex_capture(c_smileys, line, 1, smatch))
982  {
983  if (smatch[0].rm_so > 0)
984  {
985  char c = line[smatch[0].rm_so];
986  line[smatch[0].rm_so] = 0;
987 
988  if (mutt_regex_capture(c_quote_regex, line, 1, pmatch))
989  is_quote = true;
990 
991  line[smatch[0].rm_so] = c;
992  }
993  }
994  else
995  is_quote = true;
996  }
997 
998  return is_quote;
999 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
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:596
Cached regular expression.
Definition: regex3.h:89
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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)