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.7 2002/06/01 14:37:28 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], "," );
65 /* 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: */
100 /* Ist der Channel "invite-only"? */
101 if( strchr( Channel_Modes( chan ), 'i' ))
103 /* Wurde der Client invited? */
104 if( ! Lists_CheckInvited( target, chan ))
106 /* Client wurde nicht invited: */
112 /* Channel joinen (und ggf. anlegen) */
113 if( ! Channel_Join( target, channame ))
115 /* naechsten Namen ermitteln */
116 channame = strtok( NULL, "," );
119 if( ! chan ) chan = Channel_Search( channame );
120 assert( chan != NULL );
122 /* Modes setzen (wenn vorhanden) */
123 while( flags && *flags )
125 Channel_UserModeAdd( chan, target, *flags );
129 /* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
130 if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
132 /* Muessen Modes an andere Server gemeldet werden? */
133 strcpy( &modes[1], Channel_UserModes( chan, target ));
134 if( modes[1] ) modes[0] = 0x7;
135 else modes[0] = '\0';
137 /* An andere Server weiterleiten */
138 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
140 /* im Channel bekannt machen */
141 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
144 /* Modes im Channel bekannt machen */
145 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
148 if( Client_Type( Client ) == CLIENT_USER )
150 /* an Client bestaetigen */
151 IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
153 /* Topic an Client schicken */
154 topic = Channel_Topic( chan );
155 if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
157 /* Mitglieder an Client Melden */
158 IRC_Send_NAMES( Client, chan );
159 IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
162 /* naechsten Namen ermitteln */
163 channame = strtok( NULL, "," );
170 IRC_PART( CLIENT *Client, REQUEST *Req )
175 assert( Client != NULL );
176 assert( Req != NULL );
178 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
180 /* Falsche Anzahl Parameter? */
181 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
183 /* Wer ist der Absender? */
184 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
185 else target = Client;
186 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
188 /* Channel-Namen durchgehen */
189 chan = strtok( Req->argv[0], "," );
192 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
194 /* naechsten Namen ermitteln */
195 chan = strtok( NULL, "," );
199 /* naechsten Namen ermitteln */
200 chan = strtok( NULL, "," );
207 IRC_TOPIC( CLIENT *Client, REQUEST *Req )
213 assert( Client != NULL );
214 assert( Req != NULL );
216 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
218 /* Falsche Anzahl Parameter? */
219 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
221 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
223 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
225 /* Welcher Channel? */
226 chan = Channel_Search( Req->argv[0] );
227 if( ! chan ) return IRC_WriteStrClient( from, ERR_NOSUCHCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
229 /* Ist der User Mitglied in dem Channel? */
230 if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
235 topic = Channel_Topic( chan );
236 if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
237 else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
240 if( strchr( Channel_Modes( chan ), 't' ))
242 /* Topic Lock. Ist der User ein Channel Operator? */
243 if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
247 Channel_SetTopic( chan, Req->argv[1] );
248 Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
250 /* im Channel bekannt machen und an Server weiterleiten */
251 IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
252 IRC_WriteStrChannelPrefix( Client, chan, from, FALSE, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
254 if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
255 else return CONNECTED;
260 IRC_LIST( CLIENT *Client, REQUEST *Req )
265 assert( Client != NULL );
266 assert( Req != NULL );
268 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
270 /* Falsche Anzahl Parameter? */
271 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
273 if( Req->argc > 0 ) pattern = strtok( Req->argv[0], "," );
278 /* alle Channel durchgehen */
279 chan = Channel_First( );
282 /* Passt die Suchmaske auf diesen Channel? Bisher werden hier
283 * "regular expressions" aber noch nicht unterstuetzt ... */
284 if(( strcasecmp( pattern, Channel_Name( chan )) == 0 ) || ( strcmp( pattern, "*" ) == 0 ))
287 if( ! IRC_WriteStrClient( Client, RPL_LIST_MSG, Client_ID( Client), Channel_Name( chan ), Channel_MemberCount( chan ), Channel_Topic( chan ))) return DISCONNECTED;
289 chan = Channel_Next( chan );
292 /* naechsten Namen ermitteln */
293 if( Req->argc > 0 ) pattern = strtok( NULL, "," );
297 return IRC_WriteStrClient( Client, RPL_LISTEND_MSG, Client_ID( Client ));