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.12 2002/08/27 13:57:03 alex Exp $
14 * irc-channel.c: IRC-Channel-Befehle
34 #include "irc-write.h"
37 #include "irc-channel.h"
41 IRC_JOIN( CLIENT *Client, REQUEST *Req )
43 CHAR *channame, *flags, *topic, modes[8];
48 assert( Client != NULL );
49 assert( Req != NULL );
51 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
53 /* Falsche Anzahl Parameter? */
54 if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
56 /* Wer ist der Absender? */
57 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
59 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
61 /* Channel-Namen durchgehen */
63 channame = strtok( Req->argv[0], "," );
68 /* wird der Channel neu angelegt? */
69 if( Channel_Search( channame )) is_new_chan = FALSE;
70 else is_new_chan = TRUE;
72 /* Hat ein Server Channel-User-Modes uebergeben? */
73 if( Client_Type( Client ) == CLIENT_SERVER )
75 /* Channel-Flags extrahieren */
76 flags = strchr( channame, 0x7 );
85 if( Client_Type( Client ) == CLIENT_USER )
87 /* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
90 /* Erster User im Channel: Operator-Flag setzen */
95 /* Existierenden Channel suchen */
96 chan = Channel_Search( channame );
97 assert( chan != NULL );
99 /* Testen, ob Client gebanned ist */
100 if( Lists_CheckBanned( target, chan ))
102 /* Client ist gebanned: */
103 IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
105 /* naechsten Namen ermitteln */
106 channame = strtok( NULL, "," );
110 /* Ist der Channel "invite-only"? */
111 if( strchr( Channel_Modes( chan ), 'i' ))
113 /* Wurde der Client invited? */
114 if( ! Lists_CheckInvited( target, chan ))
116 /* Client wurde nicht invited: */
117 IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
119 /* naechsten Namen ermitteln */
120 channame = strtok( NULL, "," );
127 /* Channel joinen (und ggf. anlegen) */
128 if( ! Channel_Join( target, channame ))
130 /* naechsten Namen ermitteln */
131 channame = strtok( NULL, "," );
134 if( ! chan ) chan = Channel_Search( channame );
135 assert( chan != NULL );
137 /* Modes setzen (wenn vorhanden) */
138 while( flags && *flags )
140 Channel_UserModeAdd( chan, target, *flags );
144 /* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
145 if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
147 /* Muessen Modes an andere Server gemeldet werden? */
148 strcpy( &modes[1], Channel_UserModes( chan, target ));
149 if( modes[1] ) modes[0] = 0x7;
150 else modes[0] = '\0';
152 /* An andere Server weiterleiten */
153 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
155 /* im Channel bekannt machen */
156 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
159 /* Modes im Channel bekannt machen */
160 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s +%s %s", channame, &modes[1], Client_ID( target ));
163 if( Client_Type( Client ) == CLIENT_USER )
165 /* an Client bestaetigen */
166 IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
168 /* Topic an Client schicken */
169 topic = Channel_Topic( chan );
170 if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
172 /* Mitglieder an Client Melden */
173 IRC_Send_NAMES( Client, chan );
174 IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
177 /* naechsten Namen ermitteln */
178 channame = strtok( NULL, "," );
185 IRC_PART( CLIENT *Client, REQUEST *Req )
190 assert( Client != NULL );
191 assert( Req != NULL );
193 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
195 /* Falsche Anzahl Parameter? */
196 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
198 /* Wer ist der Absender? */
199 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
200 else target = Client;
201 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
203 /* Channel-Namen durchgehen */
204 chan = strtok( Req->argv[0], "," );
207 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
209 /* naechsten Namen ermitteln */
210 chan = strtok( NULL, "," );
214 /* naechsten Namen ermitteln */
215 chan = strtok( NULL, "," );
222 IRC_TOPIC( CLIENT *Client, REQUEST *Req )
228 assert( Client != NULL );
229 assert( Req != NULL );
231 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
233 /* Falsche Anzahl Parameter? */
234 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
236 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
238 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
240 /* Welcher Channel? */
241 chan = Channel_Search( Req->argv[0] );
242 if( ! chan ) return IRC_WriteStrClient( from, ERR_NOSUCHCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
244 /* Ist der User Mitglied in dem Channel? */
245 if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
250 topic = Channel_Topic( chan );
251 if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
252 else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
255 if( strchr( Channel_Modes( chan ), 't' ))
257 /* Topic Lock. Ist der User ein Channel Operator? */
258 if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
262 Channel_SetTopic( chan, Req->argv[1] );
263 Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
265 /* im Channel bekannt machen und an Server weiterleiten */
266 IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
267 IRC_WriteStrChannelPrefix( Client, chan, from, FALSE, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
269 if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
270 else return CONNECTED;
275 IRC_LIST( CLIENT *Client, REQUEST *Req )
280 assert( Client != NULL );
281 assert( Req != NULL );
283 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
285 /* Falsche Anzahl Parameter? */
286 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
288 if( Req->argc > 0 ) pattern = strtok( Req->argv[0], "," );
293 /* alle Channel durchgehen */
294 chan = Channel_First( );
297 /* Passt die Suchmaske auf diesen Channel? */
298 if( Match( pattern, Channel_Name( chan )))
301 if( ! IRC_WriteStrClient( Client, RPL_LIST_MSG, Client_ID( Client), Channel_Name( chan ), Channel_MemberCount( chan ), Channel_Topic( chan ))) return DISCONNECTED;
303 chan = Channel_Next( chan );
306 /* naechsten Namen ermitteln */
307 if( Req->argc > 0 ) pattern = strtok( NULL, "," );
311 return IRC_WriteStrClient( Client, RPL_LISTEND_MSG, Client_ID( Client ));