NeoMutt  2025-12-11-911-gd8d604
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 { "exit", OP_EXIT },
68 { "extract-keys", OP_EXTRACT_KEYS },
69 { "followup-message", OP_FOLLOWUP },
70 { "forget-passphrase", OP_FORGET_PASSPHRASE },
71 { "forward-message", OP_FORWARD_MESSAGE },
72 { "forward-to-group", OP_FORWARD_TO_GROUP },
73 { "group-chat-reply", OP_GROUP_CHAT_REPLY },
74 { "group-reply", OP_GROUP_REPLY },
75 { "list-reply", OP_LIST_REPLY },
76 { "list-subscribe", OP_LIST_SUBSCRIBE },
77 { "list-unsubscribe", OP_LIST_UNSUBSCRIBE },
78 { "pipe-entry", OP_PIPE },
79 { "pipe-message", OP_PIPE },
80 { "print-entry", OP_ATTACH_PRINT },
81 { "reply", OP_REPLY },
82 { "resend-message", OP_RESEND },
83 { "save-entry", OP_ATTACH_SAVE },
84 { "undelete-entry", OP_ATTACH_UNDELETE },
85 { "view-attach", OP_ATTACH_VIEW },
86 { "view-mailcap", OP_ATTACH_VIEW_MAILCAP },
87 { "view-pager", OP_ATTACH_VIEW_PAGER },
88 { "view-text", OP_ATTACH_VIEW_TEXT },
89 { NULL, 0 },
90};
91
95static const struct MenuOpSeq AttachmentDefaultBindings[] = { /* map: attach */
96 { OP_ATTACH_COLLAPSE, "v" },
97 { OP_ATTACH_DELETE, "d" },
98 { OP_ATTACH_EDIT_TYPE, "\005" }, // <Ctrl-E>
99 { OP_EXIT, "q" },
100 { OP_PIPE, "|" },
101 { OP_ATTACH_PRINT, "p" },
102 { OP_ATTACH_SAVE, "s" },
103 { OP_ATTACH_UNDELETE, "u" },
104 { OP_ATTACH_VIEW, "<keypadenter>" },
105 { OP_ATTACH_VIEW, "\n" }, // <Enter>
106 { OP_ATTACH_VIEW, "\r" }, // <Return>
107 { OP_ATTACH_VIEW_MAILCAP, "m" },
108 { OP_ATTACH_VIEW_TEXT, "T" },
109 { OP_BOUNCE_MESSAGE, "b" },
110 { OP_CHECK_TRADITIONAL, "\033P" }, // <Alt-P>
111 { OP_DISPLAY_HEADERS, "h" },
112 { OP_EXTRACT_KEYS, "\013" }, // <Ctrl-K>
113 { OP_FORGET_PASSPHRASE, "\006" }, // <Ctrl-F>
114 { OP_FORWARD_MESSAGE, "f" },
115 { OP_GROUP_REPLY, "g" },
116 { OP_LIST_REPLY, "L" },
117 { OP_REPLY, "r" },
118 { OP_RESEND, "\033e" }, // <Alt-e>
119 { 0, NULL },
120};
121// clang-format on
122
126void attach_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
127{
129 ASSERT(mod_data);
130
131 struct MenuDefinition *md = NULL;
132 struct SubMenu *sm = NULL;
133
135 md = km_register_menu(MENU_ATTACH, "attach");
136 km_menu_add_submenu(md, sm);
137 km_menu_add_submenu(md, sm_generic);
139
140 mod_data->menu_attach = md;
141}
142
149static void attach_collapse(struct AttachCtx *actx, struct Menu *menu, struct ConfigSubset *sub)
150{
151 int rindex, curlevel;
152
153 struct AttachPtr *cur_att = current_attachment(actx, menu);
154 cur_att->collapsed = !cur_att->collapsed;
155 /* When expanding, expand all the children too */
156 if (cur_att->collapsed)
157 return;
158
159 curlevel = cur_att->level;
160 const int index = menu_get_index(menu);
161 rindex = actx->v2r[index] + 1;
162
163 const bool c_digest_collapse = cs_subset_bool(sub, "digest_collapse");
164 while ((rindex < actx->idxlen) && (actx->idx[rindex]->level > curlevel))
165 {
166 if (c_digest_collapse && (actx->idx[rindex]->body->type == TYPE_MULTIPART) &&
167 mutt_istr_equal(actx->idx[rindex]->body->subtype, "digest"))
168 {
169 actx->idx[rindex]->collapsed = true;
170 }
171 else
172 {
173 actx->idx[rindex]->collapsed = false;
174 }
175 rindex++;
176 }
177}
178
184static bool check_attach(struct AttachPrivateData *priv)
185{
186 if (priv->attach_msg)
187 {
190 return true;
191 }
192
193 return false;
194}
195
201static bool check_readonly(struct Mailbox *m)
202{
203 if (!m || m->readonly)
204 {
206 mutt_error(_("Mailbox is read-only"));
207 return true;
208 }
209
210 return false;
211}
212
217static void recvattach_extract_pgp_keys(struct AttachPtrArray *aa)
218{
219 struct AttachPtr **app = NULL;
220 ARRAY_FOREACH(app, aa)
221 {
222 crypt_pgp_extract_key_from_attachment((*app)->fp, (*app)->body);
223 }
224}
225
231static int recvattach_pgp_check_traditional(struct AttachPtrArray *aa)
232{
233 int rc = 0;
234
235 struct AttachPtr **app = NULL;
236 ARRAY_FOREACH(app, aa)
237 {
238 rc = rc || crypt_pgp_check_traditional((*app)->fp, (*app)->body, true);
239 }
240
241 return rc;
242}
243
244// -----------------------------------------------------------------------------
245
249static int op_attach_collapse(struct AttachFunctionData *fdata, const struct KeyEvent *event)
250{
251 struct AttachPrivateData *priv = fdata->priv;
252 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
253 if (!cur_att->body->parts)
254 {
255 mutt_error(_("There are no subparts to show"));
256 return FR_ERROR;
257 }
258 attach_collapse(priv->actx, priv->menu, fdata->n->sub);
259 mutt_update_recvattach_menu(priv->actx, priv->menu, false);
260 return FR_SUCCESS;
261}
262
273static void attach_apply_set_deleted(struct AttachPtrArray *apa, bool deleted,
274 int *num_changed, int *num_blocked)
275{
276 int changed = 0;
277 int blocked = 0;
278
279 if (apa)
280 {
281 struct AttachPtr **app = NULL;
282 ARRAY_FOREACH(app, apa)
283 {
284 struct AttachPtr *ap = *app;
285 if (!ap || !ap->body)
286 continue;
287
288 if (deleted && (ap->parent_type != TYPE_MULTIPART))
289 {
290 blocked++;
291 continue;
292 }
293
294 ap->body->deleted = deleted;
295 changed++;
296 }
297 }
298
299 if (num_changed)
300 *num_changed = changed;
301 if (num_blocked)
302 *num_blocked = blocked;
303}
304
313static int op_attach_delete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
314{
315 struct AttachPrivateData *priv = fdata->priv;
316 if (check_readonly(priv->mailbox))
317 return FR_ERROR;
318
319 if (priv->mailbox->type == MUTT_POP)
320 {
322 mutt_error(_("Can't delete attachment from POP server"));
323 return FR_ERROR;
324 }
325
326 if (priv->mailbox->type == MUTT_NNTP)
327 {
329 mutt_error(_("Can't delete attachment from news server"));
330 return FR_ERROR;
331 }
332
333 if ((WithCrypto != 0) && (priv->actx->email->security & SEC_ENCRYPT))
334 {
335 mutt_message(_("Deletion of attachments from encrypted messages is unsupported"));
336 return FR_ERROR;
337 }
338 if ((WithCrypto != 0) && (priv->actx->email->security & (SEC_SIGN | SEC_PARTSIGN)))
339 {
340 mutt_message(_("Deletion of attachments from signed messages may invalidate the signature"));
341 }
342
343 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
344 if (aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix,
345 event->count) < 0)
346 {
347 ARRAY_FREE(&aa);
348 return FR_ERROR;
349 }
350
351 if (ARRAY_EMPTY(&aa))
352 {
353 ARRAY_FREE(&aa);
354 return FR_NO_ACTION;
355 }
356
357 int changed = 0;
358 int blocked = 0;
359 attach_apply_set_deleted(&aa, true, &changed, &blocked);
360 const int num = ARRAY_SIZE(&aa);
361 ARRAY_FREE(&aa);
362
363 if (blocked > 0)
364 mutt_message(_("Only deletion of multipart attachments is supported"));
365
366 if (changed == 0)
367 return blocked ? FR_ERROR : FR_NO_ACTION;
368
369 if (priv->menu->tag_prefix)
370 {
372 }
373 else
374 {
375 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
376 const int next = menu_get_index(priv->menu) + num;
377 if (c_resolve && (next < priv->menu->max))
378 {
379 menu_set_index(priv->menu, next);
380 }
381 else
382 {
384 }
385 }
386
387 return FR_SUCCESS;
388}
389
393static int op_attach_edit_type(struct AttachFunctionData *fdata, const struct KeyEvent *event)
394{
395 struct AttachPrivateData *priv = fdata->priv;
396 recvattach_edit_content_type(priv->actx, priv->menu, priv->actx->email);
398 return FR_SUCCESS;
399}
400
404static int op_attach_pipe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
405{
406 struct AttachPrivateData *priv = fdata->priv;
407 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
408 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
409 mutt_pipe_attachment_list(&aa, false);
410 ARRAY_FREE(&aa);
411 return FR_SUCCESS;
412}
413
417static int op_attach_print(struct AttachFunctionData *fdata, const struct KeyEvent *event)
418{
419 struct AttachPrivateData *priv = fdata->priv;
420 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
421 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
423 ARRAY_FREE(&aa);
424 return FR_SUCCESS;
425}
426
430static int op_attach_save(struct AttachFunctionData *fdata, const struct KeyEvent *event)
431{
432 struct AttachPrivateData *priv = fdata->priv;
433 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
434 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
435 mutt_save_attachment_list(&aa, priv->actx->email, priv->menu);
436
437 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
438 const int index = menu_get_index(priv->menu) + 1;
439 if ((ARRAY_SIZE(&aa) == 1) && c_resolve && (index < priv->menu->max))
440 menu_set_index(priv->menu, index);
441 ARRAY_FREE(&aa);
442 return FR_SUCCESS;
443}
444
451static int op_attach_undelete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
452{
453 struct AttachPrivateData *priv = fdata->priv;
454 if (check_readonly(priv->mailbox))
455 return FR_ERROR;
456
457 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
458 if (aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix,
459 event->count) < 0)
460 {
461 ARRAY_FREE(&aa);
462 return FR_ERROR;
463 }
464
465 if (ARRAY_EMPTY(&aa))
466 {
467 ARRAY_FREE(&aa);
468 return FR_NO_ACTION;
469 }
470
471 attach_apply_set_deleted(&aa, false, NULL, NULL);
472 const int num = ARRAY_SIZE(&aa);
473 ARRAY_FREE(&aa);
474
475 if (priv->menu->tag_prefix)
476 {
478 }
479 else
480 {
481 const bool c_resolve = cs_subset_bool(fdata->n->sub, "resolve");
482 const int next = menu_get_index(priv->menu) + num;
483 if (c_resolve && (next < priv->menu->max))
484 {
485 menu_set_index(priv->menu, next);
486 }
487 else
488 {
490 }
491 }
492
493 return FR_SUCCESS;
494}
495
503static int op_attach_view(struct AttachFunctionData *fdata, const struct KeyEvent *event)
504{
505 struct AttachPrivateData *priv = fdata->priv;
506 priv->op = mutt_attach_display_loop(priv->sub, priv->menu, event->op,
507 priv->actx->email, priv->actx, true);
509
510 return FR_CONTINUE;
511}
512
516static int op_attach_view_mailcap(struct AttachFunctionData *fdata, const struct KeyEvent *event)
517{
518 struct AttachPrivateData *priv = fdata->priv;
519 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
520 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_MAILCAP,
521 priv->actx->email, priv->actx, priv->menu->win);
523 return FR_SUCCESS;
524}
525
529static int op_attach_view_pager(struct AttachFunctionData *fdata, const struct KeyEvent *event)
530{
531 struct AttachPrivateData *priv = fdata->priv;
532 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
533 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_PAGER,
534 priv->actx->email, priv->actx, priv->menu->win);
536 return FR_SUCCESS;
537}
538
542static int op_attach_view_text(struct AttachFunctionData *fdata, const struct KeyEvent *event)
543{
544 struct AttachPrivateData *priv = fdata->priv;
545 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
546 mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_AS_TEXT,
547 priv->actx->email, priv->actx, priv->menu->win);
549 return FR_SUCCESS;
550}
551
555static int op_bounce_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
556{
557 struct AttachPrivateData *priv = fdata->priv;
558 if (check_attach(priv))
559 return FR_ERROR;
560 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
561 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
562 attach_bounce_message(&aa, priv->mailbox);
563 ARRAY_FREE(&aa);
565 return FR_SUCCESS;
566}
567
571static int op_check_traditional(struct AttachFunctionData *fdata, const struct KeyEvent *event)
572{
573 struct AttachPrivateData *priv = fdata->priv;
574 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
575 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
577 {
578 priv->actx->email->security = crypt_query(NULL);
580 }
581 ARRAY_FREE(&aa);
582 return FR_SUCCESS;
583}
584
588static int op_compose_to_sender(struct AttachFunctionData *fdata, const struct KeyEvent *event)
589{
590 struct AttachPrivateData *priv = fdata->priv;
591 if (check_attach(priv))
592 return FR_ERROR;
593 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
594 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
596 ARRAY_FREE(&aa);
598 return FR_SUCCESS;
599}
600
604static int op_exit(struct AttachFunctionData *fdata, const struct KeyEvent *event)
605{
606 struct AttachPrivateData *priv = fdata->priv;
607 priv->actx->email->attach_del = false;
608 for (int i = 0; i < priv->actx->idxlen; i++)
609 {
610 if (priv->actx->idx[i]->body && priv->actx->idx[i]->body->deleted)
611 {
612 priv->actx->email->attach_del = true;
613 break;
614 }
615 }
616 if (priv->actx->email->attach_del)
617 priv->actx->email->changed = true;
618
619 mutt_actx_free(&priv->actx);
620 return FR_DONE;
621}
622
626static int op_extract_keys(struct AttachFunctionData *fdata, const struct KeyEvent *event)
627{
628 struct AttachPrivateData *priv = fdata->priv;
630 return FR_NO_ACTION;
631
632 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
633 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
635 ARRAY_FREE(&aa);
637
638 return FR_SUCCESS;
639}
640
644static int op_forget_passphrase(struct AttachFunctionData *fdata, const struct KeyEvent *event)
645{
647 return FR_SUCCESS;
648}
649
653static int op_forward_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
654{
655 struct AttachPrivateData *priv = fdata->priv;
656 if (check_attach(priv))
657 return FR_ERROR;
658 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
659 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
660 mutt_attach_forward(&aa, priv->actx->email, priv->actx, SEND_NONE);
661 ARRAY_FREE(&aa);
663 return FR_SUCCESS;
664}
665
669static int op_list_subscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
670{
671 struct AttachPrivateData *priv = fdata->priv;
672 if (check_attach(priv))
673 return FR_ERROR;
674
676}
677
681static int op_list_unsubscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
682{
683 struct AttachPrivateData *priv = fdata->priv;
684 if (check_attach(priv))
685 return FR_ERROR;
686
688}
689
699static int op_reply(struct AttachFunctionData *fdata, const struct KeyEvent *event)
700{
701 struct AttachPrivateData *priv = fdata->priv;
702 if (check_attach(priv))
703 return FR_ERROR;
704
705 const int op = event->op;
706 SendFlags flags = SEND_REPLY;
707 if (op == OP_GROUP_REPLY)
708 flags |= SEND_GROUP_REPLY;
709 else if (op == OP_GROUP_CHAT_REPLY)
710 flags |= SEND_GROUP_CHAT_REPLY;
711 else if (op == OP_LIST_REPLY)
712 flags |= SEND_LIST_REPLY;
713
714 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
715 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
716 mutt_attach_reply(&aa, priv->mailbox, priv->actx->email, priv->actx, flags);
717 ARRAY_FREE(&aa);
719 return FR_SUCCESS;
720}
721
725static int op_resend(struct AttachFunctionData *fdata, const struct KeyEvent *event)
726{
727 struct AttachPrivateData *priv = fdata->priv;
728 if (check_attach(priv))
729 return FR_ERROR;
730 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
731 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
732 mutt_attach_resend(&aa, priv->mailbox);
733 ARRAY_FREE(&aa);
735 return FR_SUCCESS;
736}
737
738// -----------------------------------------------------------------------------
739
743static int op_followup(struct AttachFunctionData *fdata, const struct KeyEvent *event)
744{
745 struct AttachPrivateData *priv = fdata->priv;
746 if (check_attach(priv))
747 return FR_ERROR;
748
749 struct AttachPtr *cur_att = current_attachment(priv->actx, priv->menu);
750 if (!cur_att->body->email || !cur_att->body->email->env)
751 {
752 mutt_error(_("You may only followup to message/rfc822 parts"));
753 return FR_ERROR;
754 }
755 if (!cur_att->body->email->env->followup_to ||
756 !mutt_istr_equal(cur_att->body->email->env->followup_to, "poster") ||
757 (query_quadoption(_("Reply by mail as poster prefers?"), fdata->n->sub,
758 "followup_to_poster") != MUTT_YES))
759 {
760 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
761 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
762 mutt_attach_reply(&aa, priv->mailbox, priv->actx->email, priv->actx, SEND_NEWS | SEND_REPLY);
763 ARRAY_FREE(&aa);
765 return FR_SUCCESS;
766 }
767
768 return op_reply(fdata, event);
769}
770
774static int op_forward_to_group(struct AttachFunctionData *fdata, const struct KeyEvent *event)
775{
776 struct AttachPrivateData *priv = fdata->priv;
777 if (check_attach(priv))
778 return FR_ERROR;
779 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
780 aa_add_selection(&aa, priv->actx, priv->menu, priv->menu->tag_prefix, event->count);
781 mutt_attach_forward(&aa, priv->actx->email, priv->actx, SEND_NEWS);
782 ARRAY_FREE(&aa);
784 return FR_SUCCESS;
785}
786
787// -----------------------------------------------------------------------------
788
792static const struct AttachFunction AttachFunctions[] = {
793 // clang-format off
794 { OP_ATTACH_COLLAPSE, op_attach_collapse },
795 { OP_ATTACH_DELETE, op_attach_delete },
796 { OP_ATTACH_EDIT_TYPE, op_attach_edit_type },
797 { OP_ATTACH_PRINT, op_attach_print },
798 { OP_ATTACH_SAVE, op_attach_save },
799 { OP_ATTACH_UNDELETE, op_attach_undelete },
800 { OP_ATTACH_VIEW, op_attach_view },
801 { OP_ATTACH_VIEW_MAILCAP, op_attach_view_mailcap },
802 { OP_ATTACH_VIEW_PAGER, op_attach_view_pager },
803 { OP_ATTACH_VIEW_TEXT, op_attach_view_text },
804 { OP_BOUNCE_MESSAGE, op_bounce_message },
805 { OP_CHECK_TRADITIONAL, op_check_traditional },
806 { OP_COMPOSE_TO_SENDER, op_compose_to_sender },
807 { OP_DISPLAY_HEADERS, op_attach_view },
808 { OP_EXIT, op_exit },
809 { OP_EXTRACT_KEYS, op_extract_keys },
810 { OP_FOLLOWUP, op_followup },
811 { OP_FORGET_PASSPHRASE, op_forget_passphrase },
812 { OP_FORWARD_MESSAGE, op_forward_message },
813 { OP_FORWARD_TO_GROUP, op_forward_to_group },
814 { OP_GROUP_CHAT_REPLY, op_reply },
815 { OP_GROUP_REPLY, op_reply },
816 { OP_LIST_REPLY, op_reply },
817 { OP_LIST_SUBSCRIBE, op_list_subscribe },
818 { OP_LIST_UNSUBSCRIBE, op_list_unsubscribe },
819 { OP_PIPE, op_attach_pipe },
820 { OP_REPLY, op_reply },
821 { OP_RESEND, op_resend },
822 { 0, NULL },
823 // clang-format on
824};
825
829int attach_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
830{
831 // The Dispatcher may be called on any Window in the Dialog
832 struct MuttWindow *dlg = dialog_find(win);
833 if (!event || !dlg || !dlg->wdata)
834 {
836 return FR_ERROR;
837 }
838
839 struct Menu *menu = dlg->wdata;
840 struct AttachPrivateData *priv = menu->mdata;
841 if (!priv)
842 {
844 return FR_ERROR;
845 }
846
847 const int op = event->op;
848
849 struct AttachFunctionData fdata = {
850 .n = NeoMutt,
851 .priv = priv,
852 };
853
854 int rc = FR_UNKNOWN;
855 for (size_t i = 0; AttachFunctions[i].op != OP_NULL; i++)
856 {
857 const struct AttachFunction *fn = &AttachFunctions[i];
858 if (fn->op == op)
859 {
860 rc = fn->function(&fdata, event);
861 break;
862 }
863 }
864
866 return rc;
867}
#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 const struct MenuOpSeq AttachmentDefaultBindings[]
Key bindings for the Attachment Menu.
Definition functions.c:95
static bool check_attach(struct AttachPrivateData *priv)
Check if in attach-message mode.
Definition functions.c:184
static int recvattach_pgp_check_traditional(struct AttachPtrArray *aa)
Is the Attachment inline PGP?
Definition functions.c:231
static void attach_collapse(struct AttachCtx *actx, struct Menu *menu, struct ConfigSubset *sub)
Close the tree of the current attachment.
Definition functions.c:149
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:273
static void recvattach_extract_pgp_keys(struct AttachPtrArray *aa)
Extract PGP keys from attachments.
Definition functions.c:217
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:126
static const struct AttachFunction AttachFunctions[]
All the NeoMutt functions that the Attach supports.
Definition functions.c:792
static bool check_readonly(struct Mailbox *m)
Check if the Mailbox is readonly.
Definition functions.c:201
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
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition crypt.c:89
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:692
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_exit(struct AliasFunctionData *fdata, const struct KeyEvent *event)
exit this menu - Implements alias_function_t -
Definition functions.c:312
static int op_attach_view_text(struct AttachFunctionData *fdata, const struct KeyEvent *event)
view attachment as text - Implements attach_function_t -
Definition functions.c:542
static int op_followup(struct AttachFunctionData *fdata, const struct KeyEvent *event)
followup to newsgroup - Implements attach_function_t -
Definition functions.c:743
static int op_list_unsubscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
unsubscribe from a mailing list - Implements attach_function_t -
Definition functions.c:681
static int op_attach_edit_type(struct AttachFunctionData *fdata, const struct KeyEvent *event)
edit attachment content type - Implements attach_function_t -
Definition functions.c:393
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:725
static int op_forward_message(struct AttachFunctionData *fdata, const struct KeyEvent *event)
forward a message with comments - Implements attach_function_t -
Definition functions.c:653
static int op_attach_delete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
delete the current entry - Implements attach_function_t -
Definition functions.c:313
static int op_attach_undelete(struct AttachFunctionData *fdata, const struct KeyEvent *event)
undelete the current entry - Implements attach_function_t -
Definition functions.c:451
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:503
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:404
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:588
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:430
static int op_list_subscribe(struct AttachFunctionData *fdata, const struct KeyEvent *event)
subscribe to a mailing list - Implements attach_function_t -
Definition functions.c:669
static int op_attach_print(struct AttachFunctionData *fdata, const struct KeyEvent *event)
print the current entry - Implements attach_function_t -
Definition functions.c:417
static int op_attach_collapse(struct AttachFunctionData *fdata, const struct KeyEvent *event)
toggle display of subparts - Implements attach_function_t -
Definition functions.c:249
static int op_check_traditional(struct AttachFunctionData *fdata, const struct KeyEvent *event)
check for classic PGP - Implements attach_function_t -
Definition functions.c:571
static int op_extract_keys(struct AttachFunctionData *fdata, const struct KeyEvent *event)
extract supported public keys - Implements attach_function_t -
Definition functions.c:626
static int op_forward_to_group(struct AttachFunctionData *fdata, const struct KeyEvent *event)
forward to newsgroup - Implements attach_function_t -
Definition functions.c:774
static int op_reply(struct AttachFunctionData *fdata, const struct KeyEvent *event)
reply to a message - Implements attach_function_t -
Definition functions.c:699
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:555
static int op_forget_passphrase(struct AttachFunctionData *fdata, const struct KeyEvent *event)
wipe passphrases from memory - Implements attach_function_t -
Definition functions.c:644
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:516
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:529
int attach_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
Perform a Attach function - Implements function_dispatcher_t -.
Definition functions.c:829
#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:121
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:87
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:104
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:134
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:179
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:155
@ 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:169
@ 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:677
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:423
void mutt_pipe_attachment_list(struct AttachPtrArray *aa, bool filter)
Pipe selected attachments to a command.
Definition recvattach.c:697
@ 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:917
void mutt_print_attachment_list(struct AttachPtrArray *aa)
Print selected attachments.
Definition recvattach.c:846
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:663
@ 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:887
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:2985
bool mutt_send_list_subscribe(struct Mailbox *m, struct Email *e)
Send a mailing-list subscription email.
Definition send.c:2956
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 menu.h:77
Mapping between a function and an operation.
Definition menu.h:35
Mapping between an operation and a key sequence.
Definition menu.h:45
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 menu.h:65
@ MENU_ATTACH
Select an attachment.
Definition type.h:35