2001-12-14 09:13:43 +01:00
/*
* ngIRCd - - The Next Generation IRC Daemon
2002-01-02 03:44:36 +01:00
* Copyright ( c ) 2001 , 2002 by Alexander Barton ( alex @ barton . de )
2001-12-14 09:13:43 +01:00
*
* Dieses Programm ist freie Software . Sie koennen es unter den Bedingungen
* der GNU General Public License ( GPL ) , wie von der Free Software Foundation
* herausgegeben , weitergeben und / oder modifizieren , entweder unter Version 2
* der Lizenz oder ( wenn Sie es wuenschen ) jeder spaeteren Version .
* Naehere Informationen entnehmen Sie bitter der Datei COPYING . Eine Liste
2001-12-31 03:18:51 +01:00
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS .
2001-12-14 09:13:43 +01:00
*
2002-02-23 22:39:48 +01:00
* $ Id : irc . c , v 1.66 2002 / 02 / 23 21 : 39 : 48 alex Exp $
2001-12-14 09:13:43 +01:00
*
* irc . c : IRC - Befehle
*
* $ Log : irc . c , v $
2002-02-23 22:39:48 +01:00
* Revision 1.66 2002 / 02 / 23 21 : 39 : 48 alex
* - IRC - Befehl KILL sowie Kills bei Nick Collsisions implementiert .
*
2002-02-23 01:03:54 +01:00
* Revision 1.65 2002 / 02 / 23 00 : 03 : 54 alex
* - Ergebnistyp von Conn_GetIdle ( ) und Conn_LastPing ( ) auf " time_t " geaendert .
*
2002-02-19 21:06:45 +01:00
* Revision 1.64 2002 / 02 / 19 20 : 06 : 45 alex
* - User - Registrierung wird nicht mehr als Nick - Aenderung protokolliert ,
* - VERSION liefert nun doch wieder den Debug - Status im Reply .
*
2002-02-19 03:21:17 +01:00
* Revision 1.63 2002 / 02 / 19 02 : 21 : 17 alex
* - der Debug - Level wird bei VERSION nicht mehr geliefert . Grund : a ) absolut
* unnoetig und b ) Compiler - Fehler , wenn ohne Debug - Code configure ' d ; - ) )
*
2002-02-18 00:38:58 +01:00
* Revision 1.62 2002 / 02 / 17 23 : 38 : 58 alex
* - neuer IRC - Befehl VERSION implementiert : IRC_VERSION ( ) .
*
2002-02-17 20:03:12 +01:00
* Revision 1.61 2002 / 02 / 17 19 : 03 : 12 alex
* - NICK - Aenderungen wurden dem User selber mit dem falschen Prefix geliefert .
*
2002-02-17 18:43:14 +01:00
* Revision 1.60 2002 / 02 / 17 17 : 43 : 14 alex
* - Fehlerhafte Modes werden nun ausfuehrlicher an den Client gemeldet .
*
2002-02-17 18:30:21 +01:00
* Revision 1.59 2002 / 02 / 17 17 : 30 : 21 alex
* - NICK - Aenderungen werden an alle Server und betroffene Clients gemeldet .
* - Neue Funktion IRC_WriteStrRelatedPrefix ( ) .
*
2002-02-17 18:18:59 +01:00
* Revision 1.58 2002 / 02 / 17 17 : 18 : 59 alex
* - NICK korrigiert .
*
2002-02-14 00:05:29 +01:00
* Revision 1.57 2002 / 02 / 13 23 : 05 : 29 alex
* - Nach Connect eines Users werden LUSERS - Informationen angezeigt .
*
2002-02-13 18:52:27 +01:00
* Revision 1.56 2002 / 02 / 13 17 : 52 : 27 alex
* - es werden nun Channel - und User - Modes von Usern angenommen .
*
2002-02-12 15:40:37 +01:00
* Revision 1.55 2002 / 02 / 12 14 : 40 : 37 alex
* - via NJOIN gemeldete Benutzer wurden nicht in Channels bekannt gemacht .
*
2002-02-12 00:33:35 +01:00
* Revision 1.54 2002 / 02 / 11 23 : 33 : 35 alex
* - weitere Anpassungen an Channel - Modes und Channel - User - Modes .
*
2002-02-11 17:06:21 +01:00
* Revision 1.53 2002 / 02 / 11 16 : 06 : 21 alex
* - Die Quelle von MODE - Aenderungen wird nun korrekt weitergegeben .
*
2002-02-11 16:52:21 +01:00
* Revision 1.52 2002 / 02 / 11 15 : 52 : 21 alex
* - PONG an den Server selber wurde faelschlicherweise versucht zu forwarden .
* - Channel - Modes wurden falsch geliefert ( als User - Modes ) .
*
2002-02-11 16:15:53 +01:00
* Revision 1.51 2002 / 02 / 11 15 : 15 : 53 alex
* - PING und PONG werden nun auch korrekt an andere Server geforwarded .
* - bei MODE - Meldungen wird der letzte Parameter nicht mehr mit " : " getrennt .
*
2002-02-11 02:03:20 +01:00
* Revision 1.50 2002 / 02 / 11 01 : 03 : 20 alex
* - Aenderungen und Anpassungen an Channel - Modes und Channel - User - Modes :
* Modes werden besser geforwarded , lokale User , fuer die ein Channel
* angelegt wird , werden Channel - Operator , etc . pp . . . .
* - NJOIN ' s von Servern werden nun korrekt an andere Server weitergeleitet .
*
2002-02-06 17:51:22 +01:00
* Revision 1.49 2002 / 02 / 06 16 : 51 : 22 alex
* - neue Funktion zur MODE - Behandlung , fuer Channel - Modes vorbereitet .
*
2002-01-29 01:13:45 +01:00
* Revision 1.48 2002 / 01 / 29 00 : 13 : 45 alex
* - WHOIS zeigt nun auch die Channels an , in denen der jeweilige User Mitglied ist .
* - zu jedem Server wird nun der " Top-Server " gespeichert , somit funktioniert
* LINKS wieder korrekt .
*
2002-01-28 14:05:48 +01:00
* Revision 1.47 2002 / 01 / 28 13 : 05 : 48 alex
* - nach einem JOIN wird die Liste der Mitglieder an den Client geschickt .
* - MODE fuer Channels wird nun komplett ignoriert ( keine Fehlermeldung mehr ) .
*
2002-01-28 02:45:43 +01:00
* Revision 1.46 2002 / 01 / 28 01 : 45 : 43 alex
* - SERVER - Meldungen an neue Server sind nun in der richtigen Reihenfolge .
*
2002-01-28 02:18:14 +01:00
* Revision 1.45 2002 / 01 / 28 01 : 18 : 14 alex
* - connectierenden Servern werden Channels nun mit NJOIN bekannt gemacht .
*
2002-01-28 01:55:08 +01:00
* Revision 1.44 2002 / 01 / 28 00 : 55 : 08 alex
* - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht .
*
2002-01-27 22:56:39 +01:00
* Revision 1.43 2002 / 01 / 27 21 : 56 : 39 alex
* - IRC_WriteStrServersPrefixID ( ) und IRC_WriteStrClientPrefixID ( ) wieder entfernt .
* - einige kleinere Fixes bezueglich Channels . . .
*
2002-01-27 19:28:01 +01:00
* Revision 1.42 2002 / 01 / 27 18 : 28 : 01 alex
* - bei NICK wurde das falsche Prefix an andere Server weitergegeben .
*
2002-01-27 18:15:49 +01:00
* Revision 1.41 2002 / 01 / 27 17 : 15 : 49 alex
* - anderungen an den Funktions - Prototypen von IRC_WriteStrChannel ( ) und
* IRC_WriteStrChannelPrefix ( ) ,
* - neue : IRC_WriteStrClientPrefixID ( ) und IRC_WriteStrServersPrefixID ( ) .
*
2002-01-26 19:43:11 +01:00
* Revision 1.40 2002 / 01 / 26 18 : 43 : 11 alex
* - neue Funktionen IRC_WriteStrChannelPrefix ( ) und IRC_WriteStrChannel ( ) ,
* die IRC_Write_xxx_Related ( ) sind dafuer entfallen .
* - IRC_PRIVMSG ( ) kann nun auch mit Channels als Ziel umgehen .
*
2002-01-21 01:05:11 +01:00
* Revision 1.39 2002 / 01 / 21 00 : 05 : 11 alex
* - neue Funktionen IRC_JOIN und IRC_PART begonnen , ebenso die Funktionen
* IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix ( ) .
* - diverse Aenderungen im Zusammenhang mit Channels .
*
2002-01-18 16:31:32 +01:00
* Revision 1.38 2002 / 01 / 18 15 : 31 : 32 alex
* - die User - Modes bei einem NICK von einem Server wurden falsch uebernommen .
*
2002-01-16 23:10:18 +01:00
* Revision 1.37 2002 / 01 / 16 22 : 10 : 18 alex
* - IRC_LUSERS ( ) implementiert .
*
2002-01-12 00:50:55 +01:00
* Revision 1.36 2002 / 01 / 11 23 : 50 : 55 alex
* - LINKS implementiert , LUSERS begonnen .
*
2002-01-09 22:30:45 +01:00
* Revision 1.35 2002 / 01 / 09 21 : 30 : 45 alex
* - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet .
*
2002-01-09 02:09:58 +01:00
* Revision 1.34 2002 / 01 / 09 01 : 09 : 58 alex
* - WHOIS wird im " Strict-RFC-Mode " nicht mehr automatisch geforwarded ,
* - andere Server werden nun ueber bisherige Server und User informiert .
*
2002-01-08 00:42:12 +01:00
* Revision 1.33 2002 / 01 / 07 23 : 42 : 12 alex
* - Es werden fuer alle Server eigene Token generiert ,
* - QUIT von einem Server fuer einen User wird an andere Server geforwarded ,
* - ebenso NICK - Befehle , die " fremde " User einfuehren .
*
2002-01-07 17:02:36 +01:00
* Revision 1.32 2002 / 01 / 07 16 : 02 : 36 alex
* - Loglevel von Remote - Mode - Aenderungen angepasst ( nun Debug ) .
* - Im Debug - Mode werden nun auch PING ' s protokolliert .
*
2002-01-07 16:39:46 +01:00
* Revision 1.31 2002 / 01 / 07 15 : 39 : 46 alex
* - Server nimmt nun Server - Links an : PASS und SERVER entsprechend angepasst .
* - MODE und NICK melden nun die Aenderungen an andere Server .
*
2002-01-06 16:21:29 +01:00
* Revision 1.30 2002 / 01 / 06 15 : 21 : 29 alex
* - Loglevel und Meldungen nochmals ueberarbeitet .
* - QUIT und SQUIT forwarden nun den Grund der Trennung ,
* - WHOIS wird nun immer an den " Original-Server " weitergeleitet .
*
2002-01-06 00:24:54 +01:00
* Revision 1.29 2002 / 01 / 05 23 : 24 : 54 alex
* - WHOIS erweitert : Anfragen koennen an andere Server weitergeleitet werden .
* - Vorbereitungen fuer Ident - Abfragen bei neuen Client - Strukturen .
*
2002-01-05 21:08:02 +01:00
* Revision 1.28 2002 / 01 / 05 20 : 08 : 02 alex
* - Div . Aenderungen fuer die Server - Links ( u . a . WHOIS , QUIT , NICK angepasst ) .
* - Neue Funktionen IRC_WriteStrServer ( ) und IRC_WriteStrServerPrefix ( ) .
*
2002-01-05 20:15:03 +01:00
* Revision 1.27 2002 / 01 / 05 19 : 15 : 03 alex
* - Fehlerpruefung bei select ( ) in der " Hauptschleife " korrigiert .
*
2002-01-05 17:51:18 +01:00
* Revision 1.26 2002 / 01 / 05 16 : 51 : 18 alex
* - das Passwort von Servern wird nun ueberprueft ( PASS - und SERVER - Befehl ) .
*
2002-01-05 01:48:33 +01:00
* Revision 1.25 2002 / 01 / 05 00 : 48 : 33 alex
* - bei SQUIT wurde immer die Verbindung getrennt , auch bei Remote - Servern .
*
2002-01-04 18:58:44 +01:00
* Revision 1.24 2002 / 01 / 04 17 : 58 : 44 alex
* - IRC_WriteStrXXX ( ) - Funktionen eingefuehrt , groessere Anpassungen daran .
* - neuer Befehl SQUIT , QUIT an Server - Links angepasst .
*
2002-01-04 02:36:40 +01:00
* Revision 1.23 2002 / 01 / 04 01 : 36 : 40 alex
* - Loglevel ein wenig angepasst .
*
2002-01-04 02:21:47 +01:00
* Revision 1.22 2002 / 01 / 04 01 : 21 : 47 alex
* - Client - Strukruren werden nur noch ueber Funktionen angesprochen .
* - Weitere Anpassungen und Erweiterungen der Server - Links .
*
2002-01-03 03:26:51 +01:00
* Revision 1.21 2002 / 01 / 03 02 : 26 : 51 alex
* - neue Befehle SERVER und NJOIN begonnen ,
* - begonnen , diverse IRC - Befehle an Server - Links anzupassen .
*
2002-01-02 13:46:41 +01:00
* Revision 1.20 2002 / 01 / 02 12 : 46 : 41 alex
* - die Gross - und Kleinschreibung des Nicks kann mit NICK nun geaendert werden .
*
2002-01-02 03:51:39 +01:00
* Revision 1.19 2002 / 01 / 02 02 : 51 : 39 alex
* - Copyright - Texte angepasst .
* - neuer Befehl " ERROR " .
2002-01-02 03:44:36 +01:00
*
2001-12-31 16:33:13 +01:00
* Revision 1.17 2001 / 12 / 31 15 : 33 : 13 alex
* - neuer Befehl NAMES , kleinere Bugfixes .
* - Bug bei PING behoben : war zu restriktiv implementiert : - )
*
2001-12-31 03:18:51 +01:00
* Revision 1.16 2001 / 12 / 31 02 : 18 : 51 alex
* - viele neue Befehle ( WHOIS , ISON , OPER , DIE , RESTART ) ,
* - neuen Header " defines.h " mit ( fast ) allen Konstanten .
* - Code Cleanups und viele " kleine " Aenderungen & Bugfixes .
*
2001-12-30 20:26:11 +01:00
* Revision 1.15 2001 / 12 / 30 19 : 26 : 11 alex
* - Unterstuetzung fuer die Konfigurationsdatei eingebaut .
*
2001-12-30 12:42:00 +01:00
* Revision 1.14 2001 / 12 / 30 11 : 42 : 00 alex
* - der Server meldet nun eine ordentliche " Start-Zeit " .
*
2001-12-29 04:10:06 +01:00
* Revision 1.13 2001 / 12 / 29 03 : 10 : 06 alex
* - Neue Funktion IRC_MODE ( ) implementiert , div . Aenderungen .
* - neue configure - Optione " --enable-strict-rfc " .
*
2001-12-27 20:17:26 +01:00
* Revision 1.12 2001 / 12 / 27 19 : 17 : 26 alex
* - neue Befehle PRIVMSG , NOTICE , PING .
*
2001-12-27 17:55:41 +01:00
* Revision 1.11 2001 / 12 / 27 16 : 55 : 41 alex
* - neu : IRC_WriteStrRelated ( ) , Aenderungen auch in IRC_WriteStrClient ( ) .
*
2001-12-26 23:48:53 +01:00
* Revision 1.10 2001 / 12 / 26 22 : 48 : 53 alex
* - MOTD - Datei ist nun konfigurierbar und wird gelesen .
*
2001-12-26 15:45:37 +01:00
* Revision 1.9 2001 / 12 / 26 14 : 45 : 37 alex
* - " Code Cleanups " .
*
2001-12-26 04:21:46 +01:00
* Revision 1.8 2001 / 12 / 26 03 : 21 : 46 alex
* - PING / PONG - Befehle implementiert ,
* - Meldungen ueberarbeitet : enthalten nun ( fast ) immer den Nick .
*
2001-12-26 00:25:18 +01:00
* Revision 1.7 2001 / 12 / 25 23 : 25 : 18 alex
* - und nochmal Aenderungen am Logging ; - )
*
2001-12-26 00:13:33 +01:00
* Revision 1.6 2001 / 12 / 25 23 : 13 : 33 alex
* - Debug - Meldungen angepasst .
*
2001-12-25 23:02:42 +01:00
* Revision 1.5 2001 / 12 / 25 22 : 02 : 42 alex
* - neuer IRC - Befehl " /QUIT " . Verbessertes Logging & Debug - Ausgaben .
*
2001-12-25 20:19:30 +01:00
* Revision 1.4 2001 / 12 / 25 19 : 19 : 30 alex
* - bessere Fehler - Abfragen , diverse Bugfixes .
* - Nicks werden nur einmal vergeben : - )
* - / MOTD wird unterstuetzt .
*
2001-12-24 02:34:06 +01:00
* Revision 1.3 2001 / 12 / 24 01 : 34 : 06 alex
* - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert ( wg . BitchX )
* - MOTD - Ausgabe begonnen zu implementieren .
*
2001-12-23 22:57:16 +01:00
* Revision 1.2 2001 / 12 / 23 21 : 57 : 16 alex
* - erste IRC - Befehle zu implementieren begonnen .
*
2001-12-14 09:13:43 +01:00
* Revision 1.1 2001 / 12 / 14 08 : 13 : 43 alex
* - neues Modul begonnen : - )
*/
# include <portab.h>
# include "global.h"
# include <imp.h>
# include <assert.h>
2001-12-26 23:48:53 +01:00
# include <errno.h>
2001-12-23 22:57:16 +01:00
# include <stdarg.h>
# include <stdio.h>
2002-01-04 02:21:47 +01:00
# include <stdlib.h>
2001-12-23 22:57:16 +01:00
# include <string.h>
2001-12-30 12:42:00 +01:00
# include "ngircd.h"
2002-01-21 01:05:11 +01:00
# include "channel.h"
2001-12-23 22:57:16 +01:00
# include "client.h"
2001-12-26 23:48:53 +01:00
# include "conf.h"
2001-12-31 03:18:51 +01:00
# include "conn.h"
2001-12-23 22:57:16 +01:00
# include "log.h"
# include "messages.h"
# include "parse.h"
2001-12-31 03:18:51 +01:00
# include "tool.h"
2001-12-14 09:13:43 +01:00
# include <exp.h>
# include "irc.h"
2001-12-25 20:19:30 +01:00
# define CONNECTED TRUE
# define DISCONNECTED FALSE
LOCAL BOOLEAN Hello_User ( CLIENT * Client ) ;
LOCAL BOOLEAN Show_MOTD ( CLIENT * Client ) ;
2001-12-24 02:34:06 +01:00
2002-02-23 22:39:48 +01:00
LOCAL VOID Kill_Nick ( CHAR * Nick , CHAR * Reason ) ;
2002-01-04 02:21:47 +01:00
2002-01-28 14:05:48 +01:00
LOCAL BOOLEAN Send_NAMES ( CLIENT * Client , CHANNEL * Chan ) ;
2002-02-14 00:05:29 +01:00
LOCAL BOOLEAN Send_LUSERS ( CLIENT * Client ) ;
2002-01-28 14:05:48 +01:00
2001-12-23 22:57:16 +01:00
2001-12-14 09:13:43 +01:00
GLOBAL VOID IRC_Init ( VOID )
{
} /* IRC_Init */
GLOBAL VOID IRC_Exit ( VOID )
{
} /* IRC_Exit */
2002-01-04 18:58:44 +01:00
GLOBAL BOOLEAN IRC_WriteStrClient ( CLIENT * Client , CHAR * Format , . . . )
{
CHAR buffer [ 1000 ] ;
BOOLEAN ok = CONNECTED ;
va_list ap ;
assert ( Client ! = NULL ) ;
assert ( Format ! = NULL ) ;
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
/* an den Client selber */
ok = IRC_WriteStrClientPrefix ( Client , Client_ThisServer ( ) , buffer ) ;
return ok ;
} /* IRC_WriteStrClient */
GLOBAL BOOLEAN IRC_WriteStrClientPrefix ( CLIENT * Client , CLIENT * Prefix , CHAR * Format , . . . )
2001-12-23 22:57:16 +01:00
{
/* Text an Clients, lokal bzw. remote, senden. */
CHAR buffer [ 1000 ] ;
va_list ap ;
assert ( Client ! = NULL ) ;
assert ( Format ! = NULL ) ;
2002-01-05 20:15:03 +01:00
assert ( Prefix ! = NULL ) ;
2001-12-23 22:57:16 +01:00
va_start ( ap , Format ) ;
2001-12-27 17:55:41 +01:00
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
2001-12-23 22:57:16 +01:00
2002-01-27 18:15:49 +01:00
return Conn_WriteStr ( Client_Conn ( Client_NextHop ( Client ) ) , " :%s %s " , Client_ID ( Prefix ) , buffer ) ;
2002-01-27 22:56:39 +01:00
} /* IRC_WriteStrClientPrefix */
2002-01-27 18:15:49 +01:00
GLOBAL BOOLEAN IRC_WriteStrChannel ( CLIENT * Client , CHANNEL * Chan , BOOLEAN Remote , CHAR * Format , . . . )
{
CHAR buffer [ 1000 ] ;
va_list ap ;
assert ( Client ! = NULL ) ;
assert ( Format ! = NULL ) ;
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
return IRC_WriteStrChannelPrefix ( Client , Chan , Client_ThisServer ( ) , Remote , buffer ) ;
2002-01-26 19:43:11 +01:00
} /* IRC_WriteStrChannel */
2002-01-21 01:05:11 +01:00
2002-01-27 18:15:49 +01:00
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix ( CLIENT * Client , CHANNEL * Chan , CLIENT * Prefix , BOOLEAN Remote , CHAR * Format , . . . )
2001-12-27 17:55:41 +01:00
{
CHAR buffer [ 1000 ] ;
2002-02-17 18:18:59 +01:00
BOOLEAN sock [ MAX_CONNECTIONS ] , ok = CONNECTED ;
2002-01-26 19:43:11 +01:00
CL2CHAN * cl2chan ;
CLIENT * c ;
2002-02-17 18:18:59 +01:00
INT s , i ;
2001-12-27 17:55:41 +01:00
va_list ap ;
assert ( Client ! = NULL ) ;
2002-01-26 19:43:11 +01:00
assert ( Chan ! = NULL ) ;
2002-01-21 01:05:11 +01:00
assert ( Prefix ! = NULL ) ;
2002-01-26 19:43:11 +01:00
assert ( Format ! = NULL ) ;
2001-12-27 17:55:41 +01:00
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
2002-01-26 19:43:11 +01:00
for ( i = 0 ; i < MAX_CONNECTIONS ; i + + ) sock [ i ] = FALSE ;
2001-12-27 17:55:41 +01:00
2002-01-21 01:05:11 +01:00
/* An alle Clients, die in den selben Channels sind.
* Dabei aber nur einmal je Remote - Server */
2002-01-26 19:43:11 +01:00
cl2chan = Channel_FirstMember ( Chan ) ;
while ( cl2chan )
{
2002-01-27 22:56:39 +01:00
c = Channel_GetClient ( cl2chan ) ;
if ( ! Remote )
2002-01-27 18:15:49 +01:00
{
if ( Client_Conn ( c ) < = NONE ) c = NULL ;
2002-01-27 22:56:39 +01:00
else if ( Client_Type ( c ) = = CLIENT_SERVER ) c = NULL ;
2002-01-27 18:15:49 +01:00
}
2002-01-27 22:56:39 +01:00
if ( c ) c = Client_NextHop ( c ) ;
2002-01-27 18:15:49 +01:00
if ( c & & ( c ! = Client ) )
2002-01-26 19:43:11 +01:00
{
/* Ok, anderer Client */
2002-01-27 18:15:49 +01:00
s = Client_Conn ( c ) ;
assert ( s > = 0 ) ;
assert ( s < MAX_CONNECTIONS ) ;
sock [ s ] = TRUE ;
2002-01-26 19:43:11 +01:00
}
cl2chan = Channel_NextMember ( Chan , cl2chan ) ;
}
/* Senden ... */
for ( i = 0 ; i < MAX_CONNECTIONS ; i + + )
{
if ( sock [ i ] )
{
2002-01-27 18:15:49 +01:00
ok = Conn_WriteStr ( i , " :%s %s " , Client_ID ( Prefix ) , buffer ) ;
2002-01-26 19:43:11 +01:00
if ( ! ok ) break ;
}
}
2001-12-27 17:55:41 +01:00
return ok ;
2002-01-26 19:43:11 +01:00
} /* IRC_WriteStrChannelPrefix */
2001-12-27 17:55:41 +01:00
2002-01-05 20:15:03 +01:00
GLOBAL VOID IRC_WriteStrServers ( CLIENT * ExceptOf , CHAR * Format , . . . )
{
CHAR buffer [ 1000 ] ;
va_list ap ;
assert ( Format ! = NULL ) ;
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
/* an den Client selber */
return IRC_WriteStrServersPrefix ( ExceptOf , Client_ThisServer ( ) , buffer ) ;
} /* IRC_WriteStrServers */
GLOBAL VOID IRC_WriteStrServersPrefix ( CLIENT * ExceptOf , CLIENT * Prefix , CHAR * Format , . . . )
{
CHAR buffer [ 1000 ] ;
CLIENT * c ;
va_list ap ;
assert ( Format ! = NULL ) ;
assert ( Prefix ! = NULL ) ;
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
c = Client_First ( ) ;
while ( c )
{
if ( ( Client_Type ( c ) = = CLIENT_SERVER ) & & ( Client_Conn ( c ) > NONE ) & & ( c ! = Client_ThisServer ( ) ) & & ( c ! = ExceptOf ) )
{
/* Ziel-Server gefunden */
IRC_WriteStrClientPrefix ( c , Prefix , buffer ) ;
}
c = Client_Next ( c ) ;
}
} /* IRC_WriteStrServersPrefix */
2002-02-17 18:18:59 +01:00
GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix ( CLIENT * Client , CLIENT * Prefix , BOOLEAN Remote , CHAR * Format , . . . )
{
BOOLEAN sock [ MAX_CONNECTIONS ] , ok = CONNECTED ;
CL2CHAN * chan_cl2chan , * cl2chan ;
CHAR buffer [ 1000 ] ;
CHANNEL * chan ;
va_list ap ;
CLIENT * c ;
INT i , s ;
assert ( Client ! = NULL ) ;
assert ( Prefix ! = NULL ) ;
assert ( Format ! = NULL ) ;
va_start ( ap , Format ) ;
vsnprintf ( buffer , 1000 , Format , ap ) ;
va_end ( ap ) ;
/* initialisieren */
for ( i = 0 ; i < MAX_CONNECTIONS ; i + + ) sock [ i ] = FALSE ;
/* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
* den Text schicken . An Remote - Server aber jeweils nur einmal . */
chan_cl2chan = Channel_FirstChannelOf ( Client ) ;
while ( chan_cl2chan )
{
/* Channel des Users durchsuchen */
chan = Channel_GetChannel ( chan_cl2chan ) ;
cl2chan = Channel_FirstMember ( chan ) ;
while ( cl2chan )
{
c = Channel_GetClient ( cl2chan ) ;
if ( ! Remote )
{
if ( Client_Conn ( c ) < = NONE ) c = NULL ;
else if ( Client_Type ( c ) = = CLIENT_SERVER ) c = NULL ;
}
if ( c ) c = Client_NextHop ( c ) ;
if ( c & & ( c ! = Client ) )
{
/* Ok, anderer Client */
s = Client_Conn ( c ) ;
assert ( s > = 0 ) ;
assert ( s < MAX_CONNECTIONS ) ;
sock [ s ] = TRUE ;
}
cl2chan = Channel_NextMember ( chan , cl2chan ) ;
}
/* naechsten Channel */
chan_cl2chan = Channel_NextChannelOf ( Client , chan_cl2chan ) ;
}
/* Senden ... */
for ( i = 0 ; i < MAX_CONNECTIONS ; i + + )
{
if ( sock [ i ] )
{
ok = Conn_WriteStr ( i , " :%s %s " , Client_ID ( Prefix ) , buffer ) ;
if ( ! ok ) break ;
}
}
return ok ;
} /* IRC_WriteStrRelatedPrefix */
2001-12-23 22:57:16 +01:00
GLOBAL BOOLEAN IRC_PASS ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-03 03:26:51 +01:00
/* Fehler liefern, wenn kein lokaler Client */
2002-01-04 18:58:44 +01:00
if ( Client_Conn ( Client ) < = NONE ) return IRC_WriteStrClient ( Client , ERR_UNKNOWNCOMMAND_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-03 03:26:51 +01:00
2002-01-04 02:21:47 +01:00
if ( ( Client_Type ( Client ) = = CLIENT_UNKNOWN ) & & ( Req - > argc = = 1 ) )
2001-12-25 23:02:42 +01:00
{
2002-01-03 03:26:51 +01:00
/* noch nicht registrierte unbekannte Verbindung */
2002-01-04 02:21:47 +01:00
Log ( LOG_DEBUG , " Connection %d: got PASS command ... " , Client_Conn ( Client ) ) ;
2002-01-03 03:26:51 +01:00
/* Passwort speichern */
2002-01-04 02:21:47 +01:00
Client_SetPassword ( Client , Req - > argv [ 0 ] ) ;
2002-01-03 03:26:51 +01:00
2002-01-04 02:21:47 +01:00
Client_SetType ( Client , CLIENT_GOTPASS ) ;
2002-01-03 03:26:51 +01:00
return CONNECTED ;
}
2002-01-04 02:21:47 +01:00
else if ( ( ( Client_Type ( Client ) = = CLIENT_UNKNOWN ) | | ( Client_Type ( Client ) = = CLIENT_UNKNOWNSERVER ) ) & & ( ( Req - > argc = = 3 ) | | ( Req - > argc = = 4 ) ) )
2002-01-03 03:26:51 +01:00
{
/* noch nicht registrierte Server-Verbindung */
2002-01-04 02:21:47 +01:00
Log ( LOG_DEBUG , " Connection %d: got PASS command (new server link) ... " , Client_Conn ( Client ) ) ;
2002-01-03 03:26:51 +01:00
/* Passwort speichern */
2002-01-04 02:21:47 +01:00
Client_SetPassword ( Client , Req - > argv [ 0 ] ) ;
Client_SetType ( Client , CLIENT_GOTPASSSERVER ) ;
2002-01-03 03:26:51 +01:00
return CONNECTED ;
}
2002-01-04 02:21:47 +01:00
else if ( ( Client_Type ( Client ) = = CLIENT_UNKNOWN ) | | ( Client_Type ( Client ) = = CLIENT_UNKNOWNSERVER ) )
2002-01-03 03:26:51 +01:00
{
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-25 23:02:42 +01:00
}
2002-01-04 18:58:44 +01:00
else return IRC_WriteStrClient ( Client , ERR_ALREADYREGISTRED_MSG , Client_ID ( Client ) ) ;
2001-12-23 22:57:16 +01:00
} /* IRC_PASS */
2002-01-03 03:26:51 +01:00
GLOBAL BOOLEAN IRC_SERVER ( CLIENT * Client , REQUEST * Req )
{
2002-01-04 02:21:47 +01:00
CHAR str [ LINE_LEN ] , * ptr ;
2002-02-11 02:03:20 +01:00
CLIENT * from , * c , * cl ;
2002-01-28 02:18:14 +01:00
CL2CHAN * cl2chan ;
2002-01-28 02:45:43 +01:00
INT max_hops , i ;
2002-02-11 02:03:20 +01:00
CHANNEL * chan ;
BOOLEAN ok ;
2002-01-04 02:21:47 +01:00
2002-01-03 03:26:51 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
/* Fehler liefern, wenn kein lokaler Client */
2002-01-04 18:58:44 +01:00
if ( Client_Conn ( Client ) < = NONE ) return IRC_WriteStrClient ( Client , ERR_UNKNOWNCOMMAND_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-03 03:26:51 +01:00
2002-01-04 02:21:47 +01:00
if ( Client_Type ( Client ) = = CLIENT_GOTPASSSERVER )
2002-01-03 03:26:51 +01:00
{
/* Verbindung soll als Server-Server-Verbindung registriert werden */
2002-01-04 02:21:47 +01:00
Log ( LOG_DEBUG , " Connection %d: got SERVER command (new server link) ... " , Client_Conn ( Client ) ) ;
2002-01-03 03:26:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-07 16:39:46 +01:00
if ( ( Req - > argc ! = 2 ) & & ( Req - > argc ! = 3 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-03 03:26:51 +01:00
2002-01-05 17:51:18 +01:00
/* Ist dieser Server bei uns konfiguriert? */
for ( i = 0 ; i < Conf_Server_Count ; i + + ) if ( strcasecmp ( Req - > argv [ 0 ] , Conf_Server [ i ] . name ) = = 0 ) break ;
if ( i > = Conf_Server_Count )
{
/* Server ist nicht konfiguriert! */
2002-01-06 16:21:29 +01:00
Log ( LOG_ERR , " Connection %d: Server \" %s \" not configured here! " , Client_Conn ( Client ) , Req - > argv [ 0 ] ) ;
Conn_Close ( Client_Conn ( Client ) , NULL , " Server not configured here " , TRUE ) ;
2002-01-05 17:51:18 +01:00
return DISCONNECTED ;
}
if ( strcmp ( Client_Password ( Client ) , Conf_Server [ i ] . pwd ) ! = 0 )
{
/* Falsches Passwort */
2002-01-06 16:21:29 +01:00
Log ( LOG_ERR , " Connection %d: Bad password for server \" %s \" ! " , Client_Conn ( Client ) , Req - > argv [ 0 ] ) ;
Conn_Close ( Client_Conn ( Client ) , NULL , " Bad password " , TRUE ) ;
2002-01-05 17:51:18 +01:00
return DISCONNECTED ;
}
2002-01-03 03:26:51 +01:00
/* Ist ein Server mit dieser ID bereits registriert? */
if ( ! Client_CheckID ( Client , Req - > argv [ 0 ] ) ) return DISCONNECTED ;
2002-01-09 02:09:58 +01:00
/* Server-Strukturen fuellen ;-) */
Client_SetID ( Client , Req - > argv [ 0 ] ) ;
Client_SetHops ( Client , 1 ) ;
Client_SetInfo ( Client , Req - > argv [ Req - > argc - 1 ] ) ;
2002-01-07 16:39:46 +01:00
/* Meldet sich der Server bei uns an? */
if ( Req - > argc = = 2 )
{
/* Unseren SERVER- und PASS-Befehl senden */
ok = TRUE ;
if ( ! IRC_WriteStrClient ( Client , " PASS %s " PASSSERVERADD , Conf_Server [ i ] . pwd ) ) ok = FALSE ;
else ok = IRC_WriteStrClient ( Client , " SERVER %s 1 :%s " , Conf_ServerName , Conf_ServerInfo ) ;
if ( ! ok )
{
Conn_Close ( Client_Conn ( Client ) , " Unexpected server behavior! " , NULL , FALSE ) ;
return DISCONNECTED ;
}
2002-01-09 02:09:58 +01:00
Client_SetIntroducer ( Client , Client ) ;
Client_SetToken ( Client , 1 ) ;
2002-01-07 16:39:46 +01:00
}
2002-01-09 02:09:58 +01:00
else Client_SetToken ( Client , atoi ( Req - > argv [ 1 ] ) ) ;
2002-01-03 03:26:51 +01:00
2002-01-04 02:36:40 +01:00
Log ( LOG_NOTICE , " Server \" %s \" registered (connection %d, 1 hop - direct link). " , Client_ID ( Client ) , Client_Conn ( Client ) ) ;
2002-01-03 03:26:51 +01:00
2002-01-04 02:21:47 +01:00
Client_SetType ( Client , CLIENT_SERVER ) ;
2002-01-07 16:39:46 +01:00
2002-01-28 02:45:43 +01:00
/* maximalen Hop Count ermitteln */
max_hops = 0 ;
2002-01-09 02:09:58 +01:00
c = Client_First ( ) ;
while ( c )
{
2002-01-28 02:45:43 +01:00
if ( Client_Hops ( c ) > max_hops ) max_hops = Client_Hops ( c ) ;
c = Client_Next ( c ) ;
}
/* Alle bisherigen Server dem neuen Server bekannt machen,
* die bisherigen Server ueber den neuen informierenn */
for ( i = 0 ; i < ( max_hops + 1 ) ; i + + )
{
c = Client_First ( ) ;
while ( c )
2002-01-09 02:09:58 +01:00
{
2002-01-28 02:45:43 +01:00
if ( ( Client_Type ( c ) = = CLIENT_SERVER ) & & ( c ! = Client ) & & ( c ! = Client_ThisServer ( ) ) & & ( Client_Hops ( c ) = = i ) )
2002-01-09 02:09:58 +01:00
{
2002-01-28 02:45:43 +01:00
if ( Client_Conn ( c ) > NONE )
{
/* Dem gefundenen Server gleich den neuen
2002-02-12 15:40:37 +01:00
* Server bekannt machen */
2002-01-28 02:45:43 +01:00
if ( ! IRC_WriteStrClient ( c , " SERVER %s %d %d :%s " , Client_ID ( Client ) , Client_Hops ( Client ) + 1 , Client_MyToken ( Client ) , Client_Info ( Client ) ) ) return DISCONNECTED ;
}
/* Den neuen Server ueber den alten informieren */
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 ;
2002-01-09 02:09:58 +01:00
}
2002-01-28 02:45:43 +01:00
c = Client_Next ( c ) ;
2002-01-09 02:09:58 +01:00
}
}
2002-01-08 00:42:12 +01:00
2002-01-09 02:09:58 +01:00
/* alle User dem neuen Server bekannt machen */
c = Client_First ( ) ;
while ( c )
{
if ( Client_Type ( c ) = = CLIENT_USER )
{
/* User an neuen Server melden */
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 ;
}
c = Client_Next ( c ) ;
}
2002-01-28 02:18:14 +01:00
/* Channels dem neuen Server bekannt machen */
chan = Channel_First ( ) ;
while ( chan )
{
sprintf ( str , " NJOIN %s : " , Channel_Name ( chan ) ) ;
/* alle Member suchen */
cl2chan = Channel_FirstMember ( chan ) ;
while ( cl2chan )
{
2002-02-11 02:03:20 +01:00
cl = Channel_GetClient ( cl2chan ) ;
assert ( cl ! = NULL ) ;
/* Nick, ggf. mit Modes, anhaengen */
2002-01-28 02:18:14 +01:00
if ( str [ strlen ( str ) - 1 ] ! = ' : ' ) strcat ( str , " , " ) ;
2002-02-11 02:03:20 +01:00
if ( strchr ( Channel_UserModes ( chan , cl ) , ' v ' ) ) strcat ( str , " + " ) ;
if ( strchr ( Channel_UserModes ( chan , cl ) , ' o ' ) ) strcat ( str , " @ " ) ;
strcat ( str , Client_ID ( cl ) ) ;
2002-01-28 02:18:14 +01:00
if ( strlen ( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ) )
{
/* Zeile senden */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
sprintf ( str , " NJOIN %s : " , Channel_Name ( chan ) ) ;
}
cl2chan = Channel_NextMember ( chan , cl2chan ) ;
}
/* noch Daten da? */
if ( str [ strlen ( str ) - 1 ] ! = ' : ' )
{
/* Ja; Also senden ... */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
}
/* naechsten Channel suchen */
chan = Channel_Next ( chan ) ;
}
2002-01-07 16:39:46 +01:00
2002-01-03 03:26:51 +01:00
return CONNECTED ;
}
2002-01-04 02:21:47 +01:00
else if ( Client_Type ( Client ) = = CLIENT_SERVER )
2002-01-03 03:26:51 +01:00
{
/* Neuer Server wird im Netz angekuendigt */
2002-01-04 02:21:47 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 4 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-04 02:21:47 +01:00
/* Ist ein Server mit dieser ID bereits registriert? */
if ( ! Client_CheckID ( Client , Req - > argv [ 0 ] ) ) return DISCONNECTED ;
/* Ueberfluessige Hostnamen aus Info-Text entfernen */
ptr = strchr ( Req - > argv [ 3 ] + 2 , ' [ ' ) ;
if ( ! ptr ) ptr = Req - > argv [ 3 ] ;
2002-01-28 01:55:08 +01:00
from = Client_GetFromID ( Req - > prefix ) ;
if ( ! from )
{
/* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
Log ( LOG_ALERT , " Unknown ID in prefix of SERVER: \" %s \" ! (on connection %d) " , Req - > prefix , Client_Conn ( Client ) ) ;
Conn_Close ( Client_Conn ( Client ) , NULL , " Unknown ID in prefix of SERVER " , TRUE ) ;
return DISCONNECTED ;
}
2002-01-04 02:21:47 +01:00
/* Neue Client-Struktur anlegen */
2002-01-29 01:13:45 +01:00
c = Client_NewRemoteServer ( Client , Req - > argv [ 0 ] , from , atoi ( Req - > argv [ 1 ] ) , atoi ( Req - > argv [ 2 ] ) , ptr , TRUE ) ;
2002-01-04 02:21:47 +01:00
if ( ! c )
{
/* Neue Client-Struktur konnte nicht angelegt werden */
2002-01-06 16:21:29 +01:00
Log ( LOG_ALERT , " Can't create client structure for server! (on connection %d) " , Client_Conn ( Client ) ) ;
Conn_Close ( Client_Conn ( Client ) , NULL , " Can't allocate client structure for remote server " , TRUE ) ;
2002-01-04 02:21:47 +01:00
return DISCONNECTED ;
}
/* Log-Meldung zusammenbauen und ausgeben */
2002-01-28 01:55:08 +01:00
if ( ( Client_Hops ( c ) > 1 ) & & ( Req - > prefix [ 0 ] ) ) sprintf ( str , " connected to %s, " , Client_ID ( from ) ) ;
2002-01-04 02:21:47 +01:00
else strcpy ( str , " " ) ;
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 " : " " ) ;
2002-01-28 01:55:08 +01:00
/* Andere Server informieren */
IRC_WriteStrServersPrefix ( Client , from , " SERVER %s %d %d :%s " , Client_ID ( c ) , Client_Hops ( c ) + 1 , Client_MyToken ( c ) , Client_Info ( c ) ) ;
2002-01-03 03:26:51 +01:00
return CONNECTED ;
}
2002-01-04 18:58:44 +01:00
else return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-03 03:26:51 +01:00
} /* IRC_SERVER */
GLOBAL BOOLEAN IRC_NJOIN ( CLIENT * Client , REQUEST * Req )
{
2002-02-12 15:40:37 +01:00
CHAR * channame , * ptr , modes [ 8 ] ;
2002-02-11 02:03:20 +01:00
BOOLEAN is_op , is_voiced ;
CHANNEL * chan ;
2002-01-27 18:15:49 +01:00
CLIENT * c ;
2002-01-03 03:26:51 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_SERVER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTEREDSERVER_MSG , Client_ID ( Client ) ) ;
2002-01-03 03:26:51 +01:00
2002-01-27 18:15:49 +01:00
/* Falsche Anzahl Parameter? */
if ( Req - > argc ! = 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-02-11 02:03:20 +01:00
channame = Req - > argv [ 0 ] ;
2002-01-27 18:15:49 +01:00
ptr = strtok ( Req - > argv [ 1 ] , " , " ) ;
while ( ptr )
{
2002-02-11 02:03:20 +01:00
is_op = is_voiced = FALSE ;
2002-01-27 18:15:49 +01:00
/* Prefixe abschneiden */
2002-02-11 02:03:20 +01:00
while ( ( * ptr = = ' @ ' ) | | ( * ptr = = ' + ' ) )
{
if ( * ptr = = ' @ ' ) is_op = TRUE ;
if ( * ptr = = ' + ' ) is_voiced = TRUE ;
ptr + + ;
}
2002-01-27 18:15:49 +01:00
c = Client_GetFromID ( ptr ) ;
2002-02-11 02:03:20 +01:00
if ( c )
{
Channel_Join ( c , channame ) ;
chan = Channel_Search ( channame ) ;
assert ( chan ! = NULL ) ;
if ( is_op ) Channel_UserModeAdd ( chan , c , ' o ' ) ;
if ( is_voiced ) Channel_UserModeAdd ( chan , c , ' v ' ) ;
2002-02-12 15:40:37 +01:00
/* im Channel bekannt machen */
IRC_WriteStrChannelPrefix ( Client , chan , c , FALSE , " JOIN :%s " , channame ) ;
/* Channel-User-Modes setzen */
strcpy ( modes , Channel_UserModes ( chan , c ) ) ;
if ( modes [ 0 ] )
{
/* Modes im Channel bekannt machen */
IRC_WriteStrChannelPrefix ( Client , chan , Client , FALSE , " MODE %s +%s %s " , channame , modes , Client_ID ( c ) ) ;
}
2002-02-11 02:03:20 +01:00
}
else Log ( LOG_ERR , " Got NJOIN for unknown nick \" %s \" for channel \" %s \" ! " , ptr , channame ) ;
2002-01-27 18:15:49 +01:00
/* naechsten Nick suchen */
ptr = strtok ( NULL , " , " ) ;
}
2002-02-11 02:03:20 +01:00
/* an andere Server weiterleiten */
IRC_WriteStrServersPrefix ( Client , Client_ThisServer ( ) , " NJOIN %s :%s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
2002-01-03 03:26:51 +01:00
return CONNECTED ;
} /* IRC_NJOIN */
2001-12-23 22:57:16 +01:00
GLOBAL BOOLEAN IRC_NICK ( CLIENT * Client , REQUEST * Req )
{
2002-01-07 16:39:46 +01:00
CLIENT * intr_c , * target , * c ;
2002-01-18 16:31:32 +01:00
CHAR * modes ;
2002-01-04 02:21:47 +01:00
2001-12-23 22:57:16 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2001-12-29 04:10:06 +01:00
/* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
# ifndef STRICT_RFC
2002-01-07 16:39:46 +01:00
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 ) )
2001-12-29 04:10:06 +01:00
# else
2002-01-07 16:39:46 +01:00
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 ) )
2001-12-29 04:10:06 +01:00
# endif
2001-12-23 22:57:16 +01:00
{
2002-01-03 03:26:51 +01:00
/* User-Registrierung bzw. Nick-Aenderung */
2001-12-25 20:19:30 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 1 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-25 20:19:30 +01:00
2002-01-07 16:39:46 +01:00
/* "Ziel-Client" ermitteln */
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
target = Client_GetFromID ( Req - > prefix ) ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
}
else
{
/* Ist der Client "restricted"? */
if ( Client_HasMode ( Client , ' r ' ) ) return IRC_WriteStrClient ( Client , ERR_RESTRICTED_MSG , Client_ID ( Client ) ) ;
target = Client ;
}
2001-12-29 04:10:06 +01:00
2002-02-12 15:40:37 +01:00
# ifndef STRICT_RFC
2001-12-29 04:10:06 +01:00
/* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
* wir nichts . So macht es das Original und mind . Snak hat probleme ,
* wenn wir es nicht so machen . Ob es so okay ist ? Hm . . . */
2002-01-07 16:39:46 +01:00
if ( strcmp ( Client_ID ( target ) , Req - > argv [ 0 ] ) = = 0 ) return CONNECTED ;
2001-12-29 04:10:06 +01:00
# endif
2002-01-02 13:46:41 +01:00
/* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
* will nur die Gross - und Kleinschreibung aendern . Das darf
* er natuerlich machen : - ) */
2002-01-07 16:39:46 +01:00
if ( strcasecmp ( Client_ID ( target ) , Req - > argv [ 0 ] ) ! = 0 )
2002-01-02 13:46:41 +01:00
{
2002-01-07 16:39:46 +01:00
if ( ! Client_CheckNick ( target , Req - > argv [ 0 ] ) ) return CONNECTED ;
2002-01-02 13:46:41 +01:00
}
2001-12-26 00:13:33 +01:00
2002-02-17 18:30:21 +01:00
/* Nick-Aenderung: allen mitteilen! */
2002-02-19 21:06:45 +01:00
2002-02-17 20:03:12 +01:00
if ( Client_Type ( Client ) = = CLIENT_USER ) IRC_WriteStrClientPrefix ( Client , Client , " NICK :%s " , Req - > argv [ 0 ] ) ;
2002-02-17 18:30:21 +01:00
IRC_WriteStrServersPrefix ( Client , target , " NICK :%s " , Req - > argv [ 0 ] ) ;
IRC_WriteStrRelatedPrefix ( target , target , FALSE , " NICK :%s " , Req - > argv [ 0 ] ) ;
2002-01-07 16:39:46 +01:00
2001-12-25 20:19:30 +01:00
/* Client-Nick registrieren */
2002-01-07 16:39:46 +01:00
Client_SetID ( target , Req - > argv [ 0 ] ) ;
2001-12-23 22:57:16 +01:00
2002-01-07 16:39:46 +01:00
if ( ( Client_Type ( target ) ! = CLIENT_USER ) & & ( Client_Type ( target ) ! = CLIENT_SERVER ) )
2001-12-25 20:19:30 +01:00
{
/* Neuer Client */
2002-01-04 02:21:47 +01:00
Log ( LOG_DEBUG , " Connection %d: got NICK command ... " , Client_Conn ( Client ) ) ;
if ( Client_Type ( Client ) = = CLIENT_GOTUSER ) return Hello_User ( Client ) ;
else Client_SetType ( Client , CLIENT_GOTNICK ) ;
2001-12-25 20:19:30 +01:00
}
2002-02-19 21:06:45 +01:00
else Log ( LOG_INFO , " User \" %s \" changed nick: \" %s \" -> \" %s \" . " , Client_Mask ( target ) , Client_ID ( target ) , Req - > argv [ 0 ] ) ;
2001-12-25 20:19:30 +01:00
return CONNECTED ;
}
2002-01-04 02:21:47 +01:00
else if ( Client_Type ( Client ) = = CLIENT_SERVER )
2002-01-03 03:26:51 +01:00
{
/* Server fuehrt neuen Client ein */
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 7 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-04 02:21:47 +01:00
/* Nick ueberpruefen */
c = Client_GetFromID ( Req - > argv [ 0 ] ) ;
if ( c )
{
/* Der neue Nick ist auf diesem Server bereits registriert:
* sowohl der neue , als auch der alte Client muessen nun
* disconnectiert werden . */
2002-01-08 00:42:12 +01:00
Log ( LOG_ERR , " Server %s introduces already registered nick \" %s \" ! " , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
2002-02-23 22:39:48 +01:00
Kill_Nick ( Req - > argv [ 0 ] , " Nick collision " ) ;
2002-01-04 02:21:47 +01:00
return CONNECTED ;
}
/* Server, zu dem der Client connectiert ist, suchen */
intr_c = Client_GetFromToken ( Client , atoi ( Req - > argv [ 4 ] ) ) ;
if ( ! intr_c )
{
2002-01-08 00:42:12 +01:00
Log ( LOG_ERR , " Server %s introduces nick \" %s \" on unknown server!? " , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
2002-02-23 22:39:48 +01:00
Kill_Nick ( Req - > argv [ 0 ] , " Unknown server " ) ;
2002-01-04 02:21:47 +01:00
return CONNECTED ;
}
/* Neue Client-Struktur anlegen */
2002-01-18 16:31:32 +01:00
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 ) ;
2002-01-04 02:21:47 +01:00
if ( ! c )
{
/* Eine neue Client-Struktur konnte nicht angelegt werden.
* Der Client muss disconnectiert werden , damit der Netz -
* status konsistent bleibt . */
2002-01-06 16:21:29 +01:00
Log ( LOG_ALERT , " Can't create client structure! (on connection %d) " , Client_Conn ( Client ) ) ;
2002-02-23 22:39:48 +01:00
Kill_Nick ( Req - > argv [ 0 ] , " Server error " ) ;
2002-01-04 02:21:47 +01:00
return CONNECTED ;
}
2002-01-18 16:31:32 +01:00
modes = Client_Modes ( c ) ;
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 " : " " ) ;
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 " : " " ) ;
2002-01-03 03:26:51 +01:00
2002-01-08 00:42:12 +01:00
/* Andere Server, ausser dem Introducer, informieren */
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 ] ) ;
2002-01-03 03:26:51 +01:00
return CONNECTED ;
}
2002-01-04 18:58:44 +01:00
else return IRC_WriteStrClient ( Client , ERR_ALREADYREGISTRED_MSG , Client_ID ( Client ) ) ;
2001-12-23 22:57:16 +01:00
} /* IRC_NICK */
GLOBAL BOOLEAN IRC_USER ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2001-12-29 04:10:06 +01:00
# ifndef STRICT_RFC
2002-01-04 02:21:47 +01:00
if ( Client_Type ( Client ) = = CLIENT_GOTNICK | | Client_Type ( Client ) = = CLIENT_GOTPASS | | Client_Type ( Client ) = = CLIENT_UNKNOWN )
2001-12-29 04:10:06 +01:00
# else
2002-01-04 02:21:47 +01:00
if ( Client_Type ( Client ) = = CLIENT_GOTNICK | | Client_Type ( Client ) = = CLIENT_GOTPASS )
2001-12-29 04:10:06 +01:00
# endif
2001-12-23 22:57:16 +01:00
{
2001-12-25 20:19:30 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 4 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-26 00:13:33 +01:00
2002-01-06 00:24:54 +01:00
Client_SetUser ( Client , Req - > argv [ 0 ] , FALSE ) ;
2002-01-04 02:21:47 +01:00
Client_SetInfo ( Client , Req - > argv [ 3 ] ) ;
2001-12-26 00:13:33 +01:00
2002-01-04 02:21:47 +01:00
Log ( LOG_DEBUG , " Connection %d: got USER command ... " , Client_Conn ( Client ) ) ;
if ( Client_Type ( Client ) = = CLIENT_GOTNICK ) return Hello_User ( Client ) ;
else Client_SetType ( Client , CLIENT_GOTUSER ) ;
2001-12-25 20:19:30 +01:00
return CONNECTED ;
2001-12-23 22:57:16 +01:00
}
2002-01-04 02:21:47 +01:00
else if ( Client_Type ( Client ) = = CLIENT_USER | | Client_Type ( Client ) = = CLIENT_SERVER | | Client_Type ( Client ) = = CLIENT_SERVICE )
2001-12-23 22:57:16 +01:00
{
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , ERR_ALREADYREGISTRED_MSG , Client_ID ( Client ) ) ;
2001-12-23 22:57:16 +01:00
}
2002-01-04 18:58:44 +01:00
else return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-23 22:57:16 +01:00
} /* IRC_USER */
2001-12-25 23:02:42 +01:00
GLOBAL BOOLEAN IRC_QUIT ( CLIENT * Client , REQUEST * Req )
{
2002-01-04 18:58:44 +01:00
CLIENT * target ;
2001-12-25 23:02:42 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( ( Client_Type ( Client ) = = CLIENT_USER ) | | ( Client_Type ( Client ) = = CLIENT_SERVICE ) )
2001-12-25 23:02:42 +01:00
{
2002-01-04 18:58:44 +01:00
/* User / Service */
2001-12-25 23:02:42 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc > 1 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-25 23:02:42 +01:00
2002-01-06 16:21:29 +01:00
if ( Req - > argc = = 0 ) Conn_Close ( Client_Conn ( Client ) , " Got QUIT command. " , NULL , TRUE ) ;
else Conn_Close ( Client_Conn ( Client ) , " Got QUIT command. " , Req - > argv [ 0 ] , TRUE ) ;
2001-12-25 23:02:42 +01:00
return DISCONNECTED ;
}
2002-01-04 18:58:44 +01:00
else if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
/* Server */
/* Falsche Anzahl Parameter? */
if ( Req - > argc > 1 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
target = Client_Search ( Req - > prefix ) ;
2002-01-06 16:21:29 +01:00
if ( ! target )
{
2002-01-08 00:42:12 +01:00
Log ( LOG_ERR , " Got QUIT from %s for unknown client!? " , Client_ID ( Client ) ) ;
2002-01-06 16:21:29 +01:00
return CONNECTED ;
}
if ( Req - > argc = = 0 ) Client_Destroy ( target , " Got QUIT command. " , NULL ) ;
else Client_Destroy ( target , " Got QUIT command. " , Req - > argv [ 0 ] ) ;
2002-01-04 18:58:44 +01:00
return CONNECTED ;
}
else return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-25 23:02:42 +01:00
} /* IRC_QUIT */
2002-01-04 18:58:44 +01:00
GLOBAL BOOLEAN IRC_SQUIT ( CLIENT * Client , REQUEST * Req )
{
CLIENT * target ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
/* SQUIT ist nur fuer Server erlaubt */
if ( Client_Type ( Client ) ! = CLIENT_SERVER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
/* Falsche Anzahl Parameter? */
if ( Req - > argc ! = 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
target = Client_GetFromID ( Req - > argv [ 0 ] ) ;
if ( ! target )
{
2002-01-06 16:21:29 +01:00
Log ( LOG_ERR , " Got SQUIT from %s for unknown server \ %s \" !? " , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
2002-01-04 18:58:44 +01:00
return CONNECTED ;
}
2002-01-06 16:21:29 +01:00
if ( target = = Client ) Log ( LOG_DEBUG , " Got SQUIT from %s: %s " , Client_ID ( Client ) , Req - > argv [ 1 ] ) ;
else Log ( LOG_DEBUG , " Got SQUIT from %s for %s: %s " , Client_ID ( Client ) , Client_ID ( target ) , Req - > argv [ 1 ] ) ;
2002-01-04 18:58:44 +01:00
2002-01-07 16:39:46 +01:00
/* SQUIT an alle Server weiterleiten */
IRC_WriteStrServers ( Client , " SQUIT %s :%s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
2002-01-04 18:58:44 +01:00
2002-01-05 01:48:33 +01:00
if ( Client_Conn ( target ) > NONE )
{
2002-01-06 16:21:29 +01:00
if ( Req - > argv [ 1 ] [ 0 ] ) Conn_Close ( Client_Conn ( target ) , " Got SQUIT command. " , Req - > argv [ 1 ] , TRUE ) ;
else Conn_Close ( Client_Conn ( target ) , " Got SQUIT command. " , NULL , TRUE ) ;
2002-01-05 01:48:33 +01:00
return DISCONNECTED ;
}
else
{
2002-01-06 16:21:29 +01:00
Client_Destroy ( target , " Got SQUIT command. " , Req - > argv [ 1 ] ) ;
2002-01-05 01:48:33 +01:00
return CONNECTED ;
}
2002-01-04 18:58:44 +01:00
} /* IRC_SQUIT */
2001-12-26 04:21:46 +01:00
GLOBAL BOOLEAN IRC_PING ( CLIENT * Client , REQUEST * Req )
{
2002-02-11 16:15:53 +01:00
CLIENT * target , * from ;
2001-12-26 04:21:46 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-27 20:17:26 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc < 1 ) return IRC_WriteStrClient ( Client , ERR_NOORIGIN_MSG , Client_ID ( Client ) ) ;
2002-02-11 16:15:53 +01:00
if ( Req - > argc > 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
if ( Req - > argc = = 2 )
{
/* es wurde ein Ziel-Client angegeben */
target = Client_GetFromID ( Req - > argv [ 1 ] ) ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > argv [ 1 ] ) ;
if ( target ! = Client_ThisServer ( ) )
{
/* ok, forwarden */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > prefix ) ;
return IRC_WriteStrClientPrefix ( Client_NextHop ( target ) , from , " PING %s :%s " , Client_ID ( from ) , Req - > argv [ 1 ] ) ;
}
}
2001-12-27 20:17:26 +01:00
2002-01-08 00:42:12 +01:00
Log ( LOG_DEBUG , " Connection %d: got PING, sending PONG ... " , Client_Conn ( Client ) ) ;
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , " PONG %s :%s " , Client_ID ( Client_ThisServer ( ) ) , Client_ID ( Client ) ) ;
2001-12-26 04:21:46 +01:00
} /* IRC_PING */
GLOBAL BOOLEAN IRC_PONG ( CLIENT * Client , REQUEST * Req )
{
2002-02-11 16:15:53 +01:00
CLIENT * target , * from ;
2001-12-26 04:21:46 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-26 04:21:46 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc < 1 ) return IRC_WriteStrClient ( Client , ERR_NOORIGIN_MSG , Client_ID ( Client ) ) ;
if ( Req - > argc > 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-26 04:21:46 +01:00
2002-02-11 16:15:53 +01:00
/* forwarden? */
if ( Req - > argc = = 2 )
{
target = Client_GetFromID ( Req - > argv [ 1 ] ) ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > argv [ 1 ] ) ;
2002-02-11 16:52:21 +01:00
if ( target ! = Client_ThisServer ( ) )
{
/* ok, forwarden */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > prefix ) ;
return IRC_WriteStrClientPrefix ( Client_NextHop ( target ) , from , " PONG %s :%s " , Client_ID ( from ) , Req - > argv [ 1 ] ) ;
}
2002-02-11 16:15:53 +01:00
}
2001-12-26 04:21:46 +01:00
/* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
* aktualisiert , daher muss das hier nicht mehr gemacht werden . */
2002-02-23 01:03:54 +01:00
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 ) ) ) ;
2002-02-11 02:03:20 +01:00
else Log ( LOG_DEBUG , " Connection %d: received PONG. " , Client_Conn ( Client ) ) ;
2001-12-26 04:21:46 +01:00
return CONNECTED ;
} /* IRC_PONG */
2001-12-25 20:19:30 +01:00
GLOBAL BOOLEAN IRC_MOTD ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-25 20:19:30 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 0 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-26 00:13:33 +01:00
return Show_MOTD ( Client ) ;
2001-12-25 20:19:30 +01:00
} /* IRC_MOTD */
2001-12-27 20:17:26 +01:00
GLOBAL BOOLEAN IRC_PRIVMSG ( CLIENT * Client , REQUEST * Req )
{
2002-01-05 20:15:03 +01:00
CLIENT * to , * from ;
2002-01-26 19:43:11 +01:00
CHANNEL * chan ;
2001-12-27 20:17:26 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-05 20:15:03 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-27 20:17:26 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc = = 0 ) return IRC_WriteStrClient ( Client , ERR_NORECIPIENT_MSG , Client_ID ( Client ) , Req - > command ) ;
if ( Req - > argc = = 1 ) return IRC_WriteStrClient ( Client , ERR_NOTEXTTOSEND_MSG , Client_ID ( Client ) ) ;
if ( Req - > argc > 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-27 20:17:26 +01:00
2002-01-05 20:15:03 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
2002-01-12 00:50:55 +01:00
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
2001-12-27 20:17:26 +01:00
to = Client_Search ( Req - > argv [ 0 ] ) ;
if ( to )
{
/* Okay, Ziel ist ein User */
2002-01-26 19:43:11 +01:00
if ( Client_Conn ( from ) > NONE ) Conn_UpdateIdle ( Client_Conn ( from ) ) ;
2002-01-05 20:15:03 +01:00
return IRC_WriteStrClientPrefix ( to , from , " PRIVMSG %s :%s " , Client_ID ( to ) , Req - > argv [ 1 ] ) ;
2001-12-27 20:17:26 +01:00
}
2002-01-26 19:43:11 +01:00
chan = Channel_Search ( Req - > argv [ 0 ] ) ;
if ( chan )
{
/* Okay, Ziel ist ein Channel */
if ( Client_Conn ( from ) > NONE ) Conn_UpdateIdle ( Client_Conn ( from ) ) ;
2002-01-27 18:15:49 +01:00
return IRC_WriteStrChannelPrefix ( Client , chan , from , TRUE , " PRIVMSG %s :%s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
2002-01-26 19:43:11 +01:00
}
return IRC_WriteStrClient ( from , ERR_NOSUCHNICK_MSG , Client_ID ( from ) , Req - > argv [ 0 ] ) ;
2001-12-27 20:17:26 +01:00
} /* IRC_PRIVMSG */
GLOBAL BOOLEAN IRC_NOTICE ( CLIENT * Client , REQUEST * Req )
{
2002-01-05 20:15:03 +01:00
CLIENT * to , * from ;
2001-12-27 20:17:26 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-05 20:15:03 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-27 20:17:26 +01:00
/* Falsche Anzahl Parameter? */
if ( Req - > argc ! = 2 ) return CONNECTED ;
2002-01-05 20:15:03 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
2002-01-12 00:50:55 +01:00
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
2002-01-05 20:15:03 +01:00
2001-12-27 20:17:26 +01:00
to = Client_Search ( Req - > argv [ 0 ] ) ;
if ( to )
{
/* Okay, Ziel ist ein User */
2002-01-05 20:15:03 +01:00
return IRC_WriteStrClientPrefix ( to , from , " NOTICE %s :%s " , Client_ID ( to ) , Req - > argv [ 1 ] ) ;
2001-12-27 20:17:26 +01:00
}
2002-01-05 20:15:03 +01:00
else return CONNECTED ;
2001-12-27 20:17:26 +01:00
} /* IRC_NOTICE */
2001-12-29 04:10:06 +01:00
GLOBAL BOOLEAN IRC_MODE ( CLIENT * Client , REQUEST * Req )
{
2002-02-06 17:51:22 +01:00
CHAR * mode_ptr , the_modes [ CLIENT_MODE_LEN ] , x [ 2 ] ;
2002-02-11 17:06:21 +01:00
CLIENT * cl , * chan_cl , * prefix ;
2001-12-29 04:10:06 +01:00
BOOLEAN set , ok ;
2002-01-28 14:05:48 +01:00
CHANNEL * chan ;
2001-12-29 04:10:06 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-02-11 17:06:21 +01:00
cl = chan_cl = prefix = NULL ;
2002-02-06 17:51:22 +01:00
chan = NULL ;
/* Valider Client? */
2002-01-04 18:58:44 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-29 04:10:06 +01:00
2002-02-06 17:51:22 +01:00
/* Keine Parameter? */
2002-01-28 14:05:48 +01:00
if ( Req - > argc < 1 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-29 04:10:06 +01:00
2002-02-06 17:51:22 +01:00
/* Ziel suchen: Client bzw. Channel */
if ( Client_IsValidNick ( Req - > argv [ 0 ] ) ) cl = Client_Search ( Req - > argv [ 0 ] ) ;
if ( Channel_IsValidName ( Req - > argv [ 0 ] ) ) chan = Channel_Search ( Req - > argv [ 0 ] ) ;
2002-01-28 14:05:48 +01:00
2002-02-06 17:51:22 +01:00
/* Kein Ziel gefunden? */
if ( ( ! cl ) & & ( ! chan ) ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
2002-01-03 03:26:51 +01:00
2002-02-11 02:03:20 +01:00
assert ( ( cl & & chan ) ! = TRUE ) ;
2002-02-06 17:51:22 +01:00
/* Falsche Anzahl Parameter? */
if ( ( cl ) & & ( Req - > argc > 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
if ( ( chan ) & & ( Req - > argc > 3 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-02-11 02:03:20 +01:00
/* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
if ( ( chan ) & & ( Req - > argc = = 3 ) )
{
chan_cl = Client_Search ( Req - > argv [ 2 ] ) ;
if ( ! chan_cl ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
}
2002-01-28 14:05:48 +01:00
2002-02-06 17:51:22 +01:00
/* Wenn Anfragender ein User ist: Zugriff erlaubt? */
2002-01-04 02:21:47 +01:00
if ( Client_Type ( Client ) = = CLIENT_USER )
2002-01-03 03:26:51 +01:00
{
2002-02-06 17:51:22 +01:00
if ( cl )
{
/* MODE ist nur fuer sich selber zulaessig! */
if ( cl ! = Client ) return IRC_WriteStrClient ( Client , ERR_USERSDONTMATCH_MSG , Client_ID ( Client ) ) ;
}
if ( chan )
{
/* Darf der User die Channel-Modes ermitteln? */
}
2002-01-03 03:26:51 +01:00
}
2001-12-29 04:10:06 +01:00
2002-02-06 17:51:22 +01:00
/* Werden die Modes "nur" erfragt? */
if ( ( cl ) & & ( Req - > argc = = 1 ) ) return IRC_WriteStrClient ( Client , RPL_UMODEIS_MSG , Client_ID ( Client ) , Client_Modes ( cl ) ) ;
2002-02-11 16:52:21 +01:00
if ( ( chan ) & & ( Req - > argc = = 1 ) ) return IRC_WriteStrClient ( Client , RPL_CHANNELMODEIS_MSG , Client_ID ( Client ) , Channel_Name ( chan ) , Channel_Modes ( chan ) ) ;
2001-12-29 04:10:06 +01:00
2002-02-06 17:51:22 +01:00
mode_ptr = Req - > argv [ 1 ] ;
2001-12-29 04:10:06 +01:00
/* Sollen Modes gesetzt oder geloescht werden? */
2002-02-11 02:03:20 +01:00
if ( cl )
{
if ( * mode_ptr = = ' + ' ) set = TRUE ;
else if ( * mode_ptr = = ' - ' ) set = FALSE ;
else return IRC_WriteStrClient ( Client , ERR_UMODEUNKNOWNFLAG_MSG , Client_ID ( Client ) ) ;
mode_ptr + + ;
}
else
{
if ( * mode_ptr = = ' - ' ) set = FALSE ;
else set = TRUE ;
if ( ( * mode_ptr = = ' - ' ) | | ( * mode_ptr = = ' + ' ) ) mode_ptr + + ;
}
2002-02-11 17:06:21 +01:00
/* Prefix fuer Antworten etc. ermitteln */
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
prefix = Client_GetFromID ( Req - > prefix ) ;
if ( ! prefix ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
}
else prefix = Client ;
2001-12-29 04:10:06 +01:00
/* Reply-String mit Aenderungen vorbereiten */
2002-02-06 17:51:22 +01:00
if ( set ) strcpy ( the_modes , " + " ) ;
else strcpy ( the_modes , " - " ) ;
2001-12-29 04:10:06 +01:00
ok = TRUE ;
x [ 1 ] = ' \0 ' ;
2002-02-06 17:51:22 +01:00
while ( * mode_ptr )
2001-12-29 04:10:06 +01:00
{
x [ 0 ] = ' \0 ' ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER )
2001-12-29 04:10:06 +01:00
{
2002-02-06 17:51:22 +01:00
/* Befehl kommt von einem Server, daher
* trauen wir ihm " unbesehen " . . . */
x [ 0 ] = * mode_ptr ;
2002-01-04 18:58:44 +01:00
}
else
{
2002-02-06 17:51:22 +01:00
/* Modes validieren */
if ( cl )
2002-01-04 18:58:44 +01:00
{
2002-02-06 17:51:22 +01:00
/* User-Modes */
switch ( * mode_ptr )
{
case ' i ' :
/* invisible */
x [ 0 ] = ' i ' ;
break ;
case ' r ' :
/* restricted (kann nur gesetzt werden) */
if ( set ) x [ 0 ] = ' r ' ;
else ok = IRC_WriteStrClient ( Client , ERR_RESTRICTED_MSG , Client_ID ( Client ) ) ;
break ;
case ' o ' :
/* operator (kann nur geloescht werden) */
if ( ! set )
{
Client_SetOperByMe ( Client , FALSE ) ;
x [ 0 ] = ' o ' ;
}
else ok = IRC_WriteStrClient ( Client , ERR_UMODEUNKNOWNFLAG_MSG , Client_ID ( Client ) ) ;
break ;
default :
2002-02-12 00:33:35 +01:00
Log ( LOG_DEBUG , " Unknown mode \" %c%c \" from \" %s \" !? " , set ? ' + ' : ' - ' , * mode_ptr , Client_ID ( Client ) ) ;
2002-02-17 18:43:14 +01:00
ok = IRC_WriteStrClient ( Client , ERR_UMODEUNKNOWNFLAG2_MSG , Client_ID ( Client ) , set ? ' + ' : ' - ' , * mode_ptr ) ;
2002-02-06 17:51:22 +01:00
x [ 0 ] = ' \0 ' ;
}
}
if ( chan )
{
2002-02-12 00:33:35 +01:00
/* Ist der User ein Channel Operator? */
if ( ! strchr ( Channel_UserModes ( chan , Client ) , ' o ' ) )
{
Log ( LOG_DEBUG , " Can't change modes: \" %s \" is not operator on %s! " , Client_ID ( Client ) , Channel_Name ( chan ) ) ;
ok = IRC_WriteStrClient ( Client , ERR_CHANOPRIVSNEEDED_MSG , Client_ID ( Client ) , Channel_Name ( chan ) ) ;
break ;
}
2002-02-11 02:03:20 +01:00
/* Channel-Modes oder Channel-User-Modes */
if ( chan_cl )
{
/* Channel-User-Modes */
2002-02-12 00:33:35 +01:00
switch ( * mode_ptr )
{
2002-02-13 18:52:27 +01:00
case ' o ' :
/* Channel Operator */
x [ 0 ] = ' o ' ;
break ;
case ' v ' :
/* Voice */
x [ 0 ] = ' v ' ;
break ;
2002-02-12 00:33:35 +01:00
default :
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 ) ) ;
2002-02-17 18:43:14 +01:00
ok = IRC_WriteStrClient ( Client , ERR_UMODEUNKNOWNFLAG2_MSG , Client_ID ( Client ) , set ? ' + ' : ' - ' , * mode_ptr ) ;
2002-02-12 00:33:35 +01:00
x [ 0 ] = ' \0 ' ;
}
2002-02-11 02:03:20 +01:00
}
else
{
/* Channel-Modes */
2002-02-12 00:33:35 +01:00
switch ( * mode_ptr )
{
2002-02-13 18:52:27 +01:00
case ' a ' :
/* Anonymous */
x [ 0 ] = ' a ' ;
break ;
case ' m ' :
/* Moderated */
x [ 0 ] = ' m ' ;
break ;
case ' n ' :
/* kein Schreiben in den Channel von aussen */
x [ 0 ] = ' n ' ;
break ;
case ' p ' :
/* Private */
x [ 0 ] = ' p ' ;
break ;
case ' q ' :
/* Quite */
x [ 0 ] = ' q ' ;
break ;
case ' s ' :
/* Secret */
x [ 0 ] = ' s ' ;
break ;
case ' t ' :
/* Topic Lock */
x [ 0 ] = ' t ' ;
break ;
2002-02-12 00:33:35 +01:00
default :
Log ( LOG_DEBUG , " Unknown channel-mode \" %c%c \" from \" %s \" at %s!? " , set ? ' + ' : ' - ' , * mode_ptr , Client_ID ( Client ) , Channel_Name ( chan ) ) ;
2002-02-17 18:43:14 +01:00
ok = IRC_WriteStrClient ( Client , ERR_UMODEUNKNOWNFLAG2_MSG , Client_ID ( Client ) , set ? ' + ' : ' - ' , * mode_ptr ) ;
2002-02-12 00:33:35 +01:00
x [ 0 ] = ' \0 ' ;
}
2002-02-11 02:03:20 +01:00
}
2002-01-04 18:58:44 +01:00
}
2001-12-29 04:10:06 +01:00
}
if ( ! ok ) break ;
2002-02-06 17:51:22 +01:00
mode_ptr + + ;
2001-12-29 04:10:06 +01:00
if ( ! x [ 0 ] ) continue ;
/* Okay, gueltigen Mode gefunden */
2002-02-06 17:51:22 +01:00
if ( cl )
2001-12-29 04:10:06 +01:00
{
2002-02-06 17:51:22 +01:00
/* Es geht um User-Modes */
if ( set )
{
/* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
2002-02-11 02:03:20 +01:00
if ( Client_ModeAdd ( cl , x [ 0 ] ) ) strcat ( the_modes , x ) ;
2002-02-06 17:51:22 +01:00
}
else
{
/* Modes geloescht. Wenn der Client ihn hatte: merken */
2002-02-11 02:03:20 +01:00
if ( Client_ModeDel ( cl , x [ 0 ] ) ) strcat ( the_modes , x ) ;
2002-02-06 17:51:22 +01:00
}
2001-12-29 04:10:06 +01:00
}
2002-02-06 17:51:22 +01:00
if ( chan )
2001-12-29 04:10:06 +01:00
{
2002-02-11 02:03:20 +01:00
/* Es geht um Channel-Modes oder Channel-User-Modes */
if ( chan_cl )
{
/* Channel-User-Modes */
if ( set )
{
/* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
if ( Channel_UserModeAdd ( chan , chan_cl , x [ 0 ] ) ) strcat ( the_modes , x ) ;
}
else
{
/* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
if ( Channel_UserModeDel ( chan , chan_cl , x [ 0 ] ) ) strcat ( the_modes , x ) ;
}
}
else
{
/* Channel-Mode */
if ( set )
{
/* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
if ( Channel_ModeAdd ( chan , x [ 0 ] ) ) strcat ( the_modes , x ) ;
}
else
{
/* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
if ( Channel_ModeDel ( chan , x [ 0 ] ) ) strcat ( the_modes , x ) ;
}
}
2001-12-29 04:10:06 +01:00
}
}
2002-02-06 17:51:22 +01:00
/* Wurden Modes geaendert? */
if ( the_modes [ 1 ] )
2001-12-29 04:10:06 +01:00
{
2002-02-06 17:51:22 +01:00
if ( cl )
2002-01-04 18:58:44 +01:00
{
2002-02-11 02:03:20 +01:00
/* Client-Mode */
2002-02-06 17:51:22 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
/* Modes an andere Server forwarden */
2002-02-11 17:06:21 +01:00
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s :%s " , Client_ID ( cl ) , the_modes ) ;
2002-02-06 17:51:22 +01:00
}
else
{
/* Bestaetigung an Client schicken & andere Server informieren */
2002-02-11 17:06:21 +01:00
ok = IRC_WriteStrClientPrefix ( Client , prefix , " MODE %s %s " , Client_ID ( cl ) , the_modes ) ;
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s :%s " , Client_ID ( cl ) , the_modes ) ;
2002-02-06 17:51:22 +01:00
}
Log ( LOG_DEBUG , " User \" %s \" : Mode change, now \" %s \" . " , Client_Mask ( cl ) , Client_Modes ( cl ) ) ;
2002-01-04 18:58:44 +01:00
}
2002-02-06 17:51:22 +01:00
if ( chan )
2002-01-04 18:58:44 +01:00
{
2002-02-11 02:03:20 +01:00
/* Channel-Modes oder Channel-User-Mode */
if ( chan_cl )
{
/* Channel-User-Mode */
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
/* Modes an andere Server und Channel-User forwarden */
2002-02-11 17:06:21 +01:00
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s %s :%s " , Channel_Name ( chan ) , the_modes , Client_ID ( chan_cl ) ) ;
IRC_WriteStrChannelPrefix ( Client , chan , prefix , FALSE , " MODE %s %s %s " , Channel_Name ( chan ) , the_modes , Client_ID ( chan_cl ) ) ;
2002-02-11 02:03:20 +01:00
}
else
{
2002-02-11 16:52:21 +01:00
/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
2002-02-11 17:06:21 +01:00
ok = IRC_WriteStrClientPrefix ( Client , prefix , " MODE %s %s %s " , Channel_Name ( chan ) , the_modes , Client_ID ( chan_cl ) ) ;
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s %s :%s " , Channel_Name ( chan ) , the_modes , Client_ID ( chan_cl ) ) ;
IRC_WriteStrChannelPrefix ( Client , chan , prefix , FALSE , " MODE %s %s %s " , Channel_Name ( chan ) , the_modes , Client_ID ( chan_cl ) ) ;
2002-02-11 02:03:20 +01:00
}
Log ( LOG_DEBUG , " User \" %s \" on %s: Mode change, now \" %s \" . " , Client_Mask ( chan_cl ) , Channel_Name ( chan ) , Channel_UserModes ( chan , chan_cl ) ) ;
}
else
{
/* Channel-Mode */
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
2002-02-11 16:52:21 +01:00
/* Modes an andere Server und Channel-User forwarden */
2002-02-11 17:06:21 +01:00
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s :%s " , Channel_Name ( chan ) , the_modes ) ;
IRC_WriteStrChannelPrefix ( Client , chan , prefix , FALSE , " MODE %s %s " , Channel_Name ( chan ) , the_modes ) ;
2002-02-11 02:03:20 +01:00
}
else
{
2002-02-11 16:52:21 +01:00
/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
2002-02-11 17:06:21 +01:00
ok = IRC_WriteStrClientPrefix ( Client , prefix , " MODE %s %s " , Channel_Name ( chan ) , the_modes ) ;
IRC_WriteStrServersPrefix ( Client , prefix , " MODE %s :%s " , Channel_Name ( chan ) , the_modes ) ;
IRC_WriteStrChannelPrefix ( Client , chan , prefix , FALSE , " MODE %s %s " , Channel_Name ( chan ) , the_modes ) ;
2002-02-11 02:03:20 +01:00
}
Log ( LOG_DEBUG , " Channel \" %s \" : Mode change, now \" %s \" . " , Channel_Name ( chan ) , Channel_Modes ( chan ) ) ;
}
2002-01-04 18:58:44 +01:00
}
2001-12-29 04:10:06 +01:00
}
2002-02-06 17:51:22 +01:00
2001-12-29 04:10:06 +01:00
return ok ;
} /* IRC_MODE */
2001-12-31 03:18:51 +01:00
GLOBAL BOOLEAN IRC_OPER ( CLIENT * Client , REQUEST * Req )
{
2002-01-02 03:44:36 +01:00
INT i ;
2001-12-31 03:18:51 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 2 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-02 03:44:36 +01:00
/* Operator suchen */
for ( i = 0 ; i < Conf_Oper_Count ; i + + )
{
if ( Conf_Oper [ i ] . name [ 0 ] & & Conf_Oper [ i ] . pwd [ 0 ] & & ( strcmp ( Conf_Oper [ i ] . name , Req - > argv [ 0 ] ) = = 0 ) ) break ;
}
2002-01-06 16:21:29 +01:00
if ( i > = Conf_Oper_Count )
{
Log ( LOG_WARNING , " Got invalid OPER from \" %s \" : Name \" %s \" not configured! " , Client_Mask ( Client ) , Req - > argv [ 0 ] ) ;
return IRC_WriteStrClient ( Client , ERR_PASSWDMISMATCH_MSG , Client_ID ( Client ) ) ;
}
2001-12-31 03:18:51 +01:00
2002-01-06 16:21:29 +01:00
/* Stimmt das Passwort? */
if ( strcmp ( Conf_Oper [ i ] . pwd , Req - > argv [ 1 ] ) ! = 0 )
{
Log ( LOG_WARNING , " Got invalid OPER from \" %s \" : Bad password for \" %s \" ! " , Client_Mask ( Client ) , Conf_Oper [ i ] . name ) ;
return IRC_WriteStrClient ( Client , ERR_PASSWDMISMATCH_MSG , Client_ID ( Client ) ) ;
}
2001-12-31 03:18:51 +01:00
2002-01-04 02:21:47 +01:00
if ( ! Client_HasMode ( Client , ' o ' ) )
2001-12-31 03:18:51 +01:00
{
/* noch kein o-Mode gesetzt */
2002-01-04 02:21:47 +01:00
Client_ModeAdd ( Client , ' o ' ) ;
2002-01-21 01:05:11 +01:00
if ( ! IRC_WriteStrClient ( Client , " MODE %s :+o " , Client_ID ( Client ) ) ) return DISCONNECTED ;
2002-01-07 17:02:36 +01:00
IRC_WriteStrServersPrefix ( NULL , Client , " MODE %s :+o " , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
}
2002-01-06 16:21:29 +01:00
if ( ! Client_OperByMe ( Client ) ) Log ( LOG_NOTICE , " Got valid OPER from \" %s \" , user is an IRC operator now. " , Client_Mask ( Client ) ) ;
2001-12-31 03:18:51 +01:00
2002-01-04 02:21:47 +01:00
Client_SetOperByMe ( Client , TRUE ) ;
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , RPL_YOUREOPER_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
} /* IRC_OPER */
GLOBAL BOOLEAN IRC_DIE ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 0 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 03:18:51 +01:00
2002-01-04 18:58:44 +01:00
if ( ( ! Client_HasMode ( Client , ' o ' ) ) | | ( ! Client_OperByMe ( Client ) ) ) return IRC_WriteStrClient ( Client , ERR_NOPRIVILEGES_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
2002-01-04 02:21:47 +01:00
Log ( LOG_NOTICE , " Got DIE command from \" %s \" , going down! " , Client_Mask ( Client ) ) ;
2001-12-31 03:18:51 +01:00
NGIRCd_Quit = TRUE ;
return CONNECTED ;
} /* IRC_DIE */
GLOBAL BOOLEAN IRC_RESTART ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 0 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 03:18:51 +01:00
2002-01-04 18:58:44 +01:00
if ( ( ! Client_HasMode ( Client , ' o ' ) ) | | ( ! Client_OperByMe ( Client ) ) ) return IRC_WriteStrClient ( Client , ERR_NOPRIVILEGES_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
2002-01-04 02:21:47 +01:00
Log ( LOG_NOTICE , " Got RESTART command from \" %s \" , going down! " , Client_Mask ( Client ) ) ;
2001-12-31 03:18:51 +01:00
NGIRCd_Restart = TRUE ;
return CONNECTED ;
} /* IRC_RESTART */
2001-12-31 16:33:13 +01:00
GLOBAL BOOLEAN IRC_NAMES ( CLIENT * Client , REQUEST * Req )
{
CHAR rpl [ COMMAND_LEN ] ;
CLIENT * c ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 16:33:13 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( Req - > argc ! = 0 ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 16:33:13 +01:00
/* Noch alle User ausgeben, die in keinem Channel sind */
rpl [ 0 ] = ' \0 ' ;
c = Client_First ( ) ;
while ( c )
{
2002-01-04 02:21:47 +01:00
if ( Client_Type ( c ) = = CLIENT_USER )
2001-12-31 16:33:13 +01:00
{
/* Okay, das ist ein User */
2002-01-04 02:21:47 +01:00
strcat ( rpl , Client_ID ( c ) ) ;
2001-12-31 16:33:13 +01:00
strcat ( rpl , " " ) ;
}
/* Antwort zu lang? Splitten. */
if ( strlen ( rpl ) > 480 )
{
if ( rpl [ strlen ( rpl ) - 1 ] = = ' ' ) rpl [ strlen ( rpl ) - 1 ] = ' \0 ' ;
2002-01-04 18:58:44 +01:00
if ( ! IRC_WriteStrClient ( Client , RPL_NAMREPLY_MSG , Client_ID ( Client ) , " * " , " * " , rpl ) ) return DISCONNECTED ;
2001-12-31 16:33:13 +01:00
rpl [ 0 ] = ' \0 ' ;
}
c = Client_Next ( c ) ;
}
if ( rpl [ 0 ] )
{
/* es wurden User gefunden */
if ( rpl [ strlen ( rpl ) - 1 ] = = ' ' ) rpl [ strlen ( rpl ) - 1 ] = ' \0 ' ;
2002-01-04 18:58:44 +01:00
if ( ! IRC_WriteStrClient ( Client , RPL_NAMREPLY_MSG , Client_ID ( Client ) , " * " , " * " , rpl ) ) return DISCONNECTED ;
2001-12-31 16:33:13 +01:00
}
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , RPL_ENDOFNAMES_MSG , Client_ID ( Client ) , " * " ) ;
2001-12-31 16:33:13 +01:00
} /* IRC_NAMES */
2001-12-31 03:18:51 +01:00
GLOBAL BOOLEAN IRC_ISON ( CLIENT * Client , REQUEST * Req )
{
CHAR rpl [ COMMAND_LEN ] ;
CLIENT * c ;
CHAR * ptr ;
INT i ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( ( Req - > argc < 1 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 03:18:51 +01:00
strcpy ( rpl , RPL_ISON_MSG ) ;
for ( i = 0 ; i < Req - > argc ; i + + )
{
ptr = strtok ( Req - > argv [ i ] , " " ) ;
while ( ptr )
{
ngt_TrimStr ( ptr ) ;
2002-01-04 02:21:47 +01:00
c = Client_GetFromID ( ptr ) ;
if ( c & & ( Client_Type ( c ) = = CLIENT_USER ) )
2001-12-31 03:18:51 +01:00
{
/* Dieser Nick ist "online" */
strcat ( rpl , ptr ) ;
strcat ( rpl , " " ) ;
}
ptr = strtok ( NULL , " " ) ;
}
}
if ( rpl [ strlen ( rpl ) - 1 ] = = ' ' ) rpl [ strlen ( rpl ) - 1 ] = ' \0 ' ;
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , rpl , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
} /* IRC_ISON */
GLOBAL BOOLEAN IRC_WHOIS ( CLIENT * Client , REQUEST * Req )
{
2002-01-06 00:24:54 +01:00
CLIENT * from , * target , * c ;
2002-01-29 01:13:45 +01:00
CHAR str [ LINE_LEN + 1 ] , * ptr = NULL ;
CL2CHAN * cl2chan ;
2002-02-11 02:03:20 +01:00
CHANNEL * chan ;
2001-12-31 03:18:51 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-05 20:15:03 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( ( Req - > argc < 1 ) | | ( Req - > argc > 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 03:18:51 +01:00
/* Client suchen */
2002-01-06 00:24:54 +01:00
c = Client_GetFromID ( Req - > argv [ Req - > argc - 1 ] ) ;
if ( ( ! c ) | | ( Client_Type ( c ) ! = CLIENT_USER ) ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > argv [ Req - > argc - 1 ] ) ;
2002-01-05 20:15:03 +01:00
/* Empfaenger des WHOIS suchen */
2002-01-06 00:24:54 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
/* Forwarden an anderen Server? */
if ( Req - > argc > 1 )
{
2002-01-06 16:21:29 +01:00
/* angegebenen Ziel-Server suchen */
2002-01-06 00:24:54 +01:00
target = Client_GetFromID ( Req - > argv [ 1 ] ) ;
if ( ! target ) return IRC_WriteStrClient ( from , ERR_NOSUCHSERVER_MSG , Client_ID ( from ) , Req - > argv [ 1 ] ) ;
2002-01-06 16:21:29 +01:00
ptr = Req - > argv [ 1 ] ;
2002-01-06 00:24:54 +01:00
}
2002-01-09 02:09:58 +01:00
# ifndef STRICT_RFC
2002-01-06 16:21:29 +01:00
else if ( Client_Conn ( c ) = = NONE )
{
/* Client ist nicht von uns. Ziel-Server suchen */
target = c ;
ptr = Req - > argv [ 0 ] ;
}
2002-01-09 02:09:58 +01:00
# endif
2002-01-06 16:21:29 +01:00
else target = NULL ;
2002-01-09 22:30:45 +01:00
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 ) ;
2001-12-31 03:18:51 +01:00
/* Nick, User und Name */
2002-01-06 00:24:54 +01:00
if ( ! IRC_WriteStrClient ( from , RPL_WHOISUSER_MSG , Client_ID ( from ) , Client_ID ( c ) , Client_User ( c ) , Client_Hostname ( c ) , Client_Info ( c ) ) ) return DISCONNECTED ;
2001-12-31 03:18:51 +01:00
/* Server */
2002-01-06 00:24:54 +01:00
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 ;
2001-12-31 03:18:51 +01:00
2002-01-29 01:13:45 +01:00
/* Channels */
sprintf ( str , RPL_WHOISCHANNELS_MSG , Client_ID ( from ) , Client_ID ( c ) ) ;
cl2chan = Channel_FirstChannelOf ( c ) ;
while ( cl2chan )
{
2002-02-11 02:03:20 +01:00
chan = Channel_GetChannel ( cl2chan ) ;
assert ( chan ! = NULL ) ;
2002-01-29 01:13:45 +01:00
/* Channel-Name anhaengen */
if ( str [ strlen ( str ) - 1 ] ! = ' : ' ) strcat ( str , " " ) ;
2002-02-11 02:03:20 +01:00
if ( strchr ( Channel_UserModes ( chan , c ) , ' v ' ) ) strcat ( str , " + " ) ;
if ( strchr ( Channel_UserModes ( chan , c ) , ' o ' ) ) strcat ( str , " @ " ) ;
strcat ( str , Channel_Name ( chan ) ) ;
2002-01-29 01:13:45 +01:00
if ( strlen ( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ) )
{
/* Zeile wird zu lang: senden! */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
sprintf ( str , RPL_WHOISCHANNELS_MSG , Client_ID ( from ) , Client_ID ( c ) ) ;
}
/* naechstes Mitglied suchen */
cl2chan = Channel_NextChannelOf ( c , cl2chan ) ;
}
if ( str [ strlen ( str ) - 1 ] ! = ' : ' )
{
/* Es sind noch Daten da, die gesendet werden muessen */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
}
2001-12-31 03:18:51 +01:00
/* IRC-Operator? */
2002-01-04 02:21:47 +01:00
if ( Client_HasMode ( c , ' o ' ) )
2001-12-31 03:18:51 +01:00
{
2002-01-06 00:24:54 +01:00
if ( ! IRC_WriteStrClient ( from , RPL_WHOISOPERATOR_MSG , Client_ID ( from ) , Client_ID ( c ) ) ) return DISCONNECTED ;
2001-12-31 03:18:51 +01:00
}
/* Idle (nur lokale Clients) */
2002-01-04 02:21:47 +01:00
if ( Client_Conn ( c ) > NONE )
2001-12-31 03:18:51 +01:00
{
2002-01-06 00:24:54 +01:00
if ( ! IRC_WriteStrClient ( from , RPL_WHOISIDLE_MSG , Client_ID ( from ) , Client_ID ( c ) , Conn_GetIdle ( Client_Conn ( c ) ) ) ) return DISCONNECTED ;
2001-12-31 03:18:51 +01:00
}
/* End of Whois */
2002-01-06 00:24:54 +01:00
return IRC_WriteStrClient ( from , RPL_ENDOFWHOIS_MSG , Client_ID ( from ) , Client_ID ( c ) ) ;
2001-12-31 03:18:51 +01:00
} /* IRC_WHOIS */
GLOBAL BOOLEAN IRC_USERHOST ( CLIENT * Client , REQUEST * Req )
{
CHAR rpl [ COMMAND_LEN ] ;
CLIENT * c ;
INT max , i ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 18:58:44 +01:00
if ( Client_Type ( Client ) ! = CLIENT_USER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2001-12-31 03:18:51 +01:00
/* Falsche Anzahl Parameter? */
2002-01-04 18:58:44 +01:00
if ( ( Req - > argc < 1 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2001-12-31 03:18:51 +01:00
if ( Req - > argc > 5 ) max = 5 ;
else max = Req - > argc ;
strcpy ( rpl , RPL_USERHOST_MSG ) ;
for ( i = 0 ; i < max ; i + + )
{
2002-01-04 02:21:47 +01:00
c = Client_GetFromID ( Req - > argv [ i ] ) ;
if ( c & & ( Client_Type ( c ) = = CLIENT_USER ) )
2001-12-31 03:18:51 +01:00
{
/* Dieser Nick ist "online" */
2002-01-04 02:21:47 +01:00
strcat ( rpl , Client_ID ( c ) ) ;
if ( Client_HasMode ( c , ' o ' ) ) strcat ( rpl , " * " ) ;
2001-12-31 03:18:51 +01:00
strcat ( rpl , " = " ) ;
2002-01-04 02:21:47 +01:00
if ( Client_HasMode ( c , ' a ' ) ) strcat ( rpl , " - " ) ;
2001-12-31 03:18:51 +01:00
else strcat ( rpl , " + " ) ;
2002-01-04 02:21:47 +01:00
strcat ( rpl , Client_User ( c ) ) ;
2001-12-31 03:18:51 +01:00
strcat ( rpl , " @ " ) ;
2002-01-04 02:21:47 +01:00
strcat ( rpl , Client_Hostname ( c ) ) ;
2001-12-31 03:18:51 +01:00
strcat ( rpl , " " ) ;
}
}
if ( rpl [ strlen ( rpl ) - 1 ] = = ' ' ) rpl [ strlen ( rpl ) - 1 ] = ' \0 ' ;
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , rpl , Client_ID ( Client ) ) ;
2002-01-02 03:44:36 +01:00
} /* IRC_USERHOST */
GLOBAL BOOLEAN IRC_ERROR ( CLIENT * Client , REQUEST * Req )
{
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-04 02:21:47 +01:00
if ( Req - > argc < 1 ) Log ( LOG_NOTICE , " Got ERROR from \" %s \" ! " , Client_Mask ( Client ) ) ;
else Log ( LOG_NOTICE , " Got ERROR from \" %s \" : %s! " , Client_Mask ( Client ) , Req - > argv [ 0 ] ) ;
2002-01-02 03:44:36 +01:00
return CONNECTED ;
} /* IRC_ERROR */
2001-12-31 03:18:51 +01:00
2002-01-12 00:50:55 +01:00
GLOBAL BOOLEAN IRC_LUSERS ( CLIENT * Client , REQUEST * Req )
{
2002-01-16 23:10:18 +01:00
CLIENT * target , * from ;
2002-01-12 00:50:55 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
2002-01-16 23:10:18 +01:00
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
2002-01-12 00:50:55 +01:00
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc > 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
2002-01-16 23:10:18 +01:00
/* Absender ermitteln */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
/* An anderen Server forwarden? */
if ( Req - > argc = = 2 )
{
target = Client_GetFromID ( Req - > argv [ 1 ] ) ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > argv [ 1 ] ) ;
else if ( target ! = Client_ThisServer ( ) ) return IRC_WriteStrClientPrefix ( target , from , " LUSERS %s %s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
}
/* Wer ist der Absender? */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) target = Client_GetFromID ( Req - > prefix ) ;
else target = Client ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
2002-01-12 00:50:55 +01:00
2002-02-14 00:05:29 +01:00
Send_LUSERS ( target ) ;
2002-01-16 23:10:18 +01:00
2002-01-12 00:50:55 +01:00
return CONNECTED ;
} /* IRC_LUSERS */
GLOBAL BOOLEAN IRC_LINKS ( CLIENT * Client , REQUEST * Req )
{
CLIENT * target , * from , * c ;
CHAR * mask ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc > 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
/* Server-Mask ermitteln */
if ( Req - > argc > 0 ) mask = Req - > argv [ Req - > argc - 1 ] ;
else mask = " * " ;
/* Absender ermitteln */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) from = Client_GetFromID ( Req - > prefix ) ;
else from = Client ;
if ( ! from ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
/* An anderen Server forwarden? */
if ( Req - > argc = = 2 )
{
target = Client_GetFromID ( Req - > argv [ 0 ] ) ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
else if ( target ! = Client_ThisServer ( ) ) return IRC_WriteStrClientPrefix ( target , from , " LINKS %s %s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
}
/* Wer ist der Absender? */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) target = Client_GetFromID ( Req - > prefix ) ;
else target = Client ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
c = Client_First ( ) ;
while ( c )
{
if ( Client_Type ( c ) = = CLIENT_SERVER )
{
2002-01-29 01:13:45 +01:00
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 ;
2002-01-12 00:50:55 +01:00
}
c = Client_Next ( c ) ;
}
return IRC_WriteStrClient ( target , RPL_ENDOFLINKS_MSG , Client_ID ( target ) , mask ) ;
} /* IRC_LINKS */
2002-01-21 01:05:11 +01:00
GLOBAL BOOLEAN IRC_JOIN ( CLIENT * Client , REQUEST * Req )
{
2002-02-11 02:03:20 +01:00
CHAR * channame , * flags , modes [ 8 ] ;
BOOLEAN is_new_chan ;
2002-01-21 01:05:11 +01:00
CLIENT * target ;
2002-02-11 02:03:20 +01:00
CHANNEL * chan ;
2002-01-21 01:05:11 +01:00
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc > 1 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
/* Wer ist der Absender? */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) target = Client_GetFromID ( Req - > prefix ) ;
else target = Client ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
/* Channel-Namen durchgehen */
2002-02-11 02:03:20 +01:00
channame = strtok ( Req - > argv [ 0 ] , " , " ) ;
while ( channame )
2002-01-21 01:05:11 +01:00
{
2002-02-11 02:03:20 +01:00
/* wird der Channel neu angelegt? */
flags = NULL ;
if ( Channel_Search ( channame ) ) is_new_chan = FALSE ;
else is_new_chan = TRUE ;
/* Hat ein Server Channel-User-Modes uebergeben? */
2002-01-27 18:15:49 +01:00
if ( Client_Type ( Client ) = = CLIENT_SERVER )
{
/* Channel-Flags extrahieren */
2002-02-11 02:03:20 +01:00
flags = strchr ( channame , 0x7 ) ;
2002-01-27 18:15:49 +01:00
if ( flags ) * flags + + = ' \0 ' ;
}
2002-02-11 02:03:20 +01:00
/* neuer Channel udn lokaler Client? */
if ( is_new_chan & & ( Client_Type ( Client ) = = CLIENT_USER ) )
{
/* Dann soll der Client Channel-Operator werden! */
flags = " o " ;
}
/* Channel joinen (und ggf. anlegen) */
if ( ! Channel_Join ( target , channame ) )
2002-01-21 01:05:11 +01:00
{
/* naechsten Namen ermitteln */
2002-02-11 02:03:20 +01:00
channame = strtok ( NULL , " , " ) ;
2002-01-21 01:05:11 +01:00
continue ;
}
2002-02-11 02:03:20 +01:00
chan = Channel_Search ( channame ) ;
assert ( chan ! = NULL ) ;
/* Modes setzen (wenn vorhanden) */
while ( flags & & * flags )
{
Channel_UserModeAdd ( chan , target , * flags ) ;
flags + + ;
}
/* Muessen Modes an andere Server gemeldet werden? */
strcpy ( & modes [ 1 ] , Channel_UserModes ( chan , target ) ) ;
if ( modes [ 1 ] ) modes [ 0 ] = 0x7 ;
else modes [ 0 ] = ' \0 ' ;
2002-01-21 01:05:11 +01:00
2002-01-27 22:56:39 +01:00
/* An andere Server weiterleiten */
2002-02-11 02:03:20 +01:00
IRC_WriteStrServersPrefix ( Client , target , " JOIN :%s%s " , channame , modes ) ;
/* im Channel bekannt machen */
IRC_WriteStrChannelPrefix ( Client , chan , target , FALSE , " JOIN :%s " , channame ) ;
if ( modes [ 1 ] )
{
/* Modes im Channel bekannt machen */
IRC_WriteStrChannelPrefix ( Client , chan , target , FALSE , " MODE %s %s :%s " , channame , modes , Client_ID ( target ) ) ;
}
2002-01-21 01:05:11 +01:00
2002-01-27 18:15:49 +01:00
if ( Client_Type ( Client ) = = CLIENT_USER )
{
2002-01-27 22:56:39 +01:00
/* an Client bestaetigen */
2002-02-11 02:03:20 +01:00
IRC_WriteStrClientPrefix ( Client , target , " JOIN :%s " , channame ) ;
2002-01-27 18:15:49 +01:00
/* Topic an Client schicken */
2002-02-11 02:03:20 +01:00
IRC_WriteStrClient ( Client , RPL_TOPIC_MSG , Client_ID ( Client ) , channame , " What a wonderful channel! " ) ;
2002-01-28 14:05:48 +01:00
/* Mitglieder an Client Melden */
2002-02-11 02:03:20 +01:00
Send_NAMES ( Client , chan ) ;
2002-01-27 18:15:49 +01:00
}
2002-01-21 01:05:11 +01:00
/* naechsten Namen ermitteln */
2002-02-11 02:03:20 +01:00
channame = strtok ( NULL , " , " ) ;
2002-01-21 01:05:11 +01:00
}
return CONNECTED ;
} /* IRC_JOIN */
GLOBAL BOOLEAN IRC_PART ( CLIENT * Client , REQUEST * Req )
{
CLIENT * target ;
CHAR * chan ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
if ( ( Client_Type ( Client ) ! = CLIENT_USER ) & & ( Client_Type ( Client ) ! = CLIENT_SERVER ) ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc > 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
/* Wer ist der Absender? */
if ( Client_Type ( Client ) = = CLIENT_SERVER ) target = Client_GetFromID ( Req - > prefix ) ;
else target = Client ;
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHNICK_MSG , Client_ID ( Client ) , Req - > prefix ) ;
/* Channel-Namen durchgehen */
chan = strtok ( Req - > argv [ 0 ] , " , " ) ;
while ( chan )
{
if ( ! Channel_Part ( target , Client , chan , Req - > argc > 1 ? Req - > argv [ 1 ] : Client_ID ( target ) ) )
{
/* naechsten Namen ermitteln */
chan = strtok ( NULL , " , " ) ;
continue ;
}
/* naechsten Namen ermitteln */
chan = strtok ( NULL , " , " ) ;
}
return CONNECTED ;
} /* IRC_PART */
2002-02-18 00:38:58 +01:00
GLOBAL BOOLEAN IRC_VERSION ( CLIENT * Client , REQUEST * Req )
{
CLIENT * target ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc > 1 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
/* Ziel suchen */
if ( Req - > argc = = 1 ) target = Client_GetFromID ( Req - > argv [ 0 ] ) ;
else target = Client_ThisServer ( ) ;
/* An anderen Server weiterleiten? */
if ( target ! = Client_ThisServer ( ) )
{
if ( ! target ) return IRC_WriteStrClient ( Client , ERR_NOSUCHSERVER_MSG , Client_ID ( Client ) , Req - > argv [ 0 ] ) ;
IRC_WriteStrClientPrefix ( Client_NextHop ( target ) , Client , " VERSION %s " , Req - > argv [ 0 ] ) ;
return CONNECTED ;
}
2002-02-19 03:21:17 +01:00
2002-02-19 21:06:45 +01:00
return IRC_WriteStrClient ( Client , RPL_VERSION_MSG , Client_ID ( Client ) , NGIRCd_DebugLevel , Conf_ServerName , NGIRCd_VersionAddition ( ) ) ;
2002-02-18 00:38:58 +01:00
} /* IRC_VERSION */
2002-02-23 22:39:48 +01:00
GLOBAL BOOLEAN IRC_KILL ( CLIENT * Client , REQUEST * Req )
{
CLIENT * prefix , * c ;
assert ( Client ! = NULL ) ;
assert ( Req ! = NULL ) ;
if ( Client_Type ( Client ) ! = CLIENT_SERVER ) return IRC_WriteStrClient ( Client , ERR_NOTREGISTERED_MSG , Client_ID ( Client ) ) ;
/* Falsche Anzahl Parameter? */
if ( ( Req - > argc ! = 2 ) ) return IRC_WriteStrClient ( Client , ERR_NEEDMOREPARAMS_MSG , Client_ID ( Client ) , Req - > command ) ;
prefix = Client_GetFromID ( Req - > prefix ) ;
if ( ! prefix )
{
Log ( LOG_WARNING , " Got KILL with invalid prefix: \" %s \" ! " , Req - > prefix ) ;
prefix = Client_ThisServer ( ) ;
}
Log ( LOG_NOTICE , " Got KILL command from \" %s \" for \" %s \" : %s " , Client_Mask ( prefix ) , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
/* andere Server benachrichtigen */
IRC_WriteStrServersPrefix ( Client , prefix , " KILL %s :%s " , Req - > argv [ 0 ] , Req - > argv [ 1 ] ) ;
/* haben wir selber einen solchen Client? */
c = Client_GetFromID ( Req - > argv [ 0 ] ) ;
if ( c & & ( Client_Conn ( c ) ! = NONE ) ) Conn_Close ( Client_Conn ( c ) , NULL , Req - > argv [ 1 ] , TRUE ) ;
return CONNECTED ;
} /* IRC_KILL */
2002-01-03 03:26:51 +01:00
LOCAL BOOLEAN Hello_User ( CLIENT * Client )
2001-12-23 22:57:16 +01:00
{
assert ( Client ! = NULL ) ;
2002-01-03 03:26:51 +01:00
/* Passwort ueberpruefen */
2002-01-04 02:21:47 +01:00
if ( strcmp ( Client_Password ( Client ) , Conf_ServerPwd ) ! = 0 )
2001-12-23 22:57:16 +01:00
{
2002-01-03 03:26:51 +01:00
/* Falsches Passwort */
2002-01-06 16:21:29 +01:00
Log ( LOG_ERR , " User \" %s \" rejected (connection %d): Bad password! " , Client_Mask ( Client ) , Client_Conn ( Client ) ) ;
Conn_Close ( Client_Conn ( Client ) , NULL , " Bad password " , TRUE ) ;
2002-01-03 03:26:51 +01:00
return DISCONNECTED ;
2001-12-23 22:57:16 +01:00
}
2001-12-25 20:19:30 +01:00
2002-01-04 02:21:47 +01:00
Log ( LOG_NOTICE , " User \" %s \" registered (connection %d). " , Client_Mask ( Client ) , Client_Conn ( Client ) ) ;
2001-12-25 20:19:30 +01:00
2002-01-05 20:15:03 +01:00
/* Andere Server informieren */
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 ) ) ;
if ( ! IRC_WriteStrClient ( Client , RPL_WELCOME_MSG , Client_ID ( Client ) , Client_Mask ( Client ) ) ) return FALSE ;
if ( ! IRC_WriteStrClient ( Client , RPL_YOURHOST_MSG , Client_ID ( Client ) , Client_ID ( Client_ThisServer ( ) ) ) ) return FALSE ;
if ( ! IRC_WriteStrClient ( Client , RPL_CREATED_MSG , Client_ID ( Client ) , NGIRCd_StartStr ) ) return FALSE ;
if ( ! IRC_WriteStrClient ( Client , RPL_MYINFO_MSG , Client_ID ( Client ) , Client_ID ( Client_ThisServer ( ) ) ) ) return FALSE ;
2002-01-04 02:21:47 +01:00
Client_SetType ( Client , CLIENT_USER ) ;
2001-12-25 20:19:30 +01:00
2002-02-14 00:05:29 +01:00
if ( ! Send_LUSERS ( Client ) ) return DISCONNECTED ;
if ( ! Show_MOTD ( Client ) ) return DISCONNECTED ;
return CONNECTED ;
2001-12-24 02:34:06 +01:00
} /* Hello_User */
2001-12-25 20:19:30 +01:00
LOCAL BOOLEAN Show_MOTD ( CLIENT * Client )
2001-12-24 02:34:06 +01:00
{
2001-12-26 23:48:53 +01:00
BOOLEAN ok ;
CHAR line [ 127 ] ;
FILE * fd ;
2001-12-26 04:21:46 +01:00
assert ( Client ! = NULL ) ;
2001-12-26 23:48:53 +01:00
fd = fopen ( Conf_MotdFile , " r " ) ;
if ( ! fd )
{
Log ( LOG_WARNING , " Can't read MOTD file \" %s \" : %s " , Conf_MotdFile , strerror ( errno ) ) ;
2002-01-04 18:58:44 +01:00
return IRC_WriteStrClient ( Client , ERR_NOMOTD_MSG , Client_ID ( Client ) ) ;
2001-12-26 23:48:53 +01:00
}
2001-12-26 04:21:46 +01:00
2002-01-04 18:58:44 +01:00
IRC_WriteStrClient ( Client , RPL_MOTDSTART_MSG , Client_ID ( Client ) , Client_ID ( Client_ThisServer ( ) ) ) ;
2001-12-26 23:48:53 +01:00
while ( TRUE )
{
if ( ! fgets ( line , 126 , fd ) ) break ;
if ( line [ strlen ( line ) - 1 ] = = ' \n ' ) line [ strlen ( line ) - 1 ] = ' \0 ' ;
2002-01-05 20:15:03 +01:00
if ( ! IRC_WriteStrClient ( Client , RPL_MOTD_MSG , Client_ID ( Client ) , line ) )
{
fclose ( fd ) ;
return FALSE ;
}
2001-12-26 23:48:53 +01:00
}
2002-01-04 18:58:44 +01:00
ok = IRC_WriteStrClient ( Client , RPL_ENDOFMOTD_MSG , Client_ID ( Client ) ) ;
2001-12-26 23:48:53 +01:00
fclose ( fd ) ;
return ok ;
2001-12-24 02:34:06 +01:00
} /* Show_MOTD */
2002-02-23 22:39:48 +01:00
LOCAL VOID Kill_Nick ( CHAR * Nick , CHAR * Reason )
2002-01-04 02:21:47 +01:00
{
2002-02-23 22:39:48 +01:00
CLIENT * c ;
assert ( Nick ! = NULL ) ;
assert ( Reason ! = NULL ) ;
Log ( LOG_ERR , " User(s) with nick \" %s \" will be disconnected: %s " , Nick , Reason ) ;
/* andere Server benachrichtigen */
IRC_WriteStrServers ( NULL , " KILL %s :%s " , Nick , Reason ) ;
/* Ggf. einen eigenen Client toeten */
c = Client_GetFromID ( Nick ) ;
if ( c & & ( Client_Conn ( c ) ! = NONE ) ) Conn_Close ( Client_Conn ( c ) , NULL , Reason , TRUE ) ;
2002-01-04 02:21:47 +01:00
} /* Kill_Nick */
2002-01-28 14:05:48 +01:00
LOCAL BOOLEAN Send_NAMES ( CLIENT * Client , CHANNEL * Chan )
{
CHAR str [ LINE_LEN + 1 ] ;
CL2CHAN * cl2chan ;
2002-02-11 02:03:20 +01:00
CLIENT * cl ;
2002-01-28 14:05:48 +01:00
assert ( Client ! = NULL ) ;
assert ( Chan ! = NULL ) ;
/* Alle Mitglieder suchen */
sprintf ( str , RPL_NAMREPLY_MSG , Client_ID ( Client ) , " = " , Channel_Name ( Chan ) ) ;
cl2chan = Channel_FirstMember ( Chan ) ;
while ( cl2chan )
{
2002-02-11 02:03:20 +01:00
cl = Channel_GetClient ( cl2chan ) ;
2002-01-28 14:05:48 +01:00
/* Nick anhaengen */
if ( str [ strlen ( str ) - 1 ] ! = ' : ' ) strcat ( str , " " ) ;
2002-02-11 02:03:20 +01:00
if ( strchr ( Channel_UserModes ( Chan , cl ) , ' v ' ) ) strcat ( str , " + " ) ;
if ( strchr ( Channel_UserModes ( Chan , cl ) , ' o ' ) ) strcat ( str , " @ " ) ;
strcat ( str , Client_ID ( cl ) ) ;
2002-01-28 14:05:48 +01:00
if ( strlen ( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ) )
{
/* Zeile wird zu lang: senden! */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
sprintf ( str , RPL_NAMREPLY_MSG , Client_ID ( Client ) , " = " , Channel_Name ( Chan ) ) ;
}
/* naechstes Mitglied suchen */
cl2chan = Channel_NextMember ( Chan , cl2chan ) ;
}
if ( str [ strlen ( str ) - 1 ] ! = ' : ' )
{
/* Es sind noch Daten da, die gesendet werden muessen */
if ( ! IRC_WriteStrClient ( Client , str ) ) return DISCONNECTED ;
}
/* Ende anzeigen */
IRC_WriteStrClient ( Client , RPL_ENDOFNAMES_MSG , Client_ID ( Client ) , Channel_Name ( Chan ) ) ;
return CONNECTED ;
} /* Send_NAMES */
2002-02-14 00:05:29 +01:00
LOCAL BOOLEAN Send_LUSERS ( CLIENT * Client )
{
INT cnt ;
assert ( Client ! = NULL ) ;
/* Users, Services und Serevr im Netz */
if ( ! IRC_WriteStrClient ( Client , RPL_LUSERCLIENT_MSG , Client_ID ( Client ) , Client_UserCount ( ) , Client_ServiceCount ( ) , Client_ServerCount ( ) ) ) return DISCONNECTED ;
/* IRC-Operatoren im Netz */
cnt = Client_OperCount ( ) ;
if ( cnt > 0 )
{
if ( ! IRC_WriteStrClient ( Client , RPL_LUSEROP_MSG , Client_ID ( Client ) , cnt ) ) return DISCONNECTED ;
}
/* Unbekannt Verbindungen */
cnt = Client_UnknownCount ( ) ;
if ( cnt > 0 )
{
if ( ! IRC_WriteStrClient ( Client , RPL_LUSERUNKNOWN_MSG , Client_ID ( Client ) , cnt ) ) return DISCONNECTED ;
}
/* Channels im Netz */
if ( ! IRC_WriteStrClient ( Client , RPL_LUSERCHANNELS_MSG , Client_ID ( Client ) , Channel_Count ( ) ) ) return DISCONNECTED ;
/* Channels im Netz */
if ( ! IRC_WriteStrClient ( Client , RPL_LUSERME_MSG , Client_ID ( Client ) , Client_MyUserCount ( ) , Client_MyServiceCount ( ) , Client_MyServerCount ( ) ) ) return DISCONNECTED ;
return CONNECTED ;
} /* Send_LUSERS */
2001-12-14 09:13:43 +01:00
/* -eof- */