]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht.
[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.44 2002/01/28 00:55:08 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  *
16  * $Log: irc.c,v $
17  * Revision 1.44  2002/01/28 00:55:08  alex
18  * - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht.
19  *
20  * Revision 1.43  2002/01/27 21:56:39  alex
21  * - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
22  * - einige kleinere Fixes bezueglich Channels ...
23  *
24  * Revision 1.42  2002/01/27 18:28:01  alex
25  * - bei NICK wurde das falsche Prefix an andere Server weitergegeben.
26  *
27  * Revision 1.41  2002/01/27 17:15:49  alex
28  * - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
29  *   IRC_WriteStrChannelPrefix(),
30  * - neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
31  *
32  * Revision 1.40  2002/01/26 18:43:11  alex
33  * - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
34  *   die IRC_Write_xxx_Related() sind dafuer entfallen.
35  * - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
36  *
37  * Revision 1.39  2002/01/21 00:05:11  alex
38  * - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
39  *   IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
40  * - diverse Aenderungen im Zusammenhang mit Channels.
41  *
42  * Revision 1.38  2002/01/18 15:31:32  alex
43  * - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen.
44  *
45  * Revision 1.37  2002/01/16 22:10:18  alex
46  * - IRC_LUSERS() implementiert.
47  *
48  * Revision 1.36  2002/01/11 23:50:55  alex
49  * - LINKS implementiert, LUSERS begonnen.
50  *
51  * Revision 1.35  2002/01/09 21:30:45  alex
52  * - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet.
53  *
54  * Revision 1.34  2002/01/09 01:09:58  alex
55  * - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
56  * - andere Server werden nun ueber bisherige Server und User informiert.
57  *
58  * Revision 1.33  2002/01/07 23:42:12  alex
59  * - Es werden fuer alle Server eigene Token generiert,
60  * - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
61  * - ebenso NICK-Befehle, die "fremde" User einfuehren.
62  *
63  * Revision 1.32  2002/01/07 16:02:36  alex
64  * - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
65  * - Im Debug-Mode werden nun auch PING's protokolliert.
66  *
67  * Revision 1.31  2002/01/07 15:39:46  alex
68  * - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
69  * - MODE und NICK melden nun die Aenderungen an andere Server.
70  *
71  * Revision 1.30  2002/01/06 15:21:29  alex
72  * - Loglevel und Meldungen nochmals ueberarbeitet.
73  * - QUIT und SQUIT forwarden nun den Grund der Trennung,
74  * - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
75  *
76  * Revision 1.29  2002/01/05 23:24:54  alex
77  * - WHOIS erweitert: Anfragen koennen an andere Server weitergeleitet werden.
78  * - Vorbereitungen fuer Ident-Abfragen bei neuen Client-Strukturen.
79  *
80  * Revision 1.28  2002/01/05 20:08:02  alex
81  * - Div. Aenderungen fuer die Server-Links (u.a. WHOIS, QUIT, NICK angepasst).
82  * - Neue Funktionen IRC_WriteStrServer() und IRC_WriteStrServerPrefix().
83  *
84  * Revision 1.27  2002/01/05 19:15:03  alex
85  * - Fehlerpruefung bei select() in der "Hauptschleife" korrigiert.
86  *
87  * Revision 1.26  2002/01/05 16:51:18  alex
88  * - das Passwort von Servern wird nun ueberprueft (PASS- und SERVER-Befehl).
89  *
90  * Revision 1.25  2002/01/05 00:48:33  alex
91  * - bei SQUIT wurde immer die Verbindung getrennt, auch bei Remote-Servern.
92  *
93  * Revision 1.24  2002/01/04 17:58:44  alex
94  * - IRC_WriteStrXXX()-Funktionen eingefuehrt, groessere Anpassungen daran.
95  * - neuer Befehl SQUIT, QUIT an Server-Links angepasst.
96  *
97  * Revision 1.23  2002/01/04 01:36:40  alex
98  * - Loglevel ein wenig angepasst.
99  *
100  * Revision 1.22  2002/01/04 01:21:47  alex
101  * - Client-Strukruren werden nur noch ueber Funktionen angesprochen.
102  * - Weitere Anpassungen und Erweiterungen der Server-Links.
103  *
104  * Revision 1.21  2002/01/03 02:26:51  alex
105  * - neue Befehle SERVER und NJOIN begonnen,
106  * - begonnen, diverse IRC-Befehle an Server-Links anzupassen.
107  *
108  * Revision 1.20  2002/01/02 12:46:41  alex
109  * - die Gross- und Kleinschreibung des Nicks kann mit NICK nun geaendert werden.
110  *
111  * Revision 1.19  2002/01/02 02:51:39  alex
112  * - Copyright-Texte angepasst.
113  * - neuer Befehl "ERROR".
114  *
115  * Revision 1.17  2001/12/31 15:33:13  alex
116  * - neuer Befehl NAMES, kleinere Bugfixes.
117  * - Bug bei PING behoben: war zu restriktiv implementiert :-)
118  *
119  * Revision 1.16  2001/12/31 02:18:51  alex
120  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
121  * - neuen Header "defines.h" mit (fast) allen Konstanten.
122  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
123  *
124  * Revision 1.15  2001/12/30 19:26:11  alex
125  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
126  *
127  * Revision 1.14  2001/12/30 11:42:00  alex
128  * - der Server meldet nun eine ordentliche "Start-Zeit".
129  *
130  * Revision 1.13  2001/12/29 03:10:06  alex
131  * - Neue Funktion IRC_MODE() implementiert, div. Aenderungen.
132  * - neue configure-Optione "--enable-strict-rfc".
133  *
134  * Revision 1.12  2001/12/27 19:17:26  alex
135  * - neue Befehle PRIVMSG, NOTICE, PING.
136  *
137  * Revision 1.11  2001/12/27 16:55:41  alex
138  * - neu: IRC_WriteStrRelated(), Aenderungen auch in IRC_WriteStrClient().
139  *
140  * Revision 1.10  2001/12/26 22:48:53  alex
141  * - MOTD-Datei ist nun konfigurierbar und wird gelesen.
142  *
143  * Revision 1.9  2001/12/26 14:45:37  alex
144  * - "Code Cleanups".
145  *
146  * Revision 1.8  2001/12/26 03:21:46  alex
147  * - PING/PONG-Befehle implementiert,
148  * - Meldungen ueberarbeitet: enthalten nun (fast) immer den Nick.
149  *
150  * Revision 1.7  2001/12/25 23:25:18  alex
151  * - und nochmal Aenderungen am Logging ;-)
152  *
153  * Revision 1.6  2001/12/25 23:13:33  alex
154  * - Debug-Meldungen angepasst.
155  *
156  * Revision 1.5  2001/12/25 22:02:42  alex
157  * - neuer IRC-Befehl "/QUIT". Verbessertes Logging & Debug-Ausgaben.
158  *
159  * Revision 1.4  2001/12/25 19:19:30  alex
160  * - bessere Fehler-Abfragen, diverse Bugfixes.
161  * - Nicks werden nur einmal vergeben :-)
162  * - /MOTD wird unterstuetzt.
163  *
164  * Revision 1.3  2001/12/24 01:34:06  alex
165  * - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert (wg. BitchX)
166  * - MOTD-Ausgabe begonnen zu implementieren.
167  *
168  * Revision 1.2  2001/12/23 21:57:16  alex
169  * - erste IRC-Befehle zu implementieren begonnen.
170  *
171  * Revision 1.1  2001/12/14 08:13:43  alex
172  * - neues Modul begonnen :-)
173  */
174
175
176 #include <portab.h>
177 #include "global.h"
178
179 #include <imp.h>
180 #include <assert.h>
181 #include <errno.h>
182 #include <stdarg.h>
183 #include <stdio.h>
184 #include <stdlib.h>
185 #include <string.h>
186
187 #include "ngircd.h"
188 #include "channel.h"
189 #include "client.h"
190 #include "conf.h"
191 #include "conn.h"
192 #include "log.h"
193 #include "messages.h"
194 #include "parse.h"
195 #include "tool.h"
196
197 #include <exp.h>
198 #include "irc.h"
199
200
201 #define CONNECTED TRUE
202 #define DISCONNECTED FALSE
203
204
205 LOCAL BOOLEAN Hello_User( CLIENT *Client );
206 LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
207
208 LOCAL VOID Kill_Nick( CHAR *Nick );
209
210
211 GLOBAL VOID IRC_Init( VOID )
212 {
213 } /* IRC_Init */
214
215
216 GLOBAL VOID IRC_Exit( VOID )
217 {
218 } /* IRC_Exit */
219
220
221 GLOBAL BOOLEAN IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
222 {
223         CHAR buffer[1000];
224         BOOLEAN ok = CONNECTED;
225         va_list ap;
226
227         assert( Client != NULL );
228         assert( Format != NULL );
229
230         va_start( ap, Format );
231         vsnprintf( buffer, 1000, Format, ap );
232         va_end( ap );
233
234         /* an den Client selber */
235         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
236
237         return ok;
238 } /* IRC_WriteStrClient */
239
240
241 GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
242 {
243         /* Text an Clients, lokal bzw. remote, senden. */
244
245         CHAR buffer[1000];
246         va_list ap;
247
248         assert( Client != NULL );
249         assert( Format != NULL );
250         assert( Prefix != NULL );
251
252         va_start( ap, Format );
253         vsnprintf( buffer, 1000, Format, ap );
254         va_end( ap );
255
256         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Client_ID( Prefix ), buffer );
257 } /* IRC_WriteStrClientPrefix */
258
259
260 GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
261 {
262         CHAR buffer[1000];
263         va_list ap;
264
265         assert( Client != NULL );
266         assert( Format != NULL );
267
268         va_start( ap, Format );
269         vsnprintf( buffer, 1000, Format, ap );
270         va_end( ap );
271
272         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
273 } /* IRC_WriteStrChannel */
274
275
276 GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
277 {
278         CHAR buffer[1000];
279         BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED, i;
280         CL2CHAN *cl2chan;
281         CLIENT *c;
282         INT s;
283         va_list ap;
284
285         assert( Client != NULL );
286         assert( Chan != NULL );
287         assert( Prefix != NULL );
288         assert( Format != NULL );
289
290         va_start( ap, Format );
291         vsnprintf( buffer, 1000, Format, ap );
292         va_end( ap );
293
294         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
295
296         /* An alle Clients, die in den selben Channels sind.
297          * Dabei aber nur einmal je Remote-Server */
298         cl2chan = Channel_FirstMember( Chan );
299         while( cl2chan )
300         {
301                 c = Channel_GetClient( cl2chan );
302                 if( ! Remote )
303                 {
304                         if( Client_Conn( c ) <= NONE ) c = NULL;
305                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
306                 }
307                 if( c ) c = Client_NextHop( c );
308                         
309                 if( c && ( c != Client ))
310                 {
311                         /* Ok, anderer Client */
312                         s = Client_Conn( c );
313                         assert( s >= 0 );
314                         assert( s < MAX_CONNECTIONS );
315                         sock[s] = TRUE;
316                 }
317                 cl2chan = Channel_NextMember( Chan, cl2chan );
318         }
319
320         /* Senden ... */
321         for( i = 0; i < MAX_CONNECTIONS; i++ )
322         {
323                 if( sock[i] )
324                 {
325                         ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
326                         if( ! ok ) break;
327                 }
328         }
329         return ok;
330 } /* IRC_WriteStrChannelPrefix */
331
332
333 GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
334 {
335         CHAR buffer[1000];
336         va_list ap;
337
338         assert( Format != NULL );
339
340         va_start( ap, Format );
341         vsnprintf( buffer, 1000, Format, ap );
342         va_end( ap );
343
344         /* an den Client selber */
345         return IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
346 } /* IRC_WriteStrServers */
347
348
349 GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
350 {
351         CHAR buffer[1000];
352         CLIENT *c;
353         va_list ap;
354         
355         assert( Format != NULL );
356         assert( Prefix != NULL );
357
358         va_start( ap, Format );
359         vsnprintf( buffer, 1000, Format, ap );
360         va_end( ap );
361         
362         c = Client_First( );
363         while( c )
364         {
365                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
366                 {
367                         /* Ziel-Server gefunden */
368                         IRC_WriteStrClientPrefix( c, Prefix, buffer );
369                 }
370                 c = Client_Next( c );
371         }
372 } /* IRC_WriteStrServersPrefix */
373
374
375 GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
376 {
377         assert( Client != NULL );
378         assert( Req != NULL );
379
380         /* Fehler liefern, wenn kein lokaler Client */
381         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
382         
383         if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
384         {
385                 /* noch nicht registrierte unbekannte Verbindung */
386                 Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
387
388                 /* Passwort speichern */
389                 Client_SetPassword( Client, Req->argv[0] );
390
391                 Client_SetType( Client, CLIENT_GOTPASS );
392                 return CONNECTED;
393         }
394         else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
395         {
396                 /* noch nicht registrierte Server-Verbindung */
397                 Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
398
399                 /* Passwort speichern */
400                 Client_SetPassword( Client, Req->argv[0] );
401
402                 Client_SetType( Client, CLIENT_GOTPASSSERVER );
403                 return CONNECTED;
404         }
405         else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
406         {
407                 /* Falsche Anzahl Parameter? */
408                 return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
409         }
410         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
411 } /* IRC_PASS */
412
413
414 GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
415 {
416         CHAR str[LINE_LEN], *ptr;
417         BOOLEAN ok;
418         CLIENT *from, *c;
419         INT i;
420         
421         assert( Client != NULL );
422         assert( Req != NULL );
423
424         /* Fehler liefern, wenn kein lokaler Client */
425         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
426
427         if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
428         {
429                 /* Verbindung soll als Server-Server-Verbindung registriert werden */
430                 Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
431
432                 /* Falsche Anzahl Parameter? */
433                 if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
434
435                 /* Ist dieser Server bei uns konfiguriert? */
436                 for( i = 0; i < Conf_Server_Count; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
437                 if( i >= Conf_Server_Count )
438                 {
439                         /* Server ist nicht konfiguriert! */
440                         Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] );
441                         Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", TRUE );
442                         return DISCONNECTED;
443                 }
444                 if( strcmp( Client_Password( Client ), Conf_Server[i].pwd ) != 0 )
445                 {
446                         /* Falsches Passwort */
447                         Log( LOG_ERR, "Connection %d: Bad password for server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
448                         Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
449                         return DISCONNECTED;
450                 }
451                 
452                 /* Ist ein Server mit dieser ID bereits registriert? */
453                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
454
455                 /* Server-Strukturen fuellen ;-) */
456                 Client_SetID( Client, Req->argv[0] );
457                 Client_SetHops( Client, 1 );
458                 Client_SetInfo( Client, Req->argv[Req->argc - 1] );
459                 
460                 /* Meldet sich der Server bei uns an? */
461                 if( Req->argc == 2 )
462                 {
463                         /* Unseren SERVER- und PASS-Befehl senden */
464                         ok = TRUE;
465                         if( ! IRC_WriteStrClient( Client, "PASS %s "PASSSERVERADD, Conf_Server[i].pwd )) ok = FALSE;
466                         else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo );
467                         if( ! ok )
468                         {
469                                 Conn_Close( Client_Conn( Client ), "Unexpected server behavior!", NULL, FALSE );
470                                 return DISCONNECTED;
471                         }
472                         Client_SetIntroducer( Client, Client );
473                         Client_SetToken( Client, 1 );
474                 }
475                 else  Client_SetToken( Client, atoi( Req->argv[1] ));
476
477                 Log( LOG_NOTICE, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client ));
478
479                 Client_SetType( Client, CLIENT_SERVER );
480
481                 /* Alle bisherigen Server dem neuen Server bekannt machen,
482                  * die bisherigen Server ueber den neuen informierenn */
483                 c = Client_First( );
484                 while( c )
485                 {
486                         if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )))
487                         {
488                                 if( Client_Conn( c ) > NONE )
489                                 {
490                                         /* Dem gefundenen Server gleich den neuen
491                                          * Server bekannt machen */
492                                         if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
493                                 }
494                                 
495                                 /* Den neuen Server ueber den alten informieren */
496                                 if( ! IRC_WriteStrClientPrefix( Client, Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
497                         }
498                         c = Client_Next( c );
499                 }
500
501                 /* alle User dem neuen Server bekannt machen */
502                 c = Client_First( );
503                 while( c )
504                 {
505                         if( Client_Type( c ) == CLIENT_USER )
506                         {
507                                 /* User an neuen Server melden */
508                                 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;
509                         }
510                         c = Client_Next( c );
511                 }
512                 
513                 return CONNECTED;
514         }
515         else if( Client_Type( Client ) == CLIENT_SERVER )
516         {
517                 /* Neuer Server wird im Netz angekuendigt */
518
519                 /* Falsche Anzahl Parameter? */
520                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
521
522                 /* Ist ein Server mit dieser ID bereits registriert? */
523                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
524
525                 /* Ueberfluessige Hostnamen aus Info-Text entfernen */
526                 ptr = strchr( Req->argv[3] + 2, '[' );
527                 if( ! ptr ) ptr = Req->argv[3];
528
529                 from = Client_GetFromID( Req->prefix );
530                 if( ! from )
531                 {
532                         /* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
533                         Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
534                         Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", TRUE );
535                         return DISCONNECTED;
536                 }
537
538                 /* Neue Client-Struktur anlegen */
539                 c = Client_NewRemoteServer( Client, Req->argv[0], atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
540                 if( ! c )
541                 {
542                         /* Neue Client-Struktur konnte nicht angelegt werden */
543                         Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
544                         Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", TRUE );
545                         return DISCONNECTED;
546                 }
547
548                 /* Log-Meldung zusammenbauen und ausgeben */
549                 if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Client_ID( from ));
550                 else strcpy( str, "" );
551                 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": "" );
552
553                 /* Andere Server informieren */
554                 IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
555
556                 return CONNECTED;
557         }
558         else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
559 } /* IRC_SERVER */
560
561
562 GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
563 {
564         CHAR *chan, *ptr;
565         CLIENT *c;
566         
567         assert( Client != NULL );
568         assert( Req != NULL );
569
570         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTEREDSERVER_MSG, Client_ID( Client ));
571
572         /* Falsche Anzahl Parameter? */
573         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
574
575         chan = Req->argv[0];
576         ptr = strtok( Req->argv[1], "," );
577         while( ptr )
578         {
579                 /* Prefixe abschneiden */
580                 while(( *ptr == '@' ) || ( *ptr == '+' )) ptr++;
581
582                 c = Client_GetFromID( ptr );
583                 if( c ) Channel_Join( c, chan );
584                 else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, chan );
585                 
586                 /* naechsten Nick suchen */
587                 ptr = strtok( NULL, "," );
588         }
589         
590         return CONNECTED;
591 } /* IRC_NJOIN */
592
593
594 GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
595 {
596         CLIENT *intr_c, *target, *c;
597         CHAR *modes;
598
599         assert( Client != NULL );
600         assert( Req != NULL );
601
602         /* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
603 #ifndef STRICT_RFC
604         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 ))
605 #else
606         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 ))
607 #endif
608         {
609                 /* User-Registrierung bzw. Nick-Aenderung */
610
611                 /* Falsche Anzahl Parameter? */
612                 if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
613
614                 /* "Ziel-Client" ermitteln */
615                 if( Client_Type( Client ) == CLIENT_SERVER )
616                 {
617                         target = Client_GetFromID( Req->prefix );
618                         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
619                 }
620                 else
621                 {
622                         /* Ist der Client "restricted"? */
623                         if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
624                         target = Client;
625                 }
626
627                 /* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
628                  * wir nichts. So macht es das Original und mind. Snak hat probleme,
629                  * wenn wir es nicht so machen. Ob es so okay ist? Hm ... */
630 #ifndef STRICT_RFC
631                 if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
632 #endif
633                 
634                 /* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
635                  * will nur die Gross- und Kleinschreibung aendern. Das darf
636                  * er natuerlich machen :-) */
637                 if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
638                 {
639                         if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
640                 }
641
642                 if( Client_Type( Client ) == CLIENT_USER )
643                 {
644                         /* Nick-Aenderung: allen mitteilen! */
645                         Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
646                         IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
647                         IRC_WriteStrServersPrefix( NULL, Client, "NICK :%s", Req->argv[0] );
648                 }
649                 else if( Client_Type( Client ) == CLIENT_SERVER )
650                 {
651                         /* Nick-Aenderung: allen mitteilen! */
652                         Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
653                         IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
654                 }
655         
656                 /* Client-Nick registrieren */
657                 Client_SetID( target, Req->argv[0] );
658
659                 if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
660                 {
661                         /* Neuer Client */
662                         Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
663                         if( Client_Type( Client ) == CLIENT_GOTUSER ) return Hello_User( Client );
664                         else Client_SetType( Client, CLIENT_GOTNICK );
665                 }
666                 return CONNECTED;
667         }
668         else if( Client_Type( Client ) == CLIENT_SERVER )
669         {
670                 /* Server fuehrt neuen Client ein */
671
672                 /* Falsche Anzahl Parameter? */
673                 if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
674
675                 /* Nick ueberpruefen */
676                 c = Client_GetFromID( Req->argv[0] );
677                 if( c )
678                 {
679                         /* Der neue Nick ist auf diesem Server bereits registriert:
680                          * sowohl der neue, als auch der alte Client muessen nun
681                          * disconnectiert werden. */
682                         Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
683                         Kill_Nick( Req->argv[0] );
684                         return CONNECTED;
685                 }
686
687                 /* Server, zu dem der Client connectiert ist, suchen */
688                 intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
689                 if( ! intr_c )
690                 {
691                         Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
692                         Kill_Nick( Req->argv[0] );
693                         return CONNECTED;
694                 }
695
696                 /* Neue Client-Struktur anlegen */
697                 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 );
698                 if( ! c )
699                 {
700                         /* Eine neue Client-Struktur konnte nicht angelegt werden.
701                          * Der Client muss disconnectiert werden, damit der Netz-
702                          * status konsistent bleibt. */
703                         Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
704                         Kill_Nick( Req->argv[0] );
705                         return CONNECTED;
706                 }
707
708                 modes = Client_Modes( c );
709                 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": "" );
710                 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": "" );
711
712                 /* Andere Server, ausser dem Introducer, informieren */
713                 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] );
714
715                 return CONNECTED;
716         }
717         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
718 } /* IRC_NICK */
719
720
721 GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req )
722 {
723         assert( Client != NULL );
724         assert( Req != NULL );
725
726 #ifndef STRICT_RFC
727         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
728 #else
729         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
730 #endif
731         {
732                 /* Falsche Anzahl Parameter? */
733                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
734
735                 Client_SetUser( Client, Req->argv[0], FALSE );
736                 Client_SetInfo( Client, Req->argv[3] );
737
738                 Log( LOG_DEBUG, "Connection %d: got USER command ...", Client_Conn( Client ));
739                 if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
740                 else Client_SetType( Client, CLIENT_GOTUSER );
741                 return CONNECTED;
742         }
743         else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
744         {
745                 return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
746         }
747         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
748 } /* IRC_USER */
749
750
751 GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
752 {
753         CLIENT *target;
754         
755         assert( Client != NULL );
756         assert( Req != NULL );
757
758         if(( Client_Type( Client ) == CLIENT_USER ) || ( Client_Type( Client ) == CLIENT_SERVICE ))
759         {
760                 /* User / Service */
761                 
762                 /* Falsche Anzahl Parameter? */
763                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
764
765                 if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE );
766                 else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE );
767                 
768                 return DISCONNECTED;
769         }
770         else if ( Client_Type( Client ) == CLIENT_SERVER )
771         {
772                 /* Server */
773
774                 /* Falsche Anzahl Parameter? */
775                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
776
777                 target = Client_Search( Req->prefix );
778                 if( ! target )
779                 {
780                         Log( LOG_ERR, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
781                         return CONNECTED;
782                 }
783
784                 if( Req->argc == 0 ) Client_Destroy( target, "Got QUIT command.", NULL );
785                 else Client_Destroy( target, "Got QUIT command.", Req->argv[0] );
786
787                 return CONNECTED;
788         }
789         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
790 } /* IRC_QUIT */
791
792
793 GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
794 {
795         CLIENT *target;
796         
797         assert( Client != NULL );
798         assert( Req != NULL );
799
800         /* SQUIT ist nur fuer Server erlaubt */
801         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
802
803         /* Falsche Anzahl Parameter? */
804         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
805
806         target = Client_GetFromID( Req->argv[0] );
807         if( ! target )
808         {
809                 Log( LOG_ERR, "Got SQUIT from %s for unknown server \%s\"!?", Client_ID( Client ), Req->argv[0] );
810                 return CONNECTED;
811         }
812
813         if( target == Client ) Log( LOG_DEBUG, "Got SQUIT from %s: %s", Client_ID( Client ), Req->argv[1] );
814         else Log( LOG_DEBUG, "Got SQUIT from %s for %s: %s", Client_ID( Client ), Client_ID( target ), Req->argv[1] );
815
816         /* SQUIT an alle Server weiterleiten */
817         IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] );
818
819         if( Client_Conn( target ) > NONE )
820         {
821                 if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), "Got SQUIT command.", Req->argv[1], TRUE );
822                 else Conn_Close( Client_Conn( target ), "Got SQUIT command.", NULL, TRUE );
823                 return DISCONNECTED;
824         }
825         else
826         {
827                 Client_Destroy( target, "Got SQUIT command.", Req->argv[1] );
828                 return CONNECTED;
829         }
830 } /* IRC_SQUIT */
831
832
833 GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
834 {
835         assert( Client != NULL );
836         assert( Req != NULL );
837
838         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
839
840         /* Falsche Anzahl Parameter? */
841         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
842         if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
843
844         Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
845         return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
846 } /* IRC_PING */
847
848
849 GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
850 {
851         assert( Client != NULL );
852         assert( Req != NULL );
853
854         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
855
856         /* Falsche Anzahl Parameter? */
857         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
858         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
859
860         /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
861          * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
862
863         Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
864         return CONNECTED;
865 } /* IRC_PONG */
866
867
868 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
869 {
870         assert( Client != NULL );
871         assert( Req != NULL );
872
873         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
874
875         /* Falsche Anzahl Parameter? */
876         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
877
878         return Show_MOTD( Client );
879 } /* IRC_MOTD */
880
881
882 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
883 {
884         CLIENT *to, *from;
885         CHANNEL *chan;
886         
887         assert( Client != NULL );
888         assert( Req != NULL );
889
890         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
891
892         /* Falsche Anzahl Parameter? */
893         if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
894         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
895         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
896
897         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
898         else from = Client;
899         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
900
901         to = Client_Search( Req->argv[0] );
902         if( to )
903         {
904                 /* Okay, Ziel ist ein User */
905                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
906                 return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
907         }
908
909         chan = Channel_Search( Req->argv[0] );
910         if( chan )
911         {
912                 /* Okay, Ziel ist ein Channel */
913                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
914                 return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
915         }
916
917         return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
918 } /* IRC_PRIVMSG */
919
920
921 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
922 {
923         CLIENT *to, *from;
924
925         assert( Client != NULL );
926         assert( Req != NULL );
927
928         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
929
930         /* Falsche Anzahl Parameter? */
931         if( Req->argc != 2 ) return CONNECTED;
932
933         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
934         else from = Client;
935         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
936
937         to = Client_Search( Req->argv[0] );
938         if( to )
939         {
940                 /* Okay, Ziel ist ein User */
941                 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
942         }
943         else return CONNECTED;
944 } /* IRC_NOTICE */
945
946
947 GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
948 {
949         CHAR x[2], new_modes[CLIENT_MODE_LEN], *ptr;
950         BOOLEAN set, ok;
951         CLIENT *target;
952         
953         assert( Client != NULL );
954         assert( Req != NULL );
955
956         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
957
958         /* Falsche Anzahl Parameter? */
959         if(( Req->argc > 2 ) || ( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
960
961         /* "Ziel-Client" suchen */
962         target = Client_Search( Req->argv[0] );
963
964         /* Wer ist der Anfragende? */
965         if( Client_Type( Client ) == CLIENT_USER )
966         {
967                 /* User: MODE ist nur fuer sich selber zulaessig */
968                 if( target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
969         }
970         else
971         {
972                 /* Server: gibt es den Client ueberhaupt? */
973                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
974         }
975
976         /* Werden die Modes erfragt? */
977         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( Client ));
978
979         ptr = Req->argv[1];
980
981         /* Sollen Modes gesetzt oder geloescht werden? */
982         if( *ptr == '+' ) set = TRUE;
983         else if( *ptr == '-' ) set = FALSE;
984         else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
985
986         /* Reply-String mit Aenderungen vorbereiten */
987         if( set ) strcpy( new_modes, "+" );
988         else strcpy( new_modes, "-" );
989
990         ptr++;
991         ok = TRUE;
992         x[1] = '\0';
993         while( *ptr )
994         {
995                 x[0] = '\0';
996                 if( Client_Type( Client ) == CLIENT_SERVER )
997                 {
998                         x[0] = *ptr;
999                         ok = TRUE;
1000                 }
1001                 else
1002                 {
1003                         switch( *ptr )
1004                         {
1005                                 case 'i':
1006                                         /* invisible */
1007                                         x[0] = 'i';
1008                                         break;
1009                                 case 'r':
1010                                         /* restricted (kann nur gesetzt werden) */
1011                                         if( set ) x[0] = 'r';
1012                                         else ok = IRC_WriteStrClient( target, ERR_RESTRICTED_MSG, Client_ID( target ));
1013                                         break;
1014                                 case 'o':
1015                                         /* operator (kann nur geloescht werden) */
1016                                         if( ! set )
1017                                         {
1018                                                 Client_SetOperByMe( target, FALSE );
1019                                                 x[0] = 'o';
1020                                         }
1021                                         else ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
1022                                         break;
1023                                 default:
1024                                         ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
1025                                         x[0] = '\0';
1026                         }
1027                 }
1028                 if( ! ok ) break;
1029
1030                 ptr++;
1031                 if( ! x[0] ) continue;
1032
1033                 /* Okay, gueltigen Mode gefunden */
1034                 if( set )
1035                 {
1036                         /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
1037                         if( Client_ModeAdd( target, x[0] )) strcat( new_modes, x );
1038                 }
1039                 else
1040                 {
1041                         /* Modes geloescht. Wenn der Client ihn hatte: merken */
1042                         if( Client_ModeDel( target, x[0] )) strcat( new_modes, x );
1043                 }
1044         }
1045         
1046         /* Geanderte Modes? */
1047         if( new_modes[1] )
1048         {
1049                 if( Client_Type( Client ) == CLIENT_SERVER )
1050                 {
1051                         /* Modes an andere Server forwarden */
1052                         IRC_WriteStrServersPrefix( Client, Client, "MODE %s :%s", Client_ID( target ), new_modes );
1053                 }
1054                 else
1055                 {
1056                         /* Bestaetigung an Client schicken & andere Server informieren */
1057                         ok = IRC_WriteStrClient( Client, "MODE %s :%s", Client_ID( target ), new_modes );
1058                         IRC_WriteStrServers( Client, "MODE %s :%s", Client_ID( target ), new_modes );
1059                 }
1060                 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( target ), Client_Modes( target ));
1061         }
1062         return ok;
1063 } /* IRC_MODE */
1064
1065
1066 GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
1067 {
1068         INT i;
1069         
1070         assert( Client != NULL );
1071         assert( Req != NULL );
1072
1073         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1074         
1075         /* Falsche Anzahl Parameter? */
1076         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1077
1078         /* Operator suchen */
1079         for( i = 0; i < Conf_Oper_Count; i++)
1080         {
1081                 if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
1082         }
1083         if( i >= Conf_Oper_Count )
1084         {
1085                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Name \"%s\" not configured!", Client_Mask( Client ), Req->argv[0] );
1086                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1087         }
1088
1089         /* Stimmt das Passwort? */
1090         if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
1091         {
1092                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Bad password for \"%s\"!", Client_Mask( Client ), Conf_Oper[i].name );
1093                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1094         }
1095         
1096         if( ! Client_HasMode( Client, 'o' ))
1097         {
1098                 /* noch kein o-Mode gesetzt */
1099                 Client_ModeAdd( Client, 'o' );
1100                 if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
1101                 IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
1102         }
1103
1104         if( ! Client_OperByMe( Client )) Log( LOG_NOTICE, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
1105
1106         Client_SetOperByMe( Client, TRUE );
1107         return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
1108 } /* IRC_OPER */
1109
1110
1111 GLOBAL BOOLEAN IRC_DIE( CLIENT *Client, REQUEST *Req )
1112 {
1113         assert( Client != NULL );
1114         assert( Req != NULL );
1115
1116         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1117
1118         /* Falsche Anzahl Parameter? */
1119         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1120
1121         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1122
1123         Log( LOG_NOTICE, "Got DIE command from \"%s\", going down!", Client_Mask( Client ));
1124         NGIRCd_Quit = TRUE;
1125         return CONNECTED;
1126 } /* IRC_DIE */
1127
1128
1129 GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req )
1130 {
1131         assert( Client != NULL );
1132         assert( Req != NULL );
1133
1134         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1135
1136         /* Falsche Anzahl Parameter? */
1137         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1138
1139         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1140
1141         Log( LOG_NOTICE, "Got RESTART command from \"%s\", going down!", Client_Mask( Client ));
1142         NGIRCd_Restart = TRUE;
1143         return CONNECTED;
1144 } /* IRC_RESTART */
1145
1146
1147 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
1148 {
1149         CHAR rpl[COMMAND_LEN];
1150         CLIENT *c;
1151         
1152         assert( Client != NULL );
1153         assert( Req != NULL );
1154
1155         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1156
1157         /* Falsche Anzahl Parameter? */
1158         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1159
1160         /* Noch alle User ausgeben, die in keinem Channel sind */
1161         rpl[0] = '\0';
1162         c = Client_First( );
1163         while( c )
1164         {
1165                 if( Client_Type( c ) == CLIENT_USER )
1166                 {
1167                         /* Okay, das ist ein User */
1168                         strcat( rpl, Client_ID( c ));
1169                         strcat( rpl, " " );
1170                 }
1171
1172                 /* Antwort zu lang? Splitten. */
1173                 if( strlen( rpl ) > 480 )
1174                 {
1175                         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1176                         if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1177                         rpl[0] = '\0';
1178                 }
1179                 
1180                 c = Client_Next( c );
1181         }
1182         if( rpl[0] )
1183         {
1184                 /* es wurden User gefunden */
1185                 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1186                 if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1187         }
1188         return IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), "*" );
1189 } /* IRC_NAMES */
1190
1191
1192 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
1193 {
1194         CHAR rpl[COMMAND_LEN];
1195         CLIENT *c;
1196         CHAR *ptr;
1197         INT i;
1198         
1199         assert( Client != NULL );
1200         assert( Req != NULL );
1201
1202         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1203
1204         /* Falsche Anzahl Parameter? */
1205         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1206
1207         strcpy( rpl, RPL_ISON_MSG );
1208         for( i = 0; i < Req->argc; i++ )
1209         {
1210                 ptr = strtok( Req->argv[i], " " );
1211                 while( ptr )
1212                 {
1213                         ngt_TrimStr( ptr );
1214                         c = Client_GetFromID( ptr );
1215                         if( c && ( Client_Type( c ) == CLIENT_USER ))
1216                         {
1217                                 /* Dieser Nick ist "online" */
1218                                 strcat( rpl, ptr );
1219                                 strcat( rpl, " " );
1220                         }
1221                         ptr = strtok( NULL, " " );
1222                 }
1223         }
1224         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1225
1226         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1227 } /* IRC_ISON */
1228
1229
1230 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
1231 {
1232         CLIENT *from, *target, *c;
1233         CHAR *ptr = NULL;
1234         
1235         assert( Client != NULL );
1236         assert( Req != NULL );
1237
1238         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1239
1240         /* Falsche Anzahl Parameter? */
1241         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1242
1243         /* Client suchen */
1244         c = Client_GetFromID( Req->argv[Req->argc - 1] );
1245         if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
1246
1247         /* Empfaenger des WHOIS suchen */
1248         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1249         else from = Client;
1250         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1251         
1252         /* Forwarden an anderen Server? */
1253         if( Req->argc > 1 )
1254         {
1255                 /* angegebenen Ziel-Server suchen */
1256                 target = Client_GetFromID( Req->argv[1] );
1257                 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
1258                 ptr = Req->argv[1];
1259         }
1260 #ifndef STRICT_RFC
1261         else if( Client_Conn( c ) == NONE )
1262         {
1263                 /* Client ist nicht von uns. Ziel-Server suchen */
1264                 target = c;
1265                 ptr = Req->argv[0];
1266         }
1267 #endif
1268         else target = NULL;
1269         
1270         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 );
1271         
1272         /* Nick, User und Name */
1273         if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
1274
1275         /* Server */
1276         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;
1277
1278         /* IRC-Operator? */
1279         if( Client_HasMode( c, 'o' ))
1280         {
1281                 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
1282         }
1283
1284         /* Idle (nur lokale Clients) */
1285         if( Client_Conn( c ) > NONE )
1286         {
1287                 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
1288         }
1289
1290         /* End of Whois */
1291         return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
1292 } /* IRC_WHOIS */
1293
1294
1295 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
1296 {
1297         CHAR rpl[COMMAND_LEN];
1298         CLIENT *c;
1299         INT max, i;
1300
1301         assert( Client != NULL );
1302         assert( Req != NULL );
1303
1304         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1305
1306         /* Falsche Anzahl Parameter? */
1307         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1308
1309         if( Req->argc > 5 ) max = 5;
1310         else max = Req->argc;
1311         
1312         strcpy( rpl, RPL_USERHOST_MSG );
1313         for( i = 0; i < max; i++ )
1314         {
1315                 c = Client_GetFromID( Req->argv[i] );
1316                 if( c && ( Client_Type( c ) == CLIENT_USER ))
1317                 {
1318                         /* Dieser Nick ist "online" */
1319                         strcat( rpl, Client_ID( c ));
1320                         if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
1321                         strcat( rpl, "=" );
1322                         if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
1323                         else strcat( rpl, "+" );
1324                         strcat( rpl, Client_User( c ));
1325                         strcat( rpl, "@" );
1326                         strcat( rpl, Client_Hostname( c ));
1327                         strcat( rpl, " " );
1328                 }
1329         }
1330         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1331
1332         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1333 } /* IRC_USERHOST */
1334
1335
1336 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
1337 {
1338         assert( Client != NULL );
1339         assert( Req != NULL );
1340
1341         if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
1342         else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
1343
1344         return CONNECTED;
1345 } /* IRC_ERROR */
1346
1347
1348 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
1349 {
1350         CLIENT *target, *from;
1351         INT cnt;
1352         
1353         assert( Client != NULL );
1354         assert( Req != NULL );
1355
1356         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1357
1358         /* Falsche Anzahl Parameter? */
1359         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1360
1361         /* Absender ermitteln */
1362         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1363         else from = Client;
1364         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1365
1366         /* An anderen Server forwarden? */
1367         if( Req->argc == 2 )
1368         {
1369                 target = Client_GetFromID( Req->argv[1] );
1370                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1371                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
1372         }
1373
1374         /* Wer ist der Absender? */
1375         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1376         else target = Client;
1377         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1378         
1379         /* Users, Services und Serevr im Netz */
1380         if( ! IRC_WriteStrClient( target, RPL_LUSERCLIENT_MSG, Client_ID( target ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
1381
1382         /* IRC-Operatoren im Netz */
1383         cnt = Client_OperCount( );
1384         if( cnt > 0 )
1385         {
1386                 if( ! IRC_WriteStrClient( target, RPL_LUSEROP_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1387         }
1388
1389         /* Unbekannt Verbindungen */
1390         cnt = Client_UnknownCount( );
1391         if( cnt > 0 )
1392         {
1393                 if( ! IRC_WriteStrClient( target, RPL_LUSERUNKNOWN_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1394         }
1395
1396         /* Channels im Netz */
1397         if( ! IRC_WriteStrClient( target, RPL_LUSERCHANNELS_MSG, Client_ID( target ), Channel_Count( ))) return DISCONNECTED;
1398
1399         /* Channels im Netz */
1400         if( ! IRC_WriteStrClient( target, RPL_LUSERME_MSG, Client_ID( target ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
1401
1402         return CONNECTED;
1403 } /* IRC_LUSERS */
1404
1405
1406 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
1407 {
1408         CLIENT *target, *from, *c;
1409         CHAR *mask;
1410         
1411         assert( Client != NULL );
1412         assert( Req != NULL );
1413
1414         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1415
1416         /* Falsche Anzahl Parameter? */
1417         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1418
1419         /* Server-Mask ermitteln */
1420         if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
1421         else mask = "*";
1422
1423         /* Absender ermitteln */
1424         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1425         else from = Client;
1426         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1427         
1428         /* An anderen Server forwarden? */
1429         if( Req->argc == 2 )
1430         {
1431                 target = Client_GetFromID( Req->argv[0] );
1432                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
1433                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
1434         }
1435
1436         /* Wer ist der Absender? */
1437         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1438         else target = Client;
1439         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1440         
1441         c = Client_First( );
1442         while( c )
1443         {
1444                 if( Client_Type( c ) == CLIENT_SERVER )
1445                 {
1446                         if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_Introducer( c )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
1447                 }
1448                 c = Client_Next( c );
1449         }
1450         
1451         return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
1452 } /* IRC_LINKS */
1453
1454
1455 GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
1456 {
1457         CLIENT *target;
1458         CHAR *chan, *flags;
1459         
1460         assert( Client != NULL );
1461         assert( Req != NULL );
1462
1463         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1464
1465         /* Falsche Anzahl Parameter? */
1466         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1467
1468         /* Wer ist der Absender? */
1469         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1470         else target = Client;
1471         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1472         
1473         /* Channel-Namen durchgehen */
1474         chan = strtok( Req->argv[0], "," );
1475         while( chan )
1476         {
1477                 if( Client_Type( Client ) == CLIENT_SERVER )
1478                 {
1479                         /* Channel-Flags extrahieren */
1480                         flags = strchr( chan, 0x7 );
1481                         if( flags ) *flags++ = '\0';
1482                 }
1483                 else flags = NULL;
1484                 
1485                 if( ! Channel_Join( target, chan ))
1486                 {
1487                         /* naechsten Namen ermitteln */
1488                         chan = strtok( NULL, "," );
1489                         continue;
1490                 }
1491
1492                 /* An andere Server weiterleiten */
1493                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s", chan );
1494                 IRC_WriteStrChannelPrefix( Client, Channel_Search( chan ), target, FALSE, "JOIN :%s", chan );
1495
1496                 if( Client_Type( Client ) == CLIENT_USER )
1497                 {
1498                         /* an Client bestaetigen */
1499                         IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", chan );
1500                         /* Topic an Client schicken */
1501                         IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), chan, "What a wonderful channel!" );
1502                 }
1503                 
1504                 /* naechsten Namen ermitteln */
1505                 chan = strtok( NULL, "," );
1506         }
1507         return CONNECTED;
1508 } /* IRC_JOIN */
1509
1510
1511 GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
1512 {
1513         CLIENT *target;
1514         CHAR *chan;
1515
1516         assert( Client != NULL );
1517         assert( Req != NULL );
1518
1519         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1520
1521         /* Falsche Anzahl Parameter? */
1522         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1523
1524         /* Wer ist der Absender? */
1525         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1526         else target = Client;
1527         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1528
1529         /* Channel-Namen durchgehen */
1530         chan = strtok( Req->argv[0], "," );
1531         while( chan )
1532         {
1533                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
1534                 {
1535                         /* naechsten Namen ermitteln */
1536                         chan = strtok( NULL, "," );
1537                         continue;
1538                 }
1539
1540                 /* naechsten Namen ermitteln */
1541                 chan = strtok( NULL, "," );
1542         }
1543         return CONNECTED;
1544 } /* IRC_PART */
1545
1546
1547 LOCAL BOOLEAN Hello_User( CLIENT *Client )
1548 {
1549         assert( Client != NULL );
1550
1551         /* Passwort ueberpruefen */
1552         if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
1553         {
1554                 /* Falsches Passwort */
1555                 Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
1556                 Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
1557                 return DISCONNECTED;
1558         }
1559
1560         Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
1561
1562         /* Andere Server informieren */
1563         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 ));
1564
1565         if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return FALSE;
1566         if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1567         if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE;
1568         if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1569
1570         Client_SetType( Client, CLIENT_USER );
1571
1572         return Show_MOTD( Client );
1573 } /* Hello_User */
1574
1575
1576 LOCAL BOOLEAN Show_MOTD( CLIENT *Client )
1577 {
1578         BOOLEAN ok;
1579         CHAR line[127];
1580         FILE *fd;
1581         
1582         assert( Client != NULL );
1583
1584         fd = fopen( Conf_MotdFile, "r" );
1585         if( ! fd )
1586         {
1587                 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
1588                 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
1589         }
1590         
1591         IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
1592         while( TRUE )
1593         {
1594                 if( ! fgets( line, 126, fd )) break;
1595                 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
1596                 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
1597                 {
1598                         fclose( fd );
1599                         return FALSE;
1600                 }
1601         }
1602         ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
1603
1604         fclose( fd );
1605         
1606         return ok;
1607 } /* Show_MOTD */
1608
1609
1610 LOCAL VOID Kill_Nick( CHAR *Nick )
1611 {
1612         Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected!", Nick );
1613         /* FIXME */
1614         Log( LOG_ALERT, "[Kill_Nick() not implemented - OOOPS!]" );
1615 } /* Kill_Nick */
1616
1617
1618 /* -eof- */