]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/lists.c
- neue Funktionen Conn_InitListeners() und Conn_ExitListeners().
[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  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: lists.c,v 1.9 2002/10/03 21:49:59 alex Exp $
13  *
14  * lists.c: Verwaltung der "IRC-Listen": Ban, Invite, ...
15  */
16
17
18 #include "portab.h"
19
20 #include "imp.h"
21 #include <assert.h>
22
23 #include "defines.h"
24 #include "conn.h"
25 #include "client.h"
26 #include "channel.h"
27 #include "log.h"
28 #include "match.h"
29 #include "messages.h"
30 #include "irc-write.h"
31
32 #include <stdlib.h>
33 #include <string.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                 strncpy( TheMask, Pattern, MASK_LEN - 5 );
337                 TheMask[MASK_LEN - 5] = '\0';
338                 strcat( TheMask, "!*@*" );
339                 return TheMask;
340         }
341
342         if(( ! at ) && ( excl ))
343         {
344                 /* Domain fehlt */
345                 strncpy( TheMask, Pattern, MASK_LEN - 3 );
346                 TheMask[MASK_LEN - 3] = '\0';
347                 strcat( TheMask, "@*" );
348                 return TheMask;
349         }
350
351         if(( at ) && ( ! excl ))
352         {
353                 /* User fehlt */
354                 *at = '\0'; at++;
355                 strncpy( TheMask, Pattern, MASK_LEN - 4 );
356                 TheMask[MASK_LEN - 4] = '\0';
357                 strcat( TheMask, "!*@" );
358                 strncat( TheMask, at, strlen( TheMask ) - MASK_LEN - 1 );
359                 TheMask[MASK_LEN - 1] = '\0';
360                 return TheMask;
361         }
362
363         /* alle Teile vorhanden */
364         strncpy( TheMask, Pattern, MASK_LEN - 1 );
365         TheMask[MASK_LEN - 1] = '\0';
366         return TheMask;
367 } /* Lists_MakeMask */
368
369
370 LOCAL C2C *
371 New_C2C( CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce )
372 {
373         C2C *c2c;
374         
375         assert( Mask != NULL );
376         assert( Chan != NULL );
377
378         /* Speicher fuer Eintrag anfordern */
379         c2c = malloc( sizeof( C2C ));
380         if( ! c2c )
381         {
382                 Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
383                 return NULL;
384         }
385
386         strncpy( c2c->mask, Mask, MASK_LEN );
387         c2c->channel = Chan;
388         c2c->onlyonce = OnlyOnce;
389
390         return c2c;
391 } /* New_C2C */
392
393
394 LOCAL BOOLEAN
395 Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
396 {
397         C2C *c2c, *last;
398
399         assert( Cl2Chan != NULL );
400         assert( Client != NULL );
401         assert( Chan != NULL );
402
403         c2c = *Cl2Chan;
404         last = NULL;
405
406         while( c2c )
407         {
408                 if( c2c->channel == Chan )
409                 {
410                         /* Ok, richtiger Channel. Passt die Maske? */
411                         if( Match( c2c->mask, Client_Mask( Client )))
412                         {
413                                 /* Treffer! */
414                                 if( c2c->onlyonce )
415                                 {
416                                         /* Eintrag loeschen */
417                                         Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
418                                         if( last ) last->next = c2c->next;
419                                         else *Cl2Chan = c2c->next;
420                                         free( c2c );
421                                 }
422                                 return TRUE;
423                         }
424                 }
425                 last = c2c;
426                 c2c = c2c->next;
427         }
428
429         return FALSE;
430 } /* Check_List */
431
432
433 LOCAL BOOLEAN
434 Already_Registered( C2C *List, CHAR *Mask, CHANNEL *Chan )
435 {
436         C2C *c2c;
437
438         c2c = List;
439         while( c2c )
440         {
441                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return TRUE;
442                 c2c = c2c->next;
443         }
444         return FALSE;
445 } /* Already_Registered */
446
447
448 /* -eof- */