]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- NICK-Aenderungen werden an alle Server und betroffene Clients gemeldet.
[ngircd-alex.git] / src / ngircd / irc.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.c,v 1.59 2002/02/17 17:30:21 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  *
16  * $Log: irc.c,v $
17  * Revision 1.59  2002/02/17 17:30:21  alex
18  * - NICK-Aenderungen werden an alle Server und betroffene Clients gemeldet.
19  * - Neue Funktion IRC_WriteStrRelatedPrefix().
20  *
21  * Revision 1.58  2002/02/17 17:18:59  alex
22  * - NICK korrigiert.
23  *
24  * Revision 1.57  2002/02/13 23:05:29  alex
25  * - Nach Connect eines Users werden LUSERS-Informationen angezeigt.
26  *
27  * Revision 1.56  2002/02/13 17:52:27  alex
28  * - es werden nun Channel- und User-Modes von Usern angenommen.
29  *
30  * Revision 1.55  2002/02/12 14:40:37  alex
31  * - via NJOIN gemeldete Benutzer wurden nicht in Channels bekannt gemacht.
32  *
33  * Revision 1.54  2002/02/11 23:33:35  alex
34  * - weitere Anpassungen an Channel-Modes und Channel-User-Modes.
35  *
36  * Revision 1.53  2002/02/11 16:06:21  alex
37  * - Die Quelle von MODE-Aenderungen wird nun korrekt weitergegeben.
38  *
39  * Revision 1.52  2002/02/11 15:52:21  alex
40  * - PONG an den Server selber wurde faelschlicherweise versucht zu forwarden.
41  * - Channel-Modes wurden falsch geliefert (als User-Modes).
42  *
43  * Revision 1.51  2002/02/11 15:15:53  alex
44  * - PING und PONG werden nun auch korrekt an andere Server geforwarded.
45  * - bei MODE-Meldungen wird der letzte Parameter nicht mehr mit ":" getrennt.
46  *
47  * Revision 1.50  2002/02/11 01:03:20  alex
48  * - Aenderungen und Anpassungen an Channel-Modes und Channel-User-Modes:
49  *   Modes werden besser geforwarded, lokale User, fuer die ein Channel
50  *   angelegt wird, werden Channel-Operator, etc. pp. ...
51  * - NJOIN's von Servern werden nun korrekt an andere Server weitergeleitet.
52  *
53  * Revision 1.49  2002/02/06 16:51:22  alex
54  * - neue Funktion zur MODE-Behandlung, fuer Channel-Modes vorbereitet.
55  *
56  * Revision 1.48  2002/01/29 00:13:45  alex
57  * - WHOIS zeigt nun auch die Channels an, in denen der jeweilige User Mitglied ist.
58  * - zu jedem Server wird nun der "Top-Server" gespeichert, somit funktioniert
59  *   LINKS wieder korrekt.
60  *
61  * Revision 1.47  2002/01/28 13:05:48  alex
62  * - nach einem JOIN wird die Liste der Mitglieder an den Client geschickt.
63  * - MODE fuer Channels wird nun komplett ignoriert (keine Fehlermeldung mehr).
64  *
65  * Revision 1.46  2002/01/28 01:45:43  alex
66  * - SERVER-Meldungen an neue Server sind nun in der richtigen Reihenfolge.
67  *
68  * Revision 1.45  2002/01/28 01:18:14  alex
69  * - connectierenden Servern werden Channels nun mit NJOIN bekannt gemacht.
70  *
71  * Revision 1.44  2002/01/28 00:55:08  alex
72  * - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht.
73  *
74  * Revision 1.43  2002/01/27 21:56:39  alex
75  * - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
76  * - einige kleinere Fixes bezueglich Channels ...
77  *
78  * Revision 1.42  2002/01/27 18:28:01  alex
79  * - bei NICK wurde das falsche Prefix an andere Server weitergegeben.
80  *
81  * Revision 1.41  2002/01/27 17:15:49  alex
82  * - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
83  *   IRC_WriteStrChannelPrefix(),
84  * - neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
85  *
86  * Revision 1.40  2002/01/26 18:43:11  alex
87  * - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
88  *   die IRC_Write_xxx_Related() sind dafuer entfallen.
89  * - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
90  *
91  * Revision 1.39  2002/01/21 00:05:11  alex
92  * - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
93  *   IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
94  * - diverse Aenderungen im Zusammenhang mit Channels.
95  *
96  * Revision 1.38  2002/01/18 15:31:32  alex
97  * - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen.
98  *
99  * Revision 1.37  2002/01/16 22:10:18  alex
100  * - IRC_LUSERS() implementiert.
101  *
102  * Revision 1.36  2002/01/11 23:50:55  alex
103  * - LINKS implementiert, LUSERS begonnen.
104  *
105  * Revision 1.35  2002/01/09 21:30:45  alex
106  * - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet.
107  *
108  * Revision 1.34  2002/01/09 01:09:58  alex
109  * - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
110  * - andere Server werden nun ueber bisherige Server und User informiert.
111  *
112  * Revision 1.33  2002/01/07 23:42:12  alex
113  * - Es werden fuer alle Server eigene Token generiert,
114  * - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
115  * - ebenso NICK-Befehle, die "fremde" User einfuehren.
116  *
117  * Revision 1.32  2002/01/07 16:02:36  alex
118  * - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
119  * - Im Debug-Mode werden nun auch PING's protokolliert.
120  *
121  * Revision 1.31  2002/01/07 15:39:46  alex
122  * - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
123  * - MODE und NICK melden nun die Aenderungen an andere Server.
124  *
125  * Revision 1.30  2002/01/06 15:21:29  alex
126  * - Loglevel und Meldungen nochmals ueberarbeitet.
127  * - QUIT und SQUIT forwarden nun den Grund der Trennung,
128  * - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
129  *
130  * Revision 1.29  2002/01/05 23:24:54  alex
131  * - WHOIS erweitert: Anfragen koennen an andere Server weitergeleitet werden.
132  * - Vorbereitungen fuer Ident-Abfragen bei neuen Client-Strukturen.
133  *
134  * Revision 1.28  2002/01/05 20:08:02  alex
135  * - Div. Aenderungen fuer die Server-Links (u.a. WHOIS, QUIT, NICK angepasst).
136  * - Neue Funktionen IRC_WriteStrServer() und IRC_WriteStrServerPrefix().
137  *
138  * Revision 1.27  2002/01/05 19:15:03  alex
139  * - Fehlerpruefung bei select() in der "Hauptschleife" korrigiert.
140  *
141  * Revision 1.26  2002/01/05 16:51:18  alex
142  * - das Passwort von Servern wird nun ueberprueft (PASS- und SERVER-Befehl).
143  *
144  * Revision 1.25  2002/01/05 00:48:33  alex
145  * - bei SQUIT wurde immer die Verbindung getrennt, auch bei Remote-Servern.
146  *
147  * Revision 1.24  2002/01/04 17:58:44  alex
148  * - IRC_WriteStrXXX()-Funktionen eingefuehrt, groessere Anpassungen daran.
149  * - neuer Befehl SQUIT, QUIT an Server-Links angepasst.
150  *
151  * Revision 1.23  2002/01/04 01:36:40  alex
152  * - Loglevel ein wenig angepasst.
153  *
154  * Revision 1.22  2002/01/04 01:21:47  alex
155  * - Client-Strukruren werden nur noch ueber Funktionen angesprochen.
156  * - Weitere Anpassungen und Erweiterungen der Server-Links.
157  *
158  * Revision 1.21  2002/01/03 02:26:51  alex
159  * - neue Befehle SERVER und NJOIN begonnen,
160  * - begonnen, diverse IRC-Befehle an Server-Links anzupassen.
161  *
162  * Revision 1.20  2002/01/02 12:46:41  alex
163  * - die Gross- und Kleinschreibung des Nicks kann mit NICK nun geaendert werden.
164  *
165  * Revision 1.19  2002/01/02 02:51:39  alex
166  * - Copyright-Texte angepasst.
167  * - neuer Befehl "ERROR".
168  *
169  * Revision 1.17  2001/12/31 15:33:13  alex
170  * - neuer Befehl NAMES, kleinere Bugfixes.
171  * - Bug bei PING behoben: war zu restriktiv implementiert :-)
172  *
173  * Revision 1.16  2001/12/31 02:18:51  alex
174  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
175  * - neuen Header "defines.h" mit (fast) allen Konstanten.
176  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
177  *
178  * Revision 1.15  2001/12/30 19:26:11  alex
179  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
180  *
181  * Revision 1.14  2001/12/30 11:42:00  alex
182  * - der Server meldet nun eine ordentliche "Start-Zeit".
183  *
184  * Revision 1.13  2001/12/29 03:10:06  alex
185  * - Neue Funktion IRC_MODE() implementiert, div. Aenderungen.
186  * - neue configure-Optione "--enable-strict-rfc".
187  *
188  * Revision 1.12  2001/12/27 19:17:26  alex
189  * - neue Befehle PRIVMSG, NOTICE, PING.
190  *
191  * Revision 1.11  2001/12/27 16:55:41  alex
192  * - neu: IRC_WriteStrRelated(), Aenderungen auch in IRC_WriteStrClient().
193  *
194  * Revision 1.10  2001/12/26 22:48:53  alex
195  * - MOTD-Datei ist nun konfigurierbar und wird gelesen.
196  *
197  * Revision 1.9  2001/12/26 14:45:37  alex
198  * - "Code Cleanups".
199  *
200  * Revision 1.8  2001/12/26 03:21:46  alex
201  * - PING/PONG-Befehle implementiert,
202  * - Meldungen ueberarbeitet: enthalten nun (fast) immer den Nick.
203  *
204  * Revision 1.7  2001/12/25 23:25:18  alex
205  * - und nochmal Aenderungen am Logging ;-)
206  *
207  * Revision 1.6  2001/12/25 23:13:33  alex
208  * - Debug-Meldungen angepasst.
209  *
210  * Revision 1.5  2001/12/25 22:02:42  alex
211  * - neuer IRC-Befehl "/QUIT". Verbessertes Logging & Debug-Ausgaben.
212  *
213  * Revision 1.4  2001/12/25 19:19:30  alex
214  * - bessere Fehler-Abfragen, diverse Bugfixes.
215  * - Nicks werden nur einmal vergeben :-)
216  * - /MOTD wird unterstuetzt.
217  *
218  * Revision 1.3  2001/12/24 01:34:06  alex
219  * - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert (wg. BitchX)
220  * - MOTD-Ausgabe begonnen zu implementieren.
221  *
222  * Revision 1.2  2001/12/23 21:57:16  alex
223  * - erste IRC-Befehle zu implementieren begonnen.
224  *
225  * Revision 1.1  2001/12/14 08:13:43  alex
226  * - neues Modul begonnen :-)
227  */
228
229
230 #include <portab.h>
231 #include "global.h"
232
233 #include <imp.h>
234 #include <assert.h>
235 #include <errno.h>
236 #include <stdarg.h>
237 #include <stdio.h>
238 #include <stdlib.h>
239 #include <string.h>
240
241 #include "ngircd.h"
242 #include "channel.h"
243 #include "client.h"
244 #include "conf.h"
245 #include "conn.h"
246 #include "log.h"
247 #include "messages.h"
248 #include "parse.h"
249 #include "tool.h"
250
251 #include <exp.h>
252 #include "irc.h"
253
254
255 #define CONNECTED TRUE
256 #define DISCONNECTED FALSE
257
258
259 LOCAL BOOLEAN Hello_User( CLIENT *Client );
260 LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
261
262 LOCAL VOID Kill_Nick( CHAR *Nick );
263
264 LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan );
265 LOCAL BOOLEAN Send_LUSERS( CLIENT *Client );
266
267
268 GLOBAL VOID IRC_Init( VOID )
269 {
270 } /* IRC_Init */
271
272
273 GLOBAL VOID IRC_Exit( VOID )
274 {
275 } /* IRC_Exit */
276
277
278 GLOBAL BOOLEAN IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
279 {
280         CHAR buffer[1000];
281         BOOLEAN ok = CONNECTED;
282         va_list ap;
283
284         assert( Client != NULL );
285         assert( Format != NULL );
286
287         va_start( ap, Format );
288         vsnprintf( buffer, 1000, Format, ap );
289         va_end( ap );
290
291         /* an den Client selber */
292         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
293
294         return ok;
295 } /* IRC_WriteStrClient */
296
297
298 GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
299 {
300         /* Text an Clients, lokal bzw. remote, senden. */
301
302         CHAR buffer[1000];
303         va_list ap;
304
305         assert( Client != NULL );
306         assert( Format != NULL );
307         assert( Prefix != NULL );
308
309         va_start( ap, Format );
310         vsnprintf( buffer, 1000, Format, ap );
311         va_end( ap );
312
313         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Client_ID( Prefix ), buffer );
314 } /* IRC_WriteStrClientPrefix */
315
316
317 GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
318 {
319         CHAR buffer[1000];
320         va_list ap;
321
322         assert( Client != NULL );
323         assert( Format != NULL );
324
325         va_start( ap, Format );
326         vsnprintf( buffer, 1000, Format, ap );
327         va_end( ap );
328
329         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
330 } /* IRC_WriteStrChannel */
331
332
333 GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
334 {
335         CHAR buffer[1000];
336         BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED;
337         CL2CHAN *cl2chan;
338         CLIENT *c;
339         INT s, i;
340         va_list ap;
341
342         assert( Client != NULL );
343         assert( Chan != NULL );
344         assert( Prefix != NULL );
345         assert( Format != NULL );
346
347         va_start( ap, Format );
348         vsnprintf( buffer, 1000, Format, ap );
349         va_end( ap );
350
351         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
352
353         /* An alle Clients, die in den selben Channels sind.
354          * Dabei aber nur einmal je Remote-Server */
355         cl2chan = Channel_FirstMember( Chan );
356         while( cl2chan )
357         {
358                 c = Channel_GetClient( cl2chan );
359                 if( ! Remote )
360                 {
361                         if( Client_Conn( c ) <= NONE ) c = NULL;
362                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
363                 }
364                 if( c ) c = Client_NextHop( c );
365                         
366                 if( c && ( c != Client ))
367                 {
368                         /* Ok, anderer Client */
369                         s = Client_Conn( c );
370                         assert( s >= 0 );
371                         assert( s < MAX_CONNECTIONS );
372                         sock[s] = TRUE;
373                 }
374                 cl2chan = Channel_NextMember( Chan, cl2chan );
375         }
376
377         /* Senden ... */
378         for( i = 0; i < MAX_CONNECTIONS; i++ )
379         {
380                 if( sock[i] )
381                 {
382                         ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
383                         if( ! ok ) break;
384                 }
385         }
386         return ok;
387 } /* IRC_WriteStrChannelPrefix */
388
389
390 GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
391 {
392         CHAR buffer[1000];
393         va_list ap;
394
395         assert( Format != NULL );
396
397         va_start( ap, Format );
398         vsnprintf( buffer, 1000, Format, ap );
399         va_end( ap );
400
401         /* an den Client selber */
402         return IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
403 } /* IRC_WriteStrServers */
404
405
406 GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
407 {
408         CHAR buffer[1000];
409         CLIENT *c;
410         va_list ap;
411         
412         assert( Format != NULL );
413         assert( Prefix != NULL );
414
415         va_start( ap, Format );
416         vsnprintf( buffer, 1000, Format, ap );
417         va_end( ap );
418         
419         c = Client_First( );
420         while( c )
421         {
422                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
423                 {
424                         /* Ziel-Server gefunden */
425                         IRC_WriteStrClientPrefix( c, Prefix, buffer );
426                 }
427                 c = Client_Next( c );
428         }
429 } /* IRC_WriteStrServersPrefix */
430
431
432 GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
433 {
434         BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED;
435         CL2CHAN *chan_cl2chan, *cl2chan;
436         CHAR buffer[1000];
437         CHANNEL *chan;
438         va_list ap;
439         CLIENT *c;
440         INT i, s;
441
442         assert( Client != NULL );
443         assert( Prefix != NULL );
444         assert( Format != NULL );
445
446         va_start( ap, Format );
447         vsnprintf( buffer, 1000, Format, ap );
448         va_end( ap );
449
450         /* initialisieren */
451         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
452
453         /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
454          * den Text schicken. An Remote-Server aber jeweils nur einmal. */
455         chan_cl2chan = Channel_FirstChannelOf( Client );
456         while( chan_cl2chan )
457         {
458                 /* Channel des Users durchsuchen */
459                 chan = Channel_GetChannel( chan_cl2chan );
460                 cl2chan = Channel_FirstMember( chan );
461                 while( cl2chan )
462                 {
463                         c = Channel_GetClient( cl2chan );
464                         if( ! Remote )
465                         {
466                                 if( Client_Conn( c ) <= NONE ) c = NULL;
467                                 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
468                         }
469                         if( c ) c = Client_NextHop( c );
470
471                         if( c && ( c != Client ))
472                         {
473                                 /* Ok, anderer Client */
474                                 s = Client_Conn( c );
475                                 assert( s >= 0 );
476                                 assert( s < MAX_CONNECTIONS );
477                                 sock[s] = TRUE;
478                         }
479                         cl2chan = Channel_NextMember( chan, cl2chan );
480                 }
481                 
482                 /* naechsten Channel */
483                 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
484         }
485
486         /* Senden ... */
487         for( i = 0; i < MAX_CONNECTIONS; i++ )
488         {
489                 if( sock[i] )
490                 {
491                         ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
492                         if( ! ok ) break;
493                 }
494         }
495         return ok;
496 } /* IRC_WriteStrRelatedPrefix */
497
498
499
500 GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
501 {
502         assert( Client != NULL );
503         assert( Req != NULL );
504
505         /* Fehler liefern, wenn kein lokaler Client */
506         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
507         
508         if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
509         {
510                 /* noch nicht registrierte unbekannte Verbindung */
511                 Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
512
513                 /* Passwort speichern */
514                 Client_SetPassword( Client, Req->argv[0] );
515
516                 Client_SetType( Client, CLIENT_GOTPASS );
517                 return CONNECTED;
518         }
519         else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
520         {
521                 /* noch nicht registrierte Server-Verbindung */
522                 Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
523
524                 /* Passwort speichern */
525                 Client_SetPassword( Client, Req->argv[0] );
526
527                 Client_SetType( Client, CLIENT_GOTPASSSERVER );
528                 return CONNECTED;
529         }
530         else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
531         {
532                 /* Falsche Anzahl Parameter? */
533                 return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
534         }
535         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
536 } /* IRC_PASS */
537
538
539 GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
540 {
541         CHAR str[LINE_LEN], *ptr;
542         CLIENT *from, *c, *cl;
543         CL2CHAN *cl2chan;
544         INT max_hops, i;
545         CHANNEL *chan;
546         BOOLEAN ok;
547         
548         assert( Client != NULL );
549         assert( Req != NULL );
550
551         /* Fehler liefern, wenn kein lokaler Client */
552         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
553
554         if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
555         {
556                 /* Verbindung soll als Server-Server-Verbindung registriert werden */
557                 Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
558
559                 /* Falsche Anzahl Parameter? */
560                 if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
561
562                 /* Ist dieser Server bei uns konfiguriert? */
563                 for( i = 0; i < Conf_Server_Count; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
564                 if( i >= Conf_Server_Count )
565                 {
566                         /* Server ist nicht konfiguriert! */
567                         Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] );
568                         Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", TRUE );
569                         return DISCONNECTED;
570                 }
571                 if( strcmp( Client_Password( Client ), Conf_Server[i].pwd ) != 0 )
572                 {
573                         /* Falsches Passwort */
574                         Log( LOG_ERR, "Connection %d: Bad password for server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
575                         Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
576                         return DISCONNECTED;
577                 }
578                 
579                 /* Ist ein Server mit dieser ID bereits registriert? */
580                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
581
582                 /* Server-Strukturen fuellen ;-) */
583                 Client_SetID( Client, Req->argv[0] );
584                 Client_SetHops( Client, 1 );
585                 Client_SetInfo( Client, Req->argv[Req->argc - 1] );
586                 
587                 /* Meldet sich der Server bei uns an? */
588                 if( Req->argc == 2 )
589                 {
590                         /* Unseren SERVER- und PASS-Befehl senden */
591                         ok = TRUE;
592                         if( ! IRC_WriteStrClient( Client, "PASS %s "PASSSERVERADD, Conf_Server[i].pwd )) ok = FALSE;
593                         else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo );
594                         if( ! ok )
595                         {
596                                 Conn_Close( Client_Conn( Client ), "Unexpected server behavior!", NULL, FALSE );
597                                 return DISCONNECTED;
598                         }
599                         Client_SetIntroducer( Client, Client );
600                         Client_SetToken( Client, 1 );
601                 }
602                 else  Client_SetToken( Client, atoi( Req->argv[1] ));
603
604                 Log( LOG_NOTICE, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client ));
605
606                 Client_SetType( Client, CLIENT_SERVER );
607
608                 /* maximalen Hop Count ermitteln */
609                 max_hops = 0;
610                 c = Client_First( );
611                 while( c )
612                 {
613                         if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c );
614                         c = Client_Next( c );
615                 }
616                 
617                 /* Alle bisherigen Server dem neuen Server bekannt machen,
618                  * die bisherigen Server ueber den neuen informierenn */
619                 for( i = 0; i < ( max_hops + 1 ); i++ )
620                 {
621                         c = Client_First( );
622                         while( c )
623                         {
624                                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i ))
625                                 {
626                                         if( Client_Conn( c ) > NONE )
627                                         {
628                                                 /* Dem gefundenen Server gleich den neuen
629                                                  * Server bekannt machen */
630                                                 if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
631                                         }
632                                         
633                                         /* Den neuen Server ueber den alten informieren */
634                                         if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
635                                 }
636                                 c = Client_Next( c );
637                         }
638                 }
639
640                 /* alle User dem neuen Server bekannt machen */
641                 c = Client_First( );
642                 while( c )
643                 {
644                         if( Client_Type( c ) == CLIENT_USER )
645                         {
646                                 /* User an neuen Server melden */
647                                 if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED;
648                         }
649                         c = Client_Next( c );
650                 }
651
652                 /* Channels dem neuen Server bekannt machen */
653                 chan = Channel_First( );
654                 while( chan )
655                 {
656                         sprintf( str, "NJOIN %s :", Channel_Name( chan ));
657
658                         /* alle Member suchen */
659                         cl2chan = Channel_FirstMember( chan );
660                         while( cl2chan )
661                         {
662                                 cl = Channel_GetClient( cl2chan );
663                                 assert( cl != NULL );
664
665                                 /* Nick, ggf. mit Modes, anhaengen */
666                                 if( str[strlen( str ) - 1] != ':' ) strcat( str, "," );
667                                 if( strchr( Channel_UserModes( chan, cl ), 'v' )) strcat( str, "+" );
668                                 if( strchr( Channel_UserModes( chan, cl ), 'o' )) strcat( str, "@" );
669                                 strcat( str, Client_ID( cl ));
670
671                                 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
672                                 {
673                                         /* Zeile senden */
674                                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
675                                         sprintf( str, "NJOIN %s :", Channel_Name( chan ));
676                                 }
677                                 
678                                 cl2chan = Channel_NextMember( chan, cl2chan );
679                         }
680
681                         /* noch Daten da? */
682                         if( str[strlen( str ) - 1] != ':')
683                         {
684                                 /* Ja; Also senden ... */
685                                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
686                         }
687
688                         /* naechsten Channel suchen */
689                         chan = Channel_Next( chan );
690                 }
691                 
692                 return CONNECTED;
693         }
694         else if( Client_Type( Client ) == CLIENT_SERVER )
695         {
696                 /* Neuer Server wird im Netz angekuendigt */
697
698                 /* Falsche Anzahl Parameter? */
699                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
700
701                 /* Ist ein Server mit dieser ID bereits registriert? */
702                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
703
704                 /* Ueberfluessige Hostnamen aus Info-Text entfernen */
705                 ptr = strchr( Req->argv[3] + 2, '[' );
706                 if( ! ptr ) ptr = Req->argv[3];
707
708                 from = Client_GetFromID( Req->prefix );
709                 if( ! from )
710                 {
711                         /* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
712                         Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
713                         Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", TRUE );
714                         return DISCONNECTED;
715                 }
716
717                 /* Neue Client-Struktur anlegen */
718                 c = Client_NewRemoteServer( Client, Req->argv[0], from, atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
719                 if( ! c )
720                 {
721                         /* Neue Client-Struktur konnte nicht angelegt werden */
722                         Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
723                         Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", TRUE );
724                         return DISCONNECTED;
725                 }
726
727                 /* Log-Meldung zusammenbauen und ausgeben */
728                 if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Client_ID( from ));
729                 else strcpy( str, "" );
730                 Log( LOG_NOTICE, "Server \"%s\" registered (via %s, %s%d hop%s).", Client_ID( c ), Client_ID( Client ), str, Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
731
732                 /* Andere Server informieren */
733                 IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
734
735                 return CONNECTED;
736         }
737         else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
738 } /* IRC_SERVER */
739
740
741 GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
742 {
743         CHAR *channame, *ptr, modes[8];
744         BOOLEAN is_op, is_voiced;
745         CHANNEL *chan;
746         CLIENT *c;
747         
748         assert( Client != NULL );
749         assert( Req != NULL );
750
751         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTEREDSERVER_MSG, Client_ID( Client ));
752
753         /* Falsche Anzahl Parameter? */
754         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
755
756         channame = Req->argv[0];
757         ptr = strtok( Req->argv[1], "," );
758         while( ptr )
759         {
760                 is_op = is_voiced = FALSE;
761                 
762                 /* Prefixe abschneiden */
763                 while(( *ptr == '@' ) || ( *ptr == '+' ))
764                 {
765                         if( *ptr == '@' ) is_op = TRUE;
766                         if( *ptr == '+' ) is_voiced = TRUE;
767                         ptr++;
768                 }
769
770                 c = Client_GetFromID( ptr );
771                 if( c )
772                 {
773                         Channel_Join( c, channame );
774                         chan = Channel_Search( channame );
775                         assert( chan != NULL );
776                         
777                         if( is_op ) Channel_UserModeAdd( chan, c, 'o' );
778                         if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' );
779
780                         /* im Channel bekannt machen */
781                         IRC_WriteStrChannelPrefix( Client, chan, c, FALSE, "JOIN :%s", channame );
782
783                         /* Channel-User-Modes setzen */
784                         strcpy( modes, Channel_UserModes( chan, c ));
785                         if( modes[0] )
786                         {
787                                 /* Modes im Channel bekannt machen */
788                                 IRC_WriteStrChannelPrefix( Client, chan, Client, FALSE, "MODE %s +%s %s", channame, modes, Client_ID( c ));
789                         }
790                 }
791                 else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame );
792                 
793                 /* naechsten Nick suchen */
794                 ptr = strtok( NULL, "," );
795         }
796
797         /* an andere Server weiterleiten */
798         IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], Req->argv[1] );
799
800         return CONNECTED;
801 } /* IRC_NJOIN */
802
803
804 GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
805 {
806         CLIENT *intr_c, *target, *c;
807         CHAR *modes;
808
809         assert( Client != NULL );
810         assert( Req != NULL );
811
812         /* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
813 #ifndef STRICT_RFC
814         if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTUSER || Client_Type( Client ) == CLIENT_USER || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
815 #else
816         if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_USER || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
817 #endif
818         {
819                 /* User-Registrierung bzw. Nick-Aenderung */
820
821                 /* Falsche Anzahl Parameter? */
822                 if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
823
824                 /* "Ziel-Client" ermitteln */
825                 if( Client_Type( Client ) == CLIENT_SERVER )
826                 {
827                         target = Client_GetFromID( Req->prefix );
828                         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
829                 }
830                 else
831                 {
832                         /* Ist der Client "restricted"? */
833                         if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
834                         target = Client;
835                 }
836
837 #ifndef STRICT_RFC
838                 /* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
839                  * wir nichts. So macht es das Original und mind. Snak hat probleme,
840                  * wenn wir es nicht so machen. Ob es so okay ist? Hm ... */
841                 if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
842 #endif
843                 
844                 /* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
845                  * will nur die Gross- und Kleinschreibung aendern. Das darf
846                  * er natuerlich machen :-) */
847                 if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
848                 {
849                         if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
850                 }
851
852                 /* Nick-Aenderung: allen mitteilen! */
853                 Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
854                 if( Client_Type( Client ) == CLIENT_USER ) IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
855                 IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
856                 IRC_WriteStrRelatedPrefix( target, target, FALSE, "NICK :%s", Req->argv[0] );
857         
858                 /* Client-Nick registrieren */
859                 Client_SetID( target, Req->argv[0] );
860
861                 if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
862                 {
863                         /* Neuer Client */
864                         Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
865                         if( Client_Type( Client ) == CLIENT_GOTUSER ) return Hello_User( Client );
866                         else Client_SetType( Client, CLIENT_GOTNICK );
867                 }
868                 return CONNECTED;
869         }
870         else if( Client_Type( Client ) == CLIENT_SERVER )
871         {
872                 /* Server fuehrt neuen Client ein */
873
874                 /* Falsche Anzahl Parameter? */
875                 if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
876
877                 /* Nick ueberpruefen */
878                 c = Client_GetFromID( Req->argv[0] );
879                 if( c )
880                 {
881                         /* Der neue Nick ist auf diesem Server bereits registriert:
882                          * sowohl der neue, als auch der alte Client muessen nun
883                          * disconnectiert werden. */
884                         Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
885                         Kill_Nick( Req->argv[0] );
886                         return CONNECTED;
887                 }
888
889                 /* Server, zu dem der Client connectiert ist, suchen */
890                 intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
891                 if( ! intr_c )
892                 {
893                         Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
894                         Kill_Nick( Req->argv[0] );
895                         return CONNECTED;
896                 }
897
898                 /* Neue Client-Struktur anlegen */
899                 c = Client_NewRemoteUser( intr_c, Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], atoi( Req->argv[4] ), Req->argv[5] + 1, Req->argv[6], TRUE );
900                 if( ! c )
901                 {
902                         /* Eine neue Client-Struktur konnte nicht angelegt werden.
903                          * Der Client muss disconnectiert werden, damit der Netz-
904                          * status konsistent bleibt. */
905                         Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
906                         Kill_Nick( Req->argv[0] );
907                         return CONNECTED;
908                 }
909
910                 modes = Client_Modes( c );
911                 if( *modes ) Log( LOG_DEBUG, "User \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", Client_Mask( c ), modes, Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
912                 else Log( LOG_DEBUG, "User \"%s\" registered (via %s, on %s, %d hop%s).", Client_Mask( c ), Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
913
914                 /* Andere Server, ausser dem Introducer, informieren */
915                 IRC_WriteStrServersPrefix( Client, Client, "NICK %s %d %s %s %d %s :%s", Req->argv[0], atoi( Req->argv[1] ) + 1, Req->argv[2], Req->argv[3], Client_MyToken( intr_c ), Req->argv[5], Req->argv[6] );
916
917                 return CONNECTED;
918         }
919         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
920 } /* IRC_NICK */
921
922
923 GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req )
924 {
925         assert( Client != NULL );
926         assert( Req != NULL );
927
928 #ifndef STRICT_RFC
929         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
930 #else
931         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
932 #endif
933         {
934                 /* Falsche Anzahl Parameter? */
935                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
936
937                 Client_SetUser( Client, Req->argv[0], FALSE );
938                 Client_SetInfo( Client, Req->argv[3] );
939
940                 Log( LOG_DEBUG, "Connection %d: got USER command ...", Client_Conn( Client ));
941                 if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
942                 else Client_SetType( Client, CLIENT_GOTUSER );
943                 return CONNECTED;
944         }
945         else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
946         {
947                 return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
948         }
949         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
950 } /* IRC_USER */
951
952
953 GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
954 {
955         CLIENT *target;
956         
957         assert( Client != NULL );
958         assert( Req != NULL );
959
960         if(( Client_Type( Client ) == CLIENT_USER ) || ( Client_Type( Client ) == CLIENT_SERVICE ))
961         {
962                 /* User / Service */
963                 
964                 /* Falsche Anzahl Parameter? */
965                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
966
967                 if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE );
968                 else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE );
969                 
970                 return DISCONNECTED;
971         }
972         else if ( Client_Type( Client ) == CLIENT_SERVER )
973         {
974                 /* Server */
975
976                 /* Falsche Anzahl Parameter? */
977                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
978
979                 target = Client_Search( Req->prefix );
980                 if( ! target )
981                 {
982                         Log( LOG_ERR, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
983                         return CONNECTED;
984                 }
985
986                 if( Req->argc == 0 ) Client_Destroy( target, "Got QUIT command.", NULL );
987                 else Client_Destroy( target, "Got QUIT command.", Req->argv[0] );
988
989                 return CONNECTED;
990         }
991         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
992 } /* IRC_QUIT */
993
994
995 GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
996 {
997         CLIENT *target;
998         
999         assert( Client != NULL );
1000         assert( Req != NULL );
1001
1002         /* SQUIT ist nur fuer Server erlaubt */
1003         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1004
1005         /* Falsche Anzahl Parameter? */
1006         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1007
1008         target = Client_GetFromID( Req->argv[0] );
1009         if( ! target )
1010         {
1011                 Log( LOG_ERR, "Got SQUIT from %s for unknown server \%s\"!?", Client_ID( Client ), Req->argv[0] );
1012                 return CONNECTED;
1013         }
1014
1015         if( target == Client ) Log( LOG_DEBUG, "Got SQUIT from %s: %s", Client_ID( Client ), Req->argv[1] );
1016         else Log( LOG_DEBUG, "Got SQUIT from %s for %s: %s", Client_ID( Client ), Client_ID( target ), Req->argv[1] );
1017
1018         /* SQUIT an alle Server weiterleiten */
1019         IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] );
1020
1021         if( Client_Conn( target ) > NONE )
1022         {
1023                 if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), "Got SQUIT command.", Req->argv[1], TRUE );
1024                 else Conn_Close( Client_Conn( target ), "Got SQUIT command.", NULL, TRUE );
1025                 return DISCONNECTED;
1026         }
1027         else
1028         {
1029                 Client_Destroy( target, "Got SQUIT command.", Req->argv[1] );
1030                 return CONNECTED;
1031         }
1032 } /* IRC_SQUIT */
1033
1034
1035 GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
1036 {
1037         CLIENT *target, *from;
1038         
1039         assert( Client != NULL );
1040         assert( Req != NULL );
1041
1042         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1043
1044         /* Falsche Anzahl Parameter? */
1045         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
1046         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1047         
1048         if( Req->argc == 2 )
1049         {
1050                 /* es wurde ein Ziel-Client angegeben */
1051                 target = Client_GetFromID( Req->argv[1] );
1052                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1053                 if( target != Client_ThisServer( ))
1054                 {
1055                         /* ok, forwarden */
1056                         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1057                         else from = Client;
1058                         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
1059                         return IRC_WriteStrClientPrefix( Client_NextHop( target ), from, "PING %s :%s", Client_ID( from ), Req->argv[1] );
1060                 }
1061         }
1062
1063         Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
1064         return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
1065 } /* IRC_PING */
1066
1067
1068 GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
1069 {
1070         CLIENT *target, *from;
1071
1072         assert( Client != NULL );
1073         assert( Req != NULL );
1074
1075         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1076
1077         /* Falsche Anzahl Parameter? */
1078         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
1079         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1080
1081         /* forwarden? */
1082         if( Req->argc == 2 )
1083         {
1084                 target = Client_GetFromID( Req->argv[1] );
1085                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1086                 if( target != Client_ThisServer( ))
1087                 {
1088                         /* ok, forwarden */
1089                         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1090                         else from = Client;
1091                         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
1092                         return IRC_WriteStrClientPrefix( Client_NextHop( target ), from, "PONG %s :%s", Client_ID( from ), Req->argv[1] );
1093                 }
1094         }
1095
1096         /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
1097          * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
1098
1099         if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %d seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
1100         else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
1101
1102         return CONNECTED;
1103 } /* IRC_PONG */
1104
1105
1106 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
1107 {
1108         assert( Client != NULL );
1109         assert( Req != NULL );
1110
1111         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1112
1113         /* Falsche Anzahl Parameter? */
1114         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1115
1116         return Show_MOTD( Client );
1117 } /* IRC_MOTD */
1118
1119
1120 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
1121 {
1122         CLIENT *to, *from;
1123         CHANNEL *chan;
1124         
1125         assert( Client != NULL );
1126         assert( Req != NULL );
1127
1128         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1129
1130         /* Falsche Anzahl Parameter? */
1131         if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
1132         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
1133         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1134
1135         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1136         else from = Client;
1137         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1138
1139         to = Client_Search( Req->argv[0] );
1140         if( to )
1141         {
1142                 /* Okay, Ziel ist ein User */
1143                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
1144                 return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
1145         }
1146
1147         chan = Channel_Search( Req->argv[0] );
1148         if( chan )
1149         {
1150                 /* Okay, Ziel ist ein Channel */
1151                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
1152                 return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
1153         }
1154
1155         return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
1156 } /* IRC_PRIVMSG */
1157
1158
1159 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
1160 {
1161         CLIENT *to, *from;
1162
1163         assert( Client != NULL );
1164         assert( Req != NULL );
1165
1166         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1167
1168         /* Falsche Anzahl Parameter? */
1169         if( Req->argc != 2 ) return CONNECTED;
1170
1171         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1172         else from = Client;
1173         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1174
1175         to = Client_Search( Req->argv[0] );
1176         if( to )
1177         {
1178                 /* Okay, Ziel ist ein User */
1179                 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
1180         }
1181         else return CONNECTED;
1182 } /* IRC_NOTICE */
1183
1184
1185 GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
1186 {
1187         CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
1188         CLIENT *cl, *chan_cl, *prefix;
1189         BOOLEAN set, ok;
1190         CHANNEL *chan;
1191         
1192         assert( Client != NULL );
1193         assert( Req != NULL );
1194
1195         cl = chan_cl = prefix = NULL;
1196         chan = NULL;
1197
1198         /* Valider Client? */
1199         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1200
1201         /* Keine Parameter? */
1202         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1203
1204         /* Ziel suchen: Client bzw. Channel */
1205         if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
1206         if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
1207
1208         /* Kein Ziel gefunden? */
1209         if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
1210
1211         assert(( cl && chan ) != TRUE );
1212
1213         /* Falsche Anzahl Parameter? */
1214         if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1215         if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1216
1217         /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
1218         if(( chan ) && (Req->argc == 3 ))
1219         {
1220                 chan_cl = Client_Search( Req->argv[2] );
1221                 if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
1222         }
1223         
1224         /* Wenn Anfragender ein User ist: Zugriff erlaubt? */
1225         if( Client_Type( Client ) == CLIENT_USER )
1226         {
1227                 if( cl )
1228                 {
1229                         /* MODE ist nur fuer sich selber zulaessig! */
1230                         if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
1231                 }
1232                 if( chan )
1233                 {
1234                         /* Darf der User die Channel-Modes ermitteln? */
1235                 }
1236         }
1237
1238         /* Werden die Modes "nur" erfragt? */
1239         if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
1240         if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
1241
1242         mode_ptr = Req->argv[1];
1243
1244         /* Sollen Modes gesetzt oder geloescht werden? */
1245         if( cl )
1246         {
1247                 if( *mode_ptr == '+' ) set = TRUE;
1248                 else if( *mode_ptr == '-' ) set = FALSE;
1249                 else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1250                 mode_ptr++;
1251         }
1252         else
1253         {
1254                 if( *mode_ptr == '-' ) set = FALSE;
1255                 else set = TRUE;
1256                 if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
1257         }
1258         
1259         /* Prefix fuer Antworten etc. ermitteln */
1260         if( Client_Type( Client ) == CLIENT_SERVER )
1261         {
1262                 prefix = Client_GetFromID( Req->prefix );
1263                 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1264         }
1265         else prefix = Client;
1266
1267         /* Reply-String mit Aenderungen vorbereiten */
1268         if( set ) strcpy( the_modes, "+" );
1269         else strcpy( the_modes, "-" );
1270
1271         ok = TRUE;
1272         x[1] = '\0';
1273         while( *mode_ptr )
1274         {
1275                 x[0] = '\0';
1276                 if( Client_Type( Client ) == CLIENT_SERVER )
1277                 {
1278                         /* Befehl kommt von einem Server, daher
1279                          * trauen wir ihm "unbesehen" ... */
1280                         x[0] = *mode_ptr;
1281                 }
1282                 else
1283                 {
1284                         /* Modes validieren */
1285                         if( cl )
1286                         {
1287                                 /* User-Modes */
1288                                 switch( *mode_ptr )
1289                                 {
1290                                         case 'i':
1291                                                 /* invisible */
1292                                                 x[0] = 'i';
1293                                                 break;
1294                                         case 'r':
1295                                                 /* restricted (kann nur gesetzt werden) */
1296                                                 if( set ) x[0] = 'r';
1297                                                 else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
1298                                                 break;
1299                                         case 'o':
1300                                                 /* operator (kann nur geloescht werden) */
1301                                                 if( ! set )
1302                                                 {
1303                                                         Client_SetOperByMe( Client, FALSE );
1304                                                         x[0] = 'o';
1305                                                 }
1306                                                 else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1307                                                 break;
1308                                         default:
1309                                                 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
1310                                                 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1311                                                 x[0] = '\0';
1312                                 }
1313                         }
1314                         if( chan )
1315                         {
1316                                 /* Ist der User ein Channel Operator? */
1317                                 if( ! strchr( Channel_UserModes( chan, Client ), 'o' ))
1318                                 {
1319                                         Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan ));
1320                                         ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan ));
1321                                         break;
1322                                 }
1323                                 
1324                                 /* Channel-Modes oder Channel-User-Modes */
1325                                 if( chan_cl )
1326                                 {
1327                                         /* Channel-User-Modes */
1328                                         switch( *mode_ptr )
1329                                         {
1330                                                 case 'o':
1331                                                         /* Channel Operator */
1332                                                         x[0] = 'o';
1333                                                         break;
1334                                                 case 'v':
1335                                                         /* Voice */
1336                                                         x[0] = 'v';
1337                                                         break;
1338                                                 default:
1339                                                         Log( LOG_DEBUG, "Unknown channel-user-mode \"%c%c\" from \"%s\" on \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Client_ID( chan_cl ), Channel_Name( chan ));
1340                                                         ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1341                                                         x[0] = '\0';
1342                                         }
1343                                 }
1344                                 else
1345                                 {
1346                                         /* Channel-Modes */
1347                                         switch( *mode_ptr )
1348                                         {
1349                                                 case 'a':
1350                                                         /* Anonymous */
1351                                                         x[0] = 'a';
1352                                                         break;
1353                                                 case 'm':
1354                                                         /* Moderated */
1355                                                         x[0] = 'm';
1356                                                         break;
1357                                                 case 'n':
1358                                                         /* kein Schreiben in den Channel von aussen */
1359                                                         x[0] = 'n';
1360                                                         break;
1361                                                 case 'p':
1362                                                         /* Private */
1363                                                         x[0] = 'p';
1364                                                         break;
1365                                                 case 'q':
1366                                                         /* Quite */
1367                                                         x[0] = 'q';
1368                                                         break;
1369                                                 case 's':
1370                                                         /* Secret */
1371                                                         x[0] = 's';
1372                                                         break;
1373                                                 case 't':
1374                                                         /* Topic Lock */
1375                                                         x[0] = 't';
1376                                                         break;
1377                                                 default:
1378                                                         Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
1379                                                         ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1380                                                         x[0] = '\0';
1381                                         }
1382                                 }
1383                         }
1384                 }
1385                 if( ! ok ) break;
1386                 
1387                 mode_ptr++;
1388                 if( ! x[0] ) continue;
1389
1390                 /* Okay, gueltigen Mode gefunden */
1391                 if( cl )
1392                 {
1393                         /* Es geht um User-Modes */
1394                         if( set )
1395                         {
1396                                 /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
1397                                 if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
1398                         }
1399                         else
1400                         {
1401                                 /* Modes geloescht. Wenn der Client ihn hatte: merken */
1402                                 if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
1403                         }
1404                 }
1405                 if( chan )
1406                 {
1407                         /* Es geht um Channel-Modes oder Channel-User-Modes */
1408                         if( chan_cl )
1409                         {
1410                                 /* Channel-User-Modes */
1411                                 if( set )
1412                                 {
1413                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1414                                         if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x );
1415                                 }
1416                                 else
1417                                 {
1418                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1419                                         if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x );
1420                                 }
1421                         }
1422                         else
1423                         {
1424                                 /* Channel-Mode */
1425                                 if( set )
1426                                 {
1427                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1428                                         if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x );
1429                                 }
1430                                 else
1431                                 {
1432                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1433                                         if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x );
1434                                 }
1435                         }
1436                 }
1437         }
1438
1439         /* Wurden Modes geaendert? */
1440         if( the_modes[1] )
1441         {
1442                 if( cl )
1443                 {
1444                         /* Client-Mode */
1445                         if( Client_Type( Client ) == CLIENT_SERVER )
1446                         {
1447                                 /* Modes an andere Server forwarden */
1448                                 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
1449                         }
1450                         else
1451                         {
1452                                 /* Bestaetigung an Client schicken & andere Server informieren */
1453                                 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes );
1454                                 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
1455                         }
1456                         Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
1457                 }
1458                 if( chan )
1459                 {
1460                         /* Channel-Modes oder Channel-User-Mode */
1461                         if( chan_cl )
1462                         {
1463                                 /* Channel-User-Mode */
1464                                 if( Client_Type( Client ) == CLIENT_SERVER )
1465                                 {
1466                                         /* Modes an andere Server und Channel-User forwarden */
1467                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1468                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1469                                 }
1470                                 else
1471                                 {
1472                                         /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
1473                                         ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1474                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1475                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1476                                 }
1477                                 Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl ));
1478                         }
1479                         else
1480                         {
1481                                 /* Channel-Mode */
1482                                 if( Client_Type( Client ) == CLIENT_SERVER )
1483                                 {
1484                                         /* Modes an andere Server und Channel-User forwarden */
1485                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
1486                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
1487                                 }
1488                                 else
1489                                 {
1490                                         /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
1491                                         ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes );
1492                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
1493                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
1494                                 }
1495                                 Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
1496                         }
1497                 }
1498         }
1499
1500         return ok;
1501 } /* IRC_MODE */
1502
1503
1504 GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
1505 {
1506         INT i;
1507         
1508         assert( Client != NULL );
1509         assert( Req != NULL );
1510
1511         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1512         
1513         /* Falsche Anzahl Parameter? */
1514         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1515
1516         /* Operator suchen */
1517         for( i = 0; i < Conf_Oper_Count; i++)
1518         {
1519                 if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
1520         }
1521         if( i >= Conf_Oper_Count )
1522         {
1523                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Name \"%s\" not configured!", Client_Mask( Client ), Req->argv[0] );
1524                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1525         }
1526
1527         /* Stimmt das Passwort? */
1528         if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
1529         {
1530                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Bad password for \"%s\"!", Client_Mask( Client ), Conf_Oper[i].name );
1531                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1532         }
1533         
1534         if( ! Client_HasMode( Client, 'o' ))
1535         {
1536                 /* noch kein o-Mode gesetzt */
1537                 Client_ModeAdd( Client, 'o' );
1538                 if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
1539                 IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
1540         }
1541
1542         if( ! Client_OperByMe( Client )) Log( LOG_NOTICE, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
1543
1544         Client_SetOperByMe( Client, TRUE );
1545         return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
1546 } /* IRC_OPER */
1547
1548
1549 GLOBAL BOOLEAN IRC_DIE( CLIENT *Client, REQUEST *Req )
1550 {
1551         assert( Client != NULL );
1552         assert( Req != NULL );
1553
1554         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1555
1556         /* Falsche Anzahl Parameter? */
1557         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1558
1559         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1560
1561         Log( LOG_NOTICE, "Got DIE command from \"%s\", going down!", Client_Mask( Client ));
1562         NGIRCd_Quit = TRUE;
1563         return CONNECTED;
1564 } /* IRC_DIE */
1565
1566
1567 GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req )
1568 {
1569         assert( Client != NULL );
1570         assert( Req != NULL );
1571
1572         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1573
1574         /* Falsche Anzahl Parameter? */
1575         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1576
1577         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1578
1579         Log( LOG_NOTICE, "Got RESTART command from \"%s\", going down!", Client_Mask( Client ));
1580         NGIRCd_Restart = TRUE;
1581         return CONNECTED;
1582 } /* IRC_RESTART */
1583
1584
1585 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
1586 {
1587         CHAR rpl[COMMAND_LEN];
1588         CLIENT *c;
1589         
1590         assert( Client != NULL );
1591         assert( Req != NULL );
1592
1593         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1594
1595         /* Falsche Anzahl Parameter? */
1596         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1597
1598         /* Noch alle User ausgeben, die in keinem Channel sind */
1599         rpl[0] = '\0';
1600         c = Client_First( );
1601         while( c )
1602         {
1603                 if( Client_Type( c ) == CLIENT_USER )
1604                 {
1605                         /* Okay, das ist ein User */
1606                         strcat( rpl, Client_ID( c ));
1607                         strcat( rpl, " " );
1608                 }
1609
1610                 /* Antwort zu lang? Splitten. */
1611                 if( strlen( rpl ) > 480 )
1612                 {
1613                         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1614                         if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1615                         rpl[0] = '\0';
1616                 }
1617                 
1618                 c = Client_Next( c );
1619         }
1620         if( rpl[0] )
1621         {
1622                 /* es wurden User gefunden */
1623                 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1624                 if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1625         }
1626         return IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), "*" );
1627 } /* IRC_NAMES */
1628
1629
1630 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
1631 {
1632         CHAR rpl[COMMAND_LEN];
1633         CLIENT *c;
1634         CHAR *ptr;
1635         INT i;
1636         
1637         assert( Client != NULL );
1638         assert( Req != NULL );
1639
1640         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1641
1642         /* Falsche Anzahl Parameter? */
1643         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1644
1645         strcpy( rpl, RPL_ISON_MSG );
1646         for( i = 0; i < Req->argc; i++ )
1647         {
1648                 ptr = strtok( Req->argv[i], " " );
1649                 while( ptr )
1650                 {
1651                         ngt_TrimStr( ptr );
1652                         c = Client_GetFromID( ptr );
1653                         if( c && ( Client_Type( c ) == CLIENT_USER ))
1654                         {
1655                                 /* Dieser Nick ist "online" */
1656                                 strcat( rpl, ptr );
1657                                 strcat( rpl, " " );
1658                         }
1659                         ptr = strtok( NULL, " " );
1660                 }
1661         }
1662         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1663
1664         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1665 } /* IRC_ISON */
1666
1667
1668 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
1669 {
1670         CLIENT *from, *target, *c;
1671         CHAR str[LINE_LEN + 1], *ptr = NULL;
1672         CL2CHAN *cl2chan;
1673         CHANNEL *chan;
1674         
1675         assert( Client != NULL );
1676         assert( Req != NULL );
1677
1678         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1679
1680         /* Falsche Anzahl Parameter? */
1681         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1682
1683         /* Client suchen */
1684         c = Client_GetFromID( Req->argv[Req->argc - 1] );
1685         if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
1686
1687         /* Empfaenger des WHOIS suchen */
1688         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1689         else from = Client;
1690         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1691         
1692         /* Forwarden an anderen Server? */
1693         if( Req->argc > 1 )
1694         {
1695                 /* angegebenen Ziel-Server suchen */
1696                 target = Client_GetFromID( Req->argv[1] );
1697                 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
1698                 ptr = Req->argv[1];
1699         }
1700 #ifndef STRICT_RFC
1701         else if( Client_Conn( c ) == NONE )
1702         {
1703                 /* Client ist nicht von uns. Ziel-Server suchen */
1704                 target = c;
1705                 ptr = Req->argv[0];
1706         }
1707 #endif
1708         else target = NULL;
1709         
1710         if( target && ( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
1711         
1712         /* Nick, User und Name */
1713         if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
1714
1715         /* Server */
1716         if( ! IRC_WriteStrClient( from, RPL_WHOISSERVER_MSG, Client_ID( from ), Client_ID( c ), Client_ID( Client_Introducer( c )), Client_Info( Client_Introducer( c )))) return DISCONNECTED;
1717
1718         /* Channels */
1719         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
1720         cl2chan = Channel_FirstChannelOf( c );
1721         while( cl2chan )
1722         {
1723                 chan = Channel_GetChannel( cl2chan );
1724                 assert( chan != NULL );
1725                 
1726                 /* Channel-Name anhaengen */
1727                 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
1728                 if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
1729                 if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
1730                 strcat( str, Channel_Name( chan ));
1731
1732                 if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
1733                 {
1734                         /* Zeile wird zu lang: senden! */
1735                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
1736                         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
1737                 }
1738
1739                 /* naechstes Mitglied suchen */
1740                 cl2chan = Channel_NextChannelOf( c, cl2chan );
1741         }
1742         if( str[strlen( str ) - 1] != ':')
1743         {
1744                 /* Es sind noch Daten da, die gesendet werden muessen */
1745                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
1746         }
1747         
1748         /* IRC-Operator? */
1749         if( Client_HasMode( c, 'o' ))
1750         {
1751                 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
1752         }
1753
1754         /* Idle (nur lokale Clients) */
1755         if( Client_Conn( c ) > NONE )
1756         {
1757                 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
1758         }
1759
1760         /* End of Whois */
1761         return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
1762 } /* IRC_WHOIS */
1763
1764
1765 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
1766 {
1767         CHAR rpl[COMMAND_LEN];
1768         CLIENT *c;
1769         INT max, i;
1770
1771         assert( Client != NULL );
1772         assert( Req != NULL );
1773
1774         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1775
1776         /* Falsche Anzahl Parameter? */
1777         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1778
1779         if( Req->argc > 5 ) max = 5;
1780         else max = Req->argc;
1781         
1782         strcpy( rpl, RPL_USERHOST_MSG );
1783         for( i = 0; i < max; i++ )
1784         {
1785                 c = Client_GetFromID( Req->argv[i] );
1786                 if( c && ( Client_Type( c ) == CLIENT_USER ))
1787                 {
1788                         /* Dieser Nick ist "online" */
1789                         strcat( rpl, Client_ID( c ));
1790                         if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
1791                         strcat( rpl, "=" );
1792                         if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
1793                         else strcat( rpl, "+" );
1794                         strcat( rpl, Client_User( c ));
1795                         strcat( rpl, "@" );
1796                         strcat( rpl, Client_Hostname( c ));
1797                         strcat( rpl, " " );
1798                 }
1799         }
1800         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1801
1802         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1803 } /* IRC_USERHOST */
1804
1805
1806 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
1807 {
1808         assert( Client != NULL );
1809         assert( Req != NULL );
1810
1811         if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
1812         else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
1813
1814         return CONNECTED;
1815 } /* IRC_ERROR */
1816
1817
1818 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
1819 {
1820         CLIENT *target, *from;
1821         
1822         assert( Client != NULL );
1823         assert( Req != NULL );
1824
1825         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1826
1827         /* Falsche Anzahl Parameter? */
1828         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1829
1830         /* Absender ermitteln */
1831         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1832         else from = Client;
1833         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1834
1835         /* An anderen Server forwarden? */
1836         if( Req->argc == 2 )
1837         {
1838                 target = Client_GetFromID( Req->argv[1] );
1839                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1840                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
1841         }
1842
1843         /* Wer ist der Absender? */
1844         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1845         else target = Client;
1846         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1847         
1848         Send_LUSERS( target );
1849
1850         return CONNECTED;
1851 } /* IRC_LUSERS */
1852
1853
1854 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
1855 {
1856         CLIENT *target, *from, *c;
1857         CHAR *mask;
1858         
1859         assert( Client != NULL );
1860         assert( Req != NULL );
1861
1862         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1863
1864         /* Falsche Anzahl Parameter? */
1865         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1866
1867         /* Server-Mask ermitteln */
1868         if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
1869         else mask = "*";
1870
1871         /* Absender ermitteln */
1872         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1873         else from = Client;
1874         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1875         
1876         /* An anderen Server forwarden? */
1877         if( Req->argc == 2 )
1878         {
1879                 target = Client_GetFromID( Req->argv[0] );
1880                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
1881                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
1882         }
1883
1884         /* Wer ist der Absender? */
1885         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1886         else target = Client;
1887         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1888         
1889         c = Client_First( );
1890         while( c )
1891         {
1892                 if( Client_Type( c ) == CLIENT_SERVER )
1893                 {
1894                         if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
1895                 }
1896                 c = Client_Next( c );
1897         }
1898         
1899         return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
1900 } /* IRC_LINKS */
1901
1902
1903 GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
1904 {
1905         CHAR *channame, *flags, modes[8];
1906         BOOLEAN is_new_chan;
1907         CLIENT *target;
1908         CHANNEL *chan;
1909         
1910         assert( Client != NULL );
1911         assert( Req != NULL );
1912
1913         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1914
1915         /* Falsche Anzahl Parameter? */
1916         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1917
1918         /* Wer ist der Absender? */
1919         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1920         else target = Client;
1921         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1922         
1923         /* Channel-Namen durchgehen */
1924         channame = strtok( Req->argv[0], "," );
1925         while( channame )
1926         {
1927                 /* wird der Channel neu angelegt? */
1928                 flags = NULL;
1929
1930                 if( Channel_Search( channame )) is_new_chan = FALSE;
1931                 else is_new_chan = TRUE;
1932
1933                 /* Hat ein Server Channel-User-Modes uebergeben? */
1934                 if( Client_Type( Client ) == CLIENT_SERVER )
1935                 {
1936                         /* Channel-Flags extrahieren */
1937                         flags = strchr( channame, 0x7 );
1938                         if( flags ) *flags++ = '\0';
1939                 }
1940
1941                 /* neuer Channel udn lokaler Client? */
1942                 if( is_new_chan && ( Client_Type( Client ) == CLIENT_USER ))
1943                 {
1944                         /* Dann soll der Client Channel-Operator werden! */
1945                         flags = "o";
1946                 }
1947
1948                 /* Channel joinen (und ggf. anlegen) */
1949                 if( ! Channel_Join( target, channame ))
1950                 {
1951                         /* naechsten Namen ermitteln */
1952                         channame = strtok( NULL, "," );
1953                         continue;
1954                 }
1955                 chan = Channel_Search( channame );
1956                 assert( chan != NULL );
1957
1958                 /* Modes setzen (wenn vorhanden) */
1959                 while( flags && *flags )
1960                 {
1961                         Channel_UserModeAdd( chan, target, *flags );
1962                         flags++;
1963                 }
1964
1965                 /* Muessen Modes an andere Server gemeldet werden? */
1966                 strcpy( &modes[1], Channel_UserModes( chan, target ));
1967                 if( modes[1] ) modes[0] = 0x7;
1968                 else modes[0] = '\0';
1969
1970                 /* An andere Server weiterleiten */
1971                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
1972
1973                 /* im Channel bekannt machen */
1974                 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
1975                 if( modes[1] )
1976                 {
1977                         /* Modes im Channel bekannt machen */
1978                         IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
1979                 }
1980
1981                 if( Client_Type( Client ) == CLIENT_USER )
1982                 {
1983                         /* an Client bestaetigen */
1984                         IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
1985                         /* Topic an Client schicken */
1986                         IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, "What a wonderful channel!" );
1987                         /* Mitglieder an Client Melden */
1988                         Send_NAMES( Client, chan );
1989                 }
1990                 
1991                 /* naechsten Namen ermitteln */
1992                 channame = strtok( NULL, "," );
1993         }
1994         return CONNECTED;
1995 } /* IRC_JOIN */
1996
1997
1998 GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
1999 {
2000         CLIENT *target;
2001         CHAR *chan;
2002
2003         assert( Client != NULL );
2004         assert( Req != NULL );
2005
2006         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
2007
2008         /* Falsche Anzahl Parameter? */
2009         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
2010
2011         /* Wer ist der Absender? */
2012         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
2013         else target = Client;
2014         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
2015
2016         /* Channel-Namen durchgehen */
2017         chan = strtok( Req->argv[0], "," );
2018         while( chan )
2019         {
2020                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
2021                 {
2022                         /* naechsten Namen ermitteln */
2023                         chan = strtok( NULL, "," );
2024                         continue;
2025                 }
2026
2027                 /* naechsten Namen ermitteln */
2028                 chan = strtok( NULL, "," );
2029         }
2030         return CONNECTED;
2031 } /* IRC_PART */
2032
2033
2034 LOCAL BOOLEAN Hello_User( CLIENT *Client )
2035 {
2036         assert( Client != NULL );
2037
2038         /* Passwort ueberpruefen */
2039         if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
2040         {
2041                 /* Falsches Passwort */
2042                 Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
2043                 Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
2044                 return DISCONNECTED;
2045         }
2046
2047         Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
2048
2049         /* Andere Server informieren */
2050         IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client ));
2051
2052         if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return FALSE;
2053         if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
2054         if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE;
2055         if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
2056
2057         Client_SetType( Client, CLIENT_USER );
2058
2059         if( ! Send_LUSERS( Client )) return DISCONNECTED;
2060         if( ! Show_MOTD( Client )) return DISCONNECTED;
2061         
2062         return CONNECTED;
2063 } /* Hello_User */
2064
2065
2066 LOCAL BOOLEAN Show_MOTD( CLIENT *Client )
2067 {
2068         BOOLEAN ok;
2069         CHAR line[127];
2070         FILE *fd;
2071         
2072         assert( Client != NULL );
2073
2074         fd = fopen( Conf_MotdFile, "r" );
2075         if( ! fd )
2076         {
2077                 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
2078                 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
2079         }
2080         
2081         IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
2082         while( TRUE )
2083         {
2084                 if( ! fgets( line, 126, fd )) break;
2085                 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
2086                 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
2087                 {
2088                         fclose( fd );
2089                         return FALSE;
2090                 }
2091         }
2092         ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
2093
2094         fclose( fd );
2095         
2096         return ok;
2097 } /* Show_MOTD */
2098
2099
2100 LOCAL VOID Kill_Nick( CHAR *Nick )
2101 {
2102         Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected!", Nick );
2103         /* FIXME */
2104         Log( LOG_ALERT, "[Kill_Nick() not implemented - OOOPS!]" );
2105 } /* Kill_Nick */
2106
2107
2108 LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
2109 {
2110         CHAR str[LINE_LEN + 1];
2111         CL2CHAN *cl2chan;
2112         CLIENT *cl;
2113         
2114         assert( Client != NULL );
2115         assert( Chan != NULL );
2116
2117         /* Alle Mitglieder suchen */
2118         sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
2119         cl2chan = Channel_FirstMember( Chan );
2120         while( cl2chan )
2121         {
2122                 cl = Channel_GetClient( cl2chan );
2123
2124                 /* Nick anhaengen */
2125                 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
2126                 if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
2127                 if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
2128                 strcat( str, Client_ID( cl ));
2129
2130                 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
2131                 {
2132                         /* Zeile wird zu lang: senden! */
2133                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
2134                         sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
2135                 }
2136
2137                 /* naechstes Mitglied suchen */
2138                 cl2chan = Channel_NextMember( Chan, cl2chan );
2139         }
2140         if( str[strlen( str ) - 1] != ':')
2141         {
2142                 /* Es sind noch Daten da, die gesendet werden muessen */
2143                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
2144         }
2145
2146         /* Ende anzeigen */
2147         IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( Chan ));
2148         
2149         return CONNECTED;
2150 } /* Send_NAMES */
2151
2152
2153 LOCAL BOOLEAN Send_LUSERS( CLIENT *Client )
2154 {
2155         INT cnt;
2156
2157         assert( Client != NULL );
2158
2159         /* Users, Services und Serevr im Netz */
2160         if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
2161
2162         /* IRC-Operatoren im Netz */
2163         cnt = Client_OperCount( );
2164         if( cnt > 0 )
2165         {
2166                 if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
2167         }
2168
2169         /* Unbekannt Verbindungen */
2170         cnt = Client_UnknownCount( );
2171         if( cnt > 0 )
2172         {
2173                 if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
2174         }
2175
2176         /* Channels im Netz */
2177         if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
2178
2179         /* Channels im Netz */
2180         if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
2181         
2182         return CONNECTED;
2183 } /* Send_LUSERS */
2184
2185
2186 /* -eof- */