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.9 2002/06/10 21:10:25 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 );
84 if( Client_Type( Client ) == CLIENT_USER )
86 /* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
89 /* Erster User im Channel: Operator-Flag setzen */
94 /* Existierenden Channel suchen */
95 chan = Channel_Search( channame );
96 assert( chan != NULL );
98 /* Testen, ob Client gebanned ist */
99 if( Lists_CheckBanned( target, chan ))
101 /* Client ist gebanned: */
102 IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
104 /* naechsten Namen ermitteln */
105 channame = strtok( NULL, "," );
109 /* Ist der Channel "invite-only"? */
110 if( strchr( Channel_Modes( chan ), 'i' ))
112 /* Wurde der Client invited? */
113 if( ! Lists_CheckInvited( target, chan ))
115 /* Client wurde nicht invited: */
116 IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
118 /* naechsten Namen ermitteln */
119 channame = strtok( NULL, "," );
126 /* Channel joinen (und ggf. anlegen) */
127 if( ! Channel_Join( target, channame ))
129 /* naechsten Namen ermitteln */
130 channame = strtok( NULL, "," );
133 if( ! chan ) chan = Channel_Search( channame );
134 assert( chan != NULL );
136 /* Modes setzen (wenn vorhanden) */
137 while( flags && *flags )
139 Channel_UserModeAdd( chan, target, *flags );
143 /* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
144 if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
146 /* Muessen Modes an andere Server gemeldet werden? */
147 strcpy( &modes[1], Channel_UserModes( chan, target ));
148 if( modes[1] ) modes[0] = 0x7;
149 else modes[0] = '\0';
151 /* An andere Server weiterleiten */
152 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
154 /* im Channel bekannt machen */
155 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
158 /* Modes im Channel bekannt machen */
159 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
162 if( Client_Type( Client ) == CLIENT_USER )
164 /* an Client bestaetigen */
165 IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
167 /* Topic an Client schicken */
168 topic = Channel_Topic( chan );
169 if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
171 /* Mitglieder an Client Melden */
172 IRC_Send_NAMES( Client, chan );
173 IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
176 /* naechsten Namen ermitteln */
177 channame = strtok( NULL, "," );
184 IRC_PART( CLIENT *Client, REQUEST *Req )
189 assert( Client != NULL );
190 assert( Req != NULL );
192 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
194 /* Falsche Anzahl Parameter? */
195 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
197 /* Wer ist der Absender? */
198 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
199 else target = Client;
200 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
202 /* Channel-Namen durchgehen */
203 chan = strtok( Req->argv[0], "," );
206 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
208 /* naechsten Namen ermitteln */
209 chan = strtok( NULL, "," );
213 /* naechsten Namen ermitteln */
214 chan = strtok( NULL, "," );
221 IRC_TOPIC( CLIENT *Client, REQUEST *Req )
227 assert( Client != NULL );
228 assert( Req != NULL );
230 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
232 /* Falsche Anzahl Parameter? */
233 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
235 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
237 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
239 /* Welcher Channel? */
240 chan = Channel_Search( Req->argv[0] );
241 if( ! chan ) return IRC_WriteStrClient( from, ERR_NOSUCHCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
243 /* Ist der User Mitglied in dem Channel? */
244 if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
249 topic = Channel_Topic( chan );
250 if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
251 else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
254 if( strchr( Channel_Modes( chan ), 't' ))
256 /* Topic Lock. Ist der User ein Channel Operator? */
257 if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
261 Channel_SetTopic( chan, Req->argv[1] );
262 Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
264 /* im Channel bekannt machen und an Server weiterleiten */
265 IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
266 IRC_WriteStrChannelPrefix( Client, chan, from, FALSE, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
268 if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
269 else return CONNECTED;
274 IRC_LIST( CLIENT *Client, REQUEST *Req )
279 assert( Client != NULL );
280 assert( Req != NULL );
282 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
284 /* Falsche Anzahl Parameter? */
285 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
287 if( Req->argc > 0 ) pattern = strtok( Req->argv[0], "," );
292 /* alle Channel durchgehen */
293 chan = Channel_First( );
296 /* Passt die Suchmaske auf diesen Channel? Bisher werden hier
297 * "regular expressions" aber noch nicht unterstuetzt ... */
298 if(( strcasecmp( pattern, Channel_Name( chan )) == 0 ) || ( strcmp( pattern, "*" ) == 0 ))
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 ));