NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
23
29
30#include "config.h"
31#include <stdbool.h>
32#include <stdio.h>
33#include "mutt/lib.h"
34#include "config/lib.h"
35#include "email/lib.h"
36#include "core/lib.h"
37#include "gui/lib.h"
38#include "functions.h"
39#include "key/lib.h"
40#include "menu/lib.h"
41#include "ncrypt/lib.h"
42#include "question/lib.h"
43#include "send/lib.h"
44#include "attach.h"
45#include "module_data.h"
46#include "mutt_attach.h"
47#include "private_data.h"
48#include "recvattach.h"
49#include "recvcmd.h"
50
53 "Function not permitted in attach-message mode");
54
55// clang-format off
59static const struct MenuFuncOp OpAttach[] = { /* map: attach */
60 { "bounce-message", OP_BOUNCE_MESSAGE },
61 { "check-traditional-pgp", OP_CHECK_TRADITIONAL },
62 { "collapse-parts", OP_ATTACH_COLLAPSE },
63 { "compose-to-sender", OP_COMPOSE_TO_SENDER },
64 { "delete-entry", OP_ATTACH_DELETE },
65 { "display-toggle-weed", OP_DISPLAY_HEADERS },
66 { "edit-type", OP_ATTACH_EDIT_TYPE },
67 { "extract-keys", OP_EXTRACT_KEYS },
68 { "followup-message", OP_FOLLOWUP },
69 { "forward-message", OP_FORWARD_MESSAGE },
70 { "forward-to-group", OP_FORWARD_TO_GROUP },
71 { "group-chat-reply", OP_GROUP_CHAT_REPLY },
72 { "group-reply", OP_GROUP_REPLY },
73 { "list-reply", OP_LIST_REPLY },
74 { "list-subscribe", OP_LIST_SUBSCRIBE },
75 { "list-unsubscribe", OP_LIST_UNSUBSCRIBE },
76 { "pipe-entry", OP_PIPE },
77 { "pipe-message", OP_PIPE },
78 { "print-entry", OP_ATTACH_PRINT },
79 { "reply", OP_REPLY },
80 { "resend-message", OP_RESEND },
81 { "save-entry", OP_ATTACH_SAVE },
82 { "undelete-entry", OP_ATTACH_UNDELETE },
83 { "view-attach", OP_ATTACH_VIEW },
84 { "view-mailcap", OP_ATTACH_VIEW_MAILCAP },
85 { "view-pager", OP_ATTACH_VIEW_PAGER },
86 { "view-text", OP_ATTACH_VIEW_TEXT },
87 { NULL, 0 },
88};
89
93static const struct MenuOpSeq AttachDefaultBindings[] = { /* map: attach */
94 { OP_ATTACH_COLLAPSE, "v" },
95 { OP_ATTACH_DELETE, "d" },
96 { OP_ATTACH_EDIT_TYPE, "\005" }, // <Ctrl-E>
97 { OP_PIPE, "|" },
98 { OP_ATTACH_PRINT, "p" },
99 { OP_ATTACH_SAVE, "s" },
100 { OP_ATTACH_UNDELETE, "u" },
101 { OP_ATTACH_VIEW, "<keypadenter>" },
102 { OP_ATTACH_VIEW, "\n" }, // <Enter>
103 { OP_ATTACH_VIEW, "\r" }, // <Return>
104 { OP_ATTACH_VIEW_MAILCAP, "m" },
105 { OP_ATTACH_VIEW_TEXT, "T" },
106 { OP_BOUNCE_MESSAGE, "b" },
107 { OP_CHECK_TRADITIONAL, "\033P" }, // <Alt-P>
108 { OP_DISPLAY_HEADERS, "h" },
109 { OP_EXTRACT_KEYS, "\013" }, // <Ctrl-K>
110 { OP_FORGET_PASSPHRASE, "\006" }, // <Ctrl-F>
111 { OP_FORWARD_MESSAGE, "f" },
112 { OP_GROUP_REPLY, "g" },
113 { OP_LIST_REPLY, "L" },
114 { OP_REPLY, "r" },
115 { OP_RESEND, "\033e" }, // <Alt-e>
116 { 0, NULL },
117};
118// clang-format on
119
123void attach_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
124{
126 ASSERT(mod_data);
127
128 struct MenuDefinition *md = NULL;
129 struct SubMenu *sm = NULL;
130
132 md = km_register_menu(MENU_ATTACH, "attach");
133 km_menu_add_submenu(md, sm);
134 km_menu_add_submenu(md, sm_generic);
136
137 mod_data->menu_attach = md;
138}
139
146static void attach_collapse(struct AttachCtx *actx, struct Menu *menu, struct ConfigSubset *sub)
147{
148 int rindex;
149 int curlevel;
150
151 struct AttachPtr *cur_att = current_attachment(actx, menu);
152 cur_att->collapsed = !cur_att->collapsed;
153 /* When expanding, expand all the children too */
154 if (cur_att->collapsed)
155 return;
156
157 curlevel = cur_att->level;
158 const int index = menu_get_index(menu);
159 rindex = actx->v2r[index] + 1;
160
161 const bool c_digest_collapse = cs_subset_bool(sub, "digest_collapse");
162 while ((rindex < actx->idxlen) && (actx->idx[rindex]->level > curlevel))
163 {
164 if (c_digest_collapse && (actx->idx[rindex]->body->type == TYPE_MULTIPART) &&
165 mutt_istr_equal(actx->idx[rindex]->body->subtype, "digest"))
166 {
167 actx->idx[rindex]->collapsed = true;
168 }
169 else
170 {
171 actx->idx[rindex]->collapsed = false;
172 }
173 rindex++;
174 }
175}
176
182static bool check_attach(struct AttachPrivateData *priv)
183{
184 if (priv->attach_msg)
185 {
188 return true;
189 }
190
191 return false;
192}
193
199static bool check_readonly(struct Mailbox *m)
200{
201 if (!m || m->readonly)
202 {
204 mutt_error(_("Mailbox is read-only"));
205 return true;
206 }
207
208 return false;
209}
210
215static void recvattach_extract_pgp_keys(struct AttachPtrArray *aa)
216{
217 struct AttachPtr **app = NULL;
218 ARRAY_FOREACH(app, aa)
219 {
220 crypt_pgp_extract_key_from_attachment((*app)->fp, (*app)->body);
221 }
222}
223
229static int recvattach_pgp_check_traditional(struct AttachPtrArray *aa)
230{
231 int rc = 0;
232
233 struct AttachPtr **app = NULL;
234 ARRAY_FOREACH(app, aa)
235 {
236 rc = rc || crypt_pgp_check_traditional((*app)->fp, (*app)->body, true);
237 }
238
239 return rc;
240}
241
242// -----------------------------------------------------------------------------
243
247static int op_attach_collapse(struct AttachFunctionData *fdata, const struct KeyEvent *event)
248{
249 struct AttachPrivateData *priv = fdata->priv;
250 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
251 if (!cur_att->body->parts)
252 {
253 mutt_error(_("There are no subparts to show"));
254 return FR_ERROR;
255 }
256 attach_collapse(priv->actx, priv->menu, fdata->n->sub);
257 mutt_update_recvattach_menu(priv->actx, priv->menu, false);
258 return FR_SUCCESS;
259}
260
271static void attach_apply_set_deleted(struct AttachPtrArray *apa, bool deleted,
272 int *num_changed, int *num_blocked)
273{
274 int changed = 0;
275 int blocked = 0;
276
277 if (apa)
278 {
279 struct AttachPtr **app = NULL;
280 ARRAY_FOREACH(app, apa)
281 {
282 struct AttachPtr *ap = *app;
283 if (!ap || !ap->body)
284 continue;
285
286 if (deleted && (ap->parent_type != TYPE_MULTIPART))
287 {
288 blocked++;
289 continue;
290 }
291
292 ap->body->deleted = deleted;
293 changed++;
294 }
295 }
296
297 if (num_changed)
298 *num_changed = changed;
299 if (num_blocked)
300 *num_blocked = blocked;
301}
302
311static int op_attach_delete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
312{
313 struct AttachPrivateData *priv = fdata->priv;
314 if (check_readonly(priv->mailbox))
315 return FR_ERROR;
316
317 if (priv->mailbox->type == MUTT_POP)
318 {
320 mutt_error(_("Can't delete attachment from POP server"));
321 return FR_ERROR;
322 }
323
324 if (priv->mailbox->type == MUTT_NNTP)
325 {
327 mutt_error(_("Can't delete attachment from news server"));
328 return FR_ERROR;
329 }
330
331 if ((WithCrypto != 0) && (priv->actx->email->security & SEC_ENCRYPT))
332 {
333 mutt_message(_("Deletion of attachments from encrypted messages is unsupported"));
334 return FR_ERROR;
335 }
336 if ((WithCrypto != 0) && (priv->actx->email->security & (SEC_SIGN | SEC_PARTSIGN)))
337 {
338 mutt_message(_("Deletion of attachments from signed messages may invalidate the signature"));
339 }
340
341 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
342 if (aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix,
343 event->count) < 0)
344 {
345 ARRAY_FREE(&aa);
346 return FR_ERROR;
347 }
348
349 if (ARRAY_EMPTY(&aa))
350 {
351 ARRAY_FREE(&aa);
352 return FR_NO_ACTION;
353 }
354
355 int changed = 0;
356 int blocked = 0;
357 attach_apply_set_deleted(&aa, true, &changed, &blocked);
358 const int num = ARRAY_SIZE(&aa);
359 ARRAY_FREE(&aa);
360
361 if (blocked > 0)
362 mutt_message(_("Only deletion of multipart attachments is supported"));
363
364 if (changed == 0)
365 return blocked ? FR_ERROR : FR_NO_ACTION;
366
367 if (priv->menu->tag_prefix)
368 {
370 }
371 else
372 {
373 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
374 const int next = menu_get_index(priv->menu) + num;
375 if (c_resolve && (next < priv->menu->max))
376 {
377 menu_set_index(priv->menu, next);
378 }
379 else
380 {
382 }
383 }
384
385 return FR_SUCCESS;
386}
387
391static int op_attach_edit_type(struct AttachFunctionData *fdata, const struct KeyEvent *event)
392{
393 struct AttachPrivateData *priv = fdata->priv;
394 recvattach_edit_content_type(priv->actx, priv->menu, priv->actx->email);
396 return FR_SUCCESS;
397}
398
402static int op_attach_pipe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
403{
404 struct AttachPrivateData *priv = fdata->priv;
405 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
406 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
407 mutt_pipe_attachment_list(&aa, false);
408 ARRAY_FREE(&aa);
409 return FR_SUCCESS;
410}
411
415static int op_attach_print(struct AttachFunctionData *fdata, const struct KeyEvent *event)
416{
417 struct AttachPrivateData *priv = fdata->priv;
418 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
419 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
421 ARRAY_FREE(&aa);
422 return FR_SUCCESS;
423}
424
428static int op_attach_save(struct AttachFunctionData *fdata, const struct KeyEvent *event)
429{
430 struct AttachPrivateData *priv = fdata->priv;
431 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
432 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
433 mutt_save_attachment_list(&aa, priv->actx->email, priv->menu);
434
435 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
436 const int index = menu_get_index(priv->menu) + 1;
437 if ((ARRAY_SIZE(&aa) == 1) && c_resolve && (index < priv->menu->max))
438 menu_set_index(priv->menu, index);
439 ARRAY_FREE(&aa);
440 return FR_SUCCESS;
441}
442
449static int op_attach_undelete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
450{
451 struct AttachPrivateData *priv = fdata->priv;
452 if (check_readonly(priv->mailbox))
453 return FR_ERROR;
454
455 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
456 if (aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix,
457 event->count) < 0)
458 {
459 ARRAY_FREE(&aa);
460 return FR_ERROR;
461 }
462
463 if (ARRAY_EMPTY(&aa))
464 {
465 ARRAY_FREE(&aa);
466 return FR_NO_ACTION;
467 }
468
469 attach_apply_set_deleted(&aa, false, NULL, NULL);
470 const int num = ARRAY_SIZE(&aa);
471 ARRAY_FREE(&aa);
472
473 if (priv->menu->tag_prefix)
474 {
476 }
477 else
478 {
479 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
480 const int next = menu_get_index(priv->menu) + num;
481 if (c_resolve && (next < priv->menu->max))
482 {
483 menu_set_index(priv->menu, next);
484 }
485 else
486 {
488 }
489 }
490
491 return FR_SUCCESS;
492}
493
501static int op_attach_view(struct AttachFunctionData *fdata, const struct KeyEvent *event)
502{
503 struct AttachPrivateData *priv = fdata->priv;
504 priv->op = mutt_attach_display_loop(priv->sub, priv->menu, event->op,
505 priv->actx->email, priv->actx, true);
507
508 return FR_CONTINUE;
509}
510
514static int op_attach_view_mailcap(struct AttachFunctionData *fdata, const struct KeyEvent *event)
515{
516 struct AttachPrivateData *priv = fdata->priv;
517 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
518 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_MAILCAP,
519 priv->actx->email, priv->actx, priv->menu->win);
521 return FR_SUCCESS;
522}
523
527static int op_attach_view_pager(struct AttachFunctionData *fdata, const struct KeyEvent *event)
528{
529 struct AttachPrivateData *priv = fdata->priv;
530 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
531 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_PAGER,
532 priv->actx->email, priv->actx, priv->menu->win);
534 return FR_SUCCESS;
535}
536
540static int op_attach_view_text(struct AttachFunctionData *fdata, const struct KeyEvent *event)
541{
542 struct AttachPrivateData *priv = fdata->priv;
543 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
544 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_AS_TEXT,
545 priv->actx->email, priv->actx, priv->menu->win);
547 return FR_SUCCESS;
548}
549
553static int op_bounce_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
554{
555 struct AttachPrivateData *priv = fdata->priv;
556 if (check_attach(priv))
557 return FR_ERROR;
558 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
559 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
560 attach_bounce_message(&aa, priv->mailbox);
561 ARRAY_FREE(&aa);
563 return FR_SUCCESS;
564}
565
569static int op_check_traditional(struct AttachFunctionData *fdata, const struct KeyEvent *event)
570{
571 struct AttachPrivateData *priv = fdata->priv;
572 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
573 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
575 {
576 priv->actx->email->security = crypt_query(NULL);
578 }
579 ARRAY_FREE(&aa);
580 return FR_SUCCESS;
581}
582
586static int op_compose_to_sender(struct AttachFunctionData *fdata, const struct KeyEvent *event)
587{
588 struct AttachPrivateData *priv = fdata->priv;
589 if (check_attach(priv))
590 return FR_ERROR;
591 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
592 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
594 ARRAY_FREE(&aa);
596 return FR_SUCCESS;
597}
598
602static int op_quit(struct AttachFunctionData *fdata, const struct KeyEvent *event)
603{
604 struct AttachPrivateData *priv = fdata->priv;
605 priv->actx->email->attach_del = false;
606 for (int i = 0; i < priv->actx->idxlen; i++)
607 {
608 if (priv->actx->idx[i]->body && priv->actx->idx[i]->body->deleted)
609 {
610 priv->actx->email->attach_del = true;
611 break;
612 }
613 }
614 if (priv->actx->email->attach_del)
615 priv->actx->email->changed = true;
616
617 mutt_actx_free(&priv->actx);
618 return FR_DONE;
619}
620
624static int op_extract_keys(struct AttachFunctionData *fdata, const struct KeyEvent *event)
625{
626 struct AttachPrivateData *priv = fdata->priv;
628 return FR_NO_ACTION;
629
630 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
631 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
633 ARRAY_FREE(&aa);
635
636 return FR_SUCCESS;
637}
638
642static int op_forward_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
643{
644 struct AttachPrivateData *priv = fdata->priv;
645 if (check_attach(priv))
646 return FR_ERROR;
647 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
648 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
649 mutt_attach_forward(&aa, priv->actx->email, priv->actx, SEND_NONE);
650 ARRAY_FREE(&aa);
652 return FR_SUCCESS;
653}
654
658static int op_list_subscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
659{
660 struct AttachPrivateData *priv = fdata->priv;
661 if (check_attach(priv))
662 return FR_ERROR;
663
665}
666
670static int op_list_unsubscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
671{
672 struct AttachPrivateData *priv = fdata->priv;
673 if (check_attach(priv))
674 return FR_ERROR;
675
677}
678
688static int op_reply(struct AttachFunctionData *fdata, const struct KeyEvent *event)
689{
690 struct AttachPrivateData *priv = fdata->priv;
691 if (check_attach(priv))
692 return FR_ERROR;
693
694 const int op = event->op;
695 SendFlags flags = SEND_REPLY;
696 if (op == OP_GROUP_REPLY)
697 flags |= SEND_GROUP_REPLY;
698 else if (op == OP_GROUP_CHAT_REPLY)
699 flags |= SEND_GROUP_CHAT_REPLY;
700 else if (op == OP_LIST_REPLY)
701 flags |= SEND_LIST_REPLY;
702
703 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
704 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
705 mutt_attach_reply(&aa, priv->mailbox, priv->actx->email, priv->actx, flags);
706 ARRAY_FREE(&aa);
708 return FR_SUCCESS;
709}
710
714static int op_resend(struct AttachFunctionData *fdata, const struct KeyEvent *event)
715{
716 struct AttachPrivateData *priv = fdata->priv;
717 if (check_attach(priv))
718 return FR_ERROR;
719 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
720 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
721 mutt_attach_resend(&aa, priv->mailbox);
722 ARRAY_FREE(&aa);
724 return FR_SUCCESS;
725}
726
727// -----------------------------------------------------------------------------
728
732static int op_followup(struct AttachFunctionData *fdata, const struct KeyEvent *event)
733{
734 struct AttachPrivateData *priv = fdata->priv;
735 if (check_attach(priv))
736 return FR_ERROR;
737
738 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
739 if (!cur_att->body->email || !cur_att->body->email->env)
740 {
741 mutt_error(_("You may only followup to message/rfc822 parts"));
742 return FR_ERROR;
743 }
744 if (!cur_att->body->email->env->followup_to ||
745 !mutt_istr_equal(cur_att->body->email->env->followup_to, "poster") ||
746 (query_quadoption(_("Reply by mail as poster prefers?"), fdata->n->sub,
747 "followup_to_poster") != MUTT_YES))
748 {
749 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
750 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
751 mutt_attach_reply(&aa, priv->mailbox, priv->actx->email, priv->actx, SEND_NEWS | SEND_REPLY);
752 ARRAY_FREE(&aa);
754 return FR_SUCCESS;
755 }
756
757 return op_reply(fdata, event);
758}
759
763static int op_forward_to_group(struct AttachFunctionData *fdata, const struct KeyEvent *event)
764{
765 struct AttachPrivateData *priv = fdata->priv;
766 if (check_attach(priv))
767 return FR_ERROR;
768 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
769 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
770 mutt_attach_forward(&aa, priv->actx->email, priv->actx, SEND_NEWS);
771 ARRAY_FREE(&aa);
773 return FR_SUCCESS;
774}
775
776// -----------------------------------------------------------------------------
777
781static const struct AttachFunction AttachFunctions[] = {
782 // clang-format off
783 { OP_ATTACH_COLLAPSE, op_attach_collapse },
784 { OP_ATTACH_DELETE, op_attach_delete },
785 { OP_ATTACH_EDIT_TYPE, op_attach_edit_type },
786 { OP_ATTACH_PRINT, op_attach_print },
787 { OP_ATTACH_SAVE, op_attach_save },
788 { OP_ATTACH_UNDELETE, op_attach_undelete },
789 { OP_ATTACH_VIEW, op_attach_view },
790 { OP_ATTACH_VIEW_MAILCAP, op_attach_view_mailcap },
791 { OP_ATTACH_VIEW_PAGER, op_attach_view_pager },
792 { OP_ATTACH_VIEW_TEXT, op_attach_view_text },
793 { OP_BOUNCE_MESSAGE, op_bounce_message },
794 { OP_CHECK_TRADITIONAL, op_check_traditional },
795 { OP_COMPOSE_TO_SENDER, op_compose_to_sender },
796 { OP_DISPLAY_HEADERS, op_attach_view },
797 { OP_EXIT, op_quit },
798 { OP_EXTRACT_KEYS, op_extract_keys },
799 { OP_FOLLOWUP, op_followup },
800 { OP_FORWARD_MESSAGE, op_forward_message },
801 { OP_FORWARD_TO_GROUP, op_forward_to_group },
802 { OP_GROUP_CHAT_REPLY, op_reply },
803 { OP_GROUP_REPLY, op_reply },
804 { OP_LIST_REPLY, op_reply },
805 { OP_LIST_SUBSCRIBE, op_list_subscribe },
806 { OP_LIST_UNSUBSCRIBE, op_list_unsubscribe },
807 { OP_PIPE, op_attach_pipe },
808 { OP_QUIT, op_quit },
809 { OP_REPLY, op_reply },
810 { OP_RESEND, op_resend },
811 { 0, NULL },
812 // clang-format on
813};
814
818int attach_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
819{
820 // The Dispatcher may be called on any Window in the Dialog
821 struct MuttWindow *dlg = dialog_find(win);
822 if (!event || !dlg || !dlg->wdata)
823 {
825 return FR_ERROR;
826 }
827
828 struct Menu *menu = dlg->wdata;
829 struct AttachPrivateData *priv = menu->mdata;
830 if (!priv)
831 {
833 return FR_ERROR;
834 }
835
836 const int op = event->op;
837
838 struct AttachFunctionData fdata = {
839 .n = NeoMutt,
840 .priv = priv,
841 };
842
843 int rc = FR_UNKNOWN;
844 for (size_t i = 0; AttachFunctions[i].op != OP_NULL; i++)
845 {
846 const struct AttachFunction *fn = &AttachFunctions[i];
847 if (fn->op == op)
848 {
849 rc = fn->function(&fdata, event);
850 break;
851 }
852 }
853
855 return rc;
856}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
void mutt_actx_free(struct AttachCtx **ptr)
Free an Attachment Context.
Definition attach.c:198
static const struct MenuFuncOp OpAttach[]
Functions for the Attach Menu.
Definition functions.c:59
static bool check_attach(struct AttachPrivateData *priv)
Check if in attach-message mode.
Definition functions.c:182
static int recvattach_pgp_check_traditional(struct AttachPtrArray *aa)
Is the Attachment inline PGP?
Definition functions.c:229
static void attach_collapse(struct AttachCtx *actx, struct Menu *menu, struct ConfigSubset *sub)
Close the tree of the current attachment.
Definition functions.c:146
static void attach_apply_set_deleted(struct AttachPtrArray *apa, bool deleted, int *num_changed, int *num_blocked)
Apply the deleted flag to a working set of attachments.
Definition functions.c:271
static void recvattach_extract_pgp_keys(struct AttachPtrArray *aa)
Extract PGP keys from attachments.
Definition functions.c:215
static const struct MenuOpSeq AttachDefaultBindings[]
Key bindings for the Attachment Menu.
Definition functions.c:93
static const char * Function_not_permitted_in_attach_message_mode
Error message for unavailable functions in attach mode.
Definition functions.c:52
void attach_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Attach Keybindings - Implements ::init_keys_api.
Definition functions.c:123
static const struct AttachFunction AttachFunctions[]
All the NeoMutt functions that the Attach supports.
Definition functions.c:781
static bool check_readonly(struct Mailbox *m)
Check if the Mailbox is readonly.
Definition functions.c:199
Attachment functions.
Attach private Module data.
Private state data for Attachments.
Handling of email attachments.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:51
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:48
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:693
bool crypt_pgp_check_traditional(FILE *fp, struct Body *b, bool just_one)
Wrapper for CryptModuleSpecs::pgp_check_traditional()
Definition cryptglue.c:321
void crypt_pgp_extract_key_from_attachment(FILE *fp, struct Body *b)
Wrapper for CryptModuleSpecs::pgp_extract_key_from_attachment()
Definition cryptglue.c:460
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition dialog.c:89
void dispatcher_flush_on_error(int rv)
Flush pending keys after a dispatch error.
Definition dispatcher.c:65
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_DONE
Exit the Dialog.
Definition dispatcher.h:36
@ FR_UNKNOWN
Unknown function.
Definition dispatcher.h:34
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
@ FR_CONTINUE
Remain in the Dialog.
Definition dispatcher.h:35
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
Structs that make up an email.
void mutt_flushinp(void)
MacroEvents moved to KeyModuleData UngetKeyEvents moved to KeyModuleData.
Definition get.c:81
static int op_quit(struct AliasFunctionData *fdata, const struct KeyEvent *event)
Save changes and exit this dialog - Implements alias_function_t -.
Definition functions.c:308
static int op_attach_view_text(struct AttachFunctionData *fdata, const struct KeyEvent *event)
view attachment as text - Implements attach_function_t -
Definition functions.c:540
static int op_followup(struct AttachFunctionData *fdata, const struct KeyEvent *event)
followup to newsgroup - Implements attach_function_t -
Definition functions.c:732
static int op_list_unsubscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
unsubscribe from a mailing list - Implements attach_function_t -
Definition functions.c:670
static int op_attach_edit_type(struct AttachFunctionData *fdata, const struct KeyEvent *event)
edit attachment content type - Implements attach_function_t -
Definition functions.c:391
static int op_resend(struct AttachFunctionData *fdata, const struct KeyEvent *event)
use the current message as a template for a new one - Implements attach_function_t -
Definition functions.c:714
static int op_forward_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
forward a message with comments - Implements attach_function_t -
Definition functions.c:642
static int op_attach_delete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
delete the current entry - Implements attach_function_t -
Definition functions.c:311
static int op_attach_undelete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
undelete the current entry - Implements attach_function_t -
Definition functions.c:449
static int op_attach_view(struct AttachFunctionData *fdata, const struct KeyEvent *event)
view attachment using mailcap entry if necessary - Implements attach_function_t -
Definition functions.c:501
static int op_attach_pipe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
pipe message/attachment to a shell command - Implements attach_function_t -
Definition functions.c:402
static int op_compose_to_sender(struct AttachFunctionData *fdata, const struct KeyEvent *event)
compose new message to the current message sender - Implements attach_function_t -
Definition functions.c:586
static int op_attach_save(struct AttachFunctionData *fdata, const struct KeyEvent *event)
save message/attachment to a mailbox/file - Implements attach_function_t -
Definition functions.c:428
static int op_list_subscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
subscribe to a mailing list - Implements attach_function_t -
Definition functions.c:658
static int op_attach_print(struct AttachFunctionData *fdata, const struct KeyEvent *event)
print the current entry - Implements attach_function_t -
Definition functions.c:415
static int op_attach_collapse(struct AttachFunctionData *fdata, const struct KeyEvent *event)
toggle display of subparts - Implements attach_function_t -
Definition functions.c:247
static int op_check_traditional(struct AttachFunctionData *fdata, const struct KeyEvent *event)
check for classic PGP - Implements attach_function_t -
Definition functions.c:569
static int op_extract_keys(struct AttachFunctionData *fdata, const struct KeyEvent *event)
extract supported public keys - Implements attach_function_t -
Definition functions.c:624
static int op_forward_to_group(struct AttachFunctionData *fdata, const struct KeyEvent *event)
forward to newsgroup - Implements attach_function_t -
Definition functions.c:763
static int op_reply(struct AttachFunctionData *fdata, const struct KeyEvent *event)
reply to a message - Implements attach_function_t -
Definition functions.c:688
static int op_bounce_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
remail a message to another user - Implements attach_function_t -
Definition functions.c:553
static int op_attach_view_mailcap(struct AttachFunctionData *fdata, const struct KeyEvent *event)
force viewing of attachment using mailcap - Implements attach_function_t -
Definition functions.c:514
static int op_attach_view_pager(struct AttachFunctionData *fdata, const struct KeyEvent *event)
view attachment in pager using copiousoutput mailcap - Implements attach_function_t -
Definition functions.c:527
int attach_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
Perform a Attach function - Implements function_dispatcher_t -.
Definition functions.c:818
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
Convenience wrapper for the gui headers.
void km_menu_add_submenu(struct MenuDefinition *md, struct SubMenu *sm)
Add a SubMenu to a Menu Definition.
Definition init.c:123
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:88
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:105
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:136
Manage keymappings.
GUI present the user with a selectable list.
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition menu.c:177
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:153
@ MENU_REDRAW_INDEX
Redraw the index.
Definition lib.h:61
@ MENU_REDRAW_FULL
Redraw everything.
Definition lib.h:64
@ MENU_REDRAW_CURRENT
Redraw the current line of the menu.
Definition lib.h:63
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:167
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
@ MODULE_ID_ATTACH
ModuleAttach, Attachments
Definition module_api.h:49
Convenience wrapper for the library headers.
#define N_(a)
Definition message.h:32
#define _(a)
Definition message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
int mutt_view_attachment(FILE *fp, struct Body *b, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
Handling of email attachments.
void mutt_save_attachment_list(struct AttachPtrArray *aa, struct Email *e, struct Menu *menu)
Save a list of selected attachments.
Definition recvattach.c:425
void mutt_pipe_attachment_list(struct AttachPtrArray *aa, bool filter)
Pipe selected attachments to a command.
Definition recvattach.c:699
@ MUTT_VA_MAILCAP
Force viewing using mailcap entry.
Definition mutt_attach.h:46
@ MUTT_VA_PAGER
View attachment in pager using copiousoutput mailcap.
Definition mutt_attach.h:48
@ MUTT_VA_AS_TEXT
Force viewing as text.
Definition mutt_attach.h:47
int mutt_attach_display_loop(struct ConfigSubset *sub, struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
Event loop for the Attachment menu.
Definition recvattach.c:919
void mutt_print_attachment_list(struct AttachPtrArray *aa)
Print selected attachments.
Definition recvattach.c:848
API for encryption/signing of emails.
@ SEC_PARTSIGN
Not all parts of the email is signed.
Definition lib.h:96
@ SEC_SIGN
Email is signed.
Definition lib.h:93
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define WithCrypto
Definition lib.h:132
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
Ask the user a question.
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:384
void mutt_update_recvattach_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Update the Attachment Menu.
struct AttachPtr * current_attachment(struct AttachCtx *actx, struct Menu *menu)
Get the current attachment.
Definition recvattach.c:71
void recvattach_edit_content_type(struct AttachCtx *actx, struct Menu *menu, struct Email *e)
Edit the content type of an attachment.
Definition recvattach.c:889
Routines for managing attachments.
int aa_add_selection(struct AttachPtrArray *aa, struct AttachCtx *actx, struct Menu *menu, bool use_tagged, int count)
Build a working set of Attachments for an action.
Definition selection.c:125
void mutt_attach_mail_sender(struct AttachPtrArray *aa)
Compose an email to the sender in the email attachment.
Definition recvcmd.c:1074
void mutt_attach_reply(struct AttachPtrArray *aa, struct Mailbox *m, struct Email *e, struct AttachCtx *actx, SendFlags flags)
Attach a reply.
Definition recvcmd.c:885
void mutt_attach_resend(struct AttachPtrArray *aa, struct Mailbox *m)
Resend-message, from the attachment menu.
Definition recvcmd.c:255
void attach_bounce_message(struct AttachPtrArray *aa, struct Mailbox *m)
Bounce function, from the attachment menu.
Definition recvcmd.c:158
void mutt_attach_forward(struct AttachPtrArray *aa, struct Email *e, struct AttachCtx *actx, SendFlags flags)
Forward selected attachments.
Definition recvcmd.c:737
Send/reply with an attachment.
Convenience wrapper for the send headers.
bool mutt_send_list_unsubscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list unsubscription email.
Definition send.c:2986
bool mutt_send_list_subscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list subscription email.
Definition send.c:2957
uint32_t SendFlags
Definition send.h:64
@ SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition send.h:58
@ SEND_REPLY
Reply to sender.
Definition send.h:46
@ SEND_NONE
No flags are set.
Definition send.h:45
@ SEND_GROUP_REPLY
Reply to all.
Definition send.h:47
@ SEND_LIST_REPLY
Reply to mailing list.
Definition send.h:48
@ SEND_NEWS
Reply to a news article.
Definition send.h:59
#define ASSERT(COND)
Definition signal2.h:59
A set of attachments.
Definition attach.h:65
struct Email * email
Used by recvattach for updating.
Definition attach.h:66
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:69
short idxlen
Number of attachmentes.
Definition attach.h:70
short * v2r
Mapping from virtual to real attachment.
Definition attach.h:73
Data passed to Attach worker functions.
Definition functions.h:33
struct AttachPrivateData * priv
Attach private data.
Definition functions.h:35
struct NeoMutt * n
NeoMutt application data.
Definition functions.h:34
A NeoMutt function.
Definition functions.h:57
attach_function_t function
Function to call.
Definition functions.h:59
int op
Op code, e.g. OP_ATTACH_COLLAPSE.
Definition functions.h:58
Attach private Module data.
Definition module_data.h:32
struct MenuDefinition * menu_attach
Attach menu definition.
Definition module_data.h:40
Private state data for Attachments.
int op
Op returned from the Pager, e.g. OP_NEXT_ENTRY.
struct Menu * menu
Current Menu.
struct ConfigSubset * sub
Config subset.
struct AttachCtx * actx
List of all Attachments.
bool attach_msg
Are we in "attach message" mode?
struct Mailbox * mailbox
Current Mailbox.
An email to which things will be attached.
Definition attach.h:36
struct Body * body
Attachment.
Definition attach.h:37
bool collapsed
Group is collapsed.
Definition attach.h:45
int level
Nesting depth of attachment.
Definition attach.h:41
FILE * fp
Used in the recvattach menu.
Definition attach.h:38
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition attach.h:39
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
bool deleted
Attachment marked for deletion.
Definition body.h:88
struct Email * email
header information for message/rfc822
Definition body.h:74
char * subtype
content-type subtype
Definition body.h:61
unsigned int type
content-type primary type, ContentType
Definition body.h:40
A set of inherited config items.
Definition subset.h:46
struct Envelope * env
Envelope information.
Definition email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
bool changed
Email has been edited.
Definition email.h:77
bool attach_del
Has an attachment marked for deletion.
Definition email.h:99
char * followup_to
List of 'followup-to' fields.
Definition envelope.h:80
An event such as a keypress.
Definition get.h:75
int count
Optional count prefix, e.g. 3 for 3j
Definition get.h:78
int op
Function opcode, e.g. OP_HELP.
Definition get.h:77
A mailbox.
Definition mailbox.h:81
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
bool readonly
Don't allow changes to the mailbox.
Definition mailbox.h:118
Functions for a Dialog or Window.
Definition menudef.h:44
Mapping between a function and an operation.
Definition menu.h:37
Mapping between an operation and a key sequence.
Definition menu.h:47
Definition lib.h:86
struct MuttWindow * win
Window holding the Menu.
Definition lib.h:94
void * mdata
Private data.
Definition lib.h:155
bool tag_prefix
User has pressed <tag-prefix>
Definition lib.h:92
void * wdata
Private data.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Collection of related functions.
Definition menudef.h:33
@ MENU_ATTACH
Select an attachment.
Definition type.h:35