* 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.73 2002/02/27 03:08:05 alex Exp $
+ * $Id: irc.c,v 1.79 2002/02/27 18:57:21 alex Exp $
*
* irc.c: IRC-Befehle
*
* $Log: irc.c,v $
+ * Revision 1.79 2002/02/27 18:57:21 alex
+ * - PRIVMSG zeugt nun bei Texten an User an, wenn diese "away" sind.
+ *
+ * Revision 1.78 2002/02/27 18:23:45 alex
+ * - IRC-Befehl "AWAY" implementert.
+ *
+ * Revision 1.77 2002/02/27 17:05:41 alex
+ * - PRIVMSG beachtet nun die Channel-Modes "n" und "m".
+ *
+ * Revision 1.76 2002/02/27 16:04:14 alex
+ * - Bug bei belegtem Nickname bei User-Registrierung (NICK-Befehl) behoben.
+ *
+ * Revision 1.75 2002/02/27 15:23:27 alex
+ * - NAMES beachtet nun das "invisible" Flag ("i") von Usern.
+ *
+ * Revision 1.74 2002/02/27 03:44:53 alex
+ * - gerade eben in SQUIT eingefuehrten Bug behoben: entfernte Server werden nun
+ * nur noch geloescht, die Verbindung, von der SQUIT kam, bleibt wieder offen.
+ *
* Revision 1.73 2002/02/27 03:08:05 alex
* - Log-Meldungen bei SQUIT erneut ueberarbeitet ...
*
if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
{
/* Neuer Client */
- Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
+ Log( LOG_DEBUG, "Connection %d: got valid NICK command ...", Client_Conn( Client ));
+
+ /* Client-Nick registrieren */
+ Client_SetID( target, Req->argv[0] );
+
+ /* schon ein USER da? Dann registrieren! */
if( Client_Type( Client ) == CLIENT_GOTUSER ) return Hello_User( Client );
else Client_SetType( Client, CLIENT_GOTNICK );
}
- else Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
+ else
+ {
+ /* Nick-Aenderung */
+ Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
- /* Client-Nick registrieren */
- Client_SetID( target, Req->argv[0] );
+ /* neuen Client-Nick speichern */
+ Client_SetID( target, Req->argv[0] );
+ }
return CONNECTED;
}
Client_SetUser( Client, Req->argv[0], FALSE );
Client_SetInfo( Client, Req->argv[3] );
- Log( LOG_DEBUG, "Connection %d: got USER command ...", Client_Conn( Client ));
+ Log( LOG_DEBUG, "Connection %d: got valid USER command ...", Client_Conn( Client ));
if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
else Client_SetType( Client, CLIENT_GOTUSER );
return CONNECTED;
/* dieser Server hat die Connection */
if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), msg, Req->argv[1], TRUE );
else Conn_Close( Client_Conn( target ), msg, NULL, TRUE );
+ return DISCONNECTED;
+ }
+ else
+ {
+ /* Verbindung hielt anderer Server */
+ Client_Destroy( target, msg, Req->argv[1] );
+ return CONNECTED;
}
- else Client_Destroy( target, msg, Req->argv[1] );
-
- return DISCONNECTED;
} /* IRC_SQUIT */
GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
{
- CLIENT *to, *from;
+ BOOLEAN is_member, has_voice, is_op, ok;
+ CLIENT *cl, *from;
CHANNEL *chan;
assert( Client != NULL );
else from = Client;
if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
- to = Client_Search( Req->argv[0] );
- if( to )
+ cl = Client_Search( Req->argv[0] );
+ if( cl )
{
/* Okay, Ziel ist ein User */
+ if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' )))
+ {
+ /* Ziel-User ist AWAY: Meldung verschicken */
+ if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED;
+ }
+
+ /* Text senden */
if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
- return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
+ return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] );
}
chan = Channel_Search( Req->argv[0] );
if( chan )
{
/* Okay, Ziel ist ein Channel */
+ is_member = has_voice = is_op = FALSE;
+ if( Channel_IsMemberOf( chan, from ))
+ {
+ is_member = TRUE;
+ if( strchr( Channel_UserModes( chan, from ), 'v' )) has_voice = TRUE;
+ if( strchr( Channel_UserModes( chan, from ), 'o' )) is_op = TRUE;
+ }
+
+ /* pruefen, ob Client in Channel schreiben darf */
+ ok = TRUE;
+ if( strchr( Channel_Modes( chan ), 'n' ) && ( ! is_member )) ok = FALSE;
+ if( strchr( Channel_Modes( chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = FALSE;
+
+ if( ! ok ) return IRC_WriteStrClient( from, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( from ), Req->argv[0] );
+
+ /* Text senden */
if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
}
/* Befehl kommt von einem Server, daher
* trauen wir ihm "unbesehen" ... */
x[0] = *mode_ptr;
+
+ if(( cl ) && ( x[0] == 'a' ))
+ {
+ /* away */
+ if( set ) Client_SetAway( cl, "Away" );
+ else Client_SetAway( cl, NULL );
+ }
+
}
else
{
x[0] = 'p';
break;
case 'q':
- /* Quite */
+ /* Quiet */
x[0] = 'q';
break;
case 's':
} /* IRC_MODE */
+GLOBAL BOOLEAN IRC_AWAY( CLIENT *Client, REQUEST *Req )
+{
+ assert( Client != NULL );
+ assert( Req != NULL );
+
+ if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
+
+ /* Falsche Anzahl Parameter? */
+ if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+ if(( Req->argc == 1 ) && (Req->argv[0][0] ))
+ {
+ /* AWAY setzen */
+ Client_SetAway( Client, Req->argv[0] );
+ IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
+ return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
+ }
+ else
+ {
+ /* AWAY loeschen */
+ Client_SetAway( Client, NULL );
+ IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
+ return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
+ }
+} /* IRC_AWAY */
+
+
GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
{
INT i;
chan = Channel_Next( chan );
}
+ /* Nun noch alle Clients ausgeben, die in keinem Channel sind */
c = Client_First( );
sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
while( c )
{
- if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ))
+ if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ) && ( ! strchr( Client_Modes( c ), 'i' )))
{
/* Okay, das ist ein User: anhaengen */
if( rpl[strlen( rpl ) - 1] != ':' ) strcat( rpl, " " );
if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
}
+ /* Away? */
+ if( Client_HasMode( c, 'a' ))
+ {
+ if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED;
+ }
+
/* End of Whois */
return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
} /* IRC_WHOIS */
LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
{
+ BOOLEAN is_visible, is_member;
CHAR str[LINE_LEN + 1];
CL2CHAN *cl2chan;
CLIENT *cl;
assert( Client != NULL );
assert( Chan != NULL );
+ if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE;
+ else is_member = FALSE;
+
/* Alle Mitglieder suchen */
sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
cl2chan = Channel_FirstMember( Chan );
{
cl = Channel_GetClient( cl2chan );
- /* Nick anhaengen */
- if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
- if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
- if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
- strcat( str, Client_ID( cl ));
+ if( strchr( Client_Modes( cl ), 'i' )) is_visible = FALSE;
+ else is_visible = TRUE;
- if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
+ if( is_member || is_visible )
{
- /* Zeile wird zu lang: senden! */
- if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
- sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
+ /* Nick anhaengen */
+ if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
+ 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 ))
+ {
+ /* Zeile wird zu lang: senden! */
+ if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
+ sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
+ }
}
/* naechstes Mitglied suchen */