X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc.c;h=37df06873bb30e99c78d91c360d23a09b9bbfec1;hp=9508ecc457b9037f389f4a5cd1bbf1b7cb6f17be;hb=d38d153f;hpb=39412d648652b3fcb387cf04bf7fa9004cfcd8ba;ds=sidebyside diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index 9508ecc4..37df0687 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -25,6 +25,7 @@ #include "conn-func.h" #include "conf.h" #include "channel.h" +#include "conn-encoding.h" #include "defines.h" #include "irc-write.h" #include "log.h" @@ -43,6 +44,7 @@ static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType, static bool Send_Message_Mask PARAMS((CLIENT *from, char *command, char *targetMask, char *message, bool SendErrors)); +static bool Help PARAMS((CLIENT *Client, const char *Topic)); /** @@ -80,6 +82,17 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req ) assert( Client != NULL ); assert( Req != NULL ); + if (Client_Type(Client) != CLIENT_GOTPASS + && Client_Type(Client) != CLIENT_GOTPASS_2813 + && Client_Type(Client) != CLIENT_UNKNOWNSERVER + && Client_Type(Client) != CLIENT_SERVER + && Client_Type(Client) != CLIENT_SERVICE) { + LogDebug("Ignored ERROR command from \"%s\" ...", + Client_Mask(Client)); + IRC_SetPenalty(Client, 2); + return CONNECTED; + } + if (Req->argc < 1) Log(LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask(Client)); @@ -141,7 +154,7 @@ IRC_KILL( CLIENT *Client, REQUEST *Req ) if (Client != Client_ThisServer()) Log(LOG_NOTICE|LOG_snotice, - "Got KILL command from \"%s\" for \"%s\": %s", + "Got KILL command from \"%s\" for \"%s\": \"%s\".", Client_Mask(prefix), Req->argv[0], Req->argv[1]); /* Build reason string: Prefix the "reason" if the originator is a @@ -303,36 +316,129 @@ IRC_TRACE( CLIENT *Client, REQUEST *Req ) } /* IRC_TRACE */ +/** + * Handler for the IRC "HELP" command. + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @return CONNECTED or DISCONNECTED. + */ GLOBAL bool -IRC_HELP( CLIENT *Client, REQUEST *Req ) +IRC_HELP(CLIENT *Client, REQUEST *Req) { COMMAND *cmd; - assert( Client != NULL ); - assert( Req != NULL ); + assert(Client != NULL); + assert(Req != NULL); /* Bad number of arguments? */ - if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command ); + if (Req->argc > 1) + return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG, + Client_ID(Client), Req->command); - cmd = Parse_GetCommandStruct( ); - while( cmd->name ) - { - if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED; + IRC_SetPenalty(Client, 2); + + if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0) + || (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) { + /* Help text available and requested */ + if (Req->argc >= 1) + return Help(Client, Req->argv[0]); + + if (!Help(Client, "Intro")) + return DISCONNECTED; + return CONNECTED; + } + + cmd = Parse_GetCommandStruct(); + while(cmd->name) { + if (!IRC_WriteStrClient(Client, "NOTICE %s :%s", + Client_ID(Client), cmd->name)) + return DISCONNECTED; cmd++; } - - IRC_SetPenalty( Client, 2 ); return CONNECTED; } /* IRC_HELP */ +/** + * Send help for a given topic to the client. + * + * @param Client The client requesting help. + * @param Topoc The help topic requested. + * @return CONNECTED or DISCONNECTED. + */ +static bool +Help(CLIENT *Client, const char *Topic) +{ + char *line; + size_t helptext_len, len_str, idx_start, lines = 0; + bool in_article = false; + + assert(Client != NULL); + assert(Topic != NULL); + + helptext_len = array_bytes(&Conf_Helptext); + line = array_start(&Conf_Helptext); + while (helptext_len > 0) { + len_str = strlen(line) + 1; + assert(helptext_len >= len_str); + helptext_len -= len_str; + + if (in_article) { + /* The first character in each article text line must + * be a TAB (ASCII 9) character which will be stripped + * in the output. If it is not a TAB, the end of the + * article has been reached. */ + if (line[0] != '\t') { + if (lines > 0) + return CONNECTED; + else + break; + } + + /* A single '.' character indicates an empty line */ + if (line[1] == '.' && line[2] == '\0') + idx_start = 2; + else + idx_start = 1; + + if (!IRC_WriteStrClient(Client, "NOTICE %s :%s", + Client_ID(Client), + &line[idx_start])) + return DISCONNECTED; + lines++; + + } else { + if (line[0] == '-' && line[1] == ' ' + && strcasecmp(&line[2], Topic) == 0) + in_article = true; + } + + line += len_str; + } + + /* Help topic not found (or empty)! */ + if (!IRC_WriteStrClient(Client, "NOTICE %s :No help for \"%s\" found!", + Client_ID(Client), Topic)) + return DISCONNECTED; + + return CONNECTED; +} + + static char * -Option_String( CONN_ID Idx ) +#ifdef ZLIB +Option_String(CONN_ID Idx) +#else +Option_String(UNUSED CONN_ID Idx) +#endif { static char option_txt[8]; +#ifdef ZLIB UINT16 options; options = Conn_Options(Idx); +#endif strcpy(option_txt, "F"); /* No idea what this means, but the * original ircd sends it ... */ @@ -353,6 +459,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) CHANNEL *chan; char *currentTarget = Req->argv[0]; char *lastCurrentTarget = NULL; + char *message = NULL; assert(Client != NULL); assert(Req != NULL); @@ -384,6 +491,13 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix); +#ifdef ICONV + if (Client_Conn(Client) > NONE) + message = Conn_EncodingFrom(Client_Conn(Client), Req->argv[1]); + else +#endif + message = Req->argv[1]; + /* handle msgtarget = msgto *("," msgto) */ currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget); ngt_UpperStr(Req->command); @@ -442,7 +556,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (nick != NULL && host != NULL) { if (strcasecmp(nick, Client_ID(cl)) == 0 && strcasecmp(user, Client_User(cl)) == 0 && - strcasecmp(host, Client_HostnameCloaked(cl)) == 0) + strcasecmp(host, Client_HostnameDisplayed(cl)) == 0) break; else continue; @@ -450,7 +564,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_HostnameCloaked(cl)) != 0) + Client_HostnameDisplayed(cl)) != 0) continue; if (server != NULL && strcasecmp(server, Client_ID(Client_Introducer(cl))) != 0) @@ -485,6 +599,17 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) Req->command = "PRIVMSG"; } #endif + if (Client_HasMode(cl, 'b') && + !Client_HasMode(from, 'R') && + !Client_HasMode(from, 'o') && + !(Client_Type(from) == CLIENT_SERVER) && + !(Client_Type(from) == CLIENT_SERVICE)) { + if (SendErrors && !IRC_WriteStrClient(from, + ERR_NONONREG_MSG, + Client_ID(from), Client_ID(cl))) + return DISCONNECTED; + goto send_next_target; + } if (Client_HasMode(cl, 'C')) { cl2chan = Channel_FirstChannelOf(cl); @@ -517,12 +642,12 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) } if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s", Req->command, Client_ID(cl), - Req->argv[1])) + message)) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE && (chan = Channel_Search(currentTarget))) { if (!Channel_Write(chan, from, Client, Req->command, - SendErrors, Req->argv[1])) + SendErrors, message)) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE /* $#: server/target mask, RFC 2812, sec. 3.3.1 */ @@ -530,7 +655,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) && strchr(currentTarget, '.')) { /* targetmask */ if (!Send_Message_Mask(from, Req->command, currentTarget, - Req->argv[1], SendErrors)) + message, SendErrors)) return DISCONNECTED; } else { if (!SendErrors)