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

Compare commits

...

27 Commits

Author SHA1 Message Date
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
12 changed files with 761 additions and 149 deletions

View File

@@ -10,6 +10,20 @@
-- ChangeLog / Aenderungen --
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 +95,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.17 2002/02/15 14:35:55 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 $

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: configure.in,v 1.22 2002/01/29 00:24:17 alex Exp $
# $Id: configure.in,v 1.24 2002/02/15 14:35:55 alex Exp $
#
# $Log: configure.in,v $
# 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 +89,7 @@
AC_INIT
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AM_INIT_AUTOMAKE(ngircd,0.1.0)
AM_INIT_AUTOMAKE(ngircd,0.2.0)
AM_CONFIG_HEADER(src/config.h)
# -- Variablen --

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.36 2002/02/06 16:49:41 alex Exp $
*
* client.c: Management aller Clients
*
@@ -21,6 +21,9 @@
* Server gewesen, so existiert eine entsprechende CONNECTION-Struktur.
*
* $Log: client.c,v $
* 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 +718,8 @@ 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 )) return IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
/* Nick bereits vergeben? */
c = My_Clients;
@@ -873,6 +876,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,43 @@
* 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.57 2002/02/13 23:05:29 alex Exp $
*
* irc.c: IRC-Befehle
*
* $Log: irc.c,v $
* 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 +255,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 )
@@ -431,11 +464,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 +551,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 +584,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 +665,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 +678,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 +759,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
@@ -897,6 +967,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 +976,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 +1000,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 +1011,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 +1117,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_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
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_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
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_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
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 +1603,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 +1653,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 +1751,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 +1778,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 +1835,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 +1854,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 +1989,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 +2042,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 +2052,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 +2083,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,26 @@
* 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.28 2002/02/13 23:04:50 alex Exp $
*
* irc.h: IRC-Befehle (Header)
*
* $Log: messages.h,v $
* 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 +120,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 +173,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 +194,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 +245,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"