Coverage Report

Created: 2023-06-07 06:15

/src/neomutt/compose/attach.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Compose Attachments
4
 *
5
 * @authors
6
 * Copyright (C) 2021 Richard Russon <rich@flatcap.org>
7
 *
8
 * @copyright
9
 * This program is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License as published by the Free Software
11
 * Foundation, either version 2 of the License, or (at your option) any later
12
 * version.
13
 *
14
 * This program is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU General Public License along with
20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/**
24
 * @page compose_attach Attachments window
25
 *
26
 * The Compose Attachments Window displays the attachments of an email.
27
 *
28
 * ## Windows
29
 *
30
 * | Name                       | Type      | See Also     |
31
 * | :------------------------- | :-------- | :----------- |
32
 * | Compose Attachments Window | WT_MENU   | attach_new() |
33
 *
34
 * **Parent**
35
 * - @ref compose_dialog
36
 *
37
 * **Children**
38
 *
39
 * None.
40
 *
41
 * ## Data
42
 * - #ComposeAttachData
43
 *
44
 * The Compose Attachments Window stores its data (#ComposeAttachData) in
45
 * Menu::mdata.
46
 *
47
 * ## Events
48
 *
49
 * Once constructed, it is controlled by the following events:
50
 *
51
 * | Event Type            | Handler                   |
52
 * | :-------------------- | :------------------------ |
53
 * | #NT_CONFIG            | attach_config_observer()  |
54
 * | #NT_EMAIL             | attach_email_observer()   |
55
 * | #NT_WINDOW            | attach_window_observer()  |
56
 */
57
58
#include "config.h"
59
#include <stddef.h>
60
#include <stdbool.h>
61
#include <stdint.h>
62
#include "private.h"
63
#include "mutt/lib.h"
64
#include "config/lib.h"
65
#include "email/lib.h"
66
#include "core/lib.h"
67
#include "gui/lib.h"
68
#include "attach/lib.h"
69
#include "convert/lib.h"
70
#include "menu/lib.h"
71
#include "attach_data.h"
72
#include "format_flags.h"
73
#include "muttlib.h"
74
#include "shared_data.h"
75
76
/**
77
 * cum_attachs_size - Cumulative Attachments Size
78
 * @param sub   Config Subset
79
 * @param adata Attachment data
80
 * @retval num Bytes in attachments
81
 *
82
 * Returns the total number of bytes used by the attachments in the attachment
83
 * list _after_ content-transfer-encodings have been applied.
84
 */
85
unsigned long cum_attachs_size(struct ConfigSubset *sub, struct ComposeAttachData *adata)
86
0
{
87
0
  if (!adata || !adata->actx)
88
0
    return 0;
89
90
0
  size_t s = 0;
91
0
  struct Content *info = NULL;
92
0
  struct Body *b = NULL;
93
0
  struct AttachCtx *actx = adata->actx;
94
0
  struct AttachPtr **idx = actx->idx;
95
96
0
  for (unsigned short i = 0; i < actx->idxlen; i++)
97
0
  {
98
0
    b = idx[i]->body;
99
100
0
    if (!b->content)
101
0
      b->content = mutt_get_content_info(b->filename, b, sub);
102
103
0
    info = b->content;
104
0
    if (info)
105
0
    {
106
0
      switch (b->encoding)
107
0
      {
108
0
        case ENC_QUOTED_PRINTABLE:
109
0
          s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf;
110
0
          break;
111
0
        case ENC_BASE64:
112
0
          s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3;
113
0
          break;
114
0
        default:
115
0
          s += info->lobin + info->hibin + info->ascii + info->crlf;
116
0
          break;
117
0
      }
118
0
    }
119
0
  }
120
121
0
  return s;
122
0
}
123
124
/**
125
 * attach_email_observer - Notification that the Email has changed - Implements ::observer_t - @ingroup observer_api
126
 */
127
static int attach_email_observer(struct NotifyCallback *nc)
128
0
{
129
0
  if (nc->event_type != NT_EMAIL)
130
0
    return 0;
131
0
  if (!nc->global_data)
132
0
    return -1;
133
0
  if (nc->event_subtype != NT_EMAIL_CHANGE_ATTACH)
134
0
    return 0;
135
136
0
  struct MuttWindow *win_attach = nc->global_data;
137
138
0
  win_attach->actions |= WA_RECALC;
139
0
  mutt_debug(LL_DEBUG5, "compose done, request WA_RECALC\n");
140
141
0
  return 0;
142
0
}
143
144
/**
145
 * attach_config_observer - Notification that a Config Variable has changed - Implements ::observer_t - @ingroup observer_api
146
 */
147
int attach_config_observer(struct NotifyCallback *nc)
148
0
{
149
0
  if (nc->event_type != NT_CONFIG)
150
0
    return 0;
151
0
  if (!nc->global_data || !nc->event_data)
152
0
    return -1;
153
154
0
  struct EventConfig *ev_c = nc->event_data;
155
0
  if (!mutt_str_equal(ev_c->name, "attach_format"))
156
0
    return 0;
157
158
0
  struct MuttWindow *win_attach = nc->global_data;
159
0
  win_attach->actions |= WA_RECALC;
160
0
  mutt_debug(LL_DEBUG5, "config, request WA_RECALC\n");
161
162
0
  return 0;
163
0
}
164
165
/**
166
 * attach_window_observer - Notification that a Window has changed - Implements ::observer_t - @ingroup observer_api
167
 */
168
static int attach_window_observer(struct NotifyCallback *nc)
169
0
{
170
0
  if (nc->event_type != NT_WINDOW)
171
0
    return 0;
172
0
  if (!nc->global_data || !nc->event_data)
173
0
    return -1;
174
175
0
  struct MuttWindow *win_attach = nc->global_data;
176
0
  struct EventWindow *ev_w = nc->event_data;
177
0
  if (ev_w->win != win_attach)
178
0
    return 0;
179
180
0
  if (nc->event_subtype == NT_WINDOW_STATE)
181
0
  {
182
0
    win_attach->actions |= WA_RECALC;
183
0
    mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
184
0
  }
185
0
  else if (nc->event_subtype == NT_WINDOW_DELETE)
186
0
  {
187
0
    struct Menu *menu = win_attach->wdata;
188
0
    struct ComposeAttachData *adata = menu->mdata;
189
0
    struct AttachCtx *actx = adata->actx;
190
0
    notify_observer_remove(actx->email->notify, attach_email_observer, win_attach);
191
0
    notify_observer_remove(NeoMutt->notify, attach_config_observer, win_attach);
192
0
    notify_observer_remove(win_attach->notify, attach_window_observer, win_attach);
193
0
    mutt_debug(LL_DEBUG5, "window delete done\n");
194
0
  }
195
196
0
  return 0;
197
0
}
198
199
/**
200
 * compose_attach_tag - Tag an attachment - Implements Menu::tag() - @ingroup menu_tag
201
 */
202
static int compose_attach_tag(struct Menu *menu, int sel, int act)
203
0
{
204
0
  struct ComposeAttachData *adata = menu->mdata;
205
0
  struct AttachCtx *actx = adata->actx;
206
0
  struct Body *cur = actx->idx[actx->v2r[sel]]->body;
207
0
  bool ot = cur->tagged;
208
209
0
  cur->tagged = ((act >= 0) ? act : !cur->tagged);
210
0
  return cur->tagged - ot;
211
0
}
212
213
/**
214
 * compose_make_entry - Format a menu item for the attachment list - Implements Menu::make_entry() - @ingroup menu_make_entry
215
 *
216
 * @sa $attach_format, attach_format_str()
217
 */
218
static void compose_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
219
0
{
220
0
  struct ComposeAttachData *adata = menu->mdata;
221
0
  struct AttachCtx *actx = adata->actx;
222
0
  struct ComposeSharedData *shared = menu->win->parent->wdata;
223
0
  struct ConfigSubset *sub = shared->sub;
224
225
0
  const char *const c_attach_format = cs_subset_string(sub, "attach_format");
226
0
  mutt_expando_format(buf, buflen, 0, menu->win->state.cols, NONULL(c_attach_format),
227
0
                      attach_format_str, (intptr_t) (actx->idx[actx->v2r[line]]),
228
0
                      MUTT_FORMAT_STAT_FILE | MUTT_FORMAT_ARROWCURSOR);
229
0
}
230
231
/**
232
 * attach_new - Create the Attachments Menu
233
 * @param parent Parent Window
234
 * @param shared Shared compose data
235
 */
236
struct MuttWindow *attach_new(struct MuttWindow *parent, struct ComposeSharedData *shared)
237
0
{
238
0
  struct MuttWindow *win_attach = menu_window_new(MENU_COMPOSE, NeoMutt->sub);
239
240
0
  struct ComposeAttachData *adata = attach_data_new(shared->email);
241
242
0
  shared->adata = adata;
243
244
  // NT_COLOR is handled by the Menu Window
245
0
  notify_observer_add(NeoMutt->notify, NT_CONFIG, attach_config_observer, win_attach);
246
0
  notify_observer_add(shared->email->notify, NT_EMAIL, attach_email_observer, win_attach);
247
0
  notify_observer_add(win_attach->notify, NT_WINDOW, attach_window_observer, win_attach);
248
249
0
  struct Menu *menu = win_attach->wdata;
250
0
  menu->page_len = win_attach->state.rows;
251
0
  menu->win = win_attach;
252
253
0
  menu->make_entry = compose_make_entry;
254
0
  menu->tag = compose_attach_tag;
255
0
  menu->mdata = adata;
256
0
  menu->mdata_free = attach_data_free;
257
0
  adata->menu = menu;
258
259
0
  return win_attach;
260
0
}