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-channel.c,v 1.8 2002/06/02 14:51:14 alex Exp $
14 * irc-channel.c: IRC-Channel-Befehle
33 #include "irc-write.h"
36 #include "irc-channel.h"
40 IRC_JOIN( CLIENT *Client, REQUEST *Req )
42 CHAR *channame, *flags, *topic, modes[8];
47 assert( Client != NULL );
48 assert( Req != NULL );
50 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
52 /* Falsche Anzahl Parameter? */
53 if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
55 /* Wer ist der Absender? */
56 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
58 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
60 /* Channel-Namen durchgehen */
62 channame = strtok( Req->argv[0], "," );
67 /* wird der Channel neu angelegt? */
68 if( Channel_Search( channame )) is_new_chan = FALSE;
69 else is_new_chan = TRUE;
71 /* Hat ein Server Channel-User-Modes uebergeben? */
72 if( Client_Type( Client ) == CLIENT_SERVER )
74 /* Channel-Flags extrahieren */
75 flags = strchr( channame, 0x7 );
76 if( flags ) *flags++ = '\0';
80 if( Client_Type( Client ) == CLIENT_USER )
82 /* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
85 /* Erster User im Channel: Operator-Flag setzen */
90 /* Existierenden Channel suchen */
91 chan = Channel_Search( channame );
92 assert( chan != NULL );
94 /* Testen, ob Client gebanned ist */
95 if( Lists_CheckBanned( target, chan ))
97 /* Client ist gebanned: */
98 IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
100 /* naechsten Namen ermitteln */
101 channame = strtok( NULL, "," );
105 /* Ist der Channel "invite-only"? */
106 if( strchr( Channel_Modes( chan ), 'i' ))
108 /* Wurde der Client invited? */
109 if( ! Lists_CheckInvited( target, chan ))
111 /* Client wurde nicht invited: */
112 IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
114 /* naechsten Namen ermitteln */
115 channame = strtok( NULL, "," );
122 /* Channel joinen (und ggf. anlegen) */
123 if( ! Channel_Join( target, channame ))
125 /* naechsten Namen ermitteln */
126 channame = strtok( NULL, "," );
129 if( ! chan ) chan = Channel_Search( channame );
130 assert( chan != NULL );
132 /* Modes setzen (wenn vorhanden) */
133 while( flags && *flags )
135 Channel_UserModeAdd( chan, target, *flags );
139 /* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
140 if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
142 /* Muessen Modes an andere Server gemeldet werden? */
143 strcpy( &modes[1], Channel_UserModes( chan, target ));
144 if( modes[1] ) modes[0] = 0x7;
145 else modes[0] = '\0';
147 /* An andere Server weiterleiten */
148 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
150 /* im Channel bekannt machen */
151 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
154 /* Modes im Channel bekannt machen */
155 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
158 if( Client_Type( Client ) == CLIENT_USER )
160 /* an Client bestaetigen */
161 IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
163 /* Topic an Client schicken */
164 topic = Channel_Topic( chan );
165 if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
167 /* Mitglieder an Client Melden */
168 IRC_Send_NAMES( Client, chan );
169 IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
172 /* naechsten Namen ermitteln */
173 channame = strtok( NULL, "," );
180 IRC_PART( CLIENT *Client, REQUEST *Req )
185 assert( Client != NULL );
186 assert( Req != NULL );
188 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
190 /* Falsche Anzahl Parameter? */
191 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
193 /* Wer ist der Absender? */
194 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
195 else target = Client;
196 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
198 /* Channel-Namen durchgehen */
199 chan = strtok( Req->argv[0], "," );
202 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
204 /* naechsten Namen ermitteln */
205 chan = strtok( NULL, "," );
209 /* naechsten Namen ermitteln */
210 chan = strtok( NULL, "," );
217 IRC_TOPIC( CLIENT *Client, REQUEST *Req )
223 assert( Client != NULL );
224 assert( Req != NULL );
226 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
228 /* Falsche Anzahl Parameter? */
229 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
231 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
233 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
235 /* Welcher Channel? */
236 chan = Channel_Search( Req->argv[0] );
237 if( ! chan ) return IRC_WriteStrClient( from, ERR_NOSUCHCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
239 /* Ist der User Mitglied in dem Channel? */
240 if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
245 topic = Channel_Topic( chan );
246 if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
247 else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
250 if( strchr( Channel_Modes( chan ), 't' ))
252 /* Topic Lock. Ist der User ein Channel Operator? */
253 if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
257 Channel_SetTopic( chan, Req->argv[1] );
258 Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
260 /* im Channel bekannt machen und an Server weiterleiten */
261 IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
262 IRC_WriteStrChannelPrefix( Client, chan, from, FALSE, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
264 if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
265 else return CONNECTED;
270 IRC_LIST( CLIENT *Client, REQUEST *Req )
275 assert( Client != NULL );
276 assert( Req != NULL );
278 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
280 /* Falsche Anzahl Parameter? */
281 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
283 if( Req->argc > 0 ) pattern = strtok( Req->argv[0], "," );
288 /* alle Channel durchgehen */
289 chan = Channel_First( );
292 /* Passt die Suchmaske auf diesen Channel? Bisher werden hier
293 * "regular expressions" aber noch nicht unterstuetzt ... */
294 if(( strcasecmp( pattern, Channel_Name( chan )) == 0 ) || ( strcmp( pattern, "*" ) == 0 ))
297 if( ! IRC_WriteStrClient( Client, RPL_LIST_MSG, Client_ID( Client), Channel_Name( chan ), Channel_MemberCount( chan ), Channel_Topic( chan ))) return DISCONNECTED;
299 chan = Channel_Next( chan );
302 /* naechsten Namen ermitteln */
303 if( Req->argc > 0 ) pattern = strtok( NULL, "," );
307 return IRC_WriteStrClient( Client, RPL_LISTEND_MSG, Client_ID( Client ));