]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc.c
Debian: require "telnet" or "telnet-ssl" for building
[ngircd-alex.git] / src / ngircd / irc.c
index 7a871379a422543c416a111e6d2eeaafdd661dc5..ceb649ecf350159d1db1bc969d0a5bb496372a2a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -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"
@@ -45,6 +46,35 @@ static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
                                      bool SendErrors));
 
 
+/**
+ * Check if a list limit is reached and inform client accordingly.
+ *
+ * @param From The client.
+ * @param Count Reply item count.
+ * @param Limit Reply limit.
+ * @param Name Name of the list.
+ * @return true if list limit has been reached; false otherwise.
+ */
+GLOBAL bool
+IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit,
+                   const char *Name)
+{
+       assert(From != NULL);
+       assert(Count >= 0);
+       assert(Limit > 0);
+       assert(Name != NULL);
+
+       if (Count < Limit)
+               return false;
+
+       (void)IRC_WriteStrClient(From,
+                                "NOTICE %s :%s list limit (%d) reached!",
+                                Client_ID(From), Name, Limit);
+       IRC_SetPenalty(From, 2);
+       return true;
+}
+
+
 GLOBAL bool
 IRC_ERROR( CLIENT *Client, REQUEST *Req )
 {
@@ -298,12 +328,18 @@ IRC_HELP( CLIENT *Client, REQUEST *Req )
 
 
 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 ... */
@@ -320,9 +356,11 @@ static bool
 Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
 {
        CLIENT *cl, *from;
+       CL2CHAN *cl2chan;
        CHANNEL *chan;
        char *currentTarget = Req->argv[0];
        char *lastCurrentTarget = NULL;
+       char *message = NULL;
 
        assert(Client != NULL);
        assert(Req != NULL);
@@ -354,6 +392,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);
@@ -410,8 +455,8 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
                                    Client_Type(cl) != CLIENT_SERVICE)
                                        continue;
                                if (nick != NULL && host != NULL) {
-                                       if (strcmp(nick, Client_ID(cl)) == 0 &&
-                                           strcmp(user, Client_User(cl)) == 0 &&
+                                       if (strcasecmp(nick, Client_ID(cl)) == 0 &&
+                                           strcasecmp(user, Client_User(cl)) == 0 &&
                                            strcasecmp(host, Client_HostnameCloaked(cl)) == 0)
                                                break;
                                        else
@@ -439,11 +484,11 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
 #else
                        if (Client_Type(cl) != ForceType) {
 #endif
-                               if (!SendErrors)
-                                       return CONNECTED;
-                               return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
-                                                         Client_ID(from),
-                                                         currentTarget);
+                               if (SendErrors && !IRC_WriteStrClient(
+                                   from, ERR_NOSUCHNICK_MSG,Client_ID(from),
+                                   currentTarget))
+                                       return DISCONNECTED;
+                               goto send_next_target;
                        }
 
 #ifndef STRICT_RFC
@@ -456,6 +501,23 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
                        }
 #endif
 
+                       if (Client_HasMode(cl, 'C')) {
+                               cl2chan = Channel_FirstChannelOf(cl);
+                               while (cl2chan) {
+                                       chan = Channel_GetChannel(cl2chan);
+                                       if (Channel_IsMemberOf(chan, from))
+                                               break;
+                                       cl2chan = Channel_NextChannelOf(cl, cl2chan);
+                               }
+                               if (!cl2chan) {
+                                       if (SendErrors && !IRC_WriteStrClient(
+                                           from, ERR_NOTONSAMECHANNEL_MSG,
+                                           Client_ID(from), Client_ID(cl)))
+                                               return DISCONNECTED;
+                                       goto send_next_target;
+                               }
+                       }
+
                        if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
                            && strchr(Client_Modes(cl), 'a')) {
                                /* Target is away */
@@ -470,12 +532,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 */
@@ -483,7 +545,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)
@@ -493,6 +555,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
                                return DISCONNECTED;
                }
 
+       send_next_target:
                currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
                if (currentTarget)
                        Conn_SetPenalty(Client_Conn(Client), 1);