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.8 2002/08/26 23:39:22 alex Exp $
14 * irc-mode.c: IRC-Befehle zur Mode-Aenderung (MODE, AWAY, ...)
28 #include "irc-write.h"
38 LOCAL BOOLEAN Show_InviteList PARAMS(( CLIENT *Client, CHANNEL *Channel ));
39 LOCAL BOOLEAN Show_BanList PARAMS(( CLIENT *Client, CHANNEL *Channel ));
41 LOCAL BOOLEAN Add_Invite PARAMS(( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
42 LOCAL BOOLEAN Add_Ban PARAMS(( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
44 LOCAL BOOLEAN Del_Invite PARAMS(( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
45 LOCAL BOOLEAN Del_Ban PARAMS(( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern ));
49 IRC_MODE( CLIENT *Client, REQUEST *Req )
51 CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
52 CLIENT *cl, *chan_cl, *prefix;
56 assert( Client != NULL );
57 assert( Req != NULL );
59 cl = chan_cl = prefix = NULL;
63 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
65 /* Keine Parameter? */
66 if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
68 /* Ziel suchen: Client bzw. Channel */
69 if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
70 if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
72 /* Kein Ziel gefunden? */
73 if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
75 assert(( cl && chan ) != TRUE );
77 /* Falsche Anzahl Parameter? */
78 if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
79 if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
81 /* Prefix fuer Antworten etc. ermitteln */
82 if( Client_Type( Client ) == CLIENT_SERVER )
84 prefix = Client_Search( Req->prefix );
85 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
89 if(( chan ) && (( Req->argc == 2 ) || ( Req->argc == 3 )))
91 /* pruefen, ob "Listen-Operation": Invite, Ban */
92 if(( Req->argv[1][0] == '-' ) || ( Req->argv[1][0] == '+' )) mode_ptr = &Req->argv[1][1];
93 else mode_ptr = &Req->argv[1][0];
98 if( *mode_ptr == 'I' ) return Show_InviteList( prefix, chan );
99 if( *mode_ptr == 'b' ) return Show_BanList( prefix, chan );
103 if( Req->argv[1][0] == '+' )
105 /* Listen-Eintrag hinzufuegen */
106 if( *mode_ptr == 'I' ) return Add_Invite( prefix, chan, Req->argv[2] );
107 if( *mode_ptr == 'b' ) return Add_Ban( prefix, chan, Req->argv[2] );
109 else if( Req->argv[1][0] == '-' )
111 /* Listen-Eintrag loeschen */
112 if( *mode_ptr == 'I' ) return Del_Invite( prefix, chan, Req->argv[2] );
113 if( *mode_ptr == 'b' ) return Del_Ban( prefix, chan, Req->argv[2] );
118 /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
119 if(( chan ) && (Req->argc == 3 ))
121 chan_cl = Client_Search( Req->argv[2] );
122 if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
125 /* Wenn Anfragender ein User ist: Zugriff erlaubt? */
126 if( Client_Type( Client ) == CLIENT_USER )
130 /* MODE ist nur fuer sich selber zulaessig! */
131 if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
135 /* Darf der User die Channel-Modes ermitteln? */
139 /* Werden die Modes "nur" erfragt? */
140 if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
141 if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
143 mode_ptr = Req->argv[1];
145 /* Sollen Modes gesetzt oder geloescht werden? */
148 if( *mode_ptr == '+' ) set = TRUE;
149 else if( *mode_ptr == '-' ) set = FALSE;
150 else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
155 if( *mode_ptr == '-' ) set = FALSE;
157 if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
160 /* Reply-String mit Aenderungen vorbereiten */
161 if( set ) strcpy( the_modes, "+" );
162 else strcpy( the_modes, "-" );
169 if( Client_Type( Client ) == CLIENT_SERVER )
171 /* Befehl kommt von einem Server, daher
172 * trauen wir ihm "unbesehen" ... */
177 /* Modes validieren */
188 /* operator (kann nur geloescht werden) */
191 Client_SetOperByMe( Client, FALSE );
194 else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
197 /* restricted (kann nur gesetzt werden) */
198 if( set ) x[0] = 'r';
199 else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
202 /* server messages */
206 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
207 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
213 /* Ist der User ein Channel Operator? */
214 if( ! strchr( Channel_UserModes( chan, Client ), 'o' ))
216 Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan ));
217 ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan ));
221 /* Channel-Modes oder Channel-User-Modes */
224 /* Channel-User-Modes */
228 /* Channel Operator */
236 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 ));
237 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
255 /* kein Schreiben in den Channel von aussen */
267 Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
268 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
277 if( ! x[0] ) continue;
279 /* Okay, gueltigen Mode gefunden */
282 /* Es geht um User-Modes */
285 /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
286 if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
291 /* Modes geloescht. Wenn der Client ihn hatte: merken */
292 if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
295 /* "nachbearbeiten" */
299 if( set ) Client_SetAway( cl, DEFAULT_AWAY_MSG );
300 else Client_SetAway( cl, NULL );
305 /* Es geht um Channel-Modes oder Channel-User-Modes */
308 /* Channel-User-Modes */
311 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
312 if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x );
316 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
317 if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x );
325 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
326 if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x );
330 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
331 if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x );
337 /* Wurden Modes geaendert? */
343 if( Client_Type( Client ) == CLIENT_SERVER )
345 /* Modes an andere Server forwarden */
346 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
350 /* Bestaetigung an Client schicken & andere Server informieren */
351 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes );
352 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
354 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
358 /* Channel-Modes oder Channel-User-Mode */
361 /* Channel-User-Mode */
362 if( Client_Type( Client ) == CLIENT_SERVER )
364 /* Modes an andere Server und Channel-User forwarden */
365 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
366 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
370 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
371 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
372 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
373 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
375 Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl ));
380 if( Client_Type( Client ) == CLIENT_SERVER )
382 /* Modes an andere Server und Channel-User forwarden */
383 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
384 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
388 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
389 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes );
390 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
391 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
393 Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
403 IRC_AWAY( CLIENT *Client, REQUEST *Req )
405 assert( Client != NULL );
406 assert( Req != NULL );
408 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
410 /* Falsche Anzahl Parameter? */
411 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
413 if(( Req->argc == 1 ) && (Req->argv[0][0] ))
416 Client_SetAway( Client, Req->argv[0] );
417 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
418 return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
423 Client_SetAway( Client, NULL );
424 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
425 return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
431 Show_InviteList( CLIENT *Client, CHANNEL *Channel )
433 assert( Client != NULL );
434 assert( Channel != NULL );
436 return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
437 } /* Show_InviteList */
441 Show_BanList( CLIENT *Client, CHANNEL *Channel )
443 assert( Client != NULL );
444 assert( Channel != NULL );
446 return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
451 Add_Invite( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
455 assert( Client != NULL );
456 assert( Channel != NULL );
457 assert( Pattern != NULL );
459 mask = Lists_MakeMask( Pattern );
461 if( ! Lists_AddInvited( mask, Channel, FALSE )) return CONNECTED;
463 IRC_WriteStrChannelPrefix( Client, Channel, Client, TRUE, "MODE %s +I %s", Channel_Name( Channel ), mask );
464 if( Client_Type( Client ) == CLIENT_USER )
466 if( ! IRC_WriteStrClientPrefix( Client, Client, "MODE %s +I %s", Channel_Name( Channel ), mask )) return DISCONNECTED;
473 Add_Ban( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
475 assert( Client != NULL );
476 assert( Channel != NULL );
477 assert( Pattern != NULL );
484 Del_Invite( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
486 assert( Client != NULL );
487 assert( Channel != NULL );
488 assert( Pattern != NULL );
495 Del_Ban( CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )
497 assert( Client != NULL );
498 assert( Channel != NULL );
499 assert( Pattern != NULL );