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