- fixed some parsing bugs.
[ngircd-alex.git] / src / ngircd / irc-mode.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  * IRC commands for mode changes (MODE, AWAY, ...)
12  */
13
14
15 #include "portab.h"
16
17 static char UNUSED id[] = "$Id: irc-mode.c,v 1.21 2002/12/15 16:29:18 alex Exp $";
18
19 #include "imp.h"
20 #include <assert.h>
21 #include <string.h>
22
23 #include "conn.h"
24 #include "client.h"
25 #include "channel.h"
26 #include "defines.h"
27 #include "irc-write.h"
28 #include "lists.h"
29 #include "log.h"
30 #include "parse.h"
31 #include "messages.h"
32 #include "resolve.h"
33 #include "conf.h"
34
35 #include "exp.h"
36 #include "irc-mode.h"
37
38
39 LOCAL BOOLEAN Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ));
40 LOCAL BOOLEAN Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ));
41
42 LOCAL BOOLEAN Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
43 LOCAL BOOLEAN Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
44
45 LOCAL BOOLEAN Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
46 LOCAL BOOLEAN Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
47
48 LOCAL BOOLEAN Send_ListChange PARAMS(( CHAR *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Mask ));
49
50
51 GLOBAL BOOLEAN
52 IRC_MODE( CLIENT *Client, REQUEST *Req )
53 {
54         CLIENT *cl, *origin;
55         CHANNEL *chan;
56
57         assert( Client != NULL );
58         assert( Req != NULL );
59
60         /* No parameters? */
61         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
62
63         /* Origin for answers */
64         if( Client_Type( Client ) == CLIENT_SERVER )
65         {
66                 origin = Client_Search( Req->prefix );
67                 if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
68         }
69         else origin = Client;
70         
71         /* Channel or user mode? */
72         cl = chan = NULL;
73         if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
74         if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
75
76         if( cl ) return Client_Mode( Client, Req, origin, cl );
77         if( chan ) return Channel_Mode( Client, Req, origin, chan );
78
79         /* No target found! */
80         return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
81 } /* IRC_MODE */
82
83
84 LOCAL BOOLEAN
85 Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
86 {
87         /* Handle client mode requests */
88
89         CHAR the_modes[COMMAND_LEN], x[2], *mode_ptr;
90         BOOLEAN ok, set;
91         INT mode_arg;
92
93         /* Is the client allowed to request or change the modes? */
94         if( Client_Type( Client ) == CLIENT_USER )
95         {
96                 /* Users are only allowed to manipulate their own modes! */
97                 if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
98         }
99
100         /* Mode request: let's answer it :-) */
101         if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
102
103         mode_arg = 1;
104         mode_ptr = Req->argv[mode_arg];
105
106         /* Initial state: set or unset modes? */
107         if( *mode_ptr == '+' ) set = TRUE;
108         else if( *mode_ptr == '-' ) set = FALSE;
109         else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
110
111         /* Prepare reply string */
112         if( set ) strcpy( the_modes, "+" );
113         else strcpy( the_modes, "-" );
114
115         x[1] = '\0';
116         ok = CONNECTED;
117         while( mode_ptr )
118         {
119                 mode_ptr++;
120                 if( ! *mode_ptr )
121                 {
122                         /* Try next argument if there's any */
123                         mode_arg++;
124                         if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
125                         else break;
126                 }
127                 
128                 switch( *mode_ptr )
129                 {
130                         case '+':
131                         case '-':
132                                 if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
133                                 {
134                                         /* Action modifier ("+"/"-") must be changed ... */
135                                         if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' ))
136                                         {
137                                                 /* Adjust last action modifier in result */
138                                                 the_modes[strlen( the_modes ) - 1] = *mode_ptr;
139                                         }
140                                         else
141                                         {
142                                                 /* Append modifier character to result string */
143                                                 x[0] = *mode_ptr; strcat( the_modes, x );
144                                         }
145                                         if( *mode_ptr == '+' ) set = TRUE;
146                                         else set = FALSE;
147                                 }
148                                 continue;
149                 }
150                 
151                 x[0] = '\0';
152                 if( Client_Type( Client ) == CLIENT_SERVER )
153                 {
154                         /* MODE request was received from a server:
155                          * therefore don't validate but trust it! */
156                         x[0] = *mode_ptr;
157                 }
158                 else
159                 {
160                         /* Validate modes */
161                         switch( *mode_ptr )
162                         {
163                                 case 'i':
164                                         /* Invisible */
165                                         x[0] = 'i';
166                                         break;
167                                 case 'o':
168                                         /* IRC operator (only unsetable!) */
169                                         if( ! set )
170                                         {
171                                                 Client_SetOperByMe( Target, FALSE );
172                                                 x[0] = 'o';
173                                         }
174                                         else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
175                                         break;
176                                 case 'r':
177                                         /* Restricted (only setable) */
178                                         if( set ) x[0] = 'r';
179                                         else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
180                                         break;
181                                 case 's':
182                                         /* Server messages */
183                                         x[0] = 's';
184                                         break;
185                                 default:
186                                         Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
187                                         ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
188                                         x[0] = '\0';
189                         }
190                 }
191                 if( ! ok ) break;
192
193                 /* Is there a valid mode change? */
194                 if( ! x[0] ) continue;
195
196                 if( set )
197                 {
198                         /* Set mode */
199                         if( Client_ModeAdd( Target, x[0] )) strcat( the_modes, x );
200
201                 }
202                 else
203                 {
204                         /* Unset mode */
205                         if( Client_ModeDel( Target, x[0] )) strcat( the_modes, x );
206                 }               
207         }
208
209         /* Are there changed modes? */
210         if( the_modes[1] )
211         {
212                 /* Remoce needless action modifier characters */
213                 if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) the_modes[strlen( the_modes ) - 1] = '\0';
214
215                 if( Client_Type( Client ) == CLIENT_SERVER )
216                 {
217                         /* Forward modes to other servers */
218                         IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
219                 }
220                 else
221                 {
222                         /* Send reply to client and inform other servers */
223                         ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s", Client_ID( Target ), the_modes );
224                         IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
225                 }
226                 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target ));
227         }
228                 
229         return ok;
230 } /* Client_Mode */
231
232
233 LOCAL BOOLEAN
234 Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
235 {
236         /* Handle channel and channel-user modes */
237
238         CHAR the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], *mode_ptr;
239         BOOLEAN ok, set, modeok, skiponce;
240         INT mode_arg, arg_arg;
241         CLIENT *client;
242
243         /* Mode request: let's answer it :-) */
244         if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel ));
245
246         /* Is the user allowed to change modes? */
247         if( Client_Type( Client ) == CLIENT_USER )
248         {
249                 if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = TRUE;
250                 else modeok = FALSE;
251                 if( Conf_OperCanMode )
252                 {
253                         /* auch IRC-Operatoren duerfen MODE verwenden */
254                         if( Client_OperByMe( Origin )) modeok = TRUE;
255                 }
256         }
257         else modeok = TRUE;
258
259         mode_arg = 1;
260         mode_ptr = Req->argv[mode_arg];
261         if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
262         else arg_arg = -1;
263
264         /* Initial state: set or unset modes? */
265         skiponce = FALSE;
266         if( *mode_ptr == '-' ) set = FALSE;
267         else if( *mode_ptr == '+' ) set = TRUE;
268         else set = skiponce = TRUE;
269
270         /* Prepare reply string */
271         if( set ) strcpy( the_modes, "+" );
272         else strcpy( the_modes, "-" );
273         strcpy( the_args, " " );
274
275         x[1] = '\0';
276         ok = CONNECTED;
277         while( mode_ptr )
278         {
279                 if( ! skiponce ) mode_ptr++;
280                 if( ! *mode_ptr )
281                 {
282                         /* Try next argument if there's any */
283                         if( arg_arg > mode_arg ) mode_arg = arg_arg;
284                         else mode_arg++;
285                         if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
286                         else break;
287                         if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
288                         else arg_arg = -1;
289                 }
290                 skiponce = FALSE;
291
292                 switch( *mode_ptr )
293                 {
294                         case '+':
295                         case '-':
296                                 if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
297                                 {
298                                         /* Action modifier ("+"/"-") must be changed ... */
299                                         if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' ))
300                                         {
301                                                 /* Adjust last action modifier in result */
302                                                 the_modes[strlen( the_modes ) - 1] = *mode_ptr;
303                                         }
304                                         else
305                                         {
306                                                 /* Append modifier character to result string */
307                                                 x[0] = *mode_ptr; strcat( the_modes, x );
308                                         }
309                                         if( *mode_ptr == '+' ) set = TRUE;
310                                         else set = FALSE;
311                                 }
312                                 continue;
313                 }
314
315                 /* Are there arguments left? */
316                 if( arg_arg >= Req->argc ) arg_arg = -1;
317
318                 x[0] = '\0';
319                 client = NULL;
320                 if( Client_Type( Client ) == CLIENT_SERVER )
321                 {
322                         /* MODE request was received from a server:
323                          * therefore don't validate but trust it! */
324                         x[0] = *mode_ptr;
325                 }
326                 else
327                 {
328                         /* Validate modes */
329                         switch( *mode_ptr )
330                         {
331                                 /* Channel modes */
332                                 case 'i':
333                                         /* Invite-Only */
334                                         if( modeok ) x[0] = 'i';
335                                         else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
336                                         break;
337                                 case 'm':
338                                         /* Moderated */
339                                         if( modeok ) x[0] = 'm';
340                                         else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
341                                         break;
342                                 case 'n':
343                                         /* kein Schreiben in den Channel von aussen */
344                                         if( modeok ) x[0] = 'n';
345                                         else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
346                                         break;
347                                 case 't':
348                                         /* Topic Lock */
349                                         if( modeok ) x[0] = 't';
350                                         else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
351                                         break;
352                                 case 'P':
353                                         /* Persistent channel */
354                                         if( modeok )
355                                         {
356                                                 if( set && ( ! Client_OperByMe( Client )))
357                                                 {
358                                                         /* Only IRC operators are allowed to set P mode */
359                                                         ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
360                                                 }
361                                                 else x[0] = 'P';
362                                         }
363                                         else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
364                                         break;
365
366                                 /* Channel user modes */
367                                 case 'o':
368                                         /* Channel operator */
369                                 case 'v':
370                                         /* Voice */
371                                         if( arg_arg > mode_arg )
372                                         {
373                                                 if( modeok )
374                                                 {
375                                                         client = Client_Search( Req->argv[arg_arg] );
376                                                         if( client ) x[0] = *mode_ptr;
377                                                         else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] );
378                                                 }
379                                                 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
380                                                 Req->argv[arg_arg][0] = '\0';
381                                                 arg_arg++;
382                                         }
383                                         else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
384                                         break;
385
386                                 /* Channel lists */
387                                 case 'I':
388                                         /* Invite lists */
389                                         if( arg_arg > mode_arg )
390                                         {
391                                                 /* modify list */
392                                                 if( modeok )
393                                                 {
394                                                         if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
395                                                         else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
396                                                 }
397                                                 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
398                                                 Req->argv[arg_arg][0] = '\0';
399                                                 arg_arg++;
400                                         }
401                                         else Lists_ShowInvites( Origin, Channel );
402                                         break;
403                                 case 'b':
404                                         /* Ban lists */
405                                         if( arg_arg > mode_arg )
406                                         {
407                                                 /* modify list */
408                                                 if( modeok )
409                                                 {
410                                                         if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
411                                                         else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
412                                                 }
413                                                 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
414                                                 Req->argv[arg_arg][0] = '\0';
415                                                 arg_arg++;
416                                         }
417                                         else Lists_ShowBans( Origin, Channel );
418                                         break;
419
420                                 default:
421                                         Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel ));
422                                         ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
423                                         x[0] = '\0';
424                         }
425                 }
426                 if( ! ok ) break;
427
428                 /* Is there a valid mode change? */
429                 if( ! x[0] ) continue;
430
431                 if( set )
432                 {
433                         /* Set mode */
434                         if( client )
435                         {
436                                 /* Channel-User-Mode */
437                                 if( Channel_UserModeAdd( Channel, client, x[0] ))
438                                 {
439                                         strcat( the_args, Client_ID( client ));
440                                         strcat( the_args, " " ); strcat( the_modes, x );
441                                         Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
442                                 }
443                         }
444                         else
445                         {
446                                 /* Channel-Mode */
447                                 if( Channel_ModeAdd( Channel, x[0] ))
448                                 {
449                                         strcat( the_modes, x );
450                                         Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
451                                 }
452                         }
453                 }
454                 else
455                 {
456                         /* Unset mode */
457                         if( client )
458                         {
459                                 /* Channel-User-Mode */
460                                 if( Channel_UserModeDel( Channel, client, x[0] ))
461                                 {
462                                         strcat( the_args, Client_ID( client ));
463                                         strcat( the_args, " " ); strcat( the_modes, x );
464                                         Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
465                                 }
466                         }
467                         else
468                         {
469                                 /* Channel-Mode */
470                                 if( Channel_ModeDel( Channel, x[0] ))
471                                 {
472                                         strcat( the_modes, x );
473                                         Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
474                                 }
475                         }
476                 }               
477         }
478
479         /* Are there changed modes? */
480         if( the_modes[1] )
481         {
482                 /* Clean up mode string */
483                 if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) the_modes[strlen( the_modes ) - 1] = '\0';
484
485                 /* Clean up argument string if there are none */
486                 if( ! the_args[1] ) the_args[0] = '\0';
487
488                 if( Client_Type( Client ) == CLIENT_SERVER )
489                 {
490                         /* Forward mode changes to channel users and other servers */
491                         IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
492                         IRC_WriteStrChannelPrefix( Client, Channel, Origin, FALSE, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
493                 }
494                 else
495                 {
496                         /* Send reply to client and inform other servers and channel users */
497                         ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
498                         IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
499                         IRC_WriteStrChannelPrefix( Client, Channel, Origin, FALSE, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
500                 }
501         }
502
503         return CONNECTED;
504 } /* Channel_Mode */
505
506
507 GLOBAL BOOLEAN
508 IRC_AWAY( CLIENT *Client, REQUEST *Req )
509 {
510         assert( Client != NULL );
511         assert( Req != NULL );
512
513         /* Falsche Anzahl Parameter? */
514         if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
515
516         if(( Req->argc == 1 ) && (Req->argv[0][0] ))
517         {
518                 /* AWAY setzen */
519                 Client_SetAway( Client, Req->argv[0] );
520                 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
521                 return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
522         }
523         else
524         {
525                 /* AWAY loeschen */
526                 Client_SetAway( Client, NULL );
527                 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
528                 return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
529         }
530 } /* IRC_AWAY */
531
532
533 LOCAL BOOLEAN
534 Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
535 {
536         CHAR *mask;
537
538         assert( Client != NULL );
539         assert( Channel != NULL );
540         assert( Pattern != NULL );
541
542         mask = Lists_MakeMask( Pattern );
543
544         if( ! Lists_AddInvited( Prefix, mask, Channel, FALSE )) return CONNECTED;
545         return Send_ListChange( "+I", Prefix, Client, Channel, mask );
546 } /* Add_Invite */
547
548
549 LOCAL BOOLEAN
550 Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
551 {
552         CHAR *mask;
553
554         assert( Client != NULL );
555         assert( Channel != NULL );
556         assert( Pattern != NULL );
557
558         mask = Lists_MakeMask( Pattern );
559
560         if( ! Lists_AddBanned( Prefix, mask, Channel )) return CONNECTED;
561         return Send_ListChange( "+b", Prefix, Client, Channel, mask );
562 } /* Add_Ban */
563
564
565 LOCAL BOOLEAN
566 Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
567 {
568         CHAR *mask;
569
570         assert( Client != NULL );
571         assert( Channel != NULL );
572         assert( Pattern != NULL );
573
574         mask = Lists_MakeMask( Pattern );
575         Lists_DelInvited( mask, Channel );
576         return Send_ListChange( "-I", Prefix, Client, Channel, mask );
577 } /* Del_Invite */
578
579
580 LOCAL BOOLEAN
581 Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
582 {
583         CHAR *mask;
584
585         assert( Client != NULL );
586         assert( Channel != NULL );
587         assert( Pattern != NULL );
588
589         mask = Lists_MakeMask( Pattern );
590         Lists_DelBanned( mask, Channel );
591         return Send_ListChange( "-b", Prefix, Client, Channel, mask );
592 } /* Del_Ban */
593
594
595 LOCAL BOOLEAN
596 Send_ListChange( CHAR *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Mask )
597 {
598         /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
599
600         BOOLEAN ok;
601
602         if( Client_Type( Client ) == CLIENT_USER )
603         {
604                 /* Bestaetigung an Client */
605                 ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
606         }
607         else ok = TRUE;
608
609         /* an andere Server */
610         IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
611
612         /* und lokale User im Channel */
613         IRC_WriteStrChannelPrefix( Client, Channel, Prefix, FALSE, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
614         
615         return ok;
616 } /* Send_ListChange */
617
618
619 /* -eof- */