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