X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc.c;h=d5e4bde3d70cd1319b82f69641a6d993257be3bc;hb=543f44bff8d56785dc13a74a14d4eaa96465bf05;hp=e990cfd7a0397d2f6e42c9e42dc7d4d10db2a8af;hpb=4693226d6983b5ed4bd74b32a8daa9a3124ed17c;p=ngircd-alex.git diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index e990cfd7..d5e4bde3 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -85,6 +85,8 @@ IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit, GLOBAL bool IRC_ERROR(CLIENT *Client, REQUEST *Req) { + char *msg; + assert( Client != NULL ); assert( Req != NULL ); @@ -99,12 +101,20 @@ IRC_ERROR(CLIENT *Client, REQUEST *Req) return CONNECTED; } - if (Req->argc < 1) + if (Req->argc < 1) { + msg = "Got ERROR command"; Log(LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask(Client)); - else + } else { + msg = Req->argv[0]; Log(LOG_NOTICE, "Got ERROR from \"%s\": \"%s\"!", - Client_Mask(Client), Req->argv[0]); + Client_Mask(Client), msg); + } + + if (Client_Conn(Client) != NONE) { + Client_Destroy(Client, NULL, msg, false); + return DISCONNECTED; + } return CONNECTED; } /* IRC_ERROR */ @@ -493,11 +503,22 @@ Option_String(UNUSED CONN_ID Idx) if(options & CONN_ZIP) /* zlib compression enabled */ strlcat(option_txt, "z", sizeof(option_txt)); #endif - LogDebug(" *** %d: %d = %s", Idx, options, option_txt); return option_txt; } /* Option_String */ +/** + * Send a message to target(s). + * + * This function is used by IRC_{PRIVMSG|NOTICE|SQUERY} to actualy + * send the message(s). + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @param ForceType Required type of the destination of the message(s). + * @param SendErrors Whether to report errors back to the client or not. + * @return CONNECTED or DISCONNECTED. + */ static bool Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) { @@ -505,8 +526,10 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) CL2CHAN *cl2chan; CHANNEL *chan; char *currentTarget = Req->argv[0]; - char *lastCurrentTarget = NULL; + char *strtok_last = NULL; char *message = NULL; + char *targets[MAX_HNDL_TARGETS]; + int i, target_nr = 0; assert(Client != NULL); assert(Req != NULL); @@ -546,10 +569,19 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) message = Req->argv[1]; /* handle msgtarget = msgto *("," msgto) */ - currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget); + currentTarget = strtok_r(currentTarget, ",", &strtok_last); ngt_UpperStr(Req->command); + /* Please note that "currentTarget" is NULL when the target contains + * the separator character only, e. g. "," or ",,,," etc.! */ while (currentTarget) { + /* Make sure that there hasn't been such a target already: */ + targets[target_nr++] = currentTarget; + for(i = 0; i < target_nr - 1; i++) { + if (strcasecmp(currentTarget, targets[i]) == 0) + goto send_next_target; + } + /* Check for and handle valid of form: * RFC 2812 2.3.1: * msgto = channel / ( user [ "%" host ] "@" servername ) @@ -693,14 +725,14 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE && (chan = Channel_Search(currentTarget))) { + /* Target is a channel */ if (!Channel_Write(chan, from, Client, Req->command, SendErrors, message)) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE - /* $#: server/target mask, RFC 2812, sec. 3.3.1 */ && strchr("$#", currentTarget[0]) && strchr(currentTarget, '.')) { - /* targetmask */ + /* $#: server/host mask, RFC 2812, sec. 3.3.1 */ if (!Send_Message_Mask(from, Req->command, currentTarget, message, SendErrors)) return DISCONNECTED; @@ -713,14 +745,35 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) } send_next_target: - currentTarget = strtok_r(NULL, ",", &lastCurrentTarget); - if (currentTarget) - Conn_SetPenalty(Client_Conn(Client), 1); + currentTarget = strtok_r(NULL, ",", &strtok_last); + if (!currentTarget) + break; + + Conn_SetPenalty(Client_Conn(Client), 1); + + if (target_nr >= MAX_HNDL_TARGETS) { + /* Too many targets given! */ + return IRC_WriteErrClient(Client, + ERR_TOOMANYTARGETS_MSG, + currentTarget); + } } return CONNECTED; } /* Send_Message */ +/** + * Send a message to "target mask" target(s). + * + * See RFC 2812, sec. 3.3.1 for details. + * + * @param from The client from which this command has been received. + * @param command The command to use (PRIVMSG, NOTICE, ...). + * @param targetMask The "target mask" (will be verified by this function). + * @param message The message to send. + * @param SendErrors Whether to report errors back to the client or not. + * @return CONNECTED or DISCONNECTED. + */ static bool Send_Message_Mask(CLIENT * from, char * command, char * targetMask, char * message, bool SendErrors) @@ -747,11 +800,12 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask, if (!check_wildcards || check_wildcards[strcspn(check_wildcards, "*?")]) { if (!SendErrors) return true; - return IRC_WriteErrClient(from, ERR_WILDTOPLEVEL, targetMask); + return IRC_WriteErrClient(from, ERR_WILDTOPLEVEL_MSG, + targetMask); } - /* #: hostmask, see RFC 2812, sec. 3.3.1 */ if (targetMask[0] == '#') { + /* #: hostmask, see RFC 2812, sec. 3.3.1 */ for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) { if (Client_Type(cl) != CLIENT_USER) continue; @@ -762,7 +816,8 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask, return false; } } else { - assert(targetMask[0] == '$'); /* $: server mask, see RFC 2812, sec. 3.3.1 */ + /* $: server mask, see RFC 2812, sec. 3.3.1 */ + assert(targetMask[0] == '$'); for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) { if (Client_Type(cl) != CLIENT_USER) continue;