NeoMutt  2021-02-05-666-ge300cd
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 
46 {
47  Groups = mutt_hash_new(1031, MUTT_HASH_NO_FLAGS);
48 }
49 
56 {
57  mutt_hash_free(&Groups);
58 }
59 
65 struct Group *mutt_pattern_group(const char *pat)
66 {
67  if (!pat)
68  return NULL;
69 
70  struct Group *g = mutt_hash_find(Groups, pat);
71  if (!g)
72  {
73  mutt_debug(LL_DEBUG2, "Creating group %s\n", pat);
74  g = mutt_mem_calloc(1, sizeof(struct Group));
75  g->name = mutt_str_dup(pat);
76  STAILQ_INIT(&g->rs);
77  TAILQ_INIT(&g->al);
78  mutt_hash_insert(Groups, g->name, g);
79  }
80 
81  return g;
82 }
83 
88 static void group_remove(struct Group *g)
89 {
90  if (!g)
91  return;
92  mutt_hash_delete(Groups, g->name, g);
95  FREE(&g->name);
96  FREE(&g);
97 }
98 
103 void mutt_grouplist_clear(struct GroupList *gl)
104 {
105  if (!gl)
106  return;
107 
108  struct GroupNode *np = STAILQ_FIRST(gl);
109  struct GroupNode *next = NULL;
110  while (np)
111  {
112  group_remove(np->group);
113  next = STAILQ_NEXT(np, entries);
114  FREE(&np);
115  np = next;
116  }
117  STAILQ_INIT(gl);
118 }
119 
125 static bool empty_group(struct Group *g)
126 {
127  if (!g)
128  return true;
129  return TAILQ_EMPTY(&g->al) && STAILQ_EMPTY(&g->rs);
130 }
131 
137 void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
138 {
139  if (!gl || !group)
140  return;
141 
142  struct GroupNode *np = NULL;
143  STAILQ_FOREACH(np, gl, entries)
144  {
145  if (np->group == group)
146  return;
147  }
148  np = mutt_mem_calloc(1, sizeof(struct GroupNode));
149  np->group = group;
150  STAILQ_INSERT_TAIL(gl, np, entries);
151 }
152 
157 void mutt_grouplist_destroy(struct GroupList *gl)
158 {
159  if (!gl)
160  return;
161 
162  struct GroupNode *np = STAILQ_FIRST(gl);
163  struct GroupNode *next = NULL;
164  while (np)
165  {
166  next = STAILQ_NEXT(np, entries);
167  FREE(&np);
168  np = next;
169  }
170  STAILQ_INIT(gl);
171 }
172 
178 static void group_add_addrlist(struct Group *g, const struct AddressList *al)
179 {
180  if (!g || !al)
181  return;
182 
183  struct AddressList al_new = TAILQ_HEAD_INITIALIZER(al_new);
184  mutt_addrlist_copy(&al_new, al, false);
185  mutt_addrlist_remove_xrefs(&g->al, &al_new);
186  struct Address *a = NULL, *tmp = NULL;
187  TAILQ_FOREACH_SAFE(a, &al_new, entries, tmp)
188  {
189  TAILQ_REMOVE(&al_new, a, entries);
190  mutt_addrlist_append(&g->al, a);
191  }
192  assert(TAILQ_EMPTY(&al_new));
193 }
194 
204 static int group_add_regex(struct Group *g, const char *s, uint16_t flags, struct Buffer *err)
205 {
206  return mutt_regexlist_add(&g->rs, s, flags, err);
207 }
208 
216 static int group_remove_regex(struct Group *g, const char *s)
217 {
218  return mutt_regexlist_remove(&g->rs, s);
219 }
220 
226 void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
227 {
228  if (!gl || !al)
229  return;
230 
231  struct GroupNode *np = NULL;
232  STAILQ_FOREACH(np, gl, entries)
233  {
234  group_add_addrlist(np->group, al);
235  }
236 }
237 
245 int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
246 {
247  if (!gl || !al)
248  return -1;
249 
250  struct GroupNode *gnp = NULL;
251  STAILQ_FOREACH(gnp, gl, entries)
252  {
253  struct Address *a = NULL;
254  TAILQ_FOREACH(a, al, entries)
255  {
256  mutt_addrlist_remove(&gnp->group->al, a->mailbox);
257  }
258  if (empty_group(gnp->group))
259  {
260  group_remove(gnp->group);
261  }
262  }
263 
264  return 0;
265 }
266 
276 int mutt_grouplist_add_regex(struct GroupList *gl, const char *s,
277  uint16_t flags, struct Buffer *err)
278 {
279  if (!gl || !s)
280  return -1;
281 
282  int rc = 0;
283 
284  struct GroupNode *np = NULL;
285  STAILQ_FOREACH(np, gl, entries)
286  {
287  rc = group_add_regex(np->group, s, flags, err);
288  if (rc)
289  return rc;
290  }
291  return rc;
292 }
293 
301 int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
302 {
303  if (!gl || !s)
304  return -1;
305 
306  int rc = 0;
307  struct GroupNode *np = NULL;
308  STAILQ_FOREACH(np, gl, entries)
309  {
310  rc = group_remove_regex(np->group, s);
311  if (empty_group(np->group))
312  group_remove(np->group);
313  if (rc)
314  return rc;
315  }
316  return rc;
317 }
318 
325 bool mutt_group_match(struct Group *g, const char *s)
326 {
327  if (!g || !s)
328  return false;
329 
330  if (mutt_regexlist_match(&g->rs, s))
331  return true;
332  struct Address *a = NULL;
333  TAILQ_FOREACH(a, &g->al, entries)
334  {
335  if (a->mailbox && mutt_istr_equal(s, a->mailbox))
336  return true;
337  }
338 
339  return false;
340 }
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:354
static int group_remove_regex(struct Group *g, const char *s)
Remove a Regex from a Group.
Definition: group.c:216
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:204
int mutt_addrlist_remove(struct AddressList *al, const char *mailbox)
Remove an Address from a list.
Definition: address.c:413
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:327
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
A Hash Table.
Definition: hash.h:87
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition: regex.c:227
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
static void group_add_addrlist(struct Group *g, const struct AddressList *al)
Add an Address List to a Group.
Definition: group.c:178
static bool empty_group(struct Group *g)
Is a Group empty?
Definition: group.c:125
void mutt_grouplist_clear(struct GroupList *gl)
Clear a GroupList.
Definition: group.c:103
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
struct Group * group
Address Group.
Definition: group.h:51
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
Handling for email address groups.
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:132
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_grouplist_add(struct GroupList *gl, struct Group *group)
Add a Group to a GroupList.
Definition: group.c:137
Representation of an email address.
String manipulation buffer.
Definition: buffer.h:33
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
static void group_remove(struct Group *g)
Remove a Group from the Hash Table.
Definition: group.c:88
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
An email address.
Definition: address.h:35
char * mailbox
Mailbox and host address.
Definition: address.h:38
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:226
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:325
Log at debug level 2.
Definition: logging.h:41
#define STAILQ_INIT(head)
Definition: queue.h:372
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:276
char * name
Name of Group.
Definition: group.h:43
int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
Remove matching addresses from a GroupList.
Definition: group.c:301
#define TAILQ_INIT(head)
Definition: queue.h:765
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:192
int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition: group.c:245
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:45
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
An element in a GroupList.
Definition: group.h:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
struct RegexList rs
Group Regex patterns.
Definition: group.h:42
struct AddressList al
List of Addresses.
Definition: group.h:41
A set of email addresses.
Definition: group.h:39
void mutt_grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition: group.c:157
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1443
#define FREE(x)
Definition: memory.h:40
#define STAILQ_EMPTY(head)
Definition: queue.h:348
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:55
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:100
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:65
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490