]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/lists.c
ec0ed701b426118eba48eab04d0f4dd6dd9a20b3
[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.7 2002/09/08 00:55:45 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
58
59
60 GLOBAL VOID
61 Lists_Init( VOID )
62 {
63         /* Modul initialisieren */
64
65         My_Invites = My_Bans = NULL;
66 } /* Lists_Init */
67
68
69 GLOBAL VOID
70 Lists_Exit( VOID )
71 {
72         /* Modul abmelden */
73
74         C2C *c2c, *next;
75
76         /* Invite-Lists freigeben */
77         c2c = My_Invites;
78         while( c2c )
79         {
80                 next = c2c->next;
81                 free( c2c );
82                 c2c = next;
83         }
84
85         /* Ban-Lists freigeben */
86         c2c = My_Bans;
87         while( c2c )
88         {
89                 next = c2c->next;
90                 free( c2c );
91                 c2c = next;
92         }
93 } /* Lists_Exit */
94
95
96 GLOBAL BOOLEAN
97 Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan )
98 {
99         return Check_List( &My_Invites, Client, Chan );
100 } /* Lists_CheckInvited */
101
102
103 GLOBAL BOOLEAN
104 Lists_AddInvited( CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce )
105 {
106         C2C *c2c;
107
108         assert( Mask != NULL );
109         assert( Chan != NULL );
110
111         c2c = New_C2C( Mask, Chan, OnlyOnce );
112         if( ! c2c )
113         {
114                 Log( LOG_ERR, "Can't add new invite list entry!" );
115                 return FALSE;
116         }
117
118         /* verketten */
119         c2c->next = My_Invites;
120         My_Invites = c2c;
121
122         Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan ));
123         return TRUE;
124 } /* Lists_AddInvited */
125
126
127 GLOBAL VOID
128 Lists_DelInvited( CHAR *Mask, CHANNEL *Chan )
129 {
130         C2C *c2c, *last, *next;
131
132         assert( Mask != NULL );
133         assert( Chan != NULL );
134
135         last = NULL;
136         c2c = My_Invites;
137         while( c2c )
138         {
139                 next = c2c->next;
140                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
141                 {
142                         /* dieser Eintrag muss geloescht werden */
143                         Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
144                         if( last ) last->next = next;
145                         else My_Invites = next;
146                         free( c2c );
147                 }
148                 else last = c2c;
149                 c2c = next;
150         }
151 } /* Lists_DelInvited */
152
153
154 GLOBAL BOOLEAN
155 Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel )
156 {
157         C2C *c2c;
158
159         assert( Client != NULL );
160         assert( Channel != NULL );
161
162         c2c = My_Invites;
163         while( c2c )
164         {
165                 if( c2c->channel == Channel )
166                 {
167                         /* Eintrag fuer Channel gefunden; ausgeben: */
168                         if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
169                 }
170                 c2c = c2c->next;
171         }
172         return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
173 } /* Lists_ShowInvites */
174
175
176 GLOBAL BOOLEAN
177 Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan )
178 {
179         return Check_List( &My_Bans, Client, Chan );
180 } /* Lists_CheckBanned */
181
182
183 GLOBAL BOOLEAN
184 Lists_AddBanned( CHAR *Mask, CHANNEL *Chan )
185 {
186         C2C *c2c;
187
188         assert( Mask != NULL );
189         assert( Chan != NULL );
190
191         c2c = New_C2C( Mask, Chan, FALSE );
192         if( ! c2c )
193         {
194                 Log( LOG_ERR, "Can't add new ban list entry!" );
195                 return FALSE;
196         }
197
198         /* verketten */
199         c2c->next = My_Bans;
200         My_Bans = c2c;
201
202         Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan ));
203         return TRUE;
204 } /* Lists_AddBanned */
205
206
207 GLOBAL VOID
208 Lists_DelBanned( CHAR *Mask, CHANNEL *Chan )
209 {
210         C2C *c2c, *last, *next;
211
212         assert( Mask != NULL );
213         assert( Chan != NULL );
214
215         last = NULL;
216         c2c = My_Bans;
217         while( c2c )
218         {
219                 next = c2c->next;
220                 if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
221                 {
222                         /* dieser Eintrag muss geloescht werden */
223                         Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
224                         if( last ) last->next = next;
225                         else My_Bans = next;
226                         free( c2c );
227                 }
228                 else last = c2c;
229                 c2c = next;
230         }
231 } /* Lists_DelBanned */
232
233
234 GLOBAL BOOLEAN
235 Lists_ShowBans( CLIENT *Client, CHANNEL *Channel )
236 {
237         C2C *c2c;
238
239         assert( Client != NULL );
240         assert( Channel != NULL );
241
242         c2c = My_Bans;
243         while( c2c )
244         {
245                 if( c2c->channel == Channel )
246                 {
247                         /* Eintrag fuer Channel gefunden; ausgeben: */
248                         if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
249                 }
250                 c2c = c2c->next;
251         }
252         return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
253 } /* Lists_ShowBans */
254
255
256 GLOBAL VOID
257 Lists_DeleteChannel( CHANNEL *Chan )
258 {
259         /* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */
260
261         C2C *c2c, *last, *next;
262
263         /* Invite-List */
264         last = NULL;
265         c2c = My_Invites;
266         while( c2c )
267         {
268                 next = c2c->next;
269                 if( c2c->channel == Chan )
270                 {
271                         /* dieser Eintrag muss geloescht werden */
272                         Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
273                         if( last ) last->next = next;
274                         else My_Invites = next;
275                         free( c2c );
276                 }
277                 else last = c2c;
278                 c2c = next;
279         }
280
281         /* Ban-List */
282         last = NULL;
283         c2c = My_Bans;
284         while( c2c )
285         {
286                 next = c2c->next;
287                 if( c2c->channel == Chan )
288                 {
289                         /* dieser Eintrag muss geloescht werden */
290                         Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
291                         if( last ) last->next = next;
292                         else My_Bans = next;
293                         free( c2c );
294                 }
295                 else last = c2c;
296                 c2c = next;
297         }
298 } /* Lists_DeleteChannel */
299
300
301 GLOBAL CHAR *
302 Lists_MakeMask( CHAR *Pattern )
303 {
304         /* Hier wird aus einem "beliebigen" Pattern eine gueltige IRC-Mask erzeugt.
305         * Diese ist aber nur bis zum naechsten Aufruf von Lists_MakeMask() gueltig,
306         * da ein einziger globaler Puffer verwendet wird. ->Umkopieren!*/
307
308         STATIC CHAR TheMask[MASK_LEN];
309         CHAR *excl, *at;
310
311         assert( Pattern );
312
313         excl = strchr( Pattern, '!' );
314         at = strchr( Pattern, '@' );
315
316         if(( at ) && ( at < excl )) excl = NULL;
317
318         if(( ! at ) && ( ! excl ))
319         {
320                 /* weder ! noch @ĂŠvorhanden: als Nick annehmen */
321                 strncpy( TheMask, Pattern, MASK_LEN - 5 );
322                 TheMask[MASK_LEN - 5] = '\0';
323                 strcat( TheMask, "!*@*" );
324                 return TheMask;
325         }
326
327         if(( ! at ) && ( excl ))
328         {
329                 /* Domain fehlt */
330                 strncpy( TheMask, Pattern, MASK_LEN - 3 );
331                 TheMask[MASK_LEN - 3] = '\0';
332                 strcat( TheMask, "@*" );
333                 return TheMask;
334         }
335
336         if(( at ) && ( ! excl ))
337         {
338                 /* User fehlt */
339                 *at = '\0'; at++;
340                 strncpy( TheMask, Pattern, MASK_LEN - 4 );
341                 TheMask[MASK_LEN - 4] = '\0';
342                 strcat( TheMask, "!*@" );
343                 strncat( TheMask, at, strlen( TheMask ) - MASK_LEN - 1 );
344                 TheMask[MASK_LEN - 1] = '\0';
345                 return TheMask;
346         }
347
348         /* alle Teile vorhanden */
349         strncpy( TheMask, Pattern, MASK_LEN - 1 );
350         TheMask[MASK_LEN - 1] = '\0';
351         return TheMask;
352 } /* Lists_MakeMask */
353
354
355 LOCAL C2C *
356 New_C2C( CHAR *Mask, CHANNEL *Chan, BOOLEAN OnlyOnce )
357 {
358         C2C *c2c;
359         
360         assert( Mask != NULL );
361         assert( Chan != NULL );
362
363         /* Speicher fuer Eintrag anfordern */
364         c2c = malloc( sizeof( C2C ));
365         if( ! c2c )
366         {
367                 Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
368                 return NULL;
369         }
370
371         strncpy( c2c->mask, Mask, MASK_LEN );
372         c2c->channel = Chan;
373         c2c->onlyonce = OnlyOnce;
374
375         return c2c;
376 } /* New_C2C */
377
378
379 LOCAL BOOLEAN
380 Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
381 {
382         C2C *c2c, *last;
383
384         assert( Cl2Chan != NULL );
385         assert( Client != NULL );
386         assert( Chan != NULL );
387
388         c2c = *Cl2Chan;
389         last = NULL;
390
391         while( c2c )
392         {
393                 if( c2c->channel == Chan )
394                 {
395                         /* Ok, richtiger Channel. Passt die Maske? */
396                         if( Match( c2c->mask, Client_Mask( Client )))
397                         {
398                                 /* Treffer! */
399                                 if( c2c->onlyonce )
400                                 {
401                                         /* Eintrag loeschen */
402                                         Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
403                                         if( last ) last->next = c2c->next;
404                                         else *Cl2Chan = c2c->next;
405                                         free( c2c );
406                                 }
407                                 return TRUE;
408                         }
409                 }
410                 last = c2c;
411                 c2c = c2c->next;
412         }
413
414         return FALSE;
415 } /* Check_List */
416
417
418 /* -eof- */