X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc.c;h=8dd9bf74f2897b954c337a1f028cdecbf1cdb64f;hb=49b2d0ec98d001fbc8eedd5a183d66974f70fd52;hp=c49a77a4fcf13444afeaf8b79119eec7709416e6;hpb=e5174c629c67ba84eedc6e057c66833632293e3f;p=ngircd-alex.git diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index c49a77a4..8dd9bf74 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -7,14 +7,14 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. - * - * IRC commands */ - #include "portab.h" -static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/15 22:28:14 fw Exp $"; +/** + * @file + * IRC commands + */ #include "imp.h" #include @@ -22,10 +22,8 @@ static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/15 22:28:14 fw Exp $"; #include #include "ngircd.h" -#include "resolve.h" #include "conn-func.h" #include "conf.h" -#include "client.h" #include "channel.h" #include "defines.h" #include "irc-write.h" @@ -33,14 +31,18 @@ static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/15 22:28:14 fw Exp $"; #include "match.h" #include "messages.h" #include "parse.h" +#include "tool.h" #include "exp.h" #include "irc.h" static char *Option_String PARAMS((CONN_ID Idx)); -static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType, bool SendErrors)); -static bool Send_Message_Mask PARAMS((CLIENT *from, char *targetMask, char *message, bool SendErrors)); +static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType, + bool SendErrors)); +static bool Send_Message_Mask PARAMS((CLIENT *from, char *command, + char *targetMask, char *message, + bool SendErrors)); GLOBAL bool @@ -49,8 +51,12 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req ) assert( Client != NULL ); assert( Req != NULL ); - if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client )); - else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] ); + if (Req->argc < 1) + Log(LOG_NOTICE, "Got ERROR from \"%s\"!", + Client_Mask(Client)); + else + Log(LOG_NOTICE, "Got ERROR from \"%s\": \"%s\"!", + Client_Mask(Client), Req->argv[0]); return CONNECTED; } /* IRC_ERROR */ @@ -62,7 +68,7 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req ) * disconnect clients. It can be used by IRC operators and servers, for example * to "solve" nick collisions after netsplits. * Please note that this function is also called internally, without a real - * KILL command beeing received over the network! Client is Client_ThisServer() + * KILL command being received over the network! Client is Client_ThisServer() * in this case. */ GLOBAL bool IRC_KILL( CLIENT *Client, REQUEST *Req ) @@ -152,11 +158,15 @@ IRC_KILL( CLIENT *Client, REQUEST *Req ) Client_Type( c ), Req->argv[0] ); } - /* Kill client NOW! */ + /* Kill the client NOW: + * - Close the local connection (if there is one), + * - Destroy the CLIENT structure for remote clients. + * Note: Conn_Close() removes the CLIENT structure as well. */ conn = Client_Conn( c ); - Client_Destroy( c, NULL, reason, false ); - if( conn > NONE ) - Conn_Close( conn, NULL, reason, true ); + if(conn > NONE) + Conn_Close(conn, NULL, reason, true); + else + Client_Destroy(c, NULL, reason, false); } else Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] ); @@ -319,19 +329,19 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (Req->argc == 0) { if (!SendErrors) - return true; + return CONNECTED; return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG, Client_ID(Client), Req->command); } if (Req->argc == 1) { if (!SendErrors) - return true; + return CONNECTED; return IRC_WriteStrClient(Client, ERR_NOTEXTTOSEND_MSG, Client_ID(Client)); } if (Req->argc > 2) { if (!SendErrors) - return true; + return CONNECTED; return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command); } @@ -346,6 +356,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) /* handle msgtarget = msgto *("," msgto) */ currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget); + ngt_UpperStr(Req->command); while (currentTarget) { /* Check for and handle valid of form: @@ -395,12 +406,13 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) } for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) { - if (Client_Type(cl) != CLIENT_USER) + if (Client_Type(cl) != CLIENT_USER && + Client_Type(cl) != CLIENT_SERVICE) continue; - if (nick != NULL) { + if (nick != NULL && host != NULL) { if (strcmp(nick, Client_ID(cl)) == 0 && strcmp(user, Client_User(cl)) == 0 && - strcasecmp(host, Client_Hostname(cl)) == 0) + strcasecmp(host, Client_HostnameCloaked(cl)) == 0) break; else continue; @@ -408,7 +420,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (strcasecmp(user, Client_User(cl)) != 0) continue; if (host != NULL && strcasecmp(host, - Client_Hostname(cl)) != 0) + Client_HostnameCloaked(cl)) != 0) continue; if (server != NULL && strcasecmp(server, Client_ID(Client_Introducer(cl))) != 0) @@ -419,46 +431,66 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (cl) { /* Target is a user, enforce type */ +#ifndef STRICT_RFC + if (Client_Type(cl) != ForceType && + !(ForceType == CLIENT_USER && + (Client_Type(cl) == CLIENT_USER || + Client_Type(cl) == CLIENT_SERVICE))) { +#else if (Client_Type(cl) != ForceType) { +#endif if (!SendErrors) - return true; - if (!IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, + return CONNECTED; + return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, Client_ID(from), - currentTarget)) - return false; - } else if (SendErrors - && (Client_Type(Client) != CLIENT_SERVER) - && strchr(Client_Modes(cl), 'a')) { + currentTarget); + } + +#ifndef STRICT_RFC + if (ForceType == CLIENT_SERVICE && + (Conn_Options(Client_Conn(Client_NextHop(cl))) + & CONN_RFC1459)) { + /* SQUERY command but RFC 1459 link: convert + * request to PRIVMSG command */ + Req->command = "PRIVMSG"; + } +#endif + + if (SendErrors && (Client_Type(Client) != CLIENT_SERVER) + && strchr(Client_Modes(cl), 'a')) { /* Target is away */ - if (!SendErrors) - return true; - if (!IRC_WriteStrClient - (from, RPL_AWAY_MSG, Client_ID(from), - Client_ID(cl), Client_Away(cl))) + if (!IRC_WriteStrClient(from, RPL_AWAY_MSG, + Client_ID(from), + Client_ID(cl), + Client_Away(cl))) return DISCONNECTED; } if (Client_Conn(from) > NONE) { Conn_UpdateIdle(Client_Conn(from)); } - if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", - Client_ID(cl), Req->argv[1])) - return false; - } else if (strchr("$#", currentTarget[0]) + if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s", + Req->command, Client_ID(cl), + Req->argv[1])) + return DISCONNECTED; + } else if (ForceType != CLIENT_SERVICE + && (chan = Channel_Search(currentTarget))) { + if (!Channel_Write(chan, from, Client, Req->command, + SendErrors, Req->argv[1])) + return DISCONNECTED; + } else if (ForceType != CLIENT_SERVICE + /* $#: server/target mask, RFC 2812, sec. 3.3.1 */ + && strchr("$#", currentTarget[0]) && strchr(currentTarget, '.')) { /* targetmask */ - if (!Send_Message_Mask(from, currentTarget, + if (!Send_Message_Mask(from, Req->command, currentTarget, Req->argv[1], SendErrors)) - return false; - } else if ((chan = Channel_Search(currentTarget))) { - /* channel */ - if (!Channel_Write(chan, from, Client, Req->argv[1])) - return false; + return DISCONNECTED; } else { if (!SendErrors) - return true; + return CONNECTED; if (!IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, Client_ID(from), currentTarget)) - return false; + return DISCONNECTED; } currentTarget = strtok_r(NULL, ",", &lastCurrentTarget); @@ -469,11 +501,13 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) static bool -Send_Message_Mask(CLIENT * from, char * targetMask, char * message, bool SendErrors) +Send_Message_Mask(CLIENT * from, char * command, char * targetMask, + char * message, bool SendErrors) { CLIENT *cl; bool client_match; char *mask = targetMask + 1; + const char *check_wildcards; cl = NULL; @@ -484,25 +518,41 @@ Send_Message_Mask(CLIENT * from, char * targetMask, char * message, bool SendErr Client_ID(from)); } + /* + * RFC 2812, sec. 3.3.1 requires that targetMask have at least one + * dot (".") and no wildcards ("*", "?") following the last one. + */ + check_wildcards = strrchr(targetMask, '.'); + assert(check_wildcards != NULL); + if (check_wildcards && + check_wildcards[strcspn(check_wildcards, "*?")]) + { + if (!SendErrors) + return true; + return IRC_WriteStrClient(from, ERR_WILDTOPLEVEL, targetMask); + } + + /* #: hostmask, see RFC 2812, sec. 3.3.1 */ if (targetMask[0] == '#') { for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) { if (Client_Type(cl) != CLIENT_USER) continue; client_match = MatchCaseInsensitive(mask, Client_Hostname(cl)); if (client_match) - if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", - Client_ID(cl), message)) + if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s", + command, Client_ID(cl), message)) return false; } } else { + assert(targetMask[0] == '$'); /* $: server mask, see RFC 2812, sec. 3.3.1 */ for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) { if (Client_Type(cl) != CLIENT_USER) continue; client_match = MatchCaseInsensitive(mask, Client_ID(Client_Introducer(cl))); if (client_match) - if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", - Client_ID(cl), message)) + if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s", + command, Client_ID(cl), message)) return false; } }