Coverage Report

Created: 2023-09-25 07:17

/src/neomutt/alias/commands.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Alias commands
4
 *
5
 * @authors
6
 * Copyright (C) 2020 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 alias_commands Alias commands
25
 *
26
 * Alias commands
27
 */
28
29
#include "config.h"
30
#include <stdint.h>
31
#include <stdio.h>
32
#include "mutt/lib.h"
33
#include "address/lib.h"
34
#include "config/lib.h"
35
#include "core/lib.h"
36
#include "commands.h"
37
#include "lib.h"
38
#include "parse/lib.h"
39
#include "alias.h"
40
#include "reverse.h"
41
42
/**
43
 * parse_alias - Parse the 'alias' command - Implements Command::parse() - @ingroup command_parse
44
 *
45
 * e.g. "alias jim James Smith <js@example.com> # Pointy-haired boss"
46
 */
47
enum CommandResult parse_alias(struct Buffer *buf, struct Buffer *s,
48
                               intptr_t data, struct Buffer *err)
49
0
{
50
0
  struct Alias *tmp = NULL;
51
0
  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
52
0
  enum NotifyAlias event;
53
54
0
  if (!MoreArgs(s))
55
0
  {
56
0
    buf_strcpy(err, _("alias: no address"));
57
0
    return MUTT_CMD_WARNING;
58
0
  }
59
60
  /* name */
61
0
  parse_extract_token(buf, s, TOKEN_NO_FLAGS);
62
0
  mutt_debug(LL_DEBUG5, "First token is '%s'\n", buf->data);
63
0
  if (parse_grouplist(&gl, buf, s, err) == -1)
64
0
  {
65
0
    return MUTT_CMD_ERROR;
66
0
  }
67
0
  char *name = mutt_str_dup(buf->data);
68
69
  /* address list */
70
0
  parse_extract_token(buf, s, TOKEN_QUOTE | TOKEN_SPACE | TOKEN_SEMICOLON);
71
0
  mutt_debug(LL_DEBUG5, "Second token is '%s'\n", buf->data);
72
0
  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
73
0
  int parsed = mutt_addrlist_parse2(&al, buf->data);
74
0
  if (parsed == 0)
75
0
  {
76
0
    buf_printf(err, _("Warning: Bad address '%s' in alias '%s'"), buf->data, name);
77
0
    FREE(&name);
78
0
    goto bail;
79
0
  }
80
81
  /* IDN */
82
0
  char *estr = NULL;
83
0
  if (mutt_addrlist_to_intl(&al, &estr))
84
0
  {
85
0
    buf_printf(err, _("Warning: Bad IDN '%s' in alias '%s'"), estr, name);
86
0
    FREE(&name);
87
0
    FREE(&estr);
88
0
    goto bail;
89
0
  }
90
91
  /* check to see if an alias with this name already exists */
92
0
  TAILQ_FOREACH(tmp, &Aliases, entries)
93
0
  {
94
0
    if (mutt_istr_equal(tmp->name, name))
95
0
      break;
96
0
  }
97
98
0
  if (tmp)
99
0
  {
100
0
    FREE(&name);
101
0
    alias_reverse_delete(tmp);
102
    /* override the previous value */
103
0
    mutt_addrlist_clear(&tmp->addr);
104
0
    FREE(&tmp->comment);
105
0
    event = NT_ALIAS_CHANGE;
106
0
  }
107
0
  else
108
0
  {
109
    /* create a new alias */
110
0
    tmp = alias_new();
111
0
    tmp->name = name;
112
0
    TAILQ_INSERT_TAIL(&Aliases, tmp, entries);
113
0
    event = NT_ALIAS_ADD;
114
0
  }
115
0
  tmp->addr = al;
116
117
0
  mutt_grouplist_add_addrlist(&gl, &tmp->addr);
118
119
0
  const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
120
0
  if (c_debug_level > LL_DEBUG4)
121
0
  {
122
    /* A group is terminated with an empty address, so check a->mailbox */
123
0
    struct Address *a = NULL;
124
0
    TAILQ_FOREACH(a, &tmp->addr, entries)
125
0
    {
126
0
      if (!a->mailbox)
127
0
        break;
128
129
0
      if (a->group)
130
0
        mutt_debug(LL_DEBUG5, "  Group %s\n", buf_string(a->mailbox));
131
0
      else
132
0
        mutt_debug(LL_DEBUG5, "  %s\n", buf_string(a->mailbox));
133
0
    }
134
0
  }
135
0
  mutt_grouplist_destroy(&gl);
136
0
  if (!MoreArgs(s) && (s->dptr[0] == '#'))
137
0
  {
138
0
    char *comment = s->dptr + 1;
139
0
    SKIPWS(comment);
140
0
    tmp->comment = mutt_str_dup(comment);
141
0
  }
142
143
0
  alias_reverse_add(tmp);
144
145
0
  mutt_debug(LL_NOTIFY, "%s: %s\n",
146
0
             (event == NT_ALIAS_ADD) ? "NT_ALIAS_ADD" : "NT_ALIAS_CHANGE", tmp->name);
147
0
  struct EventAlias ev_a = { tmp };
148
0
  notify_send(NeoMutt->notify, NT_ALIAS, event, &ev_a);
149
150
0
  return MUTT_CMD_SUCCESS;
151
152
0
bail:
153
0
  mutt_grouplist_destroy(&gl);
154
0
  return MUTT_CMD_ERROR;
155
0
}
156
157
/**
158
 * parse_unalias - Parse the 'unalias' command - Implements Command::parse() - @ingroup command_parse
159
 */
160
enum CommandResult parse_unalias(struct Buffer *buf, struct Buffer *s,
161
                                 intptr_t data, struct Buffer *err)
162
0
{
163
0
  do
164
0
  {
165
0
    parse_extract_token(buf, s, TOKEN_NO_FLAGS);
166
167
0
    struct Alias *np = NULL;
168
0
    if (mutt_str_equal("*", buf->data))
169
0
    {
170
0
      TAILQ_FOREACH(np, &Aliases, entries)
171
0
      {
172
0
        alias_reverse_delete(np);
173
0
      }
174
175
0
      aliaslist_free(&Aliases);
176
0
      return MUTT_CMD_SUCCESS;
177
0
    }
178
179
0
    TAILQ_FOREACH(np, &Aliases, entries)
180
0
    {
181
0
      if (!mutt_istr_equal(buf->data, np->name))
182
0
        continue;
183
184
0
      TAILQ_REMOVE(&Aliases, np, entries);
185
0
      alias_reverse_delete(np);
186
0
      alias_free(&np);
187
0
      break;
188
0
    }
189
0
  } while (MoreArgs(s));
190
0
  return MUTT_CMD_SUCCESS;
191
0
}