2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
16 * Management of IRC lists: ban, invite, etc.
28 #include "irc-write.h"
37 #define MASK_LEN (2*CLIENT_HOST_LEN)
40 struct list_elem *next;
43 time_t valid_until; /** 0: unlimited; 1: once; t(>1): until t */
48 Lists_GetMask(const struct list_elem *e)
54 Lists_GetReason(const struct list_elem *e)
61 Lists_GetValidity(const struct list_elem *e)
64 return e->valid_until;
67 GLOBAL struct list_elem*
68 Lists_GetFirst(const struct list_head *h)
74 GLOBAL struct list_elem*
75 Lists_GetNext(const struct list_elem *e)
81 * Add a new mask to a list.
83 * @param header List head.
84 * @param Mask The IRC mask to add to the list.
85 * @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
86 * @param Reason Reason string or NULL, if no reason should be saved.
87 * @return true on success, false otherwise.
90 Lists_Add(struct list_head *header, const char *Mask, time_t ValidUntil,
93 struct list_elem *e, *newelem;
95 assert( header != NULL );
96 assert( Mask != NULL );
98 if (Lists_CheckDupeMask(header, Mask )) return true;
100 e = Lists_GetFirst(header);
102 newelem = malloc(sizeof(struct list_elem));
104 Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" );
108 strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
110 newelem->reason = malloc(strlen(Reason) + 1);
112 strlcpy(newelem->reason, Reason, strlen(Reason) + 1);
115 "Can't allocate memory for new list reason text!");
118 newelem->reason = NULL;
119 newelem->valid_until = ValidUntil;
121 header->first = newelem;
128 Lists_Unlink(struct list_head *header, struct list_elem *p, struct list_elem *victim)
130 assert(victim != NULL);
131 assert(header != NULL);
133 if (p) p->next = victim->next;
134 else header->first = victim->next;
137 free(victim->reason);
143 Lists_Del(struct list_head *header, const char *Mask)
145 struct list_elem *e, *last, *victim;
147 assert( header != NULL );
148 assert( Mask != NULL );
151 e = Lists_GetFirst(header);
153 if(strcasecmp( e->mask, Mask ) == 0 ) {
154 LogDebug("Deleted \"%s\" from list", e->mask);
157 Lists_Unlink(header, last, victim);
167 Lists_Free(struct list_head *head)
169 struct list_elem *e, *victim;
171 assert(head != NULL);
176 LogDebug("Deleted \"%s\" from invite list" , e->mask);
180 free(victim->reason);
187 Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
192 if (strcasecmp( e->mask, Mask ) == 0 )
201 Lists_MakeMask(const char *Pattern)
203 /* This function generats a valid IRC mask of "any" string. This
204 * mask is only valid until the next call to Lists_MakeMask(),
205 * because a single global buffer is used. You have to copy the
206 * generated mask to some sane location yourself! */
208 static char TheMask[MASK_LEN];
211 assert( Pattern != NULL );
213 excl = strchr( Pattern, '!' );
214 at = strchr( Pattern, '@' );
216 if(( at ) && ( at < excl )) excl = NULL;
218 if(( ! at ) && ( ! excl ))
220 /* Neither "!" nor "@" found: use string as nick name */
221 strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
222 strlcat( TheMask, "!*@*", sizeof( TheMask ));
226 if(( ! at ) && ( excl ))
228 /* Domain part is missing */
229 strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
230 strlcat( TheMask, "@*", sizeof( TheMask ));
234 if(( at ) && ( ! excl ))
236 /* User name is missing */
238 strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
239 strlcat( TheMask, "!*@", sizeof( TheMask ));
240 strlcat( TheMask, at, sizeof( TheMask ));
244 /* All parts (nick, user and domain name) are given */
245 strlcpy( TheMask, Pattern, sizeof( TheMask ));
247 } /* Lists_MakeMask */
251 Lists_Check( struct list_head *header, CLIENT *Client)
253 struct list_elem *e, *last, *next;
255 assert( header != NULL );
262 if (e->valid_until > 1 && e->valid_until < time(NULL)) {
263 /* Entry is expired, delete it */
264 LogDebug("Deleted \"%s\" from list (expired).",
266 Lists_Unlink(header, last, e);
270 if (Match(e->mask, Client_Mask(Client))) {
271 if (e->valid_until == 1 ) {
272 /* Entry is valid only once, delete it */
273 LogDebug("Deleted \"%s\" from list (used).",
275 Lists_Unlink(header, last, e);