]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc.c
Remove leftover debug message. Oops!
[ngircd-alex.git] / src / ngircd / irc.c
index e990cfd7a0397d2f6e42c9e42dc7d4d10db2a8af..72caf7d576120e6abea27d6f5fb4e1e33866643f 100644 (file)
@@ -493,11 +493,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 +516,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 +559,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 <msgto> of form:
                 * RFC 2812 2.3.1:
                 *   msgto =  channel / ( user [ "%" host ] "@" servername )
@@ -693,14 +715,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 +735,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 +790,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 +806,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;