NeoMutt  2021-10-29-220-g2b1eec
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 
38 static struct HashTable *Groups = NULL;
39 
44 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 
65 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 
79 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 
112 struct 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);
122  mutt_hash_insert(Groups, g->name, g);
123  }
124 
125  return g;
126 }
127 
132 static void group_remove(struct Group *g)
133 {
134  if (!g)
135  return;
136  mutt_hash_delete(Groups, g->name, g);
137  mutt_addrlist_clear(&g->al);
138  mutt_regexlist_free(&g->rs);
139  FREE(&g->name);
140  FREE(&g);
141 }
142 
147 void mutt_grouplist_clear(struct GroupList *gl)
148 {
149  if (!gl)
150  return;
151 
152  struct GroupNode *np = STAILQ_FIRST(gl);
153  struct GroupNode *next = NULL;
154  while (np)
155  {
156  group_remove(np->group);
157  next = STAILQ_NEXT(np, entries);
158  FREE(&np);
159  np = next;
160  }
161  STAILQ_INIT(gl);
162 }
163 
169 static bool empty_group(struct Group *g)
170 {
171  if (!g)
172  return true;
173  return TAILQ_EMPTY(&g->al) && STAILQ_EMPTY(&g->rs);
174 }
175 
181 void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
182 {
183  if (!gl || !group)
184  return;
185 
186  struct GroupNode *np = NULL;
187  STAILQ_FOREACH(np, gl, entries)
188  {
189  if (np->group == group)
190  return;
191  }
192  np = mutt_mem_calloc(1, sizeof(struct GroupNode));
193  np->group = group;
194  STAILQ_INSERT_TAIL(gl, np, entries);
195 }
196 
201 void mutt_grouplist_destroy(struct GroupList *gl)
202 {
203  if (!gl)
204  return;
205 
206  struct GroupNode *np = STAILQ_FIRST(gl);
207  struct GroupNode *next = NULL;
208  while (np)
209  {
210  next = STAILQ_NEXT(np, entries);
211  FREE(&np);
212  np = next;
213  }
214  STAILQ_INIT(gl);
215 }
216 
222 static void group_add_addrlist(struct Group *g, const struct AddressList *al)
223 {
224  if (!g || !al)
225  return;
226 
227  struct AddressList al_new = TAILQ_HEAD_INITIALIZER(al_new);
228  mutt_addrlist_copy(&al_new, al, false);
229  mutt_addrlist_remove_xrefs(&g->al, &al_new);
230  struct Address *a = NULL, *tmp = NULL;
231  TAILQ_FOREACH_SAFE(a, &al_new, entries, tmp)
232  {
233  TAILQ_REMOVE(&al_new, a, entries);
234  mutt_addrlist_append(&g->al, a);
235  }
236  assert(TAILQ_EMPTY(&al_new));
237 }
238 
248 static int group_add_regex(struct Group *g, const char *s, uint16_t flags, struct Buffer *err)
249 {
250  return mutt_regexlist_add(&g->rs, s, flags, err);
251 }
252 
260 static int group_remove_regex(struct Group *g, const char *s)
261 {
262  return mutt_regexlist_remove(&g->rs, s);
263 }
264 
270 void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
271 {
272  if (!gl || !al)
273  return;
274 
275  struct GroupNode *np = NULL;
276  STAILQ_FOREACH(np, gl, entries)
277  {
278  group_add_addrlist(np->group, al);
279  }
280 }
281 
289 int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
290 {
291  if (!gl || !al)
292  return -1;
293 
294  struct GroupNode *gnp = NULL;
295  STAILQ_FOREACH(gnp, gl, entries)
296  {
297  struct Address *a = NULL;
298  TAILQ_FOREACH(a, al, entries)
299  {
300  mutt_addrlist_remove(&gnp->group->al, a->mailbox);
301  }
302  if (empty_group(gnp->group))
303  {
304  group_remove(gnp->group);
305  }
306  }
307 
308  return 0;
309 }
310 
320 int mutt_grouplist_add_regex(struct GroupList *gl, const char *s,
321  uint16_t flags, struct Buffer *err)
322 {
323  if (!gl || !s)
324  return -1;
325 
326  int rc = 0;
327 
328  struct GroupNode *np = NULL;
329  STAILQ_FOREACH(np, gl, entries)
330  {
331  rc = group_add_regex(np->group, s, flags, err);
332  if (rc)
333  return rc;
334  }
335  return rc;
336 }
337 
345 int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
346 {
347  if (!gl || !s)
348  return -1;
349 
350  int rc = 0;
351  struct GroupNode *np = NULL;
352  STAILQ_FOREACH(np, gl, entries)
353  {
354  rc = group_remove_regex(np->group, s);
355  if (empty_group(np->group))
356  group_remove(np->group);
357  if (rc)
358  return rc;
359  }
360  return rc;
361 }
362 
369 bool mutt_group_match(struct Group *g, const char *s)
370 {
371  if (!g || !s)
372  return false;
373 
374  if (mutt_regexlist_match(&g->rs, s))
375  return true;
376  struct Address *a = NULL;
377  TAILQ_FOREACH(a, &g->al, entries)
378  {
379  if (a->mailbox && mutt_istr_equal(s, a->mailbox))
380  return true;
381  }
382 
383  return false;
384 }
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:1470
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1443
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:169
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:248
int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition: group.c:289
void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
Add a Group to a GroupList.
Definition: group.c:181
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:112
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:222
static struct HashTable * Groups
Definition: group.c:38
struct Group * group_new(const char *pat)
Create a new Address Group.
Definition: group.c:65
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:369
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:320
static int group_remove_regex(struct Group *g, const char *s)
Remove a Regex from a Group.
Definition: group.c:260
int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
Remove matching addresses from a GroupList.
Definition: group.c:345
void group_free(struct Group **ptr)
Free an Address Group.
Definition: group.c:44
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:201
void mutt_grouplist_clear(struct GroupList *gl)
Clear a GroupList.
Definition: group.c:147
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:270
Handling for email address groups.
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
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
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_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:109
@ 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:40
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:173
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:134
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition: regex.c:229
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:194
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
#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:97