NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
group.c
Go to the documentation of this file.
1
30
36
37#include "config.h"
38#include <stdio.h>
39#include "mutt/lib.h"
40#include "address/lib.h"
41#include "core/lib.h"
42#include "group.h"
43#include "parse/lib.h"
44#include "module_data.h"
45
56int parse_grouplist(struct GroupList *gl, struct Buffer *token, struct Buffer *line,
57 struct Buffer *err, struct HashTable *groups)
58{
59 while (mutt_istr_equal(token->data, "-group"))
60 {
61 if (!MoreArgs(line))
62 {
63 buf_strcpy(err, _("-group: no group name"));
64 return -1;
65 }
66
68
69 grouplist_add_group(gl, groups_get_group(groups, token->data));
70
71 if (!MoreArgs(line))
72 {
73 buf_strcpy(err, _("out of arguments"));
74 return -1;
75 }
76
78 }
79
80 return 0;
81}
82
90enum CommandResult parse_group(const struct Command *cmd, struct Buffer *line,
91 const struct ParseContext *pc, struct ParseError *pe)
92{
93 struct Buffer *err = pe->message;
94
95 if (!MoreArgs(line))
96 {
97 buf_printf(err, _("%s: too few arguments"), cmd->name);
98 return MUTT_CMD_WARNING;
99 }
100
102 ASSERT(mod_data);
103
104 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
105 enum GroupState gstate = GS_NONE;
106 struct Buffer *token = buf_pool_get();
108
109 do
110 {
112 if (parse_grouplist(&gl, token, line, err, mod_data->groups) == -1)
113 goto done;
114
115 if ((cmd->id == CMD_UNGROUP) && mutt_istr_equal(buf_string(token), "*"))
116 {
117 groups_remove_grouplist(mod_data->groups, &gl);
118 rc = MUTT_CMD_SUCCESS;
119 goto done;
120 }
121
122 if (mutt_istr_equal(buf_string(token), "-rx"))
123 {
124 gstate = GS_RX;
125 }
126 else if (mutt_istr_equal(buf_string(token), "-addr"))
127 {
128 gstate = GS_ADDR;
129 }
130 else
131 {
132 switch (gstate)
133 {
134 case GS_NONE:
135 buf_printf(err, _("%s: missing -rx or -addr"), cmd->name);
136 rc = MUTT_CMD_WARNING;
137 goto done;
138
139 case GS_RX:
140 if ((cmd->id == CMD_GROUP) &&
141 (grouplist_add_regex(&gl, buf_string(token), REG_ICASE, err) != 0))
142 {
143 goto done;
144 }
145 else if ((cmd->id == CMD_UNGROUP) &&
146 (groups_remove_regex(mod_data->groups, &gl, buf_string(token)) < 0))
147 {
148 goto done;
149 }
150 break;
151
152 case GS_ADDR:
153 {
154 char *estr = NULL;
155 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
156 mutt_addrlist_parse2(&al, buf_string(token));
157 if (TAILQ_EMPTY(&al))
158 goto done;
159 if (mutt_addrlist_to_intl(&al, &estr))
160 {
161 buf_printf(err, _("%s: warning: bad IDN '%s'"), cmd->name, estr);
163 FREE(&estr);
164 goto done;
165 }
166 if (cmd->id == CMD_GROUP)
167 grouplist_add_addrlist(&gl, &al);
168 else if (cmd->id == CMD_UNGROUP)
169 groups_remove_addrlist(mod_data->groups, &gl, &al);
171 break;
172 }
173 }
174 }
175 } while (MoreArgs(line));
176
177 rc = MUTT_CMD_SUCCESS;
178
179done:
180 buf_pool_release(&token);
182 return rc;
183}
184
191enum CommandResult parse_lists(const struct Command *cmd, struct Buffer *line,
192 const struct ParseContext *pc, struct ParseError *pe)
193{
194 struct Buffer *err = pe->message;
195
196 if (!MoreArgs(line))
197 {
198 buf_printf(err, _("%s: too few arguments"), cmd->name);
199 return MUTT_CMD_WARNING;
200 }
201
202 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
203 struct Buffer *token = buf_pool_get();
205
207 ASSERT(mod_data);
208
209 do
210 {
212
213 if (parse_grouplist(&gl, token, line, err, mod_data->groups) == -1)
214 goto done;
215
216 mutt_regexlist_remove(&mod_data->unmail, buf_string(token));
217
218 if (mutt_regexlist_add(&mod_data->mail, buf_string(token), REG_ICASE, err) != 0)
219 goto done;
220
221 if (grouplist_add_regex(&gl, buf_string(token), REG_ICASE, err) != 0)
222 goto done;
223 } while (MoreArgs(line));
224
225 rc = MUTT_CMD_SUCCESS;
226
227done:
228 buf_pool_release(&token);
230 return rc;
231}
232
239enum CommandResult parse_subscribe(const struct Command *cmd, struct Buffer *line,
240 const struct ParseContext *pc, struct ParseError *pe)
241{
242 struct Buffer *err = pe->message;
243
244 if (!MoreArgs(line))
245 {
246 buf_printf(err, _("%s: too few arguments"), cmd->name);
247 return MUTT_CMD_WARNING;
248 }
249
250 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
251 struct Buffer *token = buf_pool_get();
253
255 ASSERT(mod_data);
256
257 do
258 {
260
261 if (parse_grouplist(&gl, token, line, err, mod_data->groups) == -1)
262 goto done;
263
264 mutt_regexlist_remove(&mod_data->unmail, buf_string(token));
266
267 if (mutt_regexlist_add(&mod_data->mail, buf_string(token), REG_ICASE, err) != 0)
268 goto done;
269
270 if (mutt_regexlist_add(&mod_data->subscribed, buf_string(token), REG_ICASE, err) != 0)
271 goto done;
272
273 if (grouplist_add_regex(&gl, buf_string(token), REG_ICASE, err) != 0)
274 goto done;
275 } while (MoreArgs(line));
276
277 rc = MUTT_CMD_SUCCESS;
278
279done:
280 buf_pool_release(&token);
282 return rc;
283}
284
291enum CommandResult parse_unlists(const struct Command *cmd, struct Buffer *line,
292 const struct ParseContext *pc, struct ParseError *pe)
293{
294 struct Buffer *err = pe->message;
295
296 if (!MoreArgs(line))
297 {
298 buf_printf(err, _("%s: too few arguments"), cmd->name);
299 return MUTT_CMD_WARNING;
300 }
301
302 struct Buffer *token = buf_pool_get();
304
306 ASSERT(mod_data);
307
309 do
310 {
312 mutt_regexlist_remove(&mod_data->subscribed, buf_string(token));
313 mutt_regexlist_remove(&mod_data->mail, buf_string(token));
314
315 if (!mutt_str_equal(buf_string(token), "*") &&
316 (mutt_regexlist_add(&mod_data->unmail, buf_string(token), REG_ICASE, err) != 0))
317 {
318 goto done;
319 }
320 } while (MoreArgs(line));
321
322 rc = MUTT_CMD_SUCCESS;
323
324done:
325 buf_pool_release(&token);
326 return rc;
327}
328
335enum CommandResult parse_unsubscribe(const struct Command *cmd, struct Buffer *line,
336 const struct ParseContext *pc, struct ParseError *pe)
337{
338 struct Buffer *err = pe->message;
339
340 if (!MoreArgs(line))
341 {
342 buf_printf(err, _("%s: too few arguments"), cmd->name);
343 return MUTT_CMD_WARNING;
344 }
345
347 ASSERT(mod_data);
348
349 struct Buffer *token = buf_pool_get();
351
353 do
354 {
356 mutt_regexlist_remove(&mod_data->subscribed, buf_string(token));
357
358 if (!mutt_str_equal(buf_string(token), "*") &&
359 (mutt_regexlist_add(&mod_data->unsubscribed, buf_string(token), REG_ICASE, err) != 0))
360 {
361 goto done;
362 }
363 } while (MoreArgs(line));
364
365 rc = MUTT_CMD_SUCCESS;
366
367done:
368 buf_pool_release(&token);
369 return rc;
370}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1469
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:649
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1302
int grouplist_add_regex(struct GroupList *gl, const char *str, uint16_t flags, struct Buffer *err)
Add matching Addresses to a GroupList.
Definition group.c:245
int groups_remove_addrlist(struct HashTable *groups, struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition group.c:337
void groups_remove_grouplist(struct HashTable *groups, struct GroupList *gl)
Clear a GroupList.
Definition group.c:312
int groups_remove_regex(struct HashTable *groups, struct GroupList *gl, const char *str)
Remove matching addresses from a GroupList.
Definition group.c:368
struct Group * groups_get_group(struct HashTable *groups, const char *name)
Get a Group by its name.
Definition group.c:291
void grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition group.c:224
void grouplist_add_group(struct GroupList *gl, struct Group *g)
Add a Group to a GroupList.
Definition group.c:183
void grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition group.c:203
Email Address Handling.
int parse_grouplist(struct GroupList *gl, struct Buffer *token, struct Buffer *line, struct Buffer *err, struct HashTable *groups)
Parse a group context.
Definition group.c:56
Parse Group/Lists Commands.
GroupState
Type of email address group.
Definition group.h:38
@ GS_RX
Entry is a regular expression.
Definition group.h:40
@ GS_NONE
Group is missing an argument.
Definition group.h:39
@ GS_ADDR
Entry is an address.
Definition group.h:41
Alias private Module data.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_GROUP
:group
Definition command.h:79
@ CMD_UNGROUP
:ungroup
Definition command.h:130
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
Convenience wrapper for the core headers.
int parse_extract_token(struct Buffer *dest, struct Buffer *line, TokenFlags flags)
Extract one token from a string.
Definition extract.c:49
#define MoreArgs(buf)
Definition extract.h:31
#define TOKEN_NO_FLAGS
No flags are set.
Definition extract.h:45
enum CommandResult parse_subscribe(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'subscribe' command - Implements Command::parse() -.
Definition group.c:239
enum CommandResult parse_unlists(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'unlists' command - Implements Command::parse() -.
Definition group.c:291
enum CommandResult parse_lists(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'lists' command - Implements Command::parse() -.
Definition group.c:191
enum CommandResult parse_group(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'group' and 'ungroup' commands - Implements Command::parse() -.
Definition group.c:90
enum CommandResult parse_unsubscribe(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'unsubscribe' command - Implements Command::parse() -.
Definition group.c:335
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition hash.c:459
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
@ MODULE_ID_ALIAS
ModuleAlias, Alias
Definition module_api.h:48
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
int mutt_regexlist_add(struct RegexList *rl, const char *str, uint16_t flags, struct Buffer *err)
Compile a regex string and add it to a list.
Definition regex.c:140
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition regex.c:235
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:665
Text parsing functions.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
#define ASSERT(COND)
Definition signal2.h:59
Alias private Module data.
Definition module_data.h:33
struct RegexList subscribed
Regexes to match subscribed mailing lists.
Definition module_data.h:49
struct RegexList mail
Regexes to match mailing lists.
Definition module_data.h:48
struct HashTable * auto_subscribe_cache
Hash Table: "mailto:" (no value)
Definition module_data.h:47
struct HashTable * groups
Hash Table: "group-name" -> Group.
Definition module_data.h:45
struct RegexList unmail
Regexes to exclude false matches in mail.
Definition module_data.h:50
struct RegexList unsubscribed
Regexes to exclude false matches in subscribed.
Definition module_data.h:51
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
const char * name
Name of the Command.
Definition command.h:159
enum CommandId id
ID of the Command.
Definition command.h:160
A Hash Table.
Definition hash.h:99
Container for Accounts, Notifications.
Definition neomutt.h:41
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35