2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
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.
12 * $Id: irc-mode.c,v 1.12 2002/09/08 01:16:58 alex Exp $
14 * irc-mode.c: IRC-Befehle zur Mode-Aenderung (MODE, AWAY, ...)
28 #include "irc-write.h"
40 LOCAL BOOLEAN Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
41 LOCAL BOOLEAN Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
43 LOCAL BOOLEAN Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
44 LOCAL BOOLEAN Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
46 LOCAL BOOLEAN Send_ListChange PARAMS(( CHAR *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Mask ));
50 IRC_MODE( CLIENT *Client, REQUEST *Req )
52 CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
53 CLIENT *cl, *chan_cl, *prefix;
54 BOOLEAN set, ok, modeok;
57 assert( Client != NULL );
58 assert( Req != NULL );
60 cl = chan_cl = prefix = NULL;
64 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
66 /* Keine Parameter? */
67 if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
69 /* Ziel suchen: Client bzw. Channel */
70 if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
71 if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
73 /* Kein Ziel gefunden? */
74 if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
76 assert(( cl && chan ) != TRUE );
78 /* Falsche Anzahl Parameter? */
79 if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
80 if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
82 /* Prefix fuer Antworten etc. ermitteln */
83 if( Client_Type( Client ) == CLIENT_SERVER )
85 prefix = Client_Search( Req->prefix );
86 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
90 if(( chan ) && (( Req->argc == 2 ) || ( Req->argc == 3 )))
92 /* pruefen, ob "Listen-Operation": Invite, Ban */
93 if(( Req->argv[1][0] == '-' ) || ( Req->argv[1][0] == '+' )) mode_ptr = &Req->argv[1][1];
94 else mode_ptr = &Req->argv[1][0];
99 if( *mode_ptr == 'I' ) return Lists_ShowInvites( prefix, chan );
100 if( *mode_ptr == 'b' ) return Lists_ShowBans( prefix, chan );
104 if( Req->argv[1][0] == '+' )
106 /* Listen-Eintrag hinzufuegen */
107 if( *mode_ptr == 'I' ) return Add_Invite( prefix, Client, chan, Req->argv[2] );
108 if( *mode_ptr == 'b' ) return Add_Ban( prefix, Client, chan, Req->argv[2] );
110 else if( Req->argv[1][0] == '-' )
112 /* Listen-Eintrag loeschen */
113 if( *mode_ptr == 'I' ) return Del_Invite( prefix, Client, chan, Req->argv[2] );
114 if( *mode_ptr == 'b' ) return Del_Ban( prefix, Client, chan, Req->argv[2] );
119 /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
120 if(( chan ) && (Req->argc == 3 ))
122 chan_cl = Client_Search( Req->argv[2] );
123 if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
126 /* Wenn Anfragender ein User ist: Zugriff erlaubt? */
127 if( Client_Type( Client ) == CLIENT_USER )
131 /* MODE ist nur fuer sich selber zulaessig! */
132 if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
136 /* Darf der User die Channel-Modes ermitteln? */
140 /* Werden die Modes "nur" erfragt? */
141 if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
142 if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
144 mode_ptr = Req->argv[1];
146 /* Sollen Modes gesetzt oder geloescht werden? */
149 if( *mode_ptr == '+' ) set = TRUE;
150 else if( *mode_ptr == '-' ) set = FALSE;
151 else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
156 if( *mode_ptr == '-' ) set = FALSE;
158 if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
161 /* Reply-String mit Aenderungen vorbereiten */
162 if( set ) strcpy( the_modes, "+" );
163 else strcpy( the_modes, "-" );
170 if( Client_Type( Client ) == CLIENT_SERVER )
172 /* Befehl kommt von einem Server, daher
173 * trauen wir ihm "unbesehen" ... */
178 /* Modes validieren */
189 /* operator (kann nur geloescht werden) */
192 Client_SetOperByMe( Client, FALSE );
195 else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
198 /* restricted (kann nur gesetzt werden) */
199 if( set ) x[0] = 'r';
200 else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
203 /* server messages */
207 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
208 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
214 /* Ist der User ein Channel Operator? */
216 if( strchr( Channel_UserModes( chan, Client ), 'o' )) modeok = TRUE;
217 if( Conf_OperCanMode )
219 /* auch IRC-Operatoren duerfen MODE verwenden */
220 if( Client_OperByMe( Client )) modeok = TRUE;
225 Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan ));
226 ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan ));
230 /* Channel-Modes oder Channel-User-Modes */
233 /* Channel-User-Modes */
237 /* Channel Operator */
245 Log( LOG_DEBUG, "Unknown channel-user-mode \"%c%c\" from \"%s\" on \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Client_ID( chan_cl ), Channel_Name( chan ));
246 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
264 /* kein Schreiben in den Channel von aussen */
276 Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
277 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
286 if( ! x[0] ) continue;
288 /* Okay, gueltigen Mode gefunden */
291 /* Es geht um User-Modes */
294 /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
295 if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
300 /* Modes geloescht. Wenn der Client ihn hatte: merken */
301 if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
304 /* "nachbearbeiten" */
308 if( set ) Client_SetAway( cl, DEFAULT_AWAY_MSG );
309 else Client_SetAway( cl, NULL );
314 /* Es geht um Channel-Modes oder Channel-User-Modes */
317 /* Channel-User-Modes */
320 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
321 if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x );
325 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
326 if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x );
334 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
335 if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x );
339 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
340 if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x );
346 /* Wurden Modes geaendert? */
352 if( Client_Type( Client ) == CLIENT_SERVER )
354 /* Modes an andere Server forwarden */
355 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
359 /* Bestaetigung an Client schicken & andere Server informieren */
360 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes );
361 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
363 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
367 /* Channel-Modes oder Channel-User-Mode */
370 /* Channel-User-Mode */
371 if( Client_Type( Client ) == CLIENT_SERVER )
373 /* Modes an andere Server und Channel-User forwarden */
374 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
375 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
379 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
380 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
381 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
382 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
384 Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl ));
389 if( Client_Type( Client ) == CLIENT_SERVER )
391 /* Modes an andere Server und Channel-User forwarden */
392 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
393 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
397 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
398 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes );
399 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
400 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
402 Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
412 IRC_AWAY( CLIENT *Client, REQUEST *Req )
414 assert( Client != NULL );
415 assert( Req != NULL );
417 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
419 /* Falsche Anzahl Parameter? */
420 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
422 if(( Req->argc == 1 ) && (Req->argv[0][0] ))
425 Client_SetAway( Client, Req->argv[0] );
426 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
427 return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
432 Client_SetAway( Client, NULL );
433 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
434 return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
440 Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
444 assert( Client != NULL );
445 assert( Channel != NULL );
446 assert( Pattern != NULL );
448 mask = Lists_MakeMask( Pattern );
450 if( ! Lists_AddInvited( mask, Channel, FALSE )) return CONNECTED;
451 return Send_ListChange( "+I", Prefix, Client, Channel, mask );
456 Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
460 assert( Client != NULL );
461 assert( Channel != NULL );
462 assert( Pattern != NULL );
464 mask = Lists_MakeMask( Pattern );
466 if( ! Lists_AddBanned( mask, Channel )) return CONNECTED;
467 return Send_ListChange( "+b", Prefix, Client, Channel, mask );
472 Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
476 assert( Client != NULL );
477 assert( Channel != NULL );
478 assert( Pattern != NULL );
480 mask = Lists_MakeMask( Pattern );
481 Lists_DelInvited( mask, Channel );
482 return Send_ListChange( "-I", Prefix, Client, Channel, mask );
487 Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
491 assert( Client != NULL );
492 assert( Channel != NULL );
493 assert( Pattern != NULL );
495 mask = Lists_MakeMask( Pattern );
496 Lists_DelBanned( mask, Channel );
497 return Send_ListChange( "-b", Prefix, Client, Channel, mask );
502 Send_ListChange( CHAR *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Mask )
504 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
508 if( Client_Type( Client ) == CLIENT_USER )
510 /* Bestaetigung an Client */
511 ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
515 /* an andere Server */
516 IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
518 /* und lokale User im Channel */
519 IRC_WriteStrChannelPrefix( Client, Channel, Prefix, FALSE, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
522 } /* Send_ListChange */