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