]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-channel.c
- neues #define: REGISTER
[ngircd-alex.git] / src / ngircd / irc-channel.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
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.
11  *
12  * $Id: irc-channel.c,v 1.9 2002/06/10 21:10:25 alex Exp $
13  *
14  * irc-channel.c: IRC-Channel-Befehle
15  */
16
17
18 #include "portab.h"
19
20 #include "imp.h"
21 #include <assert.h>
22 #include <string.h>
23
24 #include "defines.h"
25 #include "conn.h"
26 #include "client.h"
27 #include "channel.h"
28 #include "lists.h"
29 #include "log.h"
30 #include "messages.h"
31 #include "parse.h"
32 #include "irc.h"
33 #include "irc-write.h"
34
35 #include "exp.h"
36 #include "irc-channel.h"
37
38
39 GLOBAL BOOLEAN
40 IRC_JOIN( CLIENT *Client, REQUEST *Req )
41 {
42         CHAR *channame, *flags, *topic, modes[8];
43         BOOLEAN is_new_chan;
44         CLIENT *target;
45         CHANNEL *chan;
46
47         assert( Client != NULL );
48         assert( Req != NULL );
49
50         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
51
52         /* Falsche Anzahl Parameter? */
53         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
54
55         /* Wer ist der Absender? */
56         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
57         else target = Client;
58         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
59
60         /* Channel-Namen durchgehen */
61         chan = NULL;
62         channame = strtok( Req->argv[0], "," );
63         while( channame )
64         {
65                 chan = flags = NULL;
66
67                 /* wird der Channel neu angelegt? */
68                 if( Channel_Search( channame )) is_new_chan = FALSE;
69                 else is_new_chan = TRUE;
70
71                 /* Hat ein Server Channel-User-Modes uebergeben? */
72                 if( Client_Type( Client ) == CLIENT_SERVER )
73                 {
74                         /* Channel-Flags extrahieren */
75                         flags = strchr( channame, 0x7 );
76                         if( flags )
77                         {
78                                 *flags = '\0';
79                                 flags++;
80                         }
81                 }
82
83                 /* Lokaler Client? */
84                 if( Client_Type( Client ) == CLIENT_USER )
85                 {
86                         /* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
87                         if( is_new_chan )
88                         {
89                                 /* Erster User im Channel: Operator-Flag setzen */
90                                 flags = "o";
91                         }
92                         else
93                         {
94                                 /* Existierenden Channel suchen */
95                                 chan = Channel_Search( channame );
96                                 assert( chan != NULL );
97
98                                 /* Testen, ob Client gebanned ist */
99                                 if( Lists_CheckBanned( target, chan ))
100                                 {
101                                         /* Client ist gebanned: */
102                                         IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
103
104                                         /* naechsten Namen ermitteln */
105                                         channame = strtok( NULL, "," );
106                                         continue;
107                                 }
108
109                                 /* Ist der Channel "invite-only"? */
110                                 if( strchr( Channel_Modes( chan ), 'i' ))
111                                 {
112                                         /* Wurde der Client invited? */
113                                         if( ! Lists_CheckInvited( target, chan ))
114                                         {
115                                                 /* Client wurde nicht invited: */
116                                                 IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
117
118                                                 /* naechsten Namen ermitteln */
119                                                 channame = strtok( NULL, "," );
120                                                 continue;
121                                         }
122                                 }
123                         }
124                 }
125
126                 /* Channel joinen (und ggf. anlegen) */
127                 if( ! Channel_Join( target, channame ))
128                 {
129                         /* naechsten Namen ermitteln */
130                         channame = strtok( NULL, "," );
131                         continue;
132                 }
133                 if( ! chan ) chan = Channel_Search( channame );
134                 assert( chan != NULL );
135
136                 /* Modes setzen (wenn vorhanden) */
137                 while( flags && *flags )
138                 {
139                         Channel_UserModeAdd( chan, target, *flags );
140                         flags++;
141                 }
142
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' );
145
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';
150
151                 /* An andere Server weiterleiten */
152                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
153
154                 /* im Channel bekannt machen */
155                 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
156                 if( modes[1] )
157                 {
158                         /* Modes im Channel bekannt machen */
159                         IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
160                 }
161
162                 if( Client_Type( Client ) == CLIENT_USER )
163                 {
164                         /* an Client bestaetigen */
165                         IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
166
167                         /* Topic an Client schicken */
168                         topic = Channel_Topic( chan );
169                         if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
170
171                         /* Mitglieder an Client Melden */
172                         IRC_Send_NAMES( Client, chan );
173                         IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
174                 }
175
176                 /* naechsten Namen ermitteln */
177                 channame = strtok( NULL, "," );
178         }
179         return CONNECTED;
180 } /* IRC_JOIN */
181
182
183 GLOBAL BOOLEAN
184 IRC_PART( CLIENT *Client, REQUEST *Req )
185 {
186         CLIENT *target;
187         CHAR *chan;
188
189         assert( Client != NULL );
190         assert( Req != NULL );
191
192         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
193
194         /* Falsche Anzahl Parameter? */
195         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
196
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 );
201
202         /* Channel-Namen durchgehen */
203         chan = strtok( Req->argv[0], "," );
204         while( chan )
205         {
206                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
207                 {
208                         /* naechsten Namen ermitteln */
209                         chan = strtok( NULL, "," );
210                         continue;
211                 }
212
213                 /* naechsten Namen ermitteln */
214                 chan = strtok( NULL, "," );
215         }
216         return CONNECTED;
217 } /* IRC_PART */
218
219
220 GLOBAL BOOLEAN
221 IRC_TOPIC( CLIENT *Client, REQUEST *Req )
222 {
223         CHANNEL *chan;
224         CLIENT *from;
225         CHAR *topic;
226
227         assert( Client != NULL );
228         assert( Req != NULL );
229
230         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
231
232         /* Falsche Anzahl Parameter? */
233         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
234
235         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
236         else from = Client;
237         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
238
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] );
242
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] );
245
246         if( Req->argc == 1 )
247         {
248                 /* Topic erfragen */
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 ));
252         }
253
254         if( strchr( Channel_Modes( chan ), 't' ))
255         {
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 ));
258         }
259
260         /* Topic setzen */
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>" );
263
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] );
267
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;
270 } /* IRC_TOPIC */
271
272
273 GLOBAL BOOLEAN
274 IRC_LIST( CLIENT *Client, REQUEST *Req )
275 {
276         CHAR *pattern;
277         CHANNEL *chan;
278
279         assert( Client != NULL );
280         assert( Req != NULL );
281
282         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
283
284         /* Falsche Anzahl Parameter? */
285         if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
286
287         if( Req->argc > 0 ) pattern = strtok( Req->argv[0], "," );
288         else pattern = "*";
289         
290         while( pattern )
291         {
292                 /* alle Channel durchgehen */
293                 chan = Channel_First( );
294                 while( chan )
295                 {
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 ))
299                         {
300                                 /* Treffer! */
301                                 if( ! IRC_WriteStrClient( Client, RPL_LIST_MSG, Client_ID( Client), Channel_Name( chan ), Channel_MemberCount( chan ), Channel_Topic( chan ))) return DISCONNECTED;
302                         }
303                         chan = Channel_Next( chan );
304                 }
305                 
306                 /* naechsten Namen ermitteln */
307                 if( Req->argc > 0 ) pattern = strtok( NULL, "," );
308                 else pattern = NULL;
309         }
310         
311         return IRC_WriteStrClient( Client, RPL_LISTEND_MSG, Client_ID( Client ));
312 } /* IRC_LIST */
313
314
315 /* -eof- */