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