Coverage Report

Created: 2023-11-19 06:09

/src/neomutt/alternates.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Alternate address handling
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 neo_alternates Alternate address handling
25
 *
26
 * Alternate address handling
27
 */
28
29
#include "config.h"
30
#include <stdbool.h>
31
#include <stdint.h>
32
#include <stdio.h>
33
#include "mutt/lib.h"
34
#include "address/lib.h"
35
#include "email/lib.h"
36
#include "core/lib.h"
37
#include "alternates.h"
38
#include "parse/lib.h"
39
#include "commands.h"
40
#include "mview.h"
41
42
static struct RegexList Alternates = STAILQ_HEAD_INITIALIZER(Alternates); ///< List of regexes to match the user's alternate email addresses
43
static struct RegexList UnAlternates = STAILQ_HEAD_INITIALIZER(UnAlternates); ///< List of regexes to exclude false matches in Alternates
44
static struct Notify *AlternatesNotify = NULL; ///< Notifications: #NotifyAlternates
45
46
/**
47
 * alternates_cleanup - Free the alternates lists
48
 */
49
void alternates_cleanup(void)
50
0
{
51
0
  notify_free(&AlternatesNotify);
52
53
0
  mutt_regexlist_free(&Alternates);
54
0
  mutt_regexlist_free(&UnAlternates);
55
0
}
56
57
/**
58
 * alternates_init - Set up the alternates lists
59
 */
60
void alternates_init(void)
61
0
{
62
0
  if (AlternatesNotify)
63
0
    return;
64
65
0
  AlternatesNotify = notify_new();
66
0
  notify_set_parent(AlternatesNotify, NeoMutt->notify);
67
0
}
68
69
/**
70
 * mutt_alternates_reset - Clear the recipient valid flag of all emails
71
 * @param mv Mailbox view
72
 */
73
void mutt_alternates_reset(struct MailboxView *mv)
74
0
{
75
0
  if (!mv || !mv->mailbox)
76
0
    return;
77
78
0
  struct Mailbox *m = mv->mailbox;
79
80
0
  for (int i = 0; i < m->msg_count; i++)
81
0
  {
82
0
    struct Email *e = m->emails[i];
83
0
    if (!e)
84
0
      break;
85
0
    e->recip_valid = false;
86
0
  }
87
0
}
88
89
/**
90
 * parse_alternates - Parse the 'alternates' command - Implements Command::parse() - @ingroup command_parse
91
 */
92
enum CommandResult parse_alternates(struct Buffer *buf, struct Buffer *s,
93
                                    intptr_t data, struct Buffer *err)
94
0
{
95
0
  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
96
97
0
  do
98
0
  {
99
0
    parse_extract_token(buf, s, TOKEN_NO_FLAGS);
100
101
0
    if (parse_grouplist(&gl, buf, s, err) == -1)
102
0
      goto bail;
103
104
0
    mutt_regexlist_remove(&UnAlternates, buf->data);
105
106
0
    if (mutt_regexlist_add(&Alternates, buf->data, REG_ICASE, err) != 0)
107
0
      goto bail;
108
109
0
    if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
110
0
      goto bail;
111
0
  } while (MoreArgs(s));
112
113
0
  mutt_grouplist_destroy(&gl);
114
115
0
  mutt_debug(LL_NOTIFY, "NT_ALTERN_ADD: %s\n", buf->data);
116
0
  notify_send(AlternatesNotify, NT_ALTERN, NT_ALTERN_ADD, NULL);
117
118
0
  return MUTT_CMD_SUCCESS;
119
120
0
bail:
121
0
  mutt_grouplist_destroy(&gl);
122
0
  return MUTT_CMD_ERROR;
123
0
}
124
125
/**
126
 * parse_unalternates - Parse the 'unalternates' command - Implements Command::parse() - @ingroup command_parse
127
 */
128
enum CommandResult parse_unalternates(struct Buffer *buf, struct Buffer *s,
129
                                      intptr_t data, struct Buffer *err)
130
0
{
131
0
  do
132
0
  {
133
0
    parse_extract_token(buf, s, TOKEN_NO_FLAGS);
134
0
    mutt_regexlist_remove(&Alternates, buf->data);
135
136
0
    if (!mutt_str_equal(buf->data, "*") &&
137
0
        (mutt_regexlist_add(&UnAlternates, buf->data, REG_ICASE, err) != 0))
138
0
    {
139
0
      return MUTT_CMD_ERROR;
140
0
    }
141
142
0
  } while (MoreArgs(s));
143
144
0
  mutt_debug(LL_NOTIFY, "NT_ALTERN_DELETE: %s\n", buf->data);
145
0
  notify_send(AlternatesNotify, NT_ALTERN, NT_ALTERN_DELETE, NULL);
146
147
0
  return MUTT_CMD_SUCCESS;
148
0
}
149
150
/**
151
 * mutt_alternates_match - Compare an Address to the Un/Alternates lists
152
 * @param addr Address to check
153
 * @retval true Address matches
154
 */
155
bool mutt_alternates_match(const char *addr)
156
0
{
157
0
  if (!addr)
158
0
    return false;
159
160
0
  if (mutt_regexlist_match(&Alternates, addr))
161
0
  {
162
0
    mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr);
163
0
    if (mutt_regexlist_match(&UnAlternates, addr))
164
0
      mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr);
165
0
    else
166
0
      return true;
167
0
  }
168
169
0
  return false;
170
0
}