Blob


1 /*
2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2005 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 */
15 #include "portab.h"
17 static char UNUSED id[] = "$Id: irc-mode.c,v 1.42 2005/05/14 20:29:34 alex Exp $";
19 #include "imp.h"
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "defines.h"
26 #include "conn.h"
27 #include "client.h"
28 #include "channel.h"
29 #include "irc-write.h"
30 #include "lists.h"
31 #include "log.h"
32 #include "parse.h"
33 #include "messages.h"
34 #include "resolve.h"
35 #include "conf.h"
37 #include "exp.h"
38 #include "irc-mode.h"
41 LOCAL bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ));
42 LOCAL bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ));
44 LOCAL bool Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
45 LOCAL bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
47 LOCAL bool Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
48 LOCAL bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
50 LOCAL bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ));
53 GLOBAL bool
54 IRC_MODE( CLIENT *Client, REQUEST *Req )
55 {
56 CLIENT *cl, *origin;
57 CHANNEL *chan;
59 assert( Client != NULL );
60 assert( Req != NULL );
62 /* No parameters? */
63 if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
65 /* Origin for answers */
66 if( Client_Type( Client ) == CLIENT_SERVER )
67 {
68 origin = Client_Search( Req->prefix );
69 if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
70 }
71 else origin = Client;
73 /* Channel or user mode? */
74 cl = chan = NULL;
75 if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
76 if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
78 if( cl ) return Client_Mode( Client, Req, origin, cl );
79 if( chan ) return Channel_Mode( Client, Req, origin, chan );
81 /* No target found! */
82 return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
83 } /* IRC_MODE */
86 LOCAL bool
87 Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
88 {
89 /* Handle client mode requests */
91 char the_modes[COMMAND_LEN], x[2], *mode_ptr;
92 bool ok, set;
93 int mode_arg;
94 size_t len;
96 /* Is the client allowed to request or change the modes? */
97 if( Client_Type( Client ) == CLIENT_USER )
98 {
99 /* Users are only allowed to manipulate their own modes! */
100 if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
103 /* Mode request: let's answer it :-) */
104 if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
106 mode_arg = 1;
107 mode_ptr = Req->argv[mode_arg];
109 /* Initial state: set or unset modes? */
110 if( *mode_ptr == '+' ) set = true;
111 else if( *mode_ptr == '-' ) set = false;
112 else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
114 /* Prepare reply string */
115 if( set ) strcpy( the_modes, "+" );
116 else strcpy( the_modes, "-" );
118 x[1] = '\0';
119 ok = CONNECTED;
120 while( mode_ptr )
122 mode_ptr++;
123 if( ! *mode_ptr )
125 /* Try next argument if there's any */
126 mode_arg++;
127 if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
128 else break;
131 switch( *mode_ptr )
133 case '+':
134 case '-':
135 if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
137 /* Action modifier ("+"/"-") must be changed ... */
138 len = strlen( the_modes ) - 1;
139 if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
141 /* Adjust last action modifier in result */
142 the_modes[len] = *mode_ptr;
144 else
146 /* Append modifier character to result string */
147 x[0] = *mode_ptr;
148 strlcat( the_modes, x, sizeof( the_modes ));
150 if( *mode_ptr == '+' ) set = true;
151 else set = false;
153 continue;
156 /* Validate modes */
157 x[0] = '\0';
158 switch( *mode_ptr )
160 case 'i': /* Invisible */
161 case 's': /* Server messages */
162 x[0] = *mode_ptr;
163 break;
165 case 'a': /* Away */
166 if( Client_Type( Client ) == CLIENT_SERVER )
168 x[0] = 'a';
169 Client_SetAway( Origin, DEFAULT_AWAY_MSG );
171 else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
172 break;
174 case 'o': /* IRC operator (only unsettable!) */
175 if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
177 Client_SetOperByMe( Target, false );
178 x[0] = 'o';
180 else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
181 break;
183 case 'r': /* Restricted (only settable) */
184 if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r';
185 else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
186 break;
188 default:
189 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
190 if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
191 x[0] = '\0';
192 goto client_exit;
194 if( ! ok ) break;
196 /* Is there a valid mode change? */
197 if( ! x[0] ) continue;
199 if( set )
201 /* Set mode */
202 if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
205 else
207 /* Unset mode */
208 if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
211 client_exit:
213 /* Are there changed modes? */
214 if( the_modes[1] )
216 /* Remoce needless action modifier characters */
217 len = strlen( the_modes ) - 1;
218 if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
220 if( Client_Type( Client ) == CLIENT_SERVER )
222 /* Forward modes to other servers */
223 IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
225 else
227 /* Send reply to client and inform other servers */
228 ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
229 IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
231 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target ));
234 IRC_SetPenalty( Client, 1 );
235 return ok;
236 } /* Client_Mode */
239 LOCAL bool
240 Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
242 /* Handle channel and channel-user modes */
244 char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr;
245 bool ok, set, modeok = false, skiponce, use_servermode = false;
246 int mode_arg, arg_arg;
247 CLIENT *client;
248 long l;
249 size_t len;
251 /* Mode request: let's answer it :-) */
252 if( Req->argc == 1 )
254 /* Member or not? -- That's the question! */
255 if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel ));
257 /* The sender is a member: generate extended reply */
258 strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes ));
259 mode_ptr = the_modes;
260 strcpy( the_args, "" );
261 while( *mode_ptr )
263 switch( *mode_ptr )
265 case 'l':
266 snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel ));
267 strlcat( the_args, argadd, sizeof( the_args ));
268 break;
269 case 'k':
270 strlcat( the_args, " ", sizeof( the_args ));
271 strlcat( the_args, Channel_Key( Channel ), sizeof( the_args ));
272 break;
274 mode_ptr++;
276 if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes ));
278 return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes );
281 /* Is the user allowed to change modes? */
282 if( Client_Type( Client ) == CLIENT_USER )
284 /* Is the originating user on that channel? */
285 if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel ));
287 /* Is he channel operator? */
288 if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = true;
289 else if( Conf_OperCanMode )
291 /* IRC-Operators can use MODE as well */
292 if( Client_OperByMe( Origin )) {
293 modeok = true;
294 if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */
298 else modeok = true;
300 mode_arg = 1;
301 mode_ptr = Req->argv[mode_arg];
302 if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
303 else arg_arg = -1;
305 /* Initial state: set or unset modes? */
306 skiponce = false;
307 if( *mode_ptr == '-' ) set = false;
308 else if( *mode_ptr == '+' ) set = true;
309 else set = skiponce = true;
311 /* Prepare reply string */
312 if( set ) strcpy( the_modes, "+" );
313 else strcpy( the_modes, "-" );
314 strcpy( the_args, " " );
316 x[1] = '\0';
317 ok = CONNECTED;
318 while( mode_ptr )
320 if( ! skiponce ) mode_ptr++;
321 if( ! *mode_ptr )
323 /* Try next argument if there's any */
324 if( arg_arg > mode_arg ) mode_arg = arg_arg;
325 else mode_arg++;
326 if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
327 else break;
328 if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
329 else arg_arg = -1;
331 skiponce = false;
333 switch( *mode_ptr )
335 case '+':
336 case '-':
337 if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
339 /* Action modifier ("+"/"-") must be changed ... */
340 len = strlen( the_modes ) - 1;
341 if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
343 /* Adjust last action modifier in result */
344 the_modes[len] = *mode_ptr;
346 else
348 /* Append modifier character to result string */
349 x[0] = *mode_ptr;
350 strlcat( the_modes, x, sizeof( the_modes ));
352 if( *mode_ptr == '+' ) set = true;
353 else set = false;
355 continue;
358 /* Are there arguments left? */
359 if( arg_arg >= Req->argc ) arg_arg = -1;
361 /* Validate modes */
362 x[0] = '\0';
363 argadd[0] = '\0';
364 client = NULL;
365 switch( *mode_ptr )
367 /* --- Channel modes --- */
369 case 'i': /* Invite only */
370 case 'm': /* Moderated */
371 case 'n': /* Only members can write */
372 case 's': /* Secret channel */
373 case 't': /* Topic locked */
374 if( modeok ) x[0] = *mode_ptr;
375 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
376 break;
378 case 'k': /* Channel key */
379 if( ! set )
381 if( modeok ) x[0] = *mode_ptr;
382 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
383 break;
385 if( arg_arg > mode_arg )
387 if( modeok )
389 Channel_ModeDel( Channel, 'k' );
390 Channel_SetKey( Channel, Req->argv[arg_arg] );
391 strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd ));
392 x[0] = *mode_ptr;
394 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
395 Req->argv[arg_arg][0] = '\0';
396 arg_arg++;
398 else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
399 break;
401 case 'l': /* Member limit */
402 if( ! set )
404 if( modeok ) x[0] = *mode_ptr;
405 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
406 break;
408 if( arg_arg > mode_arg )
410 if( modeok )
412 l = atol( Req->argv[arg_arg] );
413 if( l > 0 && l < 0xFFFF )
415 Channel_ModeDel( Channel, 'l' );
416 Channel_SetMaxUsers( Channel, l );
417 snprintf( argadd, sizeof( argadd ), "%ld", l );
418 x[0] = *mode_ptr;
421 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
422 Req->argv[arg_arg][0] = '\0';
423 arg_arg++;
425 else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
426 break;
428 case 'P': /* Persistent channel */
429 if( modeok )
431 if( set && ( ! Client_OperByMe( Client )))
433 /* Only IRC operators are allowed to set P mode */
434 ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
436 else x[0] = 'P';
438 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
439 break;
441 /* --- Channel user modes --- */
443 case 'o': /* Channel operator */
444 case 'v': /* Voice */
445 if( arg_arg > mode_arg )
447 if( modeok )
449 client = Client_Search( Req->argv[arg_arg] );
450 if( client ) x[0] = *mode_ptr;
451 else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] );
453 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
454 Req->argv[arg_arg][0] = '\0';
455 arg_arg++;
457 else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
458 break;
460 /* --- Channel lists --- */
462 case 'I': /* Invite lists */
463 if( arg_arg > mode_arg )
465 /* modify list */
466 if( modeok )
468 if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
469 else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
471 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
472 Req->argv[arg_arg][0] = '\0';
473 arg_arg++;
475 else Lists_ShowInvites( Origin, Channel );
476 break;
478 case 'b': /* Ban lists */
479 if( arg_arg > mode_arg )
481 /* modify list */
482 if( modeok )
484 if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
485 else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
487 else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
488 Req->argv[arg_arg][0] = '\0';
489 arg_arg++;
491 else Lists_ShowBans( Origin, Channel );
492 break;
494 default:
495 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel ));
496 if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
497 x[0] = '\0';
498 goto chan_exit;
500 if( ! ok ) break;
502 /* Is there a valid mode change? */
503 if( ! x[0] ) continue;
505 /* Validate target client */
506 if( client && ( ! Channel_IsMemberOf( Channel, client )))
508 if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break;
509 continue;
512 if( set )
514 /* Set mode */
515 if( client )
517 /* Channel-User-Mode */
518 if( Channel_UserModeAdd( Channel, client, x[0] ))
520 strlcat( the_args, Client_ID( client ), sizeof( the_args ));
521 strlcat( the_args, " ", sizeof( the_args ));
522 strlcat( the_modes, x, sizeof( the_modes ));
523 Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
526 else
528 /* Channel-Mode */
529 if( Channel_ModeAdd( Channel, x[0] ))
531 strlcat( the_modes, x, sizeof( the_modes ));
532 Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
536 else
538 /* Unset mode */
539 if( client )
541 /* Channel-User-Mode */
542 if( Channel_UserModeDel( Channel, client, x[0] ))
544 strlcat( the_args, Client_ID( client ), sizeof( the_args ));
545 strlcat( the_args, " ", sizeof( the_args ));
546 strlcat( the_modes, x, sizeof( the_modes ));
547 Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
550 else
552 /* Channel-Mode */
553 if( Channel_ModeDel( Channel, x[0] ))
555 strlcat( the_modes, x, sizeof( the_modes ));
556 Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
561 /* Are there additional arguments to add? */
562 if( argadd[0] )
564 len = strlen( the_args ) - 1;
565 if( the_args[len] != ' ' ) strlcat( the_args, " ", sizeof( the_args ));
566 strlcat( the_args, argadd, sizeof( the_args ));
569 chan_exit:
571 /* Are there changed modes? */
572 if( the_modes[1] )
574 /* Clean up mode string */
575 len = strlen( the_modes ) - 1;
576 if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
578 /* Clean up argument string if there are none */
579 if( ! the_args[1] ) the_args[0] = '\0';
581 if( Client_Type( Client ) == CLIENT_SERVER )
583 /* Forward mode changes to channel users and other servers */
584 IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
585 IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
587 else
589 if ( use_servermode ) Origin = Client_ThisServer();
591 /* Send reply to client and inform other servers and channel users */
592 ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
593 IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
594 IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
598 IRC_SetPenalty( Client, 1 );
599 return CONNECTED;
600 } /* Channel_Mode */
603 GLOBAL bool
604 IRC_AWAY( CLIENT *Client, REQUEST *Req )
606 assert( Client != NULL );
607 assert( Req != NULL );
609 /* Falsche Anzahl Parameter? */
610 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
612 if(( Req->argc == 1 ) && (Req->argv[0][0] ))
614 /* AWAY setzen */
615 Client_SetAway( Client, Req->argv[0] );
616 Client_ModeAdd( Client, 'a' );
617 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
618 return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
620 else
622 /* AWAY loeschen */
623 Client_ModeDel( Client, 'a' );
624 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
625 return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
627 } /* IRC_AWAY */
630 LOCAL bool
631 Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
633 char *mask;
634 bool already;
636 assert( Client != NULL );
637 assert( Channel != NULL );
638 assert( Pattern != NULL );
640 mask = Lists_MakeMask( Pattern );
642 already = Lists_IsInviteEntry( mask, Channel );
644 if( ! Lists_AddInvited( mask, Channel, false )) return CONNECTED;
646 if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
648 return Send_ListChange( "+I", Prefix, Client, Channel, mask );
649 } /* Add_Invite */
652 LOCAL bool
653 Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
655 char *mask;
656 bool already;
658 assert( Client != NULL );
659 assert( Channel != NULL );
660 assert( Pattern != NULL );
662 mask = Lists_MakeMask( Pattern );
664 already = Lists_IsBanEntry( mask, Channel );
666 if( ! Lists_AddBanned( mask, Channel )) return CONNECTED;
668 if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
670 return Send_ListChange( "+b", Prefix, Client, Channel, mask );
671 } /* Add_Ban */
674 LOCAL bool
675 Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
677 char *mask;
679 assert( Client != NULL );
680 assert( Channel != NULL );
681 assert( Pattern != NULL );
683 mask = Lists_MakeMask( Pattern );
684 Lists_DelInvited( mask, Channel );
685 return Send_ListChange( "-I", Prefix, Client, Channel, mask );
686 } /* Del_Invite */
689 LOCAL bool
690 Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
692 char *mask;
694 assert( Client != NULL );
695 assert( Channel != NULL );
696 assert( Pattern != NULL );
698 mask = Lists_MakeMask( Pattern );
699 Lists_DelBanned( mask, Channel );
700 return Send_ListChange( "-b", Prefix, Client, Channel, mask );
701 } /* Del_Ban */
704 LOCAL bool
705 Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )
707 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
709 bool ok;
711 if( Client_Type( Client ) == CLIENT_USER )
713 /* Bestaetigung an Client */
714 ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
716 else ok = true;
718 /* an andere Server */
719 IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
721 /* und lokale User im Channel */
722 IRC_WriteStrChannelPrefix( Client, Channel, Prefix, false, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
724 return ok;
725 } /* Send_ListChange */
728 /* -eof- */