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