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