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.2 2002/03/04 01:06:24 alex Exp $
14 * irc-mode.c: IRC-Befehle zur Mode-Aenderung (MODE, AWAY, ...)
16 * $Log: irc-mode.c,v $
17 * Revision 1.2 2002/03/04 01:06:24 alex
18 * - der AWAY-Mode wurde nicht ueber mehrere Server-Links weitergegeben.
20 * Revision 1.1 2002/02/27 23:26:21 alex
21 * - Modul aus irc.c bzw. irc.h ausgegliedert.
33 #include "irc-write.h"
41 GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
43 CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
44 CLIENT *cl, *chan_cl, *prefix;
48 assert( Client != NULL );
49 assert( Req != NULL );
51 cl = chan_cl = prefix = NULL;
55 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
57 /* Keine Parameter? */
58 if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
60 /* Ziel suchen: Client bzw. Channel */
61 if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
62 if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
64 /* Kein Ziel gefunden? */
65 if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
67 assert(( cl && chan ) != TRUE );
69 /* Falsche Anzahl Parameter? */
70 if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
71 if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
73 /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
74 if(( chan ) && (Req->argc == 3 ))
76 chan_cl = Client_Search( Req->argv[2] );
77 if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
80 /* Wenn Anfragender ein User ist: Zugriff erlaubt? */
81 if( Client_Type( Client ) == CLIENT_USER )
85 /* MODE ist nur fuer sich selber zulaessig! */
86 if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
90 /* Darf der User die Channel-Modes ermitteln? */
94 /* Werden die Modes "nur" erfragt? */
95 if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
96 if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
98 mode_ptr = Req->argv[1];
100 /* Sollen Modes gesetzt oder geloescht werden? */
103 if( *mode_ptr == '+' ) set = TRUE;
104 else if( *mode_ptr == '-' ) set = FALSE;
105 else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
110 if( *mode_ptr == '-' ) set = FALSE;
112 if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
115 /* Prefix fuer Antworten etc. ermitteln */
116 if( Client_Type( Client ) == CLIENT_SERVER )
118 prefix = Client_GetFromID( Req->prefix );
119 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
121 else prefix = Client;
123 /* Reply-String mit Aenderungen vorbereiten */
124 if( set ) strcpy( the_modes, "+" );
125 else strcpy( the_modes, "-" );
132 if( Client_Type( Client ) == CLIENT_SERVER )
134 /* Befehl kommt von einem Server, daher
135 * trauen wir ihm "unbesehen" ... */
140 /* Modes validieren */
151 /* restricted (kann nur gesetzt werden) */
152 if( set ) x[0] = 'r';
153 else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
156 /* operator (kann nur geloescht werden) */
159 Client_SetOperByMe( Client, FALSE );
162 else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
165 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
166 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
172 /* Ist der User ein Channel Operator? */
173 if( ! strchr( Channel_UserModes( chan, Client ), 'o' ))
175 Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan ));
176 ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan ));
180 /* Channel-Modes oder Channel-User-Modes */
183 /* Channel-User-Modes */
187 /* Channel Operator */
195 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 ));
196 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
214 /* kein Schreiben in den Channel von aussen */
234 Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
235 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
244 if( ! x[0] ) continue;
246 /* Okay, gueltigen Mode gefunden */
249 /* Es geht um User-Modes */
252 /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
253 if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
258 /* Modes geloescht. Wenn der Client ihn hatte: merken */
259 if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
262 /* "nachbearbeiten" */
266 if( set ) Client_SetAway( cl, DEFAULT_AWAY_MSG );
267 else Client_SetAway( cl, NULL );
272 /* Es geht um Channel-Modes oder Channel-User-Modes */
275 /* Channel-User-Modes */
278 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
279 if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x );
283 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
284 if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x );
292 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
293 if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x );
297 /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
298 if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x );
304 /* Wurden Modes geaendert? */
310 if( Client_Type( Client ) == CLIENT_SERVER )
312 /* Modes an andere Server forwarden */
313 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
317 /* Bestaetigung an Client schicken & andere Server informieren */
318 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes );
319 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
321 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
325 /* Channel-Modes oder Channel-User-Mode */
328 /* Channel-User-Mode */
329 if( Client_Type( Client ) == CLIENT_SERVER )
331 /* Modes an andere Server und Channel-User forwarden */
332 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
333 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
337 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
338 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
339 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
340 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
342 Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl ));
347 if( Client_Type( Client ) == CLIENT_SERVER )
349 /* Modes an andere Server und Channel-User forwarden */
350 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
351 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
355 /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
356 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes );
357 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
358 IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
360 Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
369 GLOBAL BOOLEAN IRC_AWAY( CLIENT *Client, REQUEST *Req )
371 assert( Client != NULL );
372 assert( Req != NULL );
374 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
376 /* Falsche Anzahl Parameter? */
377 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
379 if(( Req->argc == 1 ) && (Req->argv[0][0] ))
382 Client_SetAway( Client, Req->argv[0] );
383 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
384 return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
389 Client_SetAway( Client, NULL );
390 IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
391 return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));