1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-12-30 17:19:05 +00:00

Compare commits

...

41 Commits

Author SHA1 Message Date
Alexander Barton
3232c7d245 - Version 0.2.1. 2002-02-17 21:50:38 +00:00
Alexander Barton
2c0a42e935 *** empty log message *** 2002-02-17 19:08:19 +00:00
Alexander Barton
a233adfbd8 - NICK-Aenderungen wurden dem User selber mit dem falschen Prefix geliefert. 2002-02-17 19:03:12 +00:00
Alexander Barton
9f3a9df24a - Client_CheckNick() und Client_CheckID() lieferten u.U. falsche Ergebnisse. 2002-02-17 19:02:49 +00:00
Alexander Barton
44b396d9a5 - Tests auf netdb.h, stdlib.h, sys/wait.h, gethostbyaddr, gethostbyname,
strftime und die "libbe" unter BeOS (fuer syslog) ergaenzt.
2002-02-17 18:47:26 +00:00
Alexander Barton
25e1e8b690 *** empty log message *** 2002-02-17 17:47:01 +00:00
Alexander Barton
b60f369266 - Fehlerhafte Modes werden nun ausfuehrlicher an den Client gemeldet. 2002-02-17 17:43:14 +00:00
Alexander Barton
1b1b718e7e - neue Text-Konstante ERR_UMODEUNKNOWNFLAG2_MSG. 2002-02-17 17:42:53 +00:00
Alexander Barton
ce2738c984 - Beispiel-Konfiguration etwas erweitert. Doku fehlt immer noch ... 2002-02-17 17:34:50 +00:00
Alexander Barton
bec7783ec9 - NICK-Aenderungen werden an alle Server und betroffene Clients gemeldet.
- Neue Funktion IRC_WriteStrRelatedPrefix().
2002-02-17 17:30:21 +00:00
Alexander Barton
db7ea9c4b3 - NICK korrigiert. 2002-02-17 17:18:59 +00:00
anonymous
2d87beed3d *** empty log message *** 2002-02-15 15:15:48 +00:00
Alexander Barton
05a493e1d0 - CVS-Doku um anonymen Zugang ergaenzt. 2002-02-15 15:15:22 +00:00
Alexander Barton
825711973a - Version auf 0.2.1-pre im CVS angehoben ... 2002-02-15 14:57:21 +00:00
Alexander Barton
621a3ca102 - Version 0.2.0 2002-02-15 14:35:55 +00:00
Alexander Barton
57f36fc883 *** empty log message *** 2002-02-13 23:06:07 +00:00
Alexander Barton
213fa0994f - Nach Connect eines Users werden LUSERS-Informationen angezeigt. 2002-02-13 23:05:29 +00:00
Alexander Barton
b10d05f2d2 - RPL_MYINFO_MSG korrigiert. 2002-02-13 23:04:50 +00:00
Alexander Barton
645aeacf0a - CHANMODES um Operator (o) und Voiced User (v) ergaenzt. 2002-02-13 23:04:27 +00:00
Alexander Barton
70ac29b253 *** empty log message *** 2002-02-13 17:52:37 +00:00
Alexander Barton
f3f121b8f8 - es werden nun Channel- und User-Modes von Usern angenommen. 2002-02-13 17:52:27 +00:00
Alexander Barton
f908e78118 - unterstuetzte User- und Channel-Modes stehen nun in Konstanten. 2002-02-13 17:45:57 +00:00
Alexander Barton
e1a1e7ecf4 - via NJOIN gemeldete Benutzer wurden nicht in Channels bekannt gemacht. 2002-02-12 14:40:37 +00:00
Alexander Barton
6610d6e4ba - weitere Anpassungen an Channel-Modes und Channel-User-Modes. 2002-02-11 23:33:35 +00:00
Alexander Barton
207937da2a - neue Message ERR_CHANOPRIVSNEEDED_MSG definiert. 2002-02-11 23:33:12 +00:00
Alexander Barton
84a2f8ab26 - Die Quelle von MODE-Aenderungen wird nun korrekt weitergegeben. 2002-02-11 16:06:21 +00:00
Alexander Barton
5ef9ff5b2d - PONG an den Server selber wurde faelschlicherweise versucht zu forwarden.
- Channel-Modes wurden falsch geliefert (als User-Modes).
2002-02-11 15:52:21 +00:00
Alexander Barton
617cdf068e - neue Nachricht RPL_CHANNELMODEIS definiert. 2002-02-11 15:48:39 +00:00
Alexander Barton
d2d6dcbb1f - 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 15:15:53 +00:00
Alexander Barton
0595f42fbe - 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-11 01:03:20 +00:00
Alexander Barton
b9f005af75 - neue Funktion Conn_LastPing(). 2002-02-11 01:00:50 +00:00
Alexander Barton
2184b3615b - neue Funktionen Channel_ModeAdd(), Channel_ModeDel(), Channel_UserModes(),
Channel_UserModeAdd(), Channel_UserModeDel().
2002-02-11 01:00:22 +00:00
Alexander Barton
d72c55a09d - neue Funktionen Channel_ModeAdd(), Channel_ModeDel(), Channel_UserModes(),
Channel_UserModeAdd(), Channel_UserModeDel().
- Modes in CL2CHAN-Struktur werden nun korrekt initialisiert.
2002-02-11 01:00:12 +00:00
Alexander Barton
4da8fc54ac - Aktualisierungen ... 2002-02-11 00:58:12 +00:00
Alexander Barton
5c48cbff1d - neue Text-Konstante RPL_UMODEISCHAN_MSG. 2002-02-06 16:51:39 +00:00
Alexander Barton
f29ae5ae0e - neue Funktion zur MODE-Behandlung, fuer Channel-Modes vorbereitet. 2002-02-06 16:51:22 +00:00
Alexander Barton
175b20bbb5 - neue Funktion Client_IsValidNick(). 2002-02-06 16:49:56 +00:00
Alexander Barton
33944e8cdb - neue Funktion Client_IsValidNick(), Nicknames werden besser validiert. 2002-02-06 16:49:41 +00:00
Alexander Barton
40c9f5c332 - neue Funktionen Channel_Modes() und Channel_IsValidName(). 2002-02-06 16:49:10 +00:00
Alexander Barton
f53914b17a - neue Funktion Channel_Modes() und Channel_IsValidName().
- Channel-Namen werden (besser) validiert.
2002-02-06 16:48:48 +00:00
Alexander Barton
6e9ec92974 - Version auf 0.1.1-pre im CVS angehoben. 2002-01-29 01:07:15 +00:00
16 changed files with 952 additions and 184 deletions

View File

@@ -10,6 +10,28 @@
-- ChangeLog / Aenderungen --
ngIRCd 0.2.x, xx.02.2002
- NICK korrigiert: es werden nun auch alle "betroffenen" User informiert.
- configure-Script erweitert, u.a. bessere Anpassung an BeOS: dort wird
nun die "libbe" zum ngIRCd gelinkt, somit funktioniert auch syslog.
- Fehlerhafte bzw. noch nicht verstandene Modes werden nun ausfuehrlicher
an den Client geliefert.
ngIRCd 0.2.0, 15.02.2002
- Nicknames und Channel-Namen werden etwas besser auf Gueltigkeit ueber-
prueft; ist aber nach wie vor noch nicht ausreichend.
- NJOINS von Servern wurden nicht an andere Server weitergeleitet.
- Begonnen Channel-Modes und User-Channel-Modes zu implementieren: der
Server versteht an User-Modes o und v, beachtet letzteres allerdings
noch nirgends. Bekannte (aber nicht beachtete!) Channel-Modes sind
bisher a, m, n, p, q, s und t. Diese Modes werden von Usern ange-
nommen, von anderen Servern werden auch unbekannte Modes uebernommen.
- Benutzer von connectierenden Servern wurden nicht in den Channels ange-
kuendigt, es wurden nur die internen Strukturen angepasst.
- Nach dem Connect eines Users werden LUSERS-Informationen angezeigt.
ngIRCd 0.1.0, 29.01.2002
- User-Modes bei User-Registrierungen von andere Servern (NICK-Befehl)
@@ -81,4 +103,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: ChangeLog,v 1.13 2002/01/29 00:17:39 alex Exp $
$Id: ChangeLog,v 1.20 2002/02/17 19:08:19 alex Exp $

11
NEWS
View File

@@ -10,6 +10,15 @@
-- NEWS / Neuigkeiten --
ngIRCd 0.2.0, 15.02.2002
- Begonnen Channel-Modes und User-Channel-Modes zu implementieren: der
Server versteht an User-Modes o und v, beachtet letzteres allerdings
noch nirgends. Bekannte (aber nicht beachtete!) Channel-Modes sind
bisher a, m, n, p, q, s und t. Diese Modes werden von Usern ange-
nommen, von anderen Servern werden auch unbekannte Modes uebernommen.
- Nach dem Connect eines Users werden LUSERS-Informationen angezeigt.
ngIRCd 0.1.0, 29.01.2002
- Channels implementiert, bisher jedoch noch ohne Channel-Modes, d.h.
@@ -43,4 +52,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: NEWS,v 1.6 2002/01/29 00:17:39 alex Exp $
$Id: NEWS,v 1.10 2002/02/15 14:35:55 alex Exp $

4
README
View File

@@ -1,4 +1,4 @@
ngIRCd - Next Generation IRC Server
(c)2001,2002 by Alexander Barton,
@@ -42,4 +42,4 @@ Das README liest du gerade ,-)
--
$Id: README,v 1.4 2002/01/29 00:17:39 alex Exp $
$Id: README,v 1.5 2002/02/15 15:15:48 anonymous Exp $

View File

@@ -9,11 +9,27 @@
# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
#
# $Id: configure.in,v 1.22 2002/01/29 00:24:17 alex Exp $
# $Id: configure.in,v 1.27 2002/02/17 21:50:38 alex Exp $
#
# $Log: configure.in,v $
# Revision 1.27 2002/02/17 21:50:38 alex
# - Version 0.2.1.
#
# Revision 1.26 2002/02/17 18:47:26 alex
# - Tests auf netdb.h, stdlib.h, sys/wait.h, gethostbyaddr, gethostbyname,
# strftime und die "libbe" unter BeOS (fuer syslog) ergaenzt.
#
# Revision 1.25 2002/02/15 14:57:21 alex
# - Version auf 0.2.1-pre im CVS angehoben ...
#
# Revision 1.24 2002/02/15 14:35:55 alex
# - Version 0.2.0
#
# Revision 1.23 2002/01/29 01:07:15 alex
# - Version auf 0.1.1-pre im CVS angehoben.
#
# Revision 1.22 2002/01/29 00:24:17 alex
# - Version 0.0.1
# - Version 0.1.0
#
# Revision 1.21 2002/01/16 23:06:16 alex
# - Version auf 0.0.4-pre im CVS angehoben.
@@ -83,7 +99,7 @@
AC_INIT
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AM_INIT_AUTOMAKE(ngircd,0.1.0)
AM_INIT_AUTOMAKE(ngircd,0.2.1)
AM_CONFIG_HEADER(src/config.h)
# -- Variablen --
@@ -132,13 +148,13 @@ AC_ARG_WITH(portab,
]
)
AC_CHECK_HEADERS([ \
errno.h fcntl.h netinet/in.h string.h \
sys/socket.h sys/time.h unistd.h \
],,AC_MSG_ERROR([required C header missing!]))
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_HEADERS([ \
errno.h fcntl.h netdb.h netinet/in.h stdlib.h string.h \
sys/socket.h sys/time.h sys/wait.h unistd.h \
],,AC_MSG_ERROR([required C header missing!]))
# -- Datentypen --
AC_MSG_CHECKING(whether socklen_t exists)
@@ -159,14 +175,16 @@ AC_TRY_COMPILE([
AC_FUNC_MALLOC
AC_CHECK_FUNCS([ \
gethostname inet_ntoa memmove memset select \
socket strcasecmp strchr strerror strstr waitpid \
gethostbyaddr gethostbyname gethostname inet_ntoa memmove memset \
select socket strcasecmp strchr strerror strftime strstr waitpid \
],,AC_MSG_ERROR([required function missing!]))
AC_CHECK_FUNCS(inet_aton)
# -- Libraries --
AC_CHECK_LIB(be,syslog)
# -- Konfigurationsoptionen --
AC_ARG_ENABLE(syslog,

View File

@@ -14,12 +14,51 @@ Die Sourcen des ngIRCd werden mit dem "Concurrent Versions System" (CVS)
verwaltet. Somit koennen ohne Probleme mehrere Leute gleichzeitig die Sourcen
bearbeitet.
Dieser Text soll in Zukunft die Grundlagen beschreiben. Tut er aber leider
noch nicht, also frage einfach Alex direkt (siehe AUTHORS-Text), wenn du
daran interessiert bist, Zugriff auf den Quellcode via CVS zu bekommen!
[ ... more to come ... ]
I. Anonymer "Nur-Lesen"-Zugang
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Anonymer Zugriff auf die CVS-Repository von ngIRCd ist im "nur-lesen"-Modus
moeglich. Dazu sind folgende Schritte noetig:
Beim CVS-Server anmelden
$ cvs -d:pserver:anonymous@arthur.ath.cx:/usr/local/CVS/ngircd login
Als Benutzername wird "anonymous" mit einem leeren Passwort verwendet.
Nun ein "Check-Out" der Quellcodes durchfuehren:
$ cvs -d:pserver:anonymous@arthur.ath.cx:/usr/local/CVS/ngircd checkout ngircd
Dadurch wird im aktuellen Verzeichnis der neue Ordner "ngircd" mit allen
Quell-Dateien des ngIRCd erzeugt.
Dieses ist der "Arbeitsordner", alle CVS-Befehle werden in Zukunft aus
diesem Ordner bzw. einem Unterordner davon ausgefuehrt.
Wichtig: wenn ngIRCd "frisch" aus dem CVS compiliert werden soll, so
existiert das configure-Script noch nicht. Dieses muss zunaechst mit dem
Script "autogen.sh" erzeugt werden. Letzteres setzt ein installiertes GNU
automake und GNU autoconf voraus!
CVS-Tree aktualisieren:
$ cvs update
Dieser Befehl aktualisiert alle Dateien im aktuellen Verzeichnis sowie allen
Unterverzeichnissen.
$ cvs update <filename>
So kann eine einzelne Datei aktualisiert werden (auch dann, wenn sie lokal
z.B. geloescht wurde -- praktisch, um eigene "Experimente" rueckgaengig zu
machen ;-))
III. Schreibzugriff
~~~~~~~~~~~~~~~~~~~
Wer Schreibzugriff auf die CVS-Repository wuenscht, der moege sich bitte
mit Alex Barton, <alex@barton.de> in Verbindung setzen.
--
$Id: CVS.txt,v 1.4 2002/01/23 18:20:04 alex Exp $
$Id: CVS.txt,v 1.5 2002/02/15 15:15:22 alex Exp $

View File

@@ -1,4 +1,4 @@
# $Id: sample-ngircd.conf,v 1.2 2002/01/06 16:54:05 alex Exp $
# $Id: sample-ngircd.conf,v 1.3 2002/02/17 17:34:50 alex Exp $
[Global]
Name = irc.the.net
@@ -14,9 +14,14 @@
; Password = ThePwd
[Server]
; Host = host2.the.net
; Host = connect-to-host.the.net
; Name = irc2.the.net
; Port = 6666
; Password = ThePwd
; Password = ThePwd1
[Server]
; Host = wait-for-host.the.net
; Name = irc3.the.net
; Password = ThePwd2
# -eof-

View File

@@ -9,11 +9,20 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: channel.c,v 1.11 2002/01/29 00:11:10 alex Exp $
* $Id: channel.c,v 1.13 2002/02/11 01:00:12 alex Exp $
*
* channel.c: Management der Channels
*
* $Log: channel.c,v $
* Revision 1.13 2002/02/11 01:00:12 alex
* - neue Funktionen Channel_ModeAdd(), Channel_ModeDel(), Channel_UserModes(),
* Channel_UserModeAdd(), Channel_UserModeDel().
* - Modes in CL2CHAN-Struktur werden nun korrekt initialisiert.
*
* Revision 1.12 2002/02/06 16:48:48 alex
* - neue Funktion Channel_Modes() und Channel_IsValidName().
* - Channel-Namen werden (besser) validiert.
*
* Revision 1.11 2002/01/29 00:11:10 alex
* - neue Funktionen Channel_FirstChannelOf() und Channel_NextChannelOf().
*
@@ -125,7 +134,7 @@ GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name )
assert( Name != NULL );
/* Valider Channel-Name? */
if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN ))
if( ! Channel_IsValidName( Name ))
{
IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
return FALSE;
@@ -215,6 +224,13 @@ GLOBAL CHAR *Channel_Name( CHANNEL *Chan )
} /* Channel_Name */
GLOBAL CHAR *Channel_Modes( CHANNEL *Chan )
{
assert( Chan != NULL );
return Chan->modes;
} /* Channel_Modes */
GLOBAL CHANNEL *Channel_First( VOID )
{
return My_Channels;
@@ -289,6 +305,135 @@ GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan )
} /* Channel_GetChannel */
GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name )
{
/* PrŸfen, ob Name als Channelname gueltig */
assert( Name != NULL );
if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return FALSE;
return TRUE;
} /* Channel_IsValidName */
GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode )
{
/* Mode soll gesetzt werden. TRUE wird geliefert, wenn der
* Mode neu gesetzt wurde, FALSE, wenn der Channel den Mode
* bereits hatte. */
CHAR x[2];
assert( Chan != NULL );
x[0] = Mode; x[1] = '\0';
if( ! strchr( Chan->modes, x[0] ))
{
/* Client hat den Mode noch nicht -> setzen */
strcat( Chan->modes, x );
return TRUE;
}
else return FALSE;
} /* Channel_ModeAdd */
GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode )
{
/* Mode soll geloescht werden. TRUE wird geliefert, wenn der
* Mode entfernt wurde, FALSE, wenn der Channel den Mode
* ueberhaupt nicht hatte. */
CHAR x[2], *p;
assert( Chan != NULL );
x[0] = Mode; x[1] = '\0';
p = strchr( Chan->modes, x[0] );
if( ! p ) return FALSE;
/* Client hat den Mode -> loeschen */
while( *p )
{
*p = *(p + 1);
p++;
}
return TRUE;
} /* Channel_ModeDel */
GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
{
/* Channel-User-Mode soll gesetzt werden. TRUE wird geliefert,
* wenn der Mode neu gesetzt wurde, FALSE, wenn der User den
* Channel-Mode bereits hatte. */
CL2CHAN *cl2chan;
CHAR x[2];
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = Get_Cl2Chan( Chan, Client );
assert( cl2chan != NULL );
x[0] = Mode; x[1] = '\0';
if( ! strchr( cl2chan->modes, x[0] ))
{
/* Client hat den Mode noch nicht -> setzen */
strcat( cl2chan->modes, x );
return TRUE;
}
else return FALSE;
} /* Channel_UserModeAdd */
GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
{
/* Channel-User-Mode soll geloescht werden. TRUE wird geliefert,
* wenn der Mode entfernt wurde, FALSE, wenn der User den Channel-Mode
* ueberhaupt nicht hatte. */
CL2CHAN *cl2chan;
CHAR x[2], *p;
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = Get_Cl2Chan( Chan, Client );
assert( cl2chan != NULL );
x[0] = Mode; x[1] = '\0';
p = strchr( cl2chan->modes, x[0] );
if( ! p ) return FALSE;
/* Client hat den Mode -> loeschen */
while( *p )
{
*p = *(p + 1);
p++;
}
return TRUE;
} /* Channel_UserModeDel */
GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
{
/* Channel-Modes eines Users liefern */
CL2CHAN *cl2chan;
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = Get_Cl2Chan( Chan, Client );
assert( cl2chan != NULL );
return cl2chan->modes;
} /* Channel_UserModes */
LOCAL CHANNEL *New_Chan( CHAR *Name )
{
/* Neue Channel-Struktur anlegen */
@@ -338,6 +483,7 @@ LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client )
assert( Chan != NULL );
assert( Client != NULL );
/* neue CL2CHAN-Struktur anlegen */
cl2chan = malloc( sizeof( CL2CHAN ));
if( ! cl2chan )
{
@@ -346,6 +492,7 @@ LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client )
}
cl2chan->channel = Chan;
cl2chan->client = Client;
strcpy( cl2chan->modes, "" );
/* Verketten */
cl2chan->next = My_Cl2Chan;

View File

@@ -9,11 +9,18 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: channel.h,v 1.9 2002/01/29 00:11:19 alex Exp $
* $Id: channel.h,v 1.11 2002/02/11 01:00:22 alex Exp $
*
* channel.h: Management der Channels (Header)
*
* $Log: channel.h,v $
* Revision 1.11 2002/02/11 01:00:22 alex
* - neue Funktionen Channel_ModeAdd(), Channel_ModeDel(), Channel_UserModes(),
* Channel_UserModeAdd(), Channel_UserModeDel().
*
* Revision 1.10 2002/02/06 16:49:10 alex
* - neue Funktionen Channel_Modes() und Channel_IsValidName().
*
* Revision 1.9 2002/01/29 00:11:19 alex
* - neue Funktionen Channel_FirstChannelOf() und Channel_NextChannelOf().
*
@@ -89,6 +96,7 @@ GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason );
GLOBAL INT Channel_Count( VOID );
GLOBAL CHAR *Channel_Name( CHANNEL *Chan );
GLOBAL CHAR *Channel_Modes( CHANNEL *Chan );
GLOBAL CHANNEL *Channel_Search( CHAR *Name );
@@ -103,6 +111,15 @@ GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan );
GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan );
GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan );
GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name );
GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode );
GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode );
GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode );
GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode );
GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client );
#endif

View File

@@ -9,7 +9,7 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: client.c,v 1.35 2002/01/29 00:14:49 alex Exp $
* $Id: client.c,v 1.37 2002/02/17 19:02:49 alex Exp $
*
* client.c: Management aller Clients
*
@@ -21,6 +21,12 @@
* Server gewesen, so existiert eine entsprechende CONNECTION-Struktur.
*
* $Log: client.c,v $
* Revision 1.37 2002/02/17 19:02:49 alex
* - Client_CheckNick() und Client_CheckID() lieferten u.U. falsche Ergebnisse.
*
* Revision 1.36 2002/02/06 16:49:41 alex
* - neue Funktion Client_IsValidNick(), Nicknames werden besser validiert.
*
* Revision 1.35 2002/01/29 00:14:49 alex
* - neue Funktion Client_TopServer(), Client_NewXXX() angepasst.
*
@@ -715,8 +721,12 @@ GLOBAL BOOLEAN Client_CheckNick( CLIENT *Client, CHAR *Nick )
assert( Client != NULL );
assert( Nick != NULL );
/* Nick zu lang? */
if( strlen( Nick ) > CLIENT_NICK_LEN ) return IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
/* Nick ungueltig? */
if( ! Client_IsValidNick( Nick ))
{
IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
return FALSE;
}
/* Nick bereits vergeben? */
c = My_Clients;
@@ -747,7 +757,11 @@ GLOBAL BOOLEAN Client_CheckID( CLIENT *Client, CHAR *ID )
assert( ID != NULL );
/* Nick zu lang? */
if( strlen( ID ) > CLIENT_ID_LEN ) return IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), ID );
if( strlen( ID ) > CLIENT_ID_LEN )
{
IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), ID );
return FALSE;
}
/* ID bereits vergeben? */
c = My_Clients;
@@ -873,6 +887,18 @@ GLOBAL INT Client_UnknownCount( VOID )
} /* Client_UnknownCount */
GLOBAL BOOLEAN Client_IsValidNick( CHAR *Nick )
{
/* Ist der Nick gueltig? */
assert( Nick != NULL );
if( Nick[0] == '#' ) return FALSE;
if( strlen( Nick ) > CLIENT_NICK_LEN ) return FALSE;
return TRUE;
} /* Client_IsValidNick */
LOCAL INT Count( CLIENT_TYPE Type )
{
CLIENT *c;

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: client.h,v 1.21 2002/01/29 00:14:49 alex Exp $
* $Id: client.h,v 1.22 2002/02/06 16:49:56 alex Exp $
*
* client.h: Konfiguration des ngircd (Header)
*
* $Log: client.h,v $
* Revision 1.22 2002/02/06 16:49:56 alex
* - neue Funktion Client_IsValidNick().
*
* Revision 1.21 2002/01/29 00:14:49 alex
* - neue Funktion Client_TopServer(), Client_NewXXX() angepasst.
*
@@ -194,6 +197,8 @@ GLOBAL INT Client_MyUserCount( VOID );
GLOBAL INT Client_MyServiceCount( VOID );
GLOBAL INT Client_MyServerCount( VOID );
GLOBAL BOOLEAN Client_IsValidNick( CHAR *Nick );
#endif

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: conn.c,v 1.35 2002/01/18 11:12:11 alex Exp $
* $Id: conn.c,v 1.36 2002/02/11 01:00:50 alex Exp $
*
* connect.h: Verwaltung aller Netz-Verbindungen ("connections")
*
* $Log: conn.c,v $
* Revision 1.36 2002/02/11 01:00:50 alex
* - neue Funktion Conn_LastPing().
*
* Revision 1.35 2002/01/18 11:12:11 alex
* - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben.
*
@@ -570,6 +573,15 @@ GLOBAL INT32 Conn_GetIdle( CONN_ID Idx )
} /* Conn_GetIdle */
GLOBAL INT32 Conn_LastPing( CONN_ID Idx )
{
/* Zeitpunkt des letzten PING liefern */
assert( Idx >= 0 );
return My_Connections[Idx].lastping;
} /* Conn_LastPing */
LOCAL BOOLEAN Try_Write( CONN_ID Idx )
{
/* Versuchen, Daten aus dem Schreib-Puffer in den

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: conn.h,v 1.10 2002/01/06 15:18:15 alex Exp $
* $Id: conn.h,v 1.11 2002/02/11 01:00:50 alex Exp $
*
* conn.h: Verwaltung aller Netz-Verbindungen ("connections") (Header)
*
* $Log: conn.h,v $
* Revision 1.11 2002/02/11 01:00:50 alex
* - neue Funktion Conn_LastPing().
*
* Revision 1.10 2002/01/06 15:18:15 alex
* - Loglevel und Meldungen nochmals geaendert. Level passen nun besser.
*
@@ -75,6 +78,7 @@ GLOBAL VOID Conn_Close( CONN_ID Idx, CHAR *LogMsg, CHAR *FwdMsg, BOOLEAN InformC
GLOBAL VOID Conn_UpdateIdle( CONN_ID Idx );
GLOBAL INT32 Conn_GetIdle( CONN_ID Idx );
GLOBAL INT32 Conn_LastPing( CONN_ID Idx );
#endif

View File

@@ -9,11 +9,17 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: defines.h,v 1.7 2002/01/22 17:15:39 alex Exp $
* $Id: defines.h,v 1.9 2002/02/13 23:04:27 alex Exp $
*
* defines.h: (globale) Konstanten
*
* $Log: defines.h,v $
* Revision 1.9 2002/02/13 23:04:27 alex
* - CHANMODES um Operator (o) und Voiced User (v) ergaenzt.
*
* Revision 1.8 2002/02/13 17:45:57 alex
* - unterstuetzte User- und Channel-Modes stehen nun in Konstanten.
*
* Revision 1.7 2002/01/22 17:15:39 alex
* - die Fehlermeldung "interrupted system call" sollte nicht mehr auftreten.
*
@@ -82,6 +88,10 @@
#define STARTUP_DELAY 1 /* Erst n Sek. nach Start zu anderen Servern verbinden */
#define USERMODES "io" /* unterstuetzte User-Modes */
#define CHANMODES "amnopqstv" /* unterstuetzte Channel-Modes */
#endif

View File

@@ -9,11 +9,56 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: irc.c,v 1.48 2002/01/29 00:13:45 alex Exp $
* $Id: irc.c,v 1.61 2002/02/17 19:03:12 alex Exp $
*
* irc.c: IRC-Befehle
*
* $Log: irc.c,v $
* Revision 1.61 2002/02/17 19:03:12 alex
* - NICK-Aenderungen wurden dem User selber mit dem falschen Prefix geliefert.
*
* Revision 1.60 2002/02/17 17:43:14 alex
* - Fehlerhafte Modes werden nun ausfuehrlicher an den Client gemeldet.
*
* Revision 1.59 2002/02/17 17:30:21 alex
* - NICK-Aenderungen werden an alle Server und betroffene Clients gemeldet.
* - Neue Funktion IRC_WriteStrRelatedPrefix().
*
* Revision 1.58 2002/02/17 17:18:59 alex
* - NICK korrigiert.
*
* Revision 1.57 2002/02/13 23:05:29 alex
* - Nach Connect eines Users werden LUSERS-Informationen angezeigt.
*
* Revision 1.56 2002/02/13 17:52:27 alex
* - es werden nun Channel- und User-Modes von Usern angenommen.
*
* Revision 1.55 2002/02/12 14:40:37 alex
* - via NJOIN gemeldete Benutzer wurden nicht in Channels bekannt gemacht.
*
* Revision 1.54 2002/02/11 23:33:35 alex
* - weitere Anpassungen an Channel-Modes und Channel-User-Modes.
*
* Revision 1.53 2002/02/11 16:06:21 alex
* - Die Quelle von MODE-Aenderungen wird nun korrekt weitergegeben.
*
* 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).
*
* 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.
*
* 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.
*
* Revision 1.49 2002/02/06 16:51:22 alex
* - neue Funktion zur MODE-Behandlung, fuer Channel-Modes vorbereitet.
*
* 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
@@ -223,6 +268,7 @@ LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
LOCAL VOID Kill_Nick( CHAR *Nick );
LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan );
LOCAL BOOLEAN Send_LUSERS( CLIENT *Client );
GLOBAL VOID IRC_Init( VOID )
@@ -293,10 +339,10 @@ GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remot
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
{
CHAR buffer[1000];
BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED, i;
BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED;
CL2CHAN *cl2chan;
CLIENT *c;
INT s;
INT s, i;
va_list ap;
assert( Client != NULL );
@@ -389,6 +435,74 @@ GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *F
} /* IRC_WriteStrServersPrefix */
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 */
GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
{
assert( Client != NULL );
@@ -431,11 +545,11 @@ GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
{
CHAR str[LINE_LEN], *ptr;
BOOLEAN ok;
CLIENT *from, *c;
CHANNEL *chan;
CLIENT *from, *c, *cl;
CL2CHAN *cl2chan;
INT max_hops, i;
CHANNEL *chan;
BOOLEAN ok;
assert( Client != NULL );
assert( Req != NULL );
@@ -518,7 +632,7 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
if( Client_Conn( c ) > NONE )
{
/* Dem gefundenen Server gleich den neuen
* Server bekannt machen */
* Server bekannt machen */
if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
}
@@ -551,8 +665,14 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
cl2chan = Channel_FirstMember( chan );
while( cl2chan )
{
cl = Channel_GetClient( cl2chan );
assert( cl != NULL );
/* Nick, ggf. mit Modes, anhaengen */
if( str[strlen( str ) - 1] != ':' ) strcat( str, "," );
strcat( str, Client_ID( Channel_GetClient( cl2chan )));
if( strchr( Channel_UserModes( chan, cl ), 'v' )) strcat( str, "+" );
if( strchr( Channel_UserModes( chan, cl ), 'o' )) strcat( str, "@" );
strcat( str, Client_ID( cl ));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
{
@@ -626,7 +746,9 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{
CHAR *chan, *ptr;
CHAR *channame, *ptr, modes[8];
BOOLEAN is_op, is_voiced;
CHANNEL *chan;
CLIENT *c;
assert( Client != NULL );
@@ -637,21 +759,50 @@ GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
/* Falsche Anzahl Parameter? */
if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
chan = Req->argv[0];
channame = Req->argv[0];
ptr = strtok( Req->argv[1], "," );
while( ptr )
{
is_op = is_voiced = FALSE;
/* Prefixe abschneiden */
while(( *ptr == '@' ) || ( *ptr == '+' )) ptr++;
while(( *ptr == '@' ) || ( *ptr == '+' ))
{
if( *ptr == '@' ) is_op = TRUE;
if( *ptr == '+' ) is_voiced = TRUE;
ptr++;
}
c = Client_GetFromID( ptr );
if( c ) Channel_Join( c, chan );
else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, chan );
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' );
/* 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 ));
}
}
else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame );
/* naechsten Nick suchen */
ptr = strtok( NULL, "," );
}
/* an andere Server weiterleiten */
IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], Req->argv[1] );
return CONNECTED;
} /* IRC_NJOIN */
@@ -689,10 +840,10 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
target = Client;
}
#ifndef STRICT_RFC
/* 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 ... */
#ifndef STRICT_RFC
if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
#endif
@@ -704,19 +855,11 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
}
if( Client_Type( Client ) == CLIENT_USER )
{
/* Nick-Aenderung: allen mitteilen! */
Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
IRC_WriteStrServersPrefix( NULL, Client, "NICK :%s", Req->argv[0] );
}
else if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Nick-Aenderung: allen mitteilen! */
Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
}
/* Nick-Aenderung: allen mitteilen! */
Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
if( Client_Type( Client ) == CLIENT_USER ) IRC_WriteStrClientPrefix( Client, Client, "NICK :%s", Req->argv[0] );
IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
IRC_WriteStrRelatedPrefix( target, target, FALSE, "NICK :%s", Req->argv[0] );
/* Client-Nick registrieren */
Client_SetID( target, Req->argv[0] );
@@ -897,6 +1040,8 @@ GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
{
CLIENT *target, *from;
assert( Client != NULL );
assert( Req != NULL );
@@ -904,7 +1049,22 @@ GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
/* Falsche Anzahl Parameter? */
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
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] );
}
}
Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
@@ -913,6 +1073,8 @@ GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
{
CLIENT *target, *from;
assert( Client != NULL );
assert( Req != NULL );
@@ -922,10 +1084,27 @@ GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
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 );
/* 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] );
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] );
}
}
/* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
* aktualisiert, daher muss das hier nicht mehr gemacht werden. */
Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %d seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
return CONNECTED;
} /* IRC_PONG */
@@ -1011,136 +1190,319 @@ GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
{
CHAR x[2], new_modes[CLIENT_MODE_LEN], *ptr;
CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
CLIENT *cl, *chan_cl, *prefix;
BOOLEAN set, ok;
CLIENT *target;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
cl = chan_cl = prefix = NULL;
chan = NULL;
/* Valider Client? */
if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
/* Falsche Anzahl Parameter? */
/* Keine Parameter? */
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* "Ziel-Client" bzw. Channel suchen */
chan = NULL;
target = Client_Search( Req->argv[0] );
if( ! target )
{
chan = Channel_Search( Req->argv[0] );
}
/* 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] );
/* Kein Ziel gefunden? */
if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
assert(( cl && chan ) != TRUE );
/* Falsche Anzahl Parameter? */
if( target && ( 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 );
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 );
if( chan )
/* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
if(( chan ) && (Req->argc == 3 ))
{
/* Channel Modes kennen wir noch nicht ... */
Log( LOG_DEBUG, "MODE for channel \"%s\" ignored ...", Channel_Name( chan ));
return CONNECTED;
chan_cl = Client_Search( Req->argv[2] );
if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
}
/* Wer ist der Anfragende? */
/* Wenn Anfragender ein User ist: Zugriff erlaubt? */
if( Client_Type( Client ) == CLIENT_USER )
{
/* User: MODE ist nur fuer sich selber zulaessig */
if( target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
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? */
}
}
/* Werden die Modes "nur" erfragt? */
if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
mode_ptr = Req->argv[1];
/* Sollen Modes gesetzt oder geloescht werden? */
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
{
/* Server: gibt es den Client ueberhaupt? */
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
if( *mode_ptr == '-' ) set = FALSE;
else set = TRUE;
if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
}
/* Werden die Modes erfragt? */
if( Req->argc == 1 ) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( Client ));
ptr = Req->argv[1];
/* Sollen Modes gesetzt oder geloescht werden? */
if( *ptr == '+' ) set = TRUE;
else if( *ptr == '-' ) set = FALSE;
else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
/* 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;
/* Reply-String mit Aenderungen vorbereiten */
if( set ) strcpy( new_modes, "+" );
else strcpy( new_modes, "-" );
if( set ) strcpy( the_modes, "+" );
else strcpy( the_modes, "-" );
ptr++;
ok = TRUE;
x[1] = '\0';
while( *ptr )
while( *mode_ptr )
{
x[0] = '\0';
if( Client_Type( Client ) == CLIENT_SERVER )
{
x[0] = *ptr;
ok = TRUE;
/* Befehl kommt von einem Server, daher
* trauen wir ihm "unbesehen" ... */
x[0] = *mode_ptr;
}
else
{
switch( *ptr )
/* Modes validieren */
if( cl )
{
case 'i':
/* invisible */
x[0] = 'i';
/* 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:
Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
x[0] = '\0';
}
}
if( chan )
{
/* 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;
case 'r':
/* restricted (kann nur gesetzt werden) */
if( set ) x[0] = 'r';
else ok = IRC_WriteStrClient( target, ERR_RESTRICTED_MSG, Client_ID( target ));
break;
case 'o':
/* operator (kann nur geloescht werden) */
if( ! set )
}
/* Channel-Modes oder Channel-User-Modes */
if( chan_cl )
{
/* Channel-User-Modes */
switch( *mode_ptr )
{
Client_SetOperByMe( target, FALSE );
x[0] = 'o';
case 'o':
/* Channel Operator */
x[0] = 'o';
break;
case 'v':
/* Voice */
x[0] = 'v';
break;
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 ));
ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
x[0] = '\0';
}
else ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
break;
default:
ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
x[0] = '\0';
}
else
{
/* Channel-Modes */
switch( *mode_ptr )
{
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;
default:
Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr );
x[0] = '\0';
}
}
}
}
if( ! ok ) break;
ptr++;
mode_ptr++;
if( ! x[0] ) continue;
/* Okay, gueltigen Mode gefunden */
if( set )
if( cl )
{
/* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
if( Client_ModeAdd( target, x[0] )) strcat( new_modes, x );
/* Es geht um User-Modes */
if( set )
{
/* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
}
else
{
/* Modes geloescht. Wenn der Client ihn hatte: merken */
if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
}
}
else
if( chan )
{
/* Modes geloescht. Wenn der Client ihn hatte: merken */
if( Client_ModeDel( target, x[0] )) strcat( new_modes, x );
/* 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 );
}
}
}
}
/* Geanderte Modes? */
if( new_modes[1] )
/* Wurden Modes geaendert? */
if( the_modes[1] )
{
if( Client_Type( Client ) == CLIENT_SERVER )
if( cl )
{
/* Modes an andere Server forwarden */
IRC_WriteStrServersPrefix( Client, Client, "MODE %s :%s", Client_ID( target ), new_modes );
/* Client-Mode */
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Modes an andere Server forwarden */
IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
}
else
{
/* Bestaetigung an Client schicken & andere Server informieren */
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 );
}
Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
}
else
if( chan )
{
/* Bestaetigung an Client schicken & andere Server informieren */
ok = IRC_WriteStrClient( Client, "MODE %s :%s", Client_ID( target ), new_modes );
IRC_WriteStrServers( Client, "MODE %s :%s", Client_ID( target ), new_modes );
/* 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 */
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));
}
else
{
/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
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));
}
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 )
{
/* Modes an andere Server und Channel-User forwarden */
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 );
}
else
{
/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
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 );
}
Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
}
}
Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( target ), Client_Modes( target ));
}
return ok;
} /* IRC_MODE */
@@ -1314,6 +1676,7 @@ GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
CLIENT *from, *target, *c;
CHAR str[LINE_LEN + 1], *ptr = NULL;
CL2CHAN *cl2chan;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -1363,9 +1726,14 @@ GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
cl2chan = Channel_FirstChannelOf( c );
while( cl2chan )
{
chan = Channel_GetChannel( cl2chan );
assert( chan != NULL );
/* Channel-Name anhaengen */
if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
strcat( str, Channel_Name( Channel_GetChannel( cl2chan )));
if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
strcat( str, Channel_Name( chan ));
if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
{
@@ -1456,7 +1824,6 @@ GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
{
CLIENT *target, *from;
INT cnt;
assert( Client != NULL );
assert( Req != NULL );
@@ -1484,28 +1851,7 @@ GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Users, Services und Serevr im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERCLIENT_MSG, Client_ID( target ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
/* IRC-Operatoren im Netz */
cnt = Client_OperCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( target, RPL_LUSEROP_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
}
/* Unbekannt Verbindungen */
cnt = Client_UnknownCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( target, RPL_LUSERUNKNOWN_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
}
/* Channels im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERCHANNELS_MSG, Client_ID( target ), Channel_Count( ))) return DISCONNECTED;
/* Channels im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERME_MSG, Client_ID( target ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
Send_LUSERS( target );
return CONNECTED;
} /* IRC_LUSERS */
@@ -1562,8 +1908,10 @@ GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
{
CHAR *channame, *flags, modes[8];
BOOLEAN is_new_chan;
CLIENT *target;
CHAR *chan, *flags;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -1579,40 +1927,75 @@ GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Channel-Namen durchgehen */
chan = strtok( Req->argv[0], "," );
while( chan )
channame = strtok( Req->argv[0], "," );
while( channame )
{
/* 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? */
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Channel-Flags extrahieren */
flags = strchr( chan, 0x7 );
flags = strchr( channame, 0x7 );
if( flags ) *flags++ = '\0';
}
else flags = NULL;
if( ! Channel_Join( target, chan ))
/* neuer Channel udn lokaler Client? */
if( is_new_chan && ( Client_Type( Client ) == CLIENT_USER ))
{
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
continue;
/* Dann soll der Client Channel-Operator werden! */
flags = "o";
}
/* Channel joinen (und ggf. anlegen) */
if( ! Channel_Join( target, channame ))
{
/* naechsten Namen ermitteln */
channame = strtok( NULL, "," );
continue;
}
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';
/* An andere Server weiterleiten */
IRC_WriteStrServersPrefix( Client, target, "JOIN :%s", chan );
IRC_WriteStrChannelPrefix( Client, Channel_Search( chan ), target, FALSE, "JOIN :%s", chan );
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 ));
}
if( Client_Type( Client ) == CLIENT_USER )
{
/* an Client bestaetigen */
IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", chan );
IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
/* Topic an Client schicken */
IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), chan, "What a wonderful channel!" );
IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, "What a wonderful channel!" );
/* Mitglieder an Client Melden */
Send_NAMES( Client, Channel_Search( chan ));
Send_NAMES( Client, chan );
}
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
channame = strtok( NULL, "," );
}
return CONNECTED;
} /* IRC_JOIN */
@@ -1679,7 +2062,10 @@ LOCAL BOOLEAN Hello_User( CLIENT *Client )
Client_SetType( Client, CLIENT_USER );
return Show_MOTD( Client );
if( ! Send_LUSERS( Client )) return DISCONNECTED;
if( ! Show_MOTD( Client )) return DISCONNECTED;
return CONNECTED;
} /* Hello_User */
@@ -1729,6 +2115,7 @@ LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
{
CHAR str[LINE_LEN + 1];
CL2CHAN *cl2chan;
CLIENT *cl;
assert( Client != NULL );
assert( Chan != NULL );
@@ -1738,9 +2125,13 @@ LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
cl = Channel_GetClient( cl2chan );
/* Nick anhaengen */
if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
strcat( str, Client_ID( Channel_GetClient( cl2chan )));
if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
strcat( str, Client_ID( cl ));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
{
@@ -1765,4 +2156,37 @@ LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
} /* Send_NAMES */
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 */
/* -eof- */

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: irc.h,v 1.21 2002/01/27 21:53:57 alex Exp $
* $Id: irc.h,v 1.22 2002/02/17 17:18:59 alex Exp $
*
* irc.h: IRC-Befehle (Header)
*
* $Log: irc.h,v $
* Revision 1.22 2002/02/17 17:18:59 alex
* - NICK korrigiert.
*
* Revision 1.21 2002/01/27 21:53:57 alex
* - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
*
@@ -104,6 +107,7 @@ GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remot
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... );
GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... );
GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req );

View File

@@ -9,11 +9,29 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: messages.h,v 1.23 2002/01/29 00:14:05 alex Exp $
* $Id: messages.h,v 1.29 2002/02/17 17:42:53 alex Exp $
*
* irc.h: IRC-Befehle (Header)
*
* $Log: messages.h,v $
* Revision 1.29 2002/02/17 17:42:53 alex
* - neue Text-Konstante ERR_UMODEUNKNOWNFLAG2_MSG.
*
* Revision 1.28 2002/02/13 23:04:50 alex
* - RPL_MYINFO_MSG korrigiert.
*
* Revision 1.27 2002/02/13 17:45:57 alex
* - unterstuetzte User- und Channel-Modes stehen nun in Konstanten.
*
* Revision 1.26 2002/02/11 23:33:12 alex
* - neue Message ERR_CHANOPRIVSNEEDED_MSG definiert.
*
* Revision 1.25 2002/02/11 15:48:39 alex
* - neue Nachricht RPL_CHANNELMODEIS definiert.
*
* Revision 1.24 2002/02/06 16:51:39 alex
* - neue Text-Konstante RPL_UMODEISCHAN_MSG.
*
* Revision 1.23 2002/01/29 00:14:05 alex
* - RPL_WHOISCHANNELS_MSG korrigiert.
*
@@ -105,7 +123,7 @@
#define RPL_CREATED_MSG RPL_CREATED" %s :This server was started %s"
#define RPL_MYINFO "004"
#define RPL_MYINFO_MSG RPL_MYINFO" %s %s ngircd-"VERSION" ior +"
#define RPL_MYINFO_MSG RPL_MYINFO" %s :%s ngircd-"VERSION" "USERMODES" "CHANMODES
#define RPL_LUSERCLIENT "251"
#define RPL_LUSERCLIENT_MSG RPL_LUSERCLIENT" %s :There are %d users and %d services on %d servers"
@@ -158,6 +176,9 @@
#define RPL_WHOISCHANNELS "319"
#define RPL_WHOISCHANNELS_MSG RPL_WHOISCHANNELS" %s %s :"
#define RPL_CHANNELMODEIS "324"
#define RPL_CHANNELMODEIS_MSG RPL_CHANNELMODEIS" %s %s +%s"
#define RPL_NOTOPIC "331"
#define RPL_NOTOPIC_MSG RPL_NOTOPIC" %s %s :No topic is set"
@@ -176,6 +197,7 @@
#define RPL_ENDOFNAMES "366"
#define RPL_ENDOFNAMES_MSG RPL_ENDOFNAMES" %s %s :End of NAMES list"
#define RPL_YOUREOPER "381"
#define RPL_YOUREOPER_MSG RPL_YOUREOPER" %s :You are now an IRC Operator"
@@ -226,6 +248,9 @@
#define ERR_NOPRIVILEGES "481"
#define ERR_NOPRIVILEGES_MSG ERR_NOPRIVILEGES" %s :Permission denied"
#define ERR_CHANOPRIVSNEEDED "482"
#define ERR_CHANOPRIVSNEEDED_MSG ERR_CHANOPRIVSNEEDED" %s %s :You are not channel operator"
#define ERR_RESTRICTED "484"
#define ERR_RESTRICTED_MSG ERR_RESTRICTED" %s :Your connection is restricted"
@@ -233,7 +258,8 @@
#define ERR_NOOPERHOST_MSG ERR_NOOPERHOST" %s :Not configured for your host"
#define ERR_UMODEUNKNOWNFLAG "501"
#define ERR_UMODEUNKNOWNFLAG_MSG ERR_UMODEUNKNOWNFLAG" %s :Unknown mode flag"
#define ERR_UMODEUNKNOWNFLAG_MSG ERR_UMODEUNKNOWNFLAG" %s :Unknown mode"
#define ERR_UMODEUNKNOWNFLAG2_MSG ERR_UMODEUNKNOWNFLAG" %s :Unknown mode \"%c%c\""
#define ERR_USERSDONTMATCH "502"
#define ERR_USERSDONTMATCH_MSG ERR_USERSDONTMATCH" %s :Can't set/get mode for other users"