NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
group.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <assert.h>
33#include <stdbool.h>
34#include <stdlib.h>
35#include "group.h"
36#include "address.h"
37
38static struct HashTable *Groups = NULL;
39
44static void group_free(struct Group **ptr)
45{
46 if (!ptr || !*ptr)
47 return;
48
49 struct Group *g = *ptr;
50
53 FREE(&g->name);
54
55 FREE(ptr);
56}
57
65static struct Group *group_new(const char *pat)
66{
67 struct Group *g = mutt_mem_calloc(1, sizeof(struct Group));
68
69 g->name = mutt_str_dup(pat);
70 STAILQ_INIT(&g->rs);
71 TAILQ_INIT(&g->al);
72
73 return g;
74}
75
79static void group_hash_free(int type, void *obj, intptr_t data)
80{
81 struct Group *g = obj;
82 group_free(&g);
83}
84
91{
93
95}
96
103{
105}
106
112struct Group *mutt_pattern_group(const char *pat)
113{
114 if (!pat)
115 return NULL;
116
117 struct Group *g = mutt_hash_find(Groups, pat);
118 if (!g)
119 {
120 mutt_debug(LL_DEBUG2, "Creating group %s\n", pat);
121 g = group_new(pat);
123 }
124
125 return g;
126}
127
132static void group_remove(struct Group *g)
133{
134 if (!g)
135 return;
137}
138
143void mutt_grouplist_clear(struct GroupList *gl)
144{
145 if (!gl)
146 return;
147
148 struct GroupNode *np = STAILQ_FIRST(gl);
149 struct GroupNode *next = NULL;
150 while (np)
151 {
152 group_remove(np->group);
153 next = STAILQ_NEXT(np, entries);
154 FREE(&np);
155 np = next;
156 }
157 STAILQ_INIT(gl);
158}
159
165static bool empty_group(struct Group *g)
166{
167 if (!g)
168 return true;
169 return TAILQ_EMPTY(&g->al) && STAILQ_EMPTY(&g->rs);
170}
171
177void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
178{
179 if (!gl || !group)
180 return;
181
182 struct GroupNode *np = NULL;
183 STAILQ_FOREACH(np, gl, entries)
184 {
185 if (np->group == group)
186 return;
187 }
188 np = mutt_mem_calloc(1, sizeof(struct GroupNode));
189 np->group = group;
190 STAILQ_INSERT_TAIL(gl, np, entries);
191}
192
197void mutt_grouplist_destroy(struct GroupList *gl)
198{
199 if (!gl)
200 return;
201
202 struct GroupNode *np = STAILQ_FIRST(gl);
203 struct GroupNode *next = NULL;
204 while (np)
205 {
206 next = STAILQ_NEXT(np, entries);
207 FREE(&np);
208 np = next;
209 }
210 STAILQ_INIT(gl);
211}
212
218static void group_add_addrlist(struct Group *g, const struct AddressList *al)
219{
220 if (!g || !al)
221 return;
222
223 struct AddressList al_new = TAILQ_HEAD_INITIALIZER(al_new);
224 mutt_addrlist_copy(&al_new, al, false);
225 mutt_addrlist_remove_xrefs(&g->al, &al_new);
226 struct Address *a = NULL, *tmp = NULL;
227 TAILQ_FOREACH_SAFE(a, &al_new, entries, tmp)
228 {
229 TAILQ_REMOVE(&al_new, a, entries);
230 mutt_addrlist_append(&g->al, a);
231 }
232 assert(TAILQ_EMPTY(&al_new));
233}
234
244static int group_add_regex(struct Group *g, const char *s, uint16_t flags, struct Buffer *err)
245{
246 return mutt_regexlist_add(&g->rs, s, flags, err);
247}
248
256static int group_remove_regex(struct Group *g, const char *s)
257{
258 return mutt_regexlist_remove(&g->rs, s);
259}
260
266void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
267{
268 if (!gl || !al)
269 return;
270
271 struct GroupNode *np = NULL;
272 STAILQ_FOREACH(np, gl, entries)
273 {
274 group_add_addrlist(np->group, al);
275 }
276}
277
285int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
286{
287 if (!gl || !al)
288 return -1;
289
290 struct GroupNode *gnp = NULL;
291 STAILQ_FOREACH(gnp, gl, entries)
292 {
293 struct Address *a = NULL;
294 TAILQ_FOREACH(a, al, entries)
295 {
297 }
298 if (empty_group(gnp->group))
299 {
300 group_remove(gnp->group);
301 }
302 }
303
304 return 0;
305}
306
316int mutt_grouplist_add_regex(struct GroupList *gl, const char *s,
317 uint16_t flags, struct Buffer *err)
318{
319 if (!gl || !s)
320 return -1;
321
322 int rc = 0;
323
324 struct GroupNode *np = NULL;
325 STAILQ_FOREACH(np, gl, entries)
326 {
327 rc = group_add_regex(np->group, s, flags, err);
328 if (rc)
329 return rc;
330 }
331 return rc;
332}
333
341int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
342{
343 if (!gl || !s)
344 return -1;
345
346 int rc = 0;
347 struct GroupNode *np = NULL;
348 STAILQ_FOREACH(np, gl, entries)
349 {
350 rc = group_remove_regex(np->group, s);
351 if (empty_group(np->group))
352 group_remove(np->group);
353 if (rc)
354 return rc;
355 }
356 return rc;
357}
358
365bool mutt_group_match(struct Group *g, const char *s)
366{
367 if (!g || !s)
368 return false;
369
370 if (mutt_regexlist_match(&g->rs, s))
371 return true;
372 struct Address *a = NULL;
373 TAILQ_FOREACH(a, &g->al, entries)
374 {
375 if (a->mailbox && mutt_istr_equal(s, a->mailbox))
376 return true;
377 }
378
379 return false;
380}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1435
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1455
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1408
int mutt_addrlist_remove(struct AddressList *al, const char *mailbox)
Remove an Address from a list.
Definition: address.c:413
Type representing an email address.
static bool empty_group(struct Group *g)
Is a Group empty?
Definition: group.c:165
static int group_add_regex(struct Group *g, const char *s, uint16_t flags, struct Buffer *err)
Add a Regex to a Group.
Definition: group.c:244
int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition: group.c:285
void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
Add a Group to a GroupList.
Definition: group.c:177
static void group_remove(struct Group *g)
Remove a Group from the Hash Table.
Definition: group.c:132
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:102
static void group_add_addrlist(struct Group *g, const struct AddressList *al)
Add an Address List to a Group.
Definition: group.c:218
static struct HashTable * Groups
Definition: group.c:38
static void group_free(struct Group **ptr)
Free an Address Group.
Definition: group.c:44
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:365
int mutt_grouplist_add_regex(struct GroupList *gl, const char *s, uint16_t flags, struct Buffer *err)
Add matching Addresses to a GroupList.
Definition: group.c:316
static struct Group * group_new(const char *pat)
Create a new Address Group.
Definition: group.c:65
static int group_remove_regex(struct Group *g, const char *s)
Remove a Regex from a Group.
Definition: group.c:256
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:112
int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
Remove matching addresses from a GroupList.
Definition: group.c:341
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:90
void mutt_grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition: group.c:197
void mutt_grouplist_clear(struct GroupList *gl)
Clear a GroupList.
Definition: group.c:143
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:266
Handling for email address groups.
static void group_hash_free(int type, void *obj, intptr_t data)
Free our hash table data - Implements hash_hdata_free_t -.
Definition: group.c:79
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:335
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:259
void mutt_hash_set_destructor(struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
Set the destructor for a Hash Table.
Definition: hash.c:301
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:108
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:174
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:135
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition: regex.c:230
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:195
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
#define STAILQ_INIT(head)
Definition: queue.h:372
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define TAILQ_INIT(head)
Definition: queue.h:765
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
String manipulation buffer.
Definition: buffer.h:34
An element in a GroupList.
Definition: group.h:50
struct Group * group
Address Group.
Definition: group.h:51
A set of email addresses.
Definition: group.h:40
char * name
Name of Group.
Definition: group.h:43
struct AddressList al
List of Addresses.
Definition: group.h:41
struct RegexList rs
Group Regex patterns.
Definition: group.h:42
A Hash Table.
Definition: hash.h:96