]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/lists.c
Fixed some warnings of non-gcc-compilers (e. g. original Apple compiler on
[ngircd-alex.git] / src / ngircd / lists.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
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.
10  *
11  * Management of IRC lists: ban, invite, ...
12  */
13
14
15 #include "portab.h"
16
17 static char UNUSED id[] = "$Id: lists.c,v 1.13 2004/03/11 22:16:31 alex Exp $";
18
19 #include "imp.h"
20 #include <assert.h>
21
22 #include "defines.h"
23 #include "conn.h"
24 #include "client.h"
25 #include "channel.h"
26 #include "log.h"
27 #include "match.h"
28 #include "messages.h"
29 #include "irc-write.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34
35 #include "exp.h"
36 #include "lists.h"
37
38
39 #define MASK_LEN 2*CLIENT_HOST_LEN
40
41
42 typedef struct _C2C
43 {
44         struct _C2C *next;
45         CHAR mask[MASK_LEN];
46         CHANNEL *channel;
47         BOOLEAN onlyonce;
48 } C2C;
49
50
51 LOCAL C2C *My_Invites, *My_Bans;
52
53
54 LOCAL C2C *New_C2C PARAMS(( CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce ));
55
56 LOCAL BOOLEAN Check_List PARAMS(( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan ));
57 LOCAL BOOLEAN Already_Registered PARAMS(( C2C *Cl2Chan, CHAR *Mask, CHANNEL *Chan ));
58
59
60
61 GLOBAL VOID
62 Lists_Init( VOID )
63 {
64         /* Modul initialisieren */
65
66         My_Invites = My_Bans = NULL;
67 } /* Lists_Init */
68
69
70 GLOBAL VOID
71 Lists_Exit( VOID )
72 {
73         /* Modul abmelden */
74
75         C2C *c2c, *next;
76
77         /* Invite-Lists freigeben */
78         c2c = My_Invites;
79         while( c2c )
80         {
81                 next = c2c->next;
82                 free( c2c );
83                 c2c = next;
84         }
85
86         /* Ban-Lists freigeben */
87         c2c = My_Bans;
88         while( c2c )
89         {
90                 next = c2c->next;
91                 free( c2c );
92                 c2c = next;
93         }
94 } /* Lists_Exit */
95
96
97 GLOBAL BOOLEAN
98 Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan )
99 {
100         return Check_List( &My_Invites, Client, Chan );
101 } /* Lists_CheckInvited */
102
103
104 GLOBAL BOOLEAN
105 Lists_AddInvited( CLIENT *From, CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce )
106 {
107         C2C *c2c;
108
109         assert( Mask != NULL );
110         assert( Chan != NULL );
111
112         if( Already_Registered( My_Invites, Mask, Chan ))
113         {
114                 /* Eintrag ist bereits vorhanden */
115                 IRC_WriteStrClient( From, RPL_INVITELIST_MSG, Client_ID( From ), Channel_Name( Chan ), Mask );
116                 return FALSE;
117         }
118         
119         c2c = New_C2C( Mask, Chan, OnlyOnce );
120         if( ! c2c )
121         {
122                 Log( LOG_ERR, "Can't add new invite list entry!" );
123                 return FALSE;
124         }
125
126         /* verketten */
127         c2c->next = My_Invites;
128         My_Invites = c2c;
129
130         Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan ));
131         return TRUE;
132 } /* Lists_AddInvited */
133
134
135 GLOBAL VOID
136 Lists_DelInvited( CHAR *Mask, CHANNEL *Chan )
137 {
138         C2C *c2c, *last, *next;
139
140         assert( Mask != NULL );
141         assert( Chan != NULL );
142
143         last = NULL;
144         c2c = My_Invites;
145         while( c2c )
146         {
147                 next = c2c->next;
148                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
149                 {
150                         /* dieser Eintrag muss geloescht werden */
151                         Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
152                         if( last ) last->next = next;
153                         else My_Invites = next;
154                         free( c2c );
155                 }
156                 else last = c2c;
157                 c2c = next;
158         }
159 } /* Lists_DelInvited */
160
161
162 GLOBAL BOOLEAN
163 Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel )
164 {
165         C2C *c2c;
166
167         assert( Client != NULL );
168         assert( Channel != NULL );
169
170         c2c = My_Invites;
171         while( c2c )
172         {
173                 if( c2c->channel == Channel )
174                 {
175                         /* Eintrag fuer Channel gefunden; ausgeben: */
176                         if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
177                 }
178                 c2c = c2c->next;
179         }
180         return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
181 } /* Lists_ShowInvites */
182
183
184 GLOBAL BOOLEAN
185 Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan )
186 {
187         return Check_List( &My_Bans, Client, Chan );
188 } /* Lists_CheckBanned */
189
190
191 GLOBAL BOOLEAN
192 Lists_AddBanned( CLIENT *From, CHAR *Mask, CHANNEL *Chan )
193 {
194         C2C *c2c;
195
196         assert( Mask != NULL );
197         assert( Chan != NULL );
198
199         if( Already_Registered( My_Bans, Mask, Chan ))
200         {
201                 /* Eintrag ist bereits vorhanden */
202                 IRC_WriteStrClient( From, RPL_BANLIST_MSG, Client_ID( From ), Channel_Name( Chan ), Mask );
203                 return FALSE;
204         }
205
206         c2c = New_C2C( Mask, Chan, FALSE );
207         if( ! c2c )
208         {
209                 Log( LOG_ERR, "Can't add new ban list entry!" );
210                 return FALSE;
211         }
212
213         /* verketten */
214         c2c->next = My_Bans;
215         My_Bans = c2c;
216
217         Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan ));
218         return TRUE;
219 } /* Lists_AddBanned */
220
221
222 GLOBAL VOID
223 Lists_DelBanned( CHAR *Mask, CHANNEL *Chan )
224 {
225         C2C *c2c, *last, *next;
226
227         assert( Mask != NULL );
228         assert( Chan != NULL );
229
230         last = NULL;
231         c2c = My_Bans;
232         while( c2c )
233         {
234                 next = c2c->next;
235                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
236                 {
237                         /* dieser Eintrag muss geloescht werden */
238                         Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
239                         if( last ) last->next = next;
240                         else My_Bans = next;
241                         free( c2c );
242                 }
243                 else last = c2c;
244                 c2c = next;
245         }
246 } /* Lists_DelBanned */
247
248
249 GLOBAL BOOLEAN
250 Lists_ShowBans( CLIENT *Client, CHANNEL *Channel )
251 {
252         C2C *c2c;
253
254         assert( Client != NULL );
255         assert( Channel != NULL );
256
257         c2c = My_Bans;
258         while( c2c )
259         {
260                 if( c2c->channel == Channel )
261                 {
262                         /* Eintrag fuer Channel gefunden; ausgeben: */
263                         if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
264                 }
265                 c2c = c2c->next;
266         }
267         return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
268 } /* Lists_ShowBans */
269
270
271 GLOBAL VOID
272 Lists_DeleteChannel( CHANNEL *Chan )
273 {
274         /* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */
275
276         C2C *c2c, *last, *next;
277
278         /* Invite-List */
279         last = NULL;
280         c2c = My_Invites;
281         while( c2c )
282         {
283                 next = c2c->next;
284                 if( c2c->channel == Chan )
285                 {
286                         /* dieser Eintrag muss geloescht werden */
287                         Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
288                         if( last ) last->next = next;
289                         else My_Invites = next;
290                         free( c2c );
291                 }
292                 else last = c2c;
293                 c2c = next;
294         }
295
296         /* Ban-List */
297         last = NULL;
298         c2c = My_Bans;
299         while( c2c )
300         {
301                 next = c2c->next;
302                 if( c2c->channel == Chan )
303                 {
304                         /* dieser Eintrag muss geloescht werden */
305                         Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
306                         if( last ) last->next = next;
307                         else My_Bans = next;
308                         free( c2c );
309                 }
310                 else last = c2c;
311                 c2c = next;
312         }
313 } /* Lists_DeleteChannel */
314
315
316 GLOBAL CHAR *
317 Lists_MakeMask( CHAR *Pattern )
318 {
319         /* Hier wird aus einem "beliebigen" Pattern eine gueltige IRC-Mask erzeugt.
320          * Diese ist aber nur bis zum naechsten Aufruf von Lists_MakeMask() gueltig,
321          * da ein einziger globaler Puffer verwendet wird. ->Umkopieren!*/
322
323         STATIC CHAR TheMask[MASK_LEN];
324         CHAR *excl, *at;
325
326         assert( Pattern != NULL );
327
328         excl = strchr( Pattern, '!' );
329         at = strchr( Pattern, '@' );
330
331         if(( at ) && ( at < excl )) excl = NULL;
332
333         if(( ! at ) && ( ! excl ))
334         {
335                 /* weder ! noch @ vorhanden: als Nick annehmen */
336                 strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
337                 strlcat( TheMask, "!*@*", sizeof( TheMask ));
338                 return TheMask;
339         }
340
341         if(( ! at ) && ( excl ))
342         {
343                 /* Domain fehlt */
344                 strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
345                 strlcat( TheMask, "@*", sizeof( TheMask ));
346                 return TheMask;
347         }
348
349         if(( at ) && ( ! excl ))
350         {
351                 /* User fehlt */
352                 *at = '\0'; at++;
353                 strlcpy( TheMask, Pattern, sizeof( TheMask ) - strlen( at ) - 4 );
354                 strlcat( TheMask, "!*@", sizeof( TheMask ));
355                 strlcat( TheMask, at, sizeof( TheMask ));
356                 return TheMask;
357         }
358
359         /* alle Teile vorhanden */
360         strlcpy( TheMask, Pattern, sizeof( TheMask ));
361         return TheMask;
362 } /* Lists_MakeMask */
363
364
365 LOCAL C2C *
366 New_C2C( CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce )
367 {
368         C2C *c2c;
369         
370         assert( Mask != NULL );
371         assert( Chan != NULL );
372
373         /* Speicher fuer Eintrag anfordern */
374         c2c = (C2C *)malloc( sizeof( C2C ));
375         if( ! c2c )
376         {
377                 Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
378                 return NULL;
379         }
380
381         strlcpy( c2c->mask, Mask, sizeof( c2c->mask ));
382         c2c->channel = Chan;
383         c2c->onlyonce = OnlyOnce;
384
385         return c2c;
386 } /* New_C2C */
387
388
389 LOCAL BOOLEAN
390 Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
391 {
392         C2C *c2c, *last;
393
394         assert( Cl2Chan != NULL );
395         assert( Client != NULL );
396         assert( Chan != NULL );
397
398         c2c = *Cl2Chan;
399         last = NULL;
400
401         while( c2c )
402         {
403                 if( c2c->channel == Chan )
404                 {
405                         /* Ok, richtiger Channel. Passt die Maske? */
406                         if( Match( c2c->mask, Client_Mask( Client )))
407                         {
408                                 /* Treffer! */
409                                 if( c2c->onlyonce )
410                                 {
411                                         /* Eintrag loeschen */
412                                         Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
413                                         if( last ) last->next = c2c->next;
414                                         else *Cl2Chan = c2c->next;
415                                         free( c2c );
416                                 }
417                                 return TRUE;
418                         }
419                 }
420                 last = c2c;
421                 c2c = c2c->next;
422         }
423
424         return FALSE;
425 } /* Check_List */
426
427
428 LOCAL BOOLEAN
429 Already_Registered( C2C *List, CHAR *Mask, CHANNEL *Chan )
430 {
431         C2C *c2c;
432
433         c2c = List;
434         while( c2c )
435         {
436                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return TRUE;
437                 c2c = c2c->next;
438         }
439         return FALSE;
440 } /* Already_Registered */
441
442
443 /* -eof- */