]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge branch 'master+writenumeric'
authorAttila Molnar <attilamolnar@hush.com>
Thu, 25 Feb 2016 17:05:04 +0000 (18:05 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Thu, 25 Feb 2016 17:05:04 +0000 (18:05 +0100)
145 files changed:
include/convto.h [new file with mode: 0644]
include/extensible.h
include/inspircd.h
include/isupportmanager.h
include/modules.h
include/modules/stats.h [new file with mode: 0644]
include/modules/whois.h
include/numeric.h [new file with mode: 0644]
include/numericbuilder.h
include/numerics.h
include/typedefs.h
include/users.h
include/xline.h
src/channels.cpp
src/command_parse.cpp
src/configreader.cpp
src/coremods/core_channel/cmd_invite.cpp
src/coremods/core_channel/cmd_join.cpp
src/coremods/core_channel/cmd_kick.cpp
src/coremods/core_channel/cmd_names.cpp
src/coremods/core_channel/cmd_topic.cpp
src/coremods/core_info/cmd_admin.cpp
src/coremods/core_info/cmd_commands.cpp
src/coremods/core_info/cmd_info.cpp
src/coremods/core_info/cmd_modules.cpp
src/coremods/core_info/cmd_motd.cpp
src/coremods/core_info/cmd_time.cpp
src/coremods/core_info/cmd_version.cpp
src/coremods/core_list.cpp
src/coremods/core_loadmodule.cpp
src/coremods/core_lusers.cpp
src/coremods/core_oper/cmd_kill.cpp
src/coremods/core_oper/cmd_oper.cpp
src/coremods/core_oper/cmd_rehash.cpp
src/coremods/core_privmsg.cpp
src/coremods/core_reloadmodule.cpp
src/coremods/core_stats.cpp
src/coremods/core_stub.cpp
src/coremods/core_user/cmd_away.cpp
src/coremods/core_user/cmd_mode.cpp
src/coremods/core_user/cmd_nick.cpp
src/coremods/core_user/cmd_part.cpp
src/coremods/core_user/cmd_user.cpp
src/coremods/core_user/core_user.cpp
src/coremods/core_who.cpp
src/coremods/core_whois.cpp
src/coremods/core_whowas.cpp
src/coremods/core_xline/core_xline.cpp
src/listmode.cpp
src/mode.cpp
src/modes/umode_s.cpp
src/modules.cpp
src/modules/extra/m_geoip.cpp
src/modules/m_abbreviation.cpp
src/modules/m_alias.cpp
src/modules/m_allowinvite.cpp
src/modules/m_autoop.cpp
src/modules/m_banredirect.cpp
src/modules/m_blockcaps.cpp
src/modules/m_blockcolor.cpp
src/modules/m_botmode.cpp
src/modules/m_callerid.cpp
src/modules/m_cap.cpp
src/modules/m_cban.cpp
src/modules/m_censor.cpp
src/modules/m_chanfilter.cpp
src/modules/m_chghost.cpp
src/modules/m_chgident.cpp
src/modules/m_chgname.cpp
src/modules/m_commonchans.cpp
src/modules/m_customtitle.cpp
src/modules/m_cycle.cpp
src/modules/m_dccallow.cpp
src/modules/m_delaymsg.cpp
src/modules/m_denychans.cpp
src/modules/m_dnsbl.cpp
src/modules/m_exemptchanops.cpp
src/modules/m_filter.cpp
src/modules/m_globalload.cpp
src/modules/m_helpop.cpp
src/modules/m_hidechans.cpp
src/modules/m_hidelist.cpp
src/modules/m_hideoper.cpp
src/modules/m_httpd_stats.cpp
src/modules/m_joinflood.cpp
src/modules/m_jumpserver.cpp
src/modules/m_kicknorejoin.cpp
src/modules/m_knock.cpp
src/modules/m_lockserv.cpp
src/modules/m_messageflood.cpp
src/modules/m_mlock.cpp
src/modules/m_monitor.cpp
src/modules/m_muteban.cpp
src/modules/m_namedmodes.cpp
src/modules/m_nickflood.cpp
src/modules/m_nicklock.cpp
src/modules/m_noctcp.cpp
src/modules/m_nokicks.cpp
src/modules/m_nonicks.cpp
src/modules/m_nonotice.cpp
src/modules/m_ojoin.cpp
src/modules/m_operchans.cpp
src/modules/m_operlevels.cpp
src/modules/m_opermotd.cpp
src/modules/m_redirect.cpp
src/modules/m_regonlycreate.cpp
src/modules/m_remove.cpp
src/modules/m_restrictchans.cpp
src/modules/m_restrictmsg.cpp
src/modules/m_rline.cpp
src/modules/m_sajoin.cpp
src/modules/m_sakick.cpp
src/modules/m_samode.cpp
src/modules/m_sanick.cpp
src/modules/m_sapart.cpp
src/modules/m_saquit.cpp
src/modules/m_sasl.cpp
src/modules/m_satopic.cpp
src/modules/m_securelist.cpp
src/modules/m_services_account.cpp
src/modules/m_servprotect.cpp
src/modules/m_setidle.cpp
src/modules/m_showfile.cpp
src/modules/m_shun.cpp
src/modules/m_silence.cpp
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/main.h
src/modules/m_spanningtree/override_map.cpp
src/modules/m_spanningtree/override_stats.cpp
src/modules/m_spanningtree/override_whois.cpp
src/modules/m_spanningtree/uid.cpp
src/modules/m_sslinfo.cpp
src/modules/m_sslmodes.cpp
src/modules/m_starttls.cpp
src/modules/m_svshold.cpp
src/modules/m_swhois.cpp
src/modules/m_timedbans.cpp
src/modules/m_topiclock.cpp
src/modules/m_uninvite.cpp
src/modules/m_userip.cpp
src/modules/m_watch.cpp
src/server.cpp
src/usermanager.cpp
src/users.cpp
src/xline.cpp

diff --git a/include/convto.h b/include/convto.h
new file mode 100644 (file)
index 0000000..eaf14f6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+/** Template function to convert any input type to std::string
+ */
+template<typename T> inline std::string ConvNumeric(const T& in)
+{
+       if (in == 0)
+               return "0";
+       T quotient = in;
+       std::string out;
+       while (quotient)
+       {
+               out += "0123456789"[std::abs((long)quotient % 10)];
+               quotient /= 10;
+       }
+       if (in < 0)
+               out += '-';
+       std::reverse(out.begin(), out.end());
+       return out;
+}
+
+/** Template function to convert any input type to std::string
+ */
+inline std::string ConvToStr(const int in)
+{
+       return ConvNumeric(in);
+}
+
+/** Template function to convert any input type to std::string
+ */
+inline std::string ConvToStr(const long in)
+{
+       return ConvNumeric(in);
+}
+
+/** Template function to convert any input type to std::string
+ */
+inline std::string ConvToStr(const char* in)
+{
+       return in;
+}
+
+/** Template function to convert any input type to std::string
+ */
+inline std::string ConvToStr(const bool in)
+{
+       return (in ? "1" : "0");
+}
+
+/** Template function to convert any input type to std::string
+ */
+inline std::string ConvToStr(char in)
+{
+       return std::string(1, in);
+}
+
+inline const std::string& ConvToStr(const std::string& in)
+{
+       return in;
+}
+
+/** Template function to convert any input type to std::string
+ */
+template <class T> inline std::string ConvToStr(const T& in)
+{
+       std::stringstream tmp;
+       if (!(tmp << in))
+               return std::string();
+       return tmp.str();
+}
+
+/** Template function to convert any input type to any other type
+ * (usually an integer or numeric type)
+ */
+template<typename T> inline long ConvToInt(const T& in)
+{
+       std::stringstream tmp;
+       if (!(tmp << in))
+               return 0;
+       return atol(tmp.str().c_str());
+}
+
+inline uint64_t ConvToUInt64(const std::string& in)
+{
+       uint64_t ret;
+       std::istringstream tmp(in);
+       if (!(tmp >> ret))
+               return 0;
+       return ret;
+}
index 9714e9654d3d2a026c3b1f13413718caaeba6bbb..07756fb599a419fe3525fb326cfac2ff28d1ec22 100644 (file)
@@ -19,8 +19,6 @@
 
 #pragma once
 
-#include <stdint.h>
-
 enum SerializeFormat
 {
        /** Shown to a human (does not need to be unserializable) */
index 20a6508c97fc246332c887b1939f91adfabc89f0..ee09070f858799d5ffca7c534769c9a96dadc3ca 100644 (file)
@@ -32,6 +32,7 @@
 #include <cstdio>
 #include <cstring>
 #include <ctime>
+#include <stdint.h>
 
 #include <algorithm>
 #include <bitset>
@@ -64,6 +65,7 @@ struct fakederef
 };
 
 #include "config.h"
+#include "convto.h"
 #include "dynref.h"
 #include "consolecolors.h"
 #include "caller.h"
@@ -71,6 +73,7 @@ struct fakederef
 #include "extensible.h"
 #include "fileutils.h"
 #include "numerics.h"
+#include "numeric.h"
 #include "uid.h"
 #include "server.h"
 #include "users.h"
@@ -94,88 +97,6 @@ struct fakederef
 #include "bancache.h"
 #include "isupportmanager.h"
 
-/** Template function to convert any input type to std::string
- */
-template<typename T> inline std::string ConvNumeric(const T &in)
-{
-       if (in == 0)
-               return "0";
-       T quotient = in;
-       std::string out;
-       while (quotient)
-       {
-               out += "0123456789"[ std::abs( (long)quotient % 10 ) ];
-               quotient /= 10;
-       }
-       if (in < 0)
-               out += '-';
-       std::reverse(out.begin(), out.end());
-       return out;
-}
-
-/** Template function to convert any input type to std::string
- */
-inline std::string ConvToStr(const int in)
-{
-       return ConvNumeric(in);
-}
-
-/** Template function to convert any input type to std::string
- */
-inline std::string ConvToStr(const long in)
-{
-       return ConvNumeric(in);
-}
-
-/** Template function to convert any input type to std::string
- */
-inline std::string ConvToStr(const char* in)
-{
-       return in;
-}
-
-/** Template function to convert any input type to std::string
- */
-inline std::string ConvToStr(const bool in)
-{
-       return (in ? "1" : "0");
-}
-
-/** Template function to convert any input type to std::string
- */
-inline std::string ConvToStr(char in)
-{
-       return std::string(1, in);
-}
-
-/** Template function to convert any input type to std::string
- */
-template <class T> inline std::string ConvToStr(const T &in)
-{
-       std::stringstream tmp;
-       if (!(tmp << in)) return std::string();
-       return tmp.str();
-}
-
-/** Template function to convert any input type to any other type
- * (usually an integer or numeric type)
- */
-template<typename T> inline long ConvToInt(const T &in)
-{
-       std::stringstream tmp;
-       if (!(tmp << in)) return 0;
-       return atol(tmp.str().c_str());
-}
-
-inline uint64_t ConvToUInt64(const std::string& in)
-{
-       uint64_t ret;
-       std::istringstream tmp(in);
-       if (!(tmp >> ret))
-               return 0;
-       return ret;
-}
-
 /** This class contains various STATS counters
  * It is used by the InspIRCd class, which internally
  * has an instance of it.
@@ -666,3 +587,4 @@ inline void stdalgo::culldeleter::operator()(classbase* item)
 
 #include "numericbuilder.h"
 #include "modules/whois.h"
+#include "modules/stats.h"
index 1f41de5d2ed64581f3f84ff49fb0b6e1504488b9..3a0df78f940f698c8bd58c799465831e2464aa10 100644 (file)
@@ -24,7 +24,7 @@ class CoreExport ISupportManager
 {
  private:
        /** The generated lines which are sent to clients. */
-       std::vector<std::string> cachedlines;
+       std::vector<Numeric::Numeric> cachedlines;
 
  public:
        /** (Re)build the ISUPPORT vector.
@@ -34,9 +34,9 @@ class CoreExport ISupportManager
        void Build();
 
        /** Returns the cached std::vector of ISUPPORT lines.
-        * @return A list of strings prepared for sending to users
+        * @return A list of Numeric::Numeric objects prepared for sending to users
         */
-       const std::vector<std::string>& GetLines() const { return cachedlines; }
+       const std::vector<Numeric::Numeric>& GetLines() const { return cachedlines; }
 
        /** Send the 005 numerics (ISUPPORT) to a user.
         * @param user The user to send the ISUPPORT numerics to
index 526c283b2f1a96fa8426b4e754fb166a278f146b..d97f02046cd24a3b1749e6105d11c62fb0f667a6 100644 (file)
@@ -873,14 +873,10 @@ class CoreExport Module : public classbase, public usecountbase
 
        /** Called on all /STATS commands
         * This method is triggered for all /STATS use, including stats symbols handled by the core.
-        * @param symbol the symbol provided to /STATS
-        * @param user the user issuing the /STATS command
-        * @param results A string_list to append results into. You should put all your results
-        * into this string_list, rather than displaying them directly, so that your handler will
-        * work when remote STATS queries are received.
+        * @param stats Context of the /STATS request, contains requesting user, list of answer rows etc.
         * @return 1 to block the /STATS from being processed by the core, 0 to allow it
         */
-       virtual ModResult OnStats(char symbol, User* user, string_list &results);
+       virtual ModResult OnStats(Stats::Context& stats);
 
        /** Called whenever a change of a local users displayed host is attempted.
         * Return 1 to deny the host change, or 0 to allow it.
@@ -987,7 +983,7 @@ class CoreExport Module : public classbase, public usecountbase
         */
        virtual ModResult OnNamesListItem(User* issuer, Membership* item, std::string& prefixes, std::string& nick);
 
-       virtual ModResult OnNumeric(User* user, unsigned int numeric, const std::string &text);
+       virtual ModResult OnNumeric(User* user, const Numeric::Numeric& numeric);
 
        /** Called whenever a result from /WHO is about to be returned
         * @param source The user running the /WHO query
diff --git a/include/modules/stats.h b/include/modules/stats.h
new file mode 100644 (file)
index 0000000..b1e27b4
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+namespace Stats
+{
+       class Context;
+       class Row;
+}
+
+class Stats::Row : public Numeric::Numeric
+{
+ public:
+       Row(unsigned int num)
+               : Numeric(num)
+       {
+       }
+};
+
+class Stats::Context
+{
+       /** Source user of the STATS request
+        */
+       User* const source;
+
+       /** List of reply rows
+        */
+       std::vector<Row> rows;
+
+       /** Symbol indicating the type of this STATS request (usually a letter)
+        */
+       const char symbol;
+
+ public:
+       /** Constructor
+        * @param src Source user of the STATS request, can be a local or remote user
+        * @param sym Symbol (letter) indicating the type of the request
+        */
+       Context(User* src, char sym)
+               : source(src)
+               , symbol(sym)
+       {
+       }
+
+       /** Get the source user of the STATS request
+        * @return Source user of the STATS request
+        */
+       User* GetSource() const { return source; }
+
+       /** Get the list of reply rows
+        * @return List of rows generated as reply for the request
+        */
+       const std::vector<Row>& GetRows() const { return rows; }
+
+       /** Get the symbol (letter) indicating what type of STATS was requested
+        * @return Symbol specified by the requesting user
+        */
+       char GetSymbol() const { return symbol; }
+
+       /** Add a row to the reply list
+        * @param row Reply to add
+        */
+       void AddRow(const Row& row) { rows.push_back(row); }
+
+       template <typename T1>
+       void AddRow(unsigned int numeric, T1 p1)
+       {
+               Row n(numeric);
+               n.push(p1);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               n.push(p7);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               n.push(p7);
+               AddRow(n);
+       }
+};
index b64d46410760d851afcd19eedbbd9e6846eaa087..4f09d268bff7f935bafabc05c8a786a53348ea0b 100644 (file)
@@ -55,12 +55,11 @@ class Whois::LineEventListener : public Events::ModuleEventListener
         * the values numeric and text, but you cannot change the user the
         * numeric is sent to.
         * @param whois Whois context, can be used to send numerics
-        * @param numeric The numeric of the line being sent
-        * @param text The text of the numeric, including any parameters
+        * @param numeric Numeric being sent
         * @return MOD_RES_DENY to drop the line completely so that the user does not
         * receive it, or MOD_RES_PASSTHRU to allow the line to be sent.
         */
-       virtual ModResult OnWhoisLine(Context& whois, unsigned int& numeric, std::string& text) = 0;
+       virtual ModResult OnWhoisLine(Context& whois, Numeric::Numeric& numeric) = 0;
 };
 
 class Whois::Context
@@ -97,20 +96,51 @@ class Whois::Context
        User* GetTarget() const { return target; }
 
        /** Send a line of WHOIS data to the source of the WHOIS
-        * @param numeric Numeric to send
-        * @param format Format string for the numeric
-        * @param ... Parameters for the format string
         */
-       void SendLine(unsigned int numeric, const char* format, ...) CUSTOM_PRINTF(3, 4)
+       template <typename T1>
+       void SendLine(unsigned int numeric, T1 p1)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(target->nick);
+               n.push(p1);
+               SendLine(n);
+       }
+
+       template <typename T1, typename T2>
+       void SendLine(unsigned int numeric, T1 p1, T2 p2)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(target->nick);
+               n.push(p1);
+               n.push(p2);
+               SendLine(n);
+       }
+
+       template <typename T1, typename T2, typename T3>
+       void SendLine(unsigned int numeric, T1 p1, T2 p2, T3 p3)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(target->nick);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               SendLine(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4>
+       void SendLine(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4)
        {
-               std::string textbuffer;
-               VAFORMAT(textbuffer, format, format)
-               SendLine(numeric, textbuffer);
+               Numeric::Numeric n(numeric);
+               n.push(target->nick);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               SendLine(n);
        }
 
        /** Send a line of WHOIS data to the source of the WHOIS
         * @param numeric Numeric to send
-        * @param text Text of the numeric
         */
-       virtual void SendLine(unsigned int numeric, const std::string& text) = 0;
+       virtual void SendLine(Numeric::Numeric& numeric) = 0;
 };
diff --git a/include/numeric.h b/include/numeric.h
new file mode 100644 (file)
index 0000000..8044fe5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+#include "numerics.h"
+
+namespace Numeric
+{
+       class Numeric;
+}
+
+class Numeric::Numeric
+{
+       /** Numeric number
+        */
+       unsigned int numeric;
+
+       /** Parameters of the numeric
+        */
+       std::vector<std::string> params;
+
+       /** Source server of the numeric, if NULL (the default) then it is the local server
+        */
+       Server* sourceserver;
+
+ public:
+       /** Constructor
+        * @param num Numeric number (RPL_*, ERR_*)
+        */
+       Numeric(unsigned int num)
+               : numeric(num)
+               , sourceserver(NULL)
+       {
+       }
+
+       /** Add a parameter to the numeric. The parameter will be converted to a string first with ConvToStr().
+        * @param x Parameter to add
+        */
+       template <typename T>
+       Numeric& push(const T& x)
+       {
+               params.push_back(ConvToStr(x));
+               return *this;
+       }
+
+       /** Set the source server of the numeric. The source server defaults to the local server.
+        * @param server Server to set as source
+        */
+       void SetServer(Server* server) { sourceserver = server; }
+
+       /** Get the source server of the numeric
+        * @return Source server or NULL if the source is the local server
+        */
+       Server* GetServer() const { return sourceserver; }
+
+       /** Get the number of the numeric as an unsigned integer
+        * @return Numeric number as an unsigned integer
+        */
+       unsigned int GetNumeric() const { return numeric; }
+
+       /** Get the parameters of the numeric
+        * @return Parameters of the numeric as a const vector of strings
+        */
+       const std::vector<std::string>& GetParams() const { return params; }
+
+       /** Get the parameters of the numeric
+        * @return Parameters of the numeric as a vector of strings
+        */
+       std::vector<std::string>& GetParams() { return params; }
+};
+
+namespace Numerics
+{
+       /** ERR_NOSUCHNICK numeric
+        */
+       class NoSuchNick : public Numeric::Numeric
+       {
+        public:
+               NoSuchNick(const std::string& nick)
+                       : Numeric(ERR_NOSUCHNICK)
+               {
+                       push(nick);
+                       push("No such nick/channel");
+               }
+       };
+}
index 36cfeedb4b63b8fcd30c4e6c09a9f8739213a6c9..726aeff3f5c78f8cff1ff7a6c59d5d810e49caf9 100644 (file)
@@ -40,9 +40,9 @@ class Numeric::WriteNumericSink
        {
        }
 
-       void operator()(unsigned int numeric, const std::string& params) const
+       void operator()(Numeric& numeric) const
        {
-               user->WriteNumeric(numeric, params);
+               user->WriteNumeric(numeric);
        }
 };
 
@@ -50,14 +50,12 @@ template <char Sep, bool SendEmpty, typename Sink>
 class Numeric::GenericBuilder
 {
        Sink sink;
-       std::string data;
-       const unsigned int numeric;
+       Numeric numeric;
        const std::string::size_type max;
-       std::string::size_type beginpos;
 
        bool HasRoom(const std::string::size_type additional) const
        {
-               return (data.size() + additional <= max);
+               return (numeric.GetParams().back().size() + additional <= max);
        }
 
  public:
@@ -67,28 +65,28 @@ class Numeric::GenericBuilder
                , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->ServerName.size() - additionalsize - 9)
        {
                if (addparam)
-                       data.push_back(':');
-               SaveBeginPos();
+                       numeric.push(std::string());
        }
 
-       std::string& GetNumeric() { return data; }
+       Numeric& GetNumeric() { return numeric; }
 
        void Add(const std::string& entry)
        {
                if (!HasRoom(entry.size()))
                        Flush();
-               data.append(entry).push_back(Sep);
+               numeric.GetParams().back().append(entry).push_back(Sep);
        }
 
        void Add(const std::string& entry1, const std::string& entry2)
        {
                if (!HasRoom(entry1.size() + entry2.size()))
                        Flush();
-               data.append(entry1).append(entry2).push_back(Sep);
+               numeric.GetParams().back().append(entry1).append(entry2).push_back(Sep);
        }
 
        void Flush()
        {
+               std::string& data = numeric.GetParams().back();
                if (IsEmpty())
                {
                        if (!SendEmpty)
@@ -99,13 +97,11 @@ class Numeric::GenericBuilder
                        data.erase(data.size()-1);
                }
 
-               sink(numeric, data);
-               if (data.size() > beginpos)
-                       data.erase(beginpos);
+               sink(numeric);
+               data.clear();
        }
 
-       bool IsEmpty() const { return (data.size() == beginpos); }
-       void SaveBeginPos() { beginpos = data.size(); }
+       bool IsEmpty() const { return (numeric.GetParams().back().empty()); }
 };
 
 template <char Sep, bool SendEmpty>
@@ -113,7 +109,7 @@ class Numeric::Builder : public GenericBuilder<Sep, SendEmpty, WriteNumericSink>
 {
  public:
        Builder(LocalUser* user, unsigned int num, bool addparam = true, size_t additionalsize = 0)
-               : Numeric::GenericBuilder<Sep, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, addparam, additionalsize + user->nick.size())
+               : ::Numeric::GenericBuilder<Sep, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, addparam, additionalsize + user->nick.size())
        {
        }
 };
index 0447df35308a3ab1a8202a6028926e974ea892f4..72caaddccad5054addce8e9cc327bfdf2cdd813c 100644 (file)
@@ -35,7 +35,7 @@
  * Please note that the list may not be exhaustive, it'll be done when I have
  * nothing better to do with my time. -- w00t (jul 13, 2008)
  */
-enum Numerics
+enum
 {
        /*
         * Reply range of numerics.
index dfecb04837a5ce4220047764e8457e505db2d888..17c05d704a83b9e570e661388ad08b15c5a46a0c 100644 (file)
@@ -111,3 +111,8 @@ typedef XLineContainer::iterator ContainerIter;
 /** An interator in an XLineLookup
  */
 typedef XLineLookup::iterator LookupIter;
+
+namespace Stats
+{
+       class Context;
+}
index fa346a32968f2164a93aed14c447ef9ba25d7e42..5e7df74ea88293960a5b05a92d02ad493370423e 100644 (file)
@@ -519,9 +519,109 @@ class CoreExport User : public Extensible
         */
        void WriteNotice(const std::string& text) { this->WriteCommand("NOTICE", ":" + text); }
 
-       void WriteNumeric(unsigned int numeric, const char* text, ...) CUSTOM_PRINTF(3, 4);
+       void WriteRemoteNumeric(const Numeric::Numeric& numeric);
 
-       void WriteNumeric(unsigned int numeric, const std::string &text);
+       template <typename T1>
+       void WriteRemoteNumeric(unsigned int numeric, T1 p1)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               WriteRemoteNumeric(n);
+       }
+
+       template <typename T1, typename T2>
+       void WriteRemoteNumeric(unsigned int numeric, T1 p1, T2 p2)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               WriteRemoteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3>
+       void WriteRemoteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               WriteRemoteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4>
+       void WriteRemoteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               WriteRemoteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5>
+       void WriteRemoteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               WriteRemoteNumeric(n);
+       }
+
+       void WriteNumeric(const Numeric::Numeric& numeric);
+
+       template <typename T1>
+       void WriteNumeric(unsigned int numeric, T1 p1)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               WriteNumeric(n);
+       }
+
+       template <typename T1, typename T2>
+       void WriteNumeric(unsigned int numeric, T1 p1, T2 p2)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               WriteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3>
+       void WriteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               WriteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4>
+       void WriteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               WriteNumeric(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5>
+       void WriteNumeric(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
+       {
+               Numeric::Numeric n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               WriteNumeric(n);
+       }
 
        /** Write text to this user, appending CR/LF and prepending :nick!user\@host of the user provided in the first parameter.
         * @param user The user to prepend the :nick!user\@host of
index fe044d0f2d07b7ef119606dc0d7fd8464e979473..c2ede29dfb458c2904761fa8f0734d8d8b615a56 100644 (file)
@@ -520,8 +520,7 @@ class CoreExport XLineManager
         * will be expired and removed before the list is displayed.
         * @param type The type of stats to show
         * @param numeric The numeric to give to each result line
-        * @param user The username making the query
-        * @param results The string_list to receive the results
+        * @param stats Stats context
         */
-       void InvokeStats(const std::string &type, int numeric, User* user, string_list &results);
+       void InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats);
 };
index 99da0070810b1f6b4463977e58c078c436b651d4..a2d5c4a30f1831c8a72fcc63ff83c51c78ce330e 100644 (file)
@@ -180,7 +180,7 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                }
                if (user->chans.size() >= maxchans)
                {
-                       user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s :You are on too many channels", cname.c_str());
+                       user->WriteNumeric(ERR_TOOMANYCHANNELS, cname, "You are on too many channels");
                        return NULL;
                }
        }
@@ -240,7 +240,7 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                                        if (!MOD_RESULT.check(InspIRCd::TimingSafeCompare(ckey, key)))
                                        {
                                                // If no key provided, or key is not the right one, and can't bypass +k (not invited or option not enabled)
-                                               user->WriteNumeric(ERR_BADCHANNELKEY, "%s :Cannot join channel (Incorrect channel key)", chan->name.c_str());
+                                               user->WriteNumeric(ERR_BADCHANNELKEY, chan->name, "Cannot join channel (Incorrect channel key)");
                                                return NULL;
                                        }
                                }
@@ -250,7 +250,7 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                                        FIRST_MOD_RESULT(OnCheckInvite, MOD_RESULT, (user, chan));
                                        if (MOD_RESULT != MOD_RES_ALLOW)
                                        {
-                                               user->WriteNumeric(ERR_INVITEONLYCHAN, "%s :Cannot join channel (Invite only)", chan->name.c_str());
+                                               user->WriteNumeric(ERR_INVITEONLYCHAN, chan->name, "Cannot join channel (Invite only)");
                                                return NULL;
                                        }
                                }
@@ -261,14 +261,14 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                                        FIRST_MOD_RESULT(OnCheckLimit, MOD_RESULT, (user, chan));
                                        if (!MOD_RESULT.check((chan->GetUserCounter() < atol(limit.c_str()))))
                                        {
-                                               user->WriteNumeric(ERR_CHANNELISFULL, "%s :Cannot join channel (Channel is full)", chan->name.c_str());
+                                               user->WriteNumeric(ERR_CHANNELISFULL, chan->name, "Cannot join channel (Channel is full)");
                                                return NULL;
                                        }
                                }
 
                                if (chan->IsBanned(user))
                                {
-                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Cannot join channel (You're banned)", chan->name.c_str());
+                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (You're banned)");
                                        return NULL;
                                }
                        }
index c123353b0a96b94da8c6ded03762afdc7c92be3e..514394a572e2ec3a0f2cd5ad37b53ef4ab03d659 100644 (file)
@@ -217,7 +217,7 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
                if (!handler)
                {
                        if (user->registered == REG_ALL)
-                               user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :Unknown command",command.c_str());
+                               user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command");
                        ServerInstance->stats.Unknown++;
                        return;
                }
@@ -268,15 +268,15 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
                if (!user->IsModeSet(handler->flags_needed))
                {
                        user->CommandFloodPenalty += failpenalty;
-                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - You do not have the required operator privileges");
+                       user->WriteNumeric(ERR_NOPRIVILEGES, "Permission Denied - You do not have the required operator privileges");
                        return;
                }
 
                if (!user->HasPermission(command))
                {
                        user->CommandFloodPenalty += failpenalty;
-                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Oper type %s does not have access to command %s",
-                               user->oper->name.c_str(), command.c_str());
+                       user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Oper type %s does not have access to command %s",
+                               user->oper->name.c_str(), command.c_str()));
                        return;
                }
        }
@@ -287,11 +287,11 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
                user->CommandFloodPenalty += failpenalty;
                if (ServerInstance->Config->DisabledDontExist)
                {
-                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :Unknown command", command.c_str());
+                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command");
                }
                else
                {
-                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", command.c_str());
+                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "This command has been disabled.");
                }
 
                ServerInstance->SNO->WriteToSnoMask('a', "%s denied for %s (%s@%s)",
@@ -305,16 +305,16 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
        if (command_p.size() < handler->min_params)
        {
                user->CommandFloodPenalty += failpenalty;
-               user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s :Not enough parameters.", command.c_str());
+               user->WriteNumeric(ERR_NEEDMOREPARAMS, command, "Not enough parameters.");
                if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (handler->syntax.length()))
-                       user->WriteNumeric(RPL_SYNTAX, ":SYNTAX %s %s", handler->name.c_str(), handler->syntax.c_str());
+                       user->WriteNumeric(RPL_SYNTAX, InspIRCd::Format("SYNTAX %s %s", handler->name.c_str(), handler->syntax.c_str()));
                return;
        }
 
        if ((user->registered != REG_ALL) && (!handler->WorksBeforeReg()))
        {
                user->CommandFloodPenalty += failpenalty;
-               user->WriteNumeric(ERR_NOTREGISTERED, "%s :You have not registered",command.c_str());
+               user->WriteNumeric(ERR_NOTREGISTERED, command, "You have not registered");
        }
        else
        {
index 2c31fa0ae97f5e67774d1fca6f226502eaa11056..cec4be3d3d068a93041f6755d65dbedcee6443e0 100644 (file)
@@ -688,14 +688,14 @@ void ServerConfig::ApplyModules(User* user)
                        ServerInstance->SNO->WriteGlobalSno('a', "*** REHASH UNLOADED MODULE: %s", modname.c_str());
 
                        if (user)
-                               user->WriteNumeric(RPL_UNLOADEDMODULE, "%s :Module %s successfully unloaded.", modname.c_str(), modname.c_str());
+                               user->WriteNumeric(RPL_UNLOADEDMODULE, modname, InspIRCd::Format("Module %s successfully unloaded.", modname.c_str()));
                        else
                                ServerInstance->SNO->WriteGlobalSno('a', "Module %s successfully unloaded.", modname.c_str());
                }
                else
                {
                        if (user)
-                               user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :Failed to unload module %s: %s", modname.c_str(), modname.c_str(), ServerInstance->Modules->LastError().c_str());
+                               user->WriteNumeric(ERR_CANTUNLOADMODULE, modname, InspIRCd::Format("Failed to unload module %s: %s", modname.c_str(), ServerInstance->Modules->LastError().c_str()));
                        else
                                ServerInstance->SNO->WriteGlobalSno('a', "Failed to unload module %s: %s", modname.c_str(), ServerInstance->Modules->LastError().c_str());
                }
@@ -707,14 +707,14 @@ void ServerConfig::ApplyModules(User* user)
                {
                        ServerInstance->SNO->WriteGlobalSno('a', "*** REHASH LOADED MODULE: %s",adding->c_str());
                        if (user)
-                               user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module %s successfully loaded.", adding->c_str(), adding->c_str());
+                               user->WriteNumeric(RPL_LOADEDMODULE, *adding, InspIRCd::Format("Module %s successfully loaded.", adding->c_str()));
                        else
                                ServerInstance->SNO->WriteGlobalSno('a', "Module %s successfully loaded.", adding->c_str());
                }
                else
                {
                        if (user)
-                               user->WriteNumeric(ERR_CANTLOADMODULE, "%s :Failed to load module %s: %s", adding->c_str(), adding->c_str(), ServerInstance->Modules->LastError().c_str());
+                               user->WriteNumeric(ERR_CANTLOADMODULE, *adding, InspIRCd::Format("Failed to load module %s: %s", adding->c_str(), ServerInstance->Modules->LastError().c_str()));
                        else
                                ServerInstance->SNO->WriteGlobalSno('a', "Failed to load module %s: %s", adding->c_str(), ServerInstance->Modules->LastError().c_str());
                }
index c1f1b00c7bd4be6067bcb2692d148454e186a648..a1319ebc049651d2099faf6149b33c960622128b 100644 (file)
@@ -58,7 +58,7 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
 
                if ((!c) || (!u) || (u->registered != REG_ALL))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c ? parameters[0].c_str() : parameters[1].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(c ? parameters[0] : parameters[1]));
                        return CMD_FAILURE;
                }
 
@@ -77,13 +77,13 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
 
                if ((IS_LOCAL(user)) && (!c->HasUser(user)))
                {
-                       user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str());
+                       user->WriteNumeric(ERR_NOTONCHANNEL, c->name, "You're not on that channel!");
                        return CMD_FAILURE;
                }
 
                if (c->HasUser(u))
                {
-                       user->WriteNumeric(ERR_USERONCHANNEL, "%s %s :is already on channel", u->nick.c_str(), c->name.c_str());
+                       user->WriteNumeric(ERR_USERONCHANNEL, u->nick, c->name, "is already on channel");
                        return CMD_FAILURE;
                }
 
@@ -102,8 +102,8 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
                                {
                                        // Check whether halfop mode is available and phrase error message accordingly
                                        ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
-                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be a channel %soperator",
-                                               c->name.c_str(), (mh && mh->name == "halfop" ? "half-" : ""));
+                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator",
+                                               (mh && mh->name == "halfop" ? "half-" : "")));
                                        return CMD_FAILURE;
                                }
                        }
@@ -117,9 +117,9 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
 
                if (IS_LOCAL(user))
                {
-                       user->WriteNumeric(RPL_INVITING, "%s %s", u->nick.c_str(),c->name.c_str());
+                       user->WriteNumeric(RPL_INVITING, u->nick, c->name);
                        if (u->IsAway())
-                               user->WriteNumeric(RPL_AWAY, "%s :%s", u->nick.c_str(), u->awaymsg.c_str());
+                               user->WriteNumeric(RPL_AWAY, u->nick, u->awaymsg);
                }
 
                char prefix = 0;
@@ -161,9 +161,9 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
                if (list)
                {
                        for (Invite::List::const_iterator i = list->begin(); i != list->end(); ++i)
-                               user->WriteNumeric(RPL_INVITELIST, ":%s", (*i)->chan->name.c_str());
+                               user->WriteNumeric(RPL_INVITELIST, (*i)->chan->name);
                }
-               user->WriteNumeric(RPL_ENDOFINVITELIST, ":End of INVITE list");
+               user->WriteNumeric(RPL_ENDOFINVITELIST, "End of INVITE list");
        }
        return CMD_SUCCESS;
 }
index 1945bf52e2484a2a8d1df83815e00d31b5e5fcf3..06e203ead68a11b3b2a1c282050d82097a9194c4 100644 (file)
@@ -55,6 +55,6 @@ CmdResult CommandJoin::HandleLocal(const std::vector<std::string>& parameters, L
                }
        }
 
-       user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name", parameters[0].c_str());
+       user->WriteNumeric(ERR_NOSUCHCHANNEL, parameters[0], "Invalid channel name");
        return CMD_FAILURE;
 }
index 44f511bc1196554097ab95d1c68bf1a66e9effde..7f8a8a3291d28d0c445db47e8d34df945917c7b6 100644 (file)
@@ -44,7 +44,7 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User
 
        if ((!u) || (!c) || (u->registered != REG_ALL))
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c ? parameters[1].c_str() : parameters[0].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(c ? parameters[1] : parameters[0]));
                return CMD_FAILURE;
        }
 
@@ -54,13 +54,13 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User
                srcmemb = c->GetUser(user);
                if (!srcmemb)
                {
-                       user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", parameters[0].c_str());
+                       user->WriteNumeric(ERR_NOTONCHANNEL, parameters[0], "You're not on that channel!");
                        return CMD_FAILURE;
                }
 
                if (u->server->IsULine())
                {
-                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You may not kick a u-lined client", c->name.c_str());
+                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, "You may not kick a u-lined client");
                        return CMD_FAILURE;
                }
        }
@@ -68,7 +68,7 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User
        const Channel::MemberMap::iterator victimiter = c->userlist.find(u);
        if (victimiter == c->userlist.end())
        {
-               user->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s :They are not on that channel", u->nick.c_str(), c->name.c_str());
+               user->WriteNumeric(ERR_USERNOTINCHANNEL, u->nick, c->name, "They are not on that channel");
                return CMD_FAILURE;
        }
        Membership* const memb = victimiter->second;
@@ -110,8 +110,8 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User
 
                        if (them < req)
                        {
-                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be a channel %soperator",
-                                       c->name.c_str(), req > HALFOP_VALUE ? "" : "half-");
+                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator",
+                                       req > HALFOP_VALUE ? "" : "half-"));
                                return CMD_FAILURE;
                        }
                }
index 986dbe01889d7daa65b3c5822603f0c20f586c6d..53934b5e3a06bf36d5a5416b124b4410560acf02 100644 (file)
@@ -38,7 +38,7 @@ CmdResult CommandNames::HandleLocal(const std::vector<std::string>& parameters,
 
        if (!parameters.size())
        {
-               user->WriteNumeric(RPL_ENDOFNAMES, "* :End of /NAMES list.");
+               user->WriteNumeric(RPL_ENDOFNAMES, '*', "End of /NAMES list.");
                return CMD_SUCCESS;
        }
 
@@ -62,24 +62,23 @@ CmdResult CommandNames::HandleLocal(const std::vector<std::string>& parameters,
                }
        }
 
-       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
        return CMD_FAILURE;
 }
 
 void CommandNames::SendNames(LocalUser* user, Channel* chan, bool show_invisible)
 {
-       Numeric::Builder<' '> reply(user, RPL_NAMREPLY, false);
-       std::string& list = reply.GetNumeric();
+       Numeric::Builder<' '> reply(user, RPL_NAMREPLY, false, chan->name.size() + 4);
+       Numeric::Numeric& numeric = reply.GetNumeric();
        if (chan->IsModeSet(secretmode))
-               list.push_back('@');
+               numeric.push(std::string(1, '@'));
        else if (chan->IsModeSet(privatemode))
-               list.push_back('*');
+               numeric.push(std::string(1, '*'));
        else
-               list.push_back('=');
+               numeric.push(std::string(1, '='));
 
-       list.push_back(' ');
-       list.append(chan->name).append(" :");
-       reply.SaveBeginPos();
+       numeric.push(chan->name);
+       numeric.push(std::string());
 
        std::string prefixlist;
        std::string nick;
@@ -111,5 +110,5 @@ void CommandNames::SendNames(LocalUser* user, Channel* chan, bool show_invisible
        }
 
        reply.Flush();
-       user->WriteNumeric(RPL_ENDOFNAMES, "%s :End of /NAMES list.", chan->name.c_str());
+       user->WriteNumeric(RPL_ENDOFNAMES, chan->name, "End of /NAMES list.");
 }
index 8d65d764a1a7aac3e75854cf3723d4134a8bb0bf..b421489399953867c169af5712d60a418d5e9d05 100644 (file)
@@ -37,7 +37,7 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters,
        Channel* c = ServerInstance->FindChan(parameters[0]);
        if (!c)
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                return CMD_FAILURE;
        }
 
@@ -45,7 +45,7 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters,
        {
                if ((c->IsModeSet(secretmode)) && (!c->HasUser(user)))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c->name.c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(c->name));
                        return CMD_FAILURE;
                }
 
@@ -55,7 +55,7 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters,
                }
                else
                {
-                       user->WriteNumeric(RPL_NOTOPICSET, "%s :No topic is set.", c->name.c_str());
+                       user->WriteNumeric(RPL_NOTOPICSET, c->name, "No topic is set.");
                }
                return CMD_SUCCESS;
        }
@@ -70,12 +70,12 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters,
        {
                if (!c->HasUser(user))
                {
-                       user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str());
+                       user->WriteNumeric(ERR_NOTONCHANNEL, c->name, "You're not on that channel!");
                        return CMD_FAILURE;
                }
                if (c->IsModeSet(topiclockmode) && !ServerInstance->OnCheckExemption(user, c, "topiclock").check(c->GetPrefixValue(user) >= HALFOP_VALUE))
                {
-                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You do not have access to change the topic on this channel", c->name.c_str());
+                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, "You do not have access to change the topic on this channel");
                        return CMD_FAILURE;
                }
        }
@@ -86,6 +86,6 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters,
 
 void Topic::ShowTopic(LocalUser* user, Channel* chan)
 {
-       user->WriteNumeric(RPL_TOPIC, "%s :%s", chan->name.c_str(), chan->topic.c_str());
-       user->WriteNumeric(RPL_TOPICTIME, "%s %s %lu", chan->name.c_str(), chan->setby.c_str(), (unsigned long)chan->topicset);
+       user->WriteNumeric(RPL_TOPIC, chan->name, chan->topic);
+       user->WriteNumeric(RPL_TOPICTIME, chan->name, chan->setby, (unsigned long)chan->topicset);
 }
index 722ef866803069a1d26e19eb3a118b83f6ad439e..19037406b1b0dc17a46eb9a6d7f104a34e150e77 100644 (file)
@@ -34,15 +34,11 @@ CmdResult CommandAdmin::Handle (const std::vector<std::string>& parameters, User
 {
        if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName)
                return CMD_SUCCESS;
-       user->SendText(":%s %03d %s :Administrative info for %s", ServerInstance->Config->ServerName.c_str(),
-               RPL_ADMINME, user->nick.c_str(),ServerInstance->Config->ServerName.c_str());
+       user->WriteRemoteNumeric(RPL_ADMINME, InspIRCd::Format("Administrative info for %s", ServerInstance->Config->ServerName.c_str()));
        if (!AdminName.empty())
-               user->SendText(":%s %03d %s :Name     - %s", ServerInstance->Config->ServerName.c_str(),
-                       RPL_ADMINLOC1, user->nick.c_str(), AdminName.c_str());
-       user->SendText(":%s %03d %s :Nickname - %s", ServerInstance->Config->ServerName.c_str(),
-               RPL_ADMINLOC2, user->nick.c_str(), AdminNick.c_str());
-       user->SendText(":%s %03d %s :E-Mail   - %s", ServerInstance->Config->ServerName.c_str(),
-               RPL_ADMINEMAIL, user->nick.c_str(), AdminEmail.c_str());
+               user->WriteRemoteNumeric(RPL_ADMINLOC1, InspIRCd::Format("Name     - %s", AdminName.c_str()));
+       user->WriteRemoteNumeric(RPL_ADMINLOC2, InspIRCd::Format("Nickname - %s", AdminNick.c_str()));
+       user->WriteRemoteNumeric(RPL_ADMINEMAIL, InspIRCd::Format("E-Mail   - %s", AdminEmail.c_str()));
        return CMD_SUCCESS;
 }
 
index 3ff6728d8b7d075aff6585f2d2e7c9b02fee9a41..e15d178f55a36702e53a403adde429ecb8d460a3 100644 (file)
@@ -48,6 +48,6 @@ CmdResult CommandCommands::Handle (const std::vector<std::string>&, User *user)
        std::sort(list.begin(), list.end());
        for(unsigned int i=0; i < list.size(); i++)
                user->Write(list[i]);
-       user->WriteNumeric(RPL_COMMANDSEND, ":End of COMMANDS list");
+       user->WriteNumeric(RPL_COMMANDSEND, "End of COMMANDS list");
        return CMD_SUCCESS;
 }
index 8dad99453581684e212f2e9e17cef64aedbe4a30..e014fa4f2b9e2303bc5a1db6f89bbd585aadfb2f 100644 (file)
@@ -83,9 +83,9 @@ CmdResult CommandInfo::Handle (const std::vector<std::string>& parameters, User
 
        int i=0;
        while (lines[i])
-               user->SendText(":%s %03d %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_INFO, user->nick.c_str(), lines[i++]);
+               user->WriteRemoteNumeric(RPL_INFO, lines[i++]);
        FOREACH_MOD(OnInfo, (user));
-       user->SendText(":%s %03d %s :End of /INFO list", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFINFO, user->nick.c_str());
+       user->WriteRemoteNumeric(RPL_ENDOFINFO, "End of /INFO list");
        return CMD_SUCCESS;
 }
 
index 0a1420e1364b3c3ac4e7dd5dc744b86e8bdd0b8a..16931e685e4bc9e9a303f74d17297f9fc602bb28 100644 (file)
@@ -65,21 +65,18 @@ CmdResult CommandModules::Handle (const std::vector<std::string>& parameters, Us
                                        flags[pos] = '-';
 
 #ifdef PURE_STATIC
-                       user->SendText(":%s 702 %s :%s %s :%s", ServerInstance->Config->ServerName.c_str(),
-                               user->nick.c_str(), m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str());
+                       user->WriteRemoteNumeric(702, InspIRCd::Format("%s %s :%s", m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str()));
 #else
                        std::string srcrev = m->ModuleDLLManager->GetVersion();
-                       user->SendText(":%s 702 %s :%s %s :%s - %s", ServerInstance->Config->ServerName.c_str(),
-                               user->nick.c_str(), m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str(), srcrev.c_str());
+                       user->WriteRemoteNumeric(702, InspIRCd::Format("%s %s :%s - %s", m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str(), srcrev.c_str()));
 #endif
                }
                else
                {
-                       user->SendText(":%s 702 %s :%s %s", ServerInstance->Config->ServerName.c_str(),
-                               user->nick.c_str(), m->ModuleSourceFile.c_str(), V.description.c_str());
+                       user->WriteRemoteNumeric(702, InspIRCd::Format("%s %s", m->ModuleSourceFile.c_str(), V.description.c_str()));
                }
        }
-       user->SendText(":%s 703 %s :End of MODULES list", ServerInstance->Config->ServerName.c_str(), user->nick.c_str());
+       user->WriteRemoteNumeric(703, "End of MODULES list");
 
        return CMD_SUCCESS;
 }
index 57616094ede4c9976291e24cd0c94bfcd83e275d..4772f8d2c32a887372f58f17d7af05df2554dcd1 100644 (file)
@@ -48,18 +48,16 @@ CmdResult CommandMotd::Handle (const std::vector<std::string>& parameters, User
        ConfigFileCache::iterator motd = ServerInstance->Config->Files.find(motd_name);
        if (motd == ServerInstance->Config->Files.end())
        {
-               user->SendText(":%s %03d %s :Message of the day file is missing.",
-                       ServerInstance->Config->ServerName.c_str(), ERR_NOMOTD, user->nick.c_str());
+               user->WriteRemoteNumeric(ERR_NOMOTD, "Message of the day file is missing.");
                return CMD_SUCCESS;
        }
 
-       user->SendText(":%s %03d %s :%s message of the day", ServerInstance->Config->ServerName.c_str(),
-               RPL_MOTDSTART, user->nick.c_str(), ServerInstance->Config->ServerName.c_str());
+       user->WriteRemoteNumeric(RPL_MOTDSTART, InspIRCd::Format("%s message of the day", ServerInstance->Config->ServerName.c_str()));
 
        for (file_cache::iterator i = motd->second.begin(); i != motd->second.end(); i++)
-               user->SendText(":%s %03d %s :- %s", ServerInstance->Config->ServerName.c_str(), RPL_MOTD, user->nick.c_str(), i->c_str());
+               user->WriteRemoteNumeric(RPL_MOTD, InspIRCd::Format("- %s", i->c_str()));
 
-       user->SendText(":%s %03d %s :End of message of the day.", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFMOTD, user->nick.c_str());
+       user->WriteRemoteNumeric(RPL_ENDOFMOTD, "End of message of the day.");
 
        return CMD_SUCCESS;
 }
index 95cfb12fddc5bcb0c2034359f2fc0b7e7fff457e..a0b58efcc24280413b26bc453452d5e7a033b59b 100644 (file)
@@ -32,8 +32,7 @@ CmdResult CommandTime::Handle (const std::vector<std::string>& parameters, User
        if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName)
                return CMD_SUCCESS;
 
-       user->SendText(":%s %03d %s %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_TIME, user->nick.c_str(),
-               ServerInstance->Config->ServerName.c_str(), InspIRCd::TimeString(ServerInstance->Time()).c_str());
+       user->WriteRemoteNumeric(RPL_TIME, ServerInstance->Config->ServerName, InspIRCd::TimeString(ServerInstance->Time()));
 
        return CMD_SUCCESS;
 }
index eb3ab2c4e7670238a85395790aa69abba30fd753..9ec0108b13123ed675572ebf88debae05af44aa3 100644 (file)
@@ -30,7 +30,7 @@ CommandVersion::CommandVersion(Module* parent)
 CmdResult CommandVersion::Handle (const std::vector<std::string>&, User *user)
 {
        std::string version = ServerInstance->GetVersionString((user->IsOper()));
-       user->WriteNumeric(RPL_VERSION, ":%s", version.c_str());
+       user->WriteNumeric(RPL_VERSION, version);
        LocalUser *lu = IS_LOCAL(user);
        if (lu != NULL)
        {
index 278e6044d0e31fd2792d14a6ad89229849b0bbe6..67829a55edf472715d7075e5c592ede7c6f2612a 100644 (file)
@@ -53,7 +53,7 @@ CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User
 {
        int minusers = 0, maxusers = 0;
 
-       user->WriteNumeric(RPL_LISTSTART, "Channel :Users Name");
+       user->WriteNumeric(RPL_LISTSTART, "Channel", "Users Name");
 
        /* Work around mIRC suckyness. YOU SUCK, KHALED! */
        if (parameters.size() == 1)
@@ -100,16 +100,16 @@ CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User
                        if ((!n) && (chan->IsModeSet(privatemode)))
                        {
                                // Channel is private (+p) and user is outside/not privileged
-                               user->WriteNumeric(RPL_LIST, "* %ld :", users);
+                               user->WriteNumeric(RPL_LIST, '*', users, "");
                        }
                        else
                        {
                                /* User is in the channel/privileged, channel is not +s */
-                               user->WriteNumeric(RPL_LIST, "%s %ld :[+%s] %s", chan->name.c_str(), users, chan->ChanModes(n), chan->topic.c_str());
+                               user->WriteNumeric(RPL_LIST, chan->name, users, InspIRCd::Format("[+%s] %s", chan->ChanModes(n), chan->topic.c_str()));
                        }
                }
        }
-       user->WriteNumeric(RPL_LISTEND, ":End of channel list.");
+       user->WriteNumeric(RPL_LISTEND, "End of channel list.");
 
        return CMD_SUCCESS;
 }
index 1d49d89d0eb391386c9f640454de15765b34b910..09c0441988d9c70ce859431770db3ba53bb5b499 100644 (file)
@@ -43,12 +43,12 @@ CmdResult CommandLoadmodule::Handle (const std::vector<std::string>& parameters,
        if (ServerInstance->Modules->Load(parameters[0]))
        {
                ServerInstance->SNO->WriteGlobalSno('a', "NEW MODULE: %s loaded %s",user->nick.c_str(), parameters[0].c_str());
-               user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module successfully loaded.", parameters[0].c_str());
+               user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "Module successfully loaded.");
                return CMD_SUCCESS;
        }
        else
        {
-               user->WriteNumeric(ERR_CANTLOADMODULE, "%s :%s", parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+               user->WriteNumeric(ERR_CANTLOADMODULE, parameters[0], ServerInstance->Modules->LastError());
                return CMD_FAILURE;
        }
 }
@@ -80,26 +80,25 @@ CmdResult CommandUnloadmodule::Handle(const std::vector<std::string>& parameters
        if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") &&
                InspIRCd::Match(parameters[0], "core_*.so", ascii_case_insensitive_map))
        {
-               user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload core commands!", parameters[0].c_str());
+               user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], "You cannot unload core commands!");
                return CMD_FAILURE;
        }
 
        Module* m = ServerInstance->Modules->Find(parameters[0]);
        if (m == creator)
        {
-               user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload module loading commands!", parameters[0].c_str());
+               user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], "You cannot unload module loading commands!");
                return CMD_FAILURE;
        }
 
        if (m && ServerInstance->Modules->Unload(m))
        {
                ServerInstance->SNO->WriteGlobalSno('a', "MODULE UNLOADED: %s unloaded %s", user->nick.c_str(), parameters[0].c_str());
-               user->WriteNumeric(RPL_UNLOADEDMODULE, "%s :Module successfully unloaded.", parameters[0].c_str());
+               user->WriteNumeric(RPL_UNLOADEDMODULE, parameters[0], "Module successfully unloaded.");
        }
        else
        {
-               user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :%s", parameters[0].c_str(),
-                       m ? ServerInstance->Modules->LastError().c_str() : "No such module");
+               user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], (m ? ServerInstance->Modules->LastError() : "No such module"));
                return CMD_FAILURE;
        }
 
index 2529ca42bd37fddc06aa2baeaebfbb358c863402..a0d0d0205ee26a310358e407978696da3cb8a690 100644 (file)
@@ -84,19 +84,19 @@ CmdResult CommandLusers::Handle (const std::vector<std::string>&, User *user)
 
        counters.UpdateMaxUsers();
 
-       user->WriteNumeric(RPL_LUSERCLIENT, ":There are %d users and %d invisible on %d servers",
-                       n_users - counters.invisible, counters.invisible, n_serv);
+       user->WriteNumeric(RPL_LUSERCLIENT, InspIRCd::Format("There are %d users and %d invisible on %d servers",
+                       n_users - counters.invisible, counters.invisible, n_serv));
 
        if (ServerInstance->Users->OperCount())
-               user->WriteNumeric(RPL_LUSEROP, "%d :operator(s) online", ServerInstance->Users->OperCount());
+               user->WriteNumeric(RPL_LUSEROP, ServerInstance->Users.OperCount(), "operator(s) online");
 
        if (ServerInstance->Users->UnregisteredUserCount())
-               user->WriteNumeric(RPL_LUSERUNKNOWN, "%d :unknown connections", ServerInstance->Users->UnregisteredUserCount());
+               user->WriteNumeric(RPL_LUSERUNKNOWN, ServerInstance->Users.UnregisteredUserCount(), "unknown connections");
 
-       user->WriteNumeric(RPL_LUSERCHANNELS, "%lu :channels formed", (unsigned long)ServerInstance->GetChans().size());
-       user->WriteNumeric(RPL_LUSERME, ":I have %d clients and %d servers", ServerInstance->Users->LocalUserCount(),n_local_servs);
-       user->WriteNumeric(RPL_LOCALUSERS, ":Current local users: %d  Max: %d", ServerInstance->Users->LocalUserCount(), counters.max_local);
-       user->WriteNumeric(RPL_GLOBALUSERS, ":Current global users: %d  Max: %d", n_users, counters.max_global);
+       user->WriteNumeric(RPL_LUSERCHANNELS, ServerInstance->GetChans().size(), "channels formed");
+       user->WriteNumeric(RPL_LUSERME, InspIRCd::Format("I have %d clients and %d servers", ServerInstance->Users.LocalUserCount(), n_local_servs));
+       user->WriteNumeric(RPL_LOCALUSERS, InspIRCd::Format("Current local users: %d  Max: %d", ServerInstance->Users.LocalUserCount(), counters.max_local));
+       user->WriteNumeric(RPL_GLOBALUSERS, InspIRCd::Format("Current global users: %d  Max: %d", n_users, counters.max_global));
 
        return CMD_SUCCESS;
 }
index 4a0cb2f28eb1cc380f9d4ee98aae65ab7fd19831..0d111ce02e911f5cd13a3758b547c39b4b6a3efb 100644 (file)
@@ -129,7 +129,7 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
        }
        else
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                return CMD_FAILURE;
        }
 
index e4ba69549e6f7a6ffb6adce0da1a754c8c15bd3d..9c06583a8a7f595481c3ab09204d00dcfcc8d499 100644 (file)
@@ -63,7 +63,7 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
                fields.append("hosts");
 
        // tell them they suck, and lag them up to help prevent brute-force attacks
-       user->WriteNumeric(ERR_NOOPERHOST, ":Invalid oper credentials");
+       user->WriteNumeric(ERR_NOOPERHOST, "Invalid oper credentials");
        user->CommandFloodPenalty += 10000;
 
        ServerInstance->SNO->WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': The following fields do not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
index 19d2fa8c20260657c5a05b7e5c68971a5d3d0686..5ce38eb2c39cd8e1f82867eaa0922dd37f481dfe 100644 (file)
@@ -68,7 +68,7 @@ CmdResult CommandRehash::Handle (const std::vector<std::string>& parameters, Use
                ServerInstance->SNO->WriteGlobalSno('a', m);
 
                if (IS_LOCAL(user))
-                       user->WriteNumeric(RPL_REHASHING, "%s :Rehashing", FileSystem::GetFileName(ServerInstance->ConfigFileName).c_str());
+                       user->WriteNumeric(RPL_REHASHING, FileSystem::GetFileName(ServerInstance->ConfigFileName), "Rehashing");
                else
                        ServerInstance->PI->SendUserNotice(user, "*** Rehashing server " + FileSystem::GetFileName(ServerInstance->ConfigFileName));
 
index d691464c0660eff89ab8883239908044cc41892d..cccba0850501f1ac6c7ba7138c570327d8237fd9 100644 (file)
@@ -130,13 +130,13 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
                        {
                                if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(user))
                                {
-                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (no external messages)", chan->name.c_str());
+                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (no external messages)");
                                        return CMD_FAILURE;
                                }
 
                                if (chan->IsModeSet(moderatedmode))
                                {
-                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (+m)", chan->name.c_str());
+                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (+m)");
                                        return CMD_FAILURE;
                                }
 
@@ -144,7 +144,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
                                {
                                        if (chan->IsBanned(user))
                                        {
-                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str());
+                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're banned)");
                                                return CMD_FAILURE;
                                        }
                                }
@@ -161,7 +161,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
                        /* Check again, a module may have zapped the input string */
                        if (temp.empty())
                        {
-                               user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send");
+                               user->WriteNumeric(ERR_NOTEXTTOSEND, "No text to send");
                                return CMD_FAILURE;
                        }
 
@@ -181,7 +181,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
                else
                {
                        /* no such nick/channel */
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", target);
+                       user->WriteNumeric(Numerics::NoSuchNick(target));
                        return CMD_FAILURE;
                }
                return CMD_SUCCESS;
@@ -202,7 +202,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
                        if (dest && strcasecmp(dest->server->GetName().c_str(), targetserver + 1))
                        {
                                /* Incorrect server for user */
-                               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                                return CMD_FAILURE;
                        }
                }
@@ -216,14 +216,14 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
        {
                if (parameters[1].empty())
                {
-                       user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send");
+                       user->WriteNumeric(ERR_NOTEXTTOSEND, "No text to send");
                        return CMD_FAILURE;
                }
 
                if ((dest->IsAway()) && (mt == MSG_PRIVMSG))
                {
                        /* auto respond with aweh msg */
-                       user->WriteNumeric(RPL_AWAY, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str());
+                       user->WriteNumeric(RPL_AWAY, dest->nick, dest->awaymsg);
                }
 
                ModResult MOD_RESULT;
@@ -248,7 +248,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
        else
        {
                /* no such nick/channel */
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                return CMD_FAILURE;
        }
        return CMD_SUCCESS;
index 0d01d9e856519a44c7fb9bd5c7fab2cfc33545a9..6fcec8ac20cbb0a0f55c13c73d5913320ade5639 100644 (file)
@@ -601,7 +601,7 @@ class ReloadAction : public HandlerBase0<void>
                ServerInstance->SNO->WriteGlobalSno('a', "RELOAD MODULE: %s %ssuccessfully reloaded", passedname.c_str(), result ? "" : "un");
                User* user = ServerInstance->FindUUID(uuid);
                if (user)
-                       user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module %ssuccessfully reloaded.", passedname.c_str(), result ? "" : "un");
+                       user->WriteNumeric(RPL_LOADEDMODULE, passedname, InspIRCd::Format("Module %ssuccessfully reloaded.", (result ? "" : "un")));
 
                ServerInstance->GlobalCulls.AddItem(this);
        }
@@ -612,8 +612,7 @@ CmdResult CommandReloadmodule::Handle (const std::vector<std::string>& parameter
        Module* m = ServerInstance->Modules->Find(parameters[0]);
        if (m == creator)
        {
-               user->WriteNumeric(RPL_LOADEDMODULE, "%s :You cannot reload core_reloadmodule.so (unload and load it)",
-                       parameters[0].c_str());
+               user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "You cannot reload core_reloadmodule.so (unload and load it)");
                return CMD_FAILURE;
        }
 
@@ -627,7 +626,7 @@ CmdResult CommandReloadmodule::Handle (const std::vector<std::string>& parameter
        }
        else
        {
-               user->WriteNumeric(RPL_LOADEDMODULE, "%s :Could not find module by that name", parameters[0].c_str());
+               user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "Could not find module by that name");
                return CMD_FAILURE;
        }
 }
index 9fb232bc0192bb7a2e1d0210f1e580a09042df3d..69f1f3cf89e384d16568cf608e1231781cf30911 100644 (file)
@@ -31,7 +31,7 @@
  */
 class CommandStats : public Command
 {
-       void DoStats(char statschar, User* user, string_list &results);
+       void DoStats(Stats::Context& stats);
  public:
        /** Constructor for stats.
         */
@@ -50,20 +50,23 @@ class CommandStats : public Command
        }
 };
 
-static void GenerateStatsLl(User* user, string_list& results, char c)
+static void GenerateStatsLl(Stats::Context& stats)
 {
-       results.push_back(InspIRCd::Format("211 %s nick[ident@%s] sendq cmds_out bytes_out cmds_in bytes_in time_open", user->nick.c_str(), (c == 'l' ? "host" : "ip")));
+       stats.AddRow(211, InspIRCd::Format("nick[ident@%s] sendq cmds_out bytes_out cmds_in bytes_in time_open", (stats.GetSymbol() == 'l' ? "host" : "ip")));
 
        const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
        for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
        {
                LocalUser* u = *i;
-               results.push_back("211 "+user->nick+" "+u->nick+"["+u->ident+"@"+(c == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->signon));
+               stats.AddRow(211, u->nick+"["+u->ident+"@"+(stats.GetSymbol() == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->signon));
        }
 }
 
-void CommandStats::DoStats(char statschar, User* user, string_list &results)
+void CommandStats::DoStats(Stats::Context& stats)
 {
+       User* const user = stats.GetSource();
+       const char statschar = stats.GetSymbol();
+
        bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos;
        bool isRemoteOper = IS_REMOTE(user) && (user->IsOper());
        bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex");
@@ -74,15 +77,15 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                "%s '%c' denied for %s (%s@%s)",
                                (IS_LOCAL(user) ? "Stats" : "Remote stats"),
                                statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
-               results.push_back("481 " + user->nick + " :Permission Denied - STATS " + statschar + " requires the servers/auspex priv.");
+               stats.AddRow(481, (std::string("Permission Denied - STATS ") + statschar + " requires the servers/auspex priv."));
                return;
        }
 
        ModResult MOD_RESULT;
-       FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results));
+       FIRST_MOD_RESULT(OnStats, MOD_RESULT, (stats));
        if (MOD_RESULT == MOD_RES_DENY)
        {
-               results.push_back("219 "+user->nick+" "+statschar+" :End of /STATS report");
+               stats.AddRow(219, statschar, "End of /STATS report");
                ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",
                        (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
                return;
@@ -107,8 +110,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                std::string type = ls->bind_tag->getString("type", "clients");
                                std::string hook = ls->bind_tag->getString("ssl", "plaintext");
 
-                               results.push_back("249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+
-                                       " (" + type + ", " + hook + ")");
+                               stats.AddRow(249, ip + ":"+ConvToStr(ls->bind_port) + " (" + type + ", " + hook + ")");
                        }
                }
                break;
@@ -123,25 +125,29 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i)
                        {
                                ConnectClass* c = *i;
-                               std::stringstream res;
-                               res << "215 " << user->nick << " I " << c->name << ' ';
+                               Stats::Row row(215);
+                               row.push("I").push(c->name);
+
+                               std::string param;
                                if (c->type == CC_ALLOW)
-                                       res << '+';
+                                       param.push_back('+');
                                if (c->type == CC_DENY)
-                                       res << '-';
+                                       param.push_back('-');
 
                                if (c->type == CC_NAMED)
-                                       res << '*';
+                                       param.push_back('*');
                                else
-                                       res << c->host;
+                                       param.append(c->host);
 
-                               res << ' ' << c->config->getString("port", "*") << ' ';
+                               row.push(param).push(c->config->getString("port", "*"));
+                               row.push(ConvToStr(c->GetRecvqMax())).push(ConvToStr(c->GetSendqSoftMax())).push(ConvToStr(c->GetSendqHardMax())).push(ConvToStr(c->GetCommandRate()));
 
-                               res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax()
-                                       << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold();
+                               param = ConvToStr(c->GetPenaltyThreshold());
                                if (c->fakelag)
-                                       res << '*';
-                               results.push_back(res.str());
+                                       param.push_back('*');
+                               row.push(param);
+
+                               stats.AddRow(row);
                        }
                }
                break;
@@ -152,9 +158,8 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
                        {
                                ConnectClass* c = *i;
-                               results.push_back("215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : SocketEngine::GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *");
-                               results.push_back("218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+
-                                               ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout()));
+                               stats.AddRow(215, 'i', "NOMATCH", '*', c->GetHost(), (c->limit ? c->limit : SocketEngine::GetMaxFds()), idx, ServerInstance->Config->ServerName, '*');
+                               stats.AddRow(218, 'Y', idx, c->GetPingTime(), '0', c->GetSendqHardMax(), ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout()));
                                idx++;
                        }
                }
@@ -170,37 +175,37 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                if (!oper->server->IsULine())
                                {
                                        LocalUser* lu = IS_LOCAL(oper);
-                                       results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
+                                       stats.AddRow(249, oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
                                                        (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable"));
                                        idx++;
                                }
                        }
-                       results.push_back("249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)");
+                       stats.AddRow(249, ConvToStr(idx)+" OPER(s)");
                }
                break;
 
                case 'k':
-                       ServerInstance->XLines->InvokeStats("K",216,user,results);
+                       ServerInstance->XLines->InvokeStats("K",216,stats);
                break;
                case 'g':
-                       ServerInstance->XLines->InvokeStats("G",223,user,results);
+                       ServerInstance->XLines->InvokeStats("G",223,stats);
                break;
                case 'q':
-                       ServerInstance->XLines->InvokeStats("Q",217,user,results);
+                       ServerInstance->XLines->InvokeStats("Q",217,stats);
                break;
                case 'Z':
-                       ServerInstance->XLines->InvokeStats("Z",223,user,results);
+                       ServerInstance->XLines->InvokeStats("Z",223,stats);
                break;
                case 'e':
-                       ServerInstance->XLines->InvokeStats("E",223,user,results);
+                       ServerInstance->XLines->InvokeStats("E",223,stats);
                break;
                case 'E':
                {
-                       const SocketEngine::Statistics& stats = SocketEngine::GetStats();
-                       results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(stats.TotalEvents));
-                       results.push_back("249 "+user->nick+" :Read events:  "+ConvToStr(stats.ReadEvents));
-                       results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(stats.WriteEvents));
-                       results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(stats.ErrorEvents));
+                       const SocketEngine::Statistics& sestats = SocketEngine::GetStats();
+                       stats.AddRow(249, "Total events: "+ConvToStr(sestats.TotalEvents));
+                       stats.AddRow(249, "Read events:  "+ConvToStr(sestats.ReadEvents));
+                       stats.AddRow(249, "Write events: "+ConvToStr(sestats.WriteEvents));
+                       stats.AddRow(249, "Error events: "+ConvToStr(sestats.ErrorEvents));
                        break;
                }
 
@@ -213,7 +218,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                if (i->second->use_count)
                                {
                                        /* RPL_STATSCOMMANDS */
-                                       results.push_back("212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count));
+                                       stats.AddRow(212, i->second->name, i->second->use_count);
                                }
                        }
                }
@@ -222,9 +227,9 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                /* stats z (debug and memory info) */
                case 'z':
                {
-                       results.push_back("249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->GetUsers().size()));
-                       results.push_back("249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->GetChans().size()));
-                       results.push_back("249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser.GetCommands().size()));
+                       stats.AddRow(249, "Users: "+ConvToStr(ServerInstance->Users->GetUsers().size()));
+                       stats.AddRow(249, "Channels: "+ConvToStr(ServerInstance->GetChans().size()));
+                       stats.AddRow(249, "Commands: "+ConvToStr(ServerInstance->Parser.GetCommands().size()));
 
                        float kbitpersec_in, kbitpersec_out, kbitpersec_total;
                        char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30];
@@ -235,9 +240,9 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out);
                        snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in);
 
-                       results.push_back("249 "+user->nick+" :Bandwidth total:  "+ConvToStr(kbitpersec_total_s)+" kilobits/sec");
-                       results.push_back("249 "+user->nick+" :Bandwidth out:    "+ConvToStr(kbitpersec_out_s)+" kilobits/sec");
-                       results.push_back("249 "+user->nick+" :Bandwidth in:     "+ConvToStr(kbitpersec_in_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth total:  "+ConvToStr(kbitpersec_total_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth out:    "+ConvToStr(kbitpersec_out_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth in:     "+ConvToStr(kbitpersec_in_s)+" kilobits/sec");
 
 #ifndef _WIN32
                        /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef.
@@ -248,11 +253,11 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */
                        if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */
                        {
-                               results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K");
-                               results.push_back("249 "+user->nick+" :Signals:          "+ConvToStr(R.ru_nsignals));
-                               results.push_back("249 "+user->nick+" :Page faults:      "+ConvToStr(R.ru_majflt));
-                               results.push_back("249 "+user->nick+" :Swaps:            "+ConvToStr(R.ru_nswap));
-                               results.push_back("249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw));
+                               stats.AddRow(249, "Total allocation: "+ConvToStr(R.ru_maxrss)+"K");
+                               stats.AddRow(249, "Signals:          "+ConvToStr(R.ru_nsignals));
+                               stats.AddRow(249, "Page faults:      "+ConvToStr(R.ru_majflt));
+                               stats.AddRow(249, "Swaps:            "+ConvToStr(R.ru_nswap));
+                               stats.AddRow(249, "Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw));
 
                                char percent[30];
 
@@ -262,21 +267,21 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                float per = (n_eaten / n_elapsed) * 100;
 
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (now):    "+percent);
+                               stats.AddRow(249, std::string("CPU Use (now):    ")+percent);
 
                                n_elapsed = ServerInstance->Time() - ServerInstance->startup_time;
                                n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0;
                                per = (n_eaten / n_elapsed) * 100;
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (total):  "+percent);
+                               stats.AddRow(249, std::string("CPU Use (total):  ")+percent);
                        }
 #else
                        PROCESS_MEMORY_COUNTERS MemCounters;
                        if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters)))
                        {
-                               results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K");
-                               results.push_back("249 "+user->nick+" :Pagefile usage:   "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K");
-                               results.push_back("249 "+user->nick+" :Page faults:      "+ConvToStr(MemCounters.PageFaultCount));
+                               stats.AddRow(249, "Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K");
+                               stats.AddRow(249, "Pagefile usage:   "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K");
+                               stats.AddRow(249, "Page faults:      "+ConvToStr(MemCounters.PageFaultCount));
                        }
 
                        FILETIME CreationTime;
@@ -296,13 +301,13 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                char percent[30];
 
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (now):    "+percent);
+                               stats.AddRow(249, std::string("CPU Use (now):    ")+percent);
 
                                n_elapsed = ServerInstance->Time() - ServerInstance->startup_time;
                                n_eaten = (double)(( (uint64_t)(KernelTime.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime))/100000;
                                per = (n_eaten / n_elapsed);
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (total):  "+percent);
+                               stats.AddRow(249, std::string("CPU Use (total):  ")+percent));
                        }
 #endif
                }
@@ -310,12 +315,12 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
 
                case 'T':
                {
-                       results.push_back("249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats.Accept)+" refused "+ConvToStr(ServerInstance->stats.Refused));
-                       results.push_back("249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats.Unknown));
-                       results.push_back("249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats.Collisions));
-                       results.push_back("249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats.DnsGood+ServerInstance->stats.DnsBad)+" succeeded "+ConvToStr(ServerInstance->stats.DnsGood)+" failed "+ConvToStr(ServerInstance->stats.DnsBad));
-                       results.push_back("249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats.Connects));
-                       results.push_back(InspIRCd::Format("249 %s :bytes sent %5.2fK recv %5.2fK", user->nick.c_str(),
+                       stats.AddRow(249, "accepts "+ConvToStr(ServerInstance->stats.Accept)+" refused "+ConvToStr(ServerInstance->stats.Refused));
+                       stats.AddRow(249, "unknown commands "+ConvToStr(ServerInstance->stats.Unknown));
+                       stats.AddRow(249, "nick collisions "+ConvToStr(ServerInstance->stats.Collisions));
+                       stats.AddRow(249, "dns requests "+ConvToStr(ServerInstance->stats.DnsGood+ServerInstance->stats.DnsBad)+" succeeded "+ConvToStr(ServerInstance->stats.DnsGood)+" failed "+ConvToStr(ServerInstance->stats.DnsBad));
+                       stats.AddRow(249, "connection count "+ConvToStr(ServerInstance->stats.Connects));
+                       stats.AddRow(249, InspIRCd::Format("bytes sent %5.2fK recv %5.2fK",
                                ServerInstance->stats.Sent / 1024.0, ServerInstance->stats.Recv / 1024.0));
                }
                break;
@@ -327,8 +332,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for(ConfigIter i = tags.first; i != tags.second; ++i)
                        {
                                ConfigTag* tag = i->second;
-                               results.push_back("243 "+user->nick+" O "+tag->getString("host")+" * "+
-                                       tag->getString("name") + " " + tag->getString("type")+" 0");
+                               stats.AddRow(243, 'O', tag->getString("host"), '*', tag->getString("name"), tag->getString("type"), '0');
                        }
                }
                break;
@@ -349,7 +353,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                        if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A'])
                                                cmodes.push_back(c);
                                }
-                               results.push_back("243 "+user->nick+" O "+tag->name.c_str() + " " + umodes + " " + cmodes);
+                               stats.AddRow(243, 'O', tag->name, umodes, cmodes);
                        }
                }
                break;
@@ -358,14 +362,14 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                case 'l':
                /* stats L (show user I/O stats with IP addresses) */
                case 'L':
-                       GenerateStatsLl(user, results, statschar);
+                       GenerateStatsLl(stats);
                break;
 
                /* stats u (show server uptime) */
                case 'u':
                {
                        unsigned int up = static_cast<unsigned int>(ServerInstance->Time() - ServerInstance->startup_time);
-                       results.push_back(InspIRCd::Format("242 %s :Server up %u days, %.2u:%.2u:%.2u", user->nick.c_str(),
+                       stats.AddRow(242, InspIRCd::Format("Server up %u days, %.2u:%.2u:%.2u",
                                up / 86400, (up / 3600) % 24, (up / 60) % 60, up % 60));
                }
                break;
@@ -374,7 +378,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                break;
        }
 
-       results.push_back("219 "+user->nick+" "+statschar+" :End of /STATS report");
+       stats.AddRow(219, statschar, "End of /STATS report");
        ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",
                (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
        return;
@@ -390,13 +394,14 @@ CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User
                        localuser->CommandFloodPenalty += 2000;
                return CMD_SUCCESS;
        }
-       string_list values;
-       char search = parameters[0][0];
-       DoStats(search, user, values);
-
-       const std::string p = ":" + ServerInstance->Config->ServerName + " ";
-       for (size_t i = 0; i < values.size(); i++)
-               user->SendText(p + values[i]);
+       Stats::Context stats(user, parameters[0][0]);
+       DoStats(stats);
+       const std::vector<Stats::Row>& rows = stats.GetRows();
+       for (std::vector<Stats::Row>::const_iterator i = rows.begin(); i != rows.end(); ++i)
+       {
+               const Stats::Row& row = *i;
+               user->WriteRemoteNumeric(row);
+       }
 
        return CMD_SUCCESS;
 }
index 20f6888b5c54af5967d3555637c09c476c4db329..91fc162419d4bb48dd892d686d4ca93d53a7c292 100644 (file)
@@ -70,8 +70,8 @@ class CommandLinks : public Command
         */
        CmdResult Handle(const std::vector<std::string>& parameters, User* user)
        {
-               user->WriteNumeric(RPL_LINKS, "%s %s :0 %s", ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerDesc.c_str());
-               user->WriteNumeric(RPL_ENDOFLINKS, "* :End of /LINKS list.");
+               user->WriteNumeric(RPL_LINKS, ServerInstance->Config->ServerName, ServerInstance->Config->ServerName, InspIRCd::Format("0 %s", ServerInstance->Config->ServerDesc.c_str()));
+               user->WriteNumeric(RPL_ENDOFLINKS, '*', "End of /LINKS list.");
                return CMD_SUCCESS;
        }
 };
@@ -98,11 +98,11 @@ class CommandServer : public Command
        {
                if (user->registered == REG_ALL)
                {
-                       user->WriteNumeric(ERR_ALREADYREGISTERED, ":You are already registered. (Perhaps your IRC client does not have a /SERVER command).");
+                       user->WriteNumeric(ERR_ALREADYREGISTERED, "You are already registered. (Perhaps your IRC client does not have a /SERVER command).");
                }
                else
                {
-                       user->WriteNumeric(ERR_NOTREGISTERED, "SERVER :You may not register as a server (servers have separate ports from clients, change your config)");
+                       user->WriteNumeric(ERR_NOTREGISTERED, "SERVER", "You may not register as a server (servers have separate ports from clients, change your config)");
                }
                return CMD_FAILURE;
        }
index adc6e6c18a17b59e46e483e00013edf7360888d7..fb720a5a7d61da7fcdf97a568e32da6fd6b1b1d2 100644 (file)
@@ -43,7 +43,7 @@ CmdResult CommandAway::Handle (const std::vector<std::string>& parameters, User
                user->awaytime = ServerInstance->Time();
                user->awaymsg.assign(parameters[0], 0, ServerInstance->Config->Limits.MaxAway);
 
-               user->WriteNumeric(RPL_NOWAWAY, ":You have been marked as being away");
+               user->WriteNumeric(RPL_NOWAWAY, "You have been marked as being away");
        }
        else
        {
@@ -53,7 +53,7 @@ CmdResult CommandAway::Handle (const std::vector<std::string>& parameters, User
                        return CMD_FAILURE;
 
                user->awaymsg.clear();
-               user->WriteNumeric(RPL_UNAWAY, ":You are no longer marked as being away");
+               user->WriteNumeric(RPL_UNAWAY, "You are no longer marked as being away");
        }
 
        return CMD_SUCCESS;
index a62bf51ca47f7647583a3857f169494e0032c01a..b1790bb89eb77d133b5cce795bf1c233fbcdfa5d 100644 (file)
@@ -45,7 +45,7 @@ CmdResult CommandMode::Handle(const std::vector<std::string>& parameters, User*
 
        if ((!targetchannel) && (!targetuser))
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", target.c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(target));
                return CMD_FAILURE;
        }
        if (parameters.size() == 1)
@@ -70,7 +70,7 @@ CmdResult CommandMode::Handle(const std::vector<std::string>& parameters, User*
                        if ((targetuser) && (user != targetuser))
                        {
                                // Local users may only change the modes of other users if a module explicitly allows it
-                               user->WriteNumeric(ERR_USERSDONTMATCH, ":Can't change mode for other users");
+                               user->WriteNumeric(ERR_USERSDONTMATCH, "Can't change mode for other users");
                                return CMD_FAILURE;
                        }
 
@@ -135,8 +135,8 @@ void CommandMode::DisplayCurrentModes(User* user, User* targetuser, Channel* tar
        if (targetchannel)
        {
                // Display channel's current mode string
-               user->WriteNumeric(RPL_CHANNELMODEIS, "%s +%s", targetchannel->name.c_str(), targetchannel->ChanModes(targetchannel->HasUser(user)));
-               user->WriteNumeric(RPL_CHANNELCREATED, "%s %lu", targetchannel->name.c_str(), (unsigned long)targetchannel->age);
+               user->WriteNumeric(RPL_CHANNELMODEIS, targetchannel->name, (std::string("+") + targetchannel->ChanModes(targetchannel->HasUser(user))));
+               user->WriteNumeric(RPL_CHANNELCREATED, targetchannel->name, (unsigned long)targetchannel->age);
        }
        else
        {
@@ -157,7 +157,7 @@ void CommandMode::DisplayCurrentModes(User* user, User* targetuser, Channel* tar
                }
                else
                {
-                       user->WriteNumeric(ERR_USERSDONTMATCH, ":Can't view modes for other users");
+                       user->WriteNumeric(ERR_USERSDONTMATCH, "Can't view modes for other users");
                }
        }
 }
index a62e1c207ca87717b6d6fa1237e0e6effa9432e2..45e7adae59e229041da73d5a8e06b36f6bdcdc49 100644 (file)
@@ -47,7 +47,7 @@ CmdResult CommandNick::HandleLocal(const std::vector<std::string>& parameters, L
 
        if (newnick.empty())
        {
-               user->WriteNumeric(ERR_ERRONEUSNICKNAME, "* :Erroneous Nickname");
+               user->WriteNumeric(ERR_ERRONEUSNICKNAME, '*', "Erroneous Nickname");
                return CMD_FAILURE;
        }
 
@@ -57,7 +57,7 @@ CmdResult CommandNick::HandleLocal(const std::vector<std::string>& parameters, L
        }
        else if (!ServerInstance->IsNick(newnick))
        {
-               user->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Erroneous Nickname", newnick.c_str());
+               user->WriteNumeric(ERR_ERRONEUSNICKNAME, newnick, "Erroneous Nickname");
                return CMD_FAILURE;
        }
 
@@ -77,7 +77,7 @@ CmdResult CommandNick::HandleLocal(const std::vector<std::string>& parameters, L
                        Channel* chan = (*i)->chan;
                        if (chan->GetPrefixValue(user) < VOICE_VALUE && chan->IsBanned(user))
                        {
-                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str());
+                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're banned)");
                                return CMD_FAILURE;
                        }
                }
index 77aafd1b37380c803975d455e28cba15e1829653..4da2787d902b13f4d958e1d65ab0d1c8d86bdd2e 100644 (file)
@@ -46,13 +46,13 @@ CmdResult CommandPart::Handle (const std::vector<std::string>& parameters, User
 
        if (!c)
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                return CMD_FAILURE;
        }
 
        if (!c->PartUser(user, reason))
        {
-               user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel", c->name.c_str());
+               user->WriteNumeric(ERR_NOTONCHANNEL, c->name, "You're not on that channel");
                return CMD_FAILURE;
        }
 
index cbf4f5e08b97ae1487561c28946d96304ca06ec2..37ac116df54280c8a660b28df13a0b061d4bd138 100644 (file)
@@ -40,7 +40,7 @@ CmdResult CommandUser::HandleLocal(const std::vector<std::string>& parameters, L
                         * RFC says we must use this numeric, so we do. Let's make it a little more nub friendly though. :)
                         *  -- Craig, and then w00t.
                         */
-                       user->WriteNumeric(ERR_NEEDMOREPARAMS, "USER :Your username is not valid");
+                       user->WriteNumeric(ERR_NEEDMOREPARAMS, name, "Your username is not valid");
                        return CMD_FAILURE;
                }
                else
@@ -57,7 +57,7 @@ CmdResult CommandUser::HandleLocal(const std::vector<std::string>& parameters, L
        }
        else
        {
-               user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister");
+               user->WriteNumeric(ERR_ALREADYREGISTERED, "You may not reregister");
                user->CommandFloodPenalty += 1000;
                return CMD_FAILURE;
        }
index dd778548ab95514a37e87157c92756ff70b9e9e6..a2ffc009ebd9283b670a706329242800d53c7be3 100644 (file)
@@ -46,7 +46,7 @@ class CommandPass : public SplitCommand
                if (user->registered == REG_ALL)
                {
                        user->CommandFloodPenalty += 1000;
-                       user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister");
+                       user->WriteNumeric(ERR_ALREADYREGISTERED, "You may not reregister");
                        return CMD_FAILURE;
                }
                user->password = parameters[0];
index 8b9258d71d374160f2bbb8a3e792a93697436ad6..1bc03c78e0cb3d038ec8defe271b34f320a5795c 100644 (file)
@@ -385,7 +385,7 @@ CmdResult CommandWho::Handle (const std::vector<std::string>& parameters, User *
        /* Send the results out */
        for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
                user->WriteServ(*n);
-       user->WriteNumeric(RPL_ENDOFWHO, "%s :End of /WHO list.", *parameters[0].c_str() ? parameters[0].c_str() : "*");
+       user->WriteNumeric(RPL_ENDOFWHO, (*parameters[0].c_str() ? parameters[0] : "*"), "End of /WHO list.");
 
        // Penalize the user a bit for large queries
        // (add one unit of penalty per 200 results)
index ecc406a8cff8f52435d604de956a6b61071a2f99..90a630f9cff6aa98bcee0e27a89b9f1be8016185 100644 (file)
@@ -33,20 +33,16 @@ class WhoisContextImpl : public Whois::Context
        }
 
        using Whois::Context::SendLine;
-       void SendLine(unsigned int numeric, const std::string& text) CXX11_OVERRIDE;
+       void SendLine(Numeric::Numeric& numeric) CXX11_OVERRIDE;
 };
 
-void WhoisContextImpl::SendLine(unsigned int numeric, const std::string& text)
+void WhoisContextImpl::SendLine(Numeric::Numeric& numeric)
 {
-       std::string copy_text = target->nick;
-       copy_text.push_back(' ');
-       copy_text.append(text);
-
        ModResult MOD_RESULT;
-       FIRST_MOD_RESULT_CUSTOM(lineevprov, Whois::LineEventListener, OnWhoisLine, MOD_RESULT, (*this, numeric, copy_text));
+       FIRST_MOD_RESULT_CUSTOM(lineevprov, Whois::LineEventListener, OnWhoisLine, MOD_RESULT, (*this, numeric));
 
        if (MOD_RESULT != MOD_RES_DENY)
-               source->WriteNumeric(numeric, copy_text);
+               source->WriteNumeric(numeric);
 }
 
 /** Handle /WHOIS.
@@ -95,9 +91,9 @@ class WhoisNumericSink
        {
        }
 
-       void operator()(unsigned int numeric, const std::string& text) const
+       void operator()(Numeric::Numeric& numeric) const
        {
-               whois.SendLine(numeric, text);
+               whois.SendLine(numeric);
        }
 };
 
@@ -150,7 +146,7 @@ class WhoisChanList
        {
                num.Flush();
                if (!spynum.IsEmpty())
-                       whois.SendLine(336, ":is on private/secret channels:");
+                       whois.SendLine(336, "is on private/secret channels:");
                spynum.Flush();
        }
 };
@@ -180,45 +176,45 @@ void CommandWhois::DoWhois(LocalUser* user, User* dest, unsigned long signon, un
 {
        WhoisContextImpl whois(user, dest, lineevprov);
 
-       whois.SendLine(311, "%s %s * :%s", dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str());
+       whois.SendLine(311, dest->ident, dest->dhost, '*', dest->fullname);
        if (whois.IsSelfWhois() || user->HasPrivPermission("users/auspex"))
        {
-               whois.SendLine(378, ":is connecting from %s@%s %s", dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str());
+               whois.SendLine(378, InspIRCd::Format("is connecting from %s@%s %s", dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str()));
        }
 
        SendChanList(whois);
 
        if (!whois.IsSelfWhois() && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
        {
-               whois.SendLine(312, "%s :%s", ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str());
+               whois.SendLine(312, ServerInstance->Config->HideWhoisServer, ServerInstance->Config->Network);
        }
        else
        {
-               whois.SendLine(312, "%s :%s", dest->server->GetName().c_str(), dest->server->GetDesc().c_str());
+               whois.SendLine(312, dest->server->GetName(), dest->server->GetDesc());
        }
 
        if (dest->IsAway())
        {
-               whois.SendLine(301, ":%s", dest->awaymsg.c_str());
+               whois.SendLine(301, dest->awaymsg);
        }
 
        if (dest->IsOper())
        {
                if (ServerInstance->Config->GenericOper)
-                       whois.SendLine(313, ":is an IRC operator");
+                       whois.SendLine(313, "is an IRC operator");
                else
-                       whois.SendLine(313, ":is %s %s on %s", (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str());
+                       whois.SendLine(313, InspIRCd::Format("is %s %s on %s", (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"), dest->oper->name.c_str(), ServerInstance->Config->Network.c_str()));
        }
 
        if (whois.IsSelfWhois() || user->HasPrivPermission("users/auspex"))
        {
                if (dest->IsModeSet(snomaskmode))
                {
-                       whois.SendLine(379, ":is using modes +%s %s", dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str());
+                       whois.SendLine(379, InspIRCd::Format("is using modes +%s %s", dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str()));
                }
                else
                {
-                       whois.SendLine(379, ":is using modes +%s", dest->FormatModes());
+                       whois.SendLine(379, InspIRCd::Format("is using modes +%s", dest->FormatModes()));
                }
        }
 
@@ -230,10 +226,10 @@ void CommandWhois::DoWhois(LocalUser* user, User* dest, unsigned long signon, un
         */
        if ((idle) || (signon))
        {
-               whois.SendLine(317, "%lu %lu :seconds idle, signon time", idle, signon);
+               whois.SendLine(317, idle, signon, "seconds idle, signon time");
        }
 
-       whois.SendLine(318, ":End of /WHOIS list.");
+       whois.SendLine(318, "End of /WHOIS list.");
 }
 
 CmdResult CommandWhois::HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target)
@@ -296,8 +292,8 @@ CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters,
        else
        {
                /* no such nick/channel */
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
-               user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
+               user->WriteNumeric(Numerics::NoSuchNick(!parameters[userindex].empty() ? parameters[userindex] : "*"));
+               user->WriteNumeric(RPL_ENDOFWHOIS, (!parameters[userindex].empty() ? parameters[userindex] : "*"), "End of /WHOIS list.");
                return CMD_FAILURE;
        }
 
index 79ce94cc9f8f8b3603816c2ec43d9976b698d1dc..f52fb0174e849bc20790095ae190e5069c007fb4 100644 (file)
@@ -35,14 +35,14 @@ CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, Use
        /* if whowas disabled in config */
        if (!manager.IsEnabled())
        {
-               user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", name.c_str());
+               user->WriteNumeric(ERR_UNKNOWNCOMMAND, name, "This command has been disabled.");
                return CMD_FAILURE;
        }
 
        const WhoWas::Nick* const nick = manager.FindNick(parameters[0]);
        if (!nick)
        {
-               user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str());
+               user->WriteNumeric(ERR_WASNOSUCHNICK, parameters[0], "There was no such nickname");
        }
        else
        {
@@ -51,18 +51,18 @@ CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, Use
                {
                        WhoWas::Entry* u = *i;
 
-                       user->WriteNumeric(RPL_WHOWASUSER, "%s %s %s * :%s", parameters[0].c_str(), u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str());
+                       user->WriteNumeric(RPL_WHOWASUSER, parameters[0], u->ident, u->dhost, '*', u->gecos);
 
                        if (user->HasPrivPermission("users/auspex"))
-                               user->WriteNumeric(RPL_WHOWASIP, "%s :was connecting from *@%s", parameters[0].c_str(), u->host.c_str());
+                               user->WriteNumeric(RPL_WHOWASIP, parameters[0], InspIRCd::Format("was connecting from *@%s", u->host.c_str()));
 
                        std::string signon = InspIRCd::TimeString(u->signon);
                        bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"));
-                       user->WriteNumeric(RPL_WHOISSERVER, "%s %s :%s", parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str());
+                       user->WriteNumeric(RPL_WHOISSERVER, parameters[0], (hide_server ? ServerInstance->Config->HideWhoisServer : u->server), signon);
                }
        }
 
-       user->WriteNumeric(RPL_ENDOFWHOWAS, "%s :End of WHOWAS", parameters[0].c_str());
+       user->WriteNumeric(RPL_ENDOFWHOWAS, parameters[0], "End of WHOWAS");
        return CMD_SUCCESS;
 }
 
@@ -270,10 +270,10 @@ class ModuleWhoWas : public Module
                cmd.manager.Add(user);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results)
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol == 'z')
-                       results.push_back("249 "+user->nick+" :Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
+               if (stats.GetSymbol() == 'z')
+                       stats.AddRow(249, "Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
 
                return MOD_RES_PASSTHRU;
        }
index 7fa7da0197369fb412955489fb1e261473e11443..93ac1db311868040137f1a63269eb4daceb770cc 100644 (file)
@@ -80,7 +80,7 @@ class CoreModXLine : public Module
                }
 
                // Send a numeric because if we deny then the core doesn't reply anything
-               user->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Invalid nickname: %s", newnick.c_str(), xline->reason.c_str());
+               user->WriteNumeric(ERR_ERRONEUSNICKNAME, newnick, InspIRCd::Format("Invalid nickname: %s", xline->reason.c_str()));
                return MOD_RES_DENY;
        }
 
index 35964dfb3396d9f893f78e63aa2d682d0c39e53d..cd034688c8ec2b6be81b8ce47f7c929d17fd7cc3 100644 (file)
@@ -35,15 +35,15 @@ void ListModeBase::DisplayList(User* user, Channel* channel)
        {
                for (ModeList::const_iterator it = cd->list.begin(); it != cd->list.end(); ++it)
                {
-                       user->WriteNumeric(listnumeric, "%s %s %s %lu", channel->name.c_str(), it->mask.c_str(), it->setter.c_str(), (unsigned long) it->time);
+                       user->WriteNumeric(listnumeric, channel->name, it->mask, it->setter, (unsigned long) it->time);
                }
        }
-       user->WriteNumeric(endoflistnumeric, "%s :%s", channel->name.c_str(), endofliststring.c_str());
+       user->WriteNumeric(endoflistnumeric, channel->name, endofliststring);
 }
 
 void ListModeBase::DisplayEmptyList(User* user, Channel* channel)
 {
-       user->WriteNumeric(endoflistnumeric, "%s :%s", channel->name.c_str(), endofliststring.c_str());
+       user->WriteNumeric(endoflistnumeric, channel->name, endofliststring);
 }
 
 void ListModeBase::RemoveMode(Channel* channel, Modes::ChangeList& changelist)
@@ -212,7 +212,7 @@ bool ListModeBase::ValidateParam(User*, Channel*, std::string&)
 
 void ListModeBase::TellListTooLong(User* source, Channel* channel, std::string& parameter)
 {
-       source->WriteNumeric(ERR_BANLISTFULL, "%s %s :Channel ban list is full", channel->name.c_str(), parameter.c_str());
+       source->WriteNumeric(ERR_BANLISTFULL, channel->name, parameter, "Channel ban list is full");
 }
 
 void ListModeBase::TellAlreadyOnList(User*, Channel*, std::string&)
index 6038f6f5b0a04771516ae3f90f922fd7c37d5fdd..b29eda828e197a01f5f9bb2a0a65f8c9c7c647ac 100644 (file)
@@ -175,7 +175,7 @@ ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::str
 
        if (!target)
        {
-               source->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameter.c_str());
+               source->WriteNumeric(Numerics::NoSuchNick(parameter));
                return MODEACTION_DENY;
        }
 
@@ -263,11 +263,10 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                                        }
                                }
                                if (neededmh)
-                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must have channel %s access or above to %sset channel mode %c",
-                                               chan->name.c_str(), neededmh->name.c_str(), adding ? "" : "un", modechar);
+                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, chan->name, InspIRCd::Format("You must have channel %s access or above to %sset channel mode %c",
+                                               neededmh->name.c_str(), adding ? "" : "un", modechar));
                                else
-                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You cannot %sset channel mode %c",
-                                               chan->name.c_str(), adding ? "" : "un", modechar);
+                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, chan->name, InspIRCd::Format("You cannot %sset channel mode %c", (adding ? "" : "un"), modechar));
                                return MODEACTION_DENY;
                        }
                }
@@ -294,8 +293,8 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
                if (disabled[modechar - 'A'])
                {
-                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - %s mode %c has been locked by the administrator",
-                               type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
+                       user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c has been locked by the administrator",
+                               type == MODETYPE_CHANNEL ? "channel" : "user", modechar));
                        return MODEACTION_DENY;
                }
        }
@@ -305,13 +304,13 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                /* It's an oper only mode, and they don't have access to it. */
                if (user->IsOper())
                {
-                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Oper type %s does not have access to set %s mode %c",
-                                       user->oper->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
+                       user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Oper type %s does not have access to set %s mode %c",
+                                       user->oper->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar));
                }
                else
                {
-                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Only operators may set %s mode %c",
-                                       type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
+                       user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Only operators may set %s mode %c",
+                                       type == MODETYPE_CHANNEL ? "channel" : "user", modechar));
                }
                return MODEACTION_DENY;
        }
@@ -359,7 +358,7 @@ void ModeParser::ModeParamsToChangeList(User* user, ModeType type, const std::ve
                if (!mh)
                {
                        /* No mode handler? Unknown mode character then. */
-                       user->WriteNumeric(type == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK, "%c :is unknown mode char to me", modechar);
+                       user->WriteNumeric(type == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK, modechar, "is unknown mode char to me");
                        continue;
                }
 
index 08ee7f562486dc4190a9f6cf94867106402d8bf3..f0fa5e94bb784a8cd97db6da64f9dbfcd0809421 100644 (file)
@@ -99,7 +99,7 @@ std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::
                                {
                                        if (!ServerInstance->SNO->IsSnomaskUsable(*i))
                                        {
-                                               user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%c :is unknown snomask char to me", *i);
+                                               user->WriteNumeric(ERR_UNKNOWNSNOMASK, *i, "is unknown snomask char to me");
                                                continue;
                                        }
                                }
index 292986df500327b8ae4ed1584e14584a0ef2d5f9..b107a4b439d801174495267854284ac7e002eda6 100644 (file)
@@ -107,7 +107,7 @@ ModResult   Module::OnCheckLimit(User*, Channel*) { DetachEvent(I_OnCheckLimit); r
 ModResult      Module::OnCheckChannelBan(User*, Channel*) { DetachEvent(I_OnCheckChannelBan); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnCheckBan(User*, Channel*, const std::string&) { DetachEvent(I_OnCheckBan); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnExtBanCheck(User*, Channel*, char) { DetachEvent(I_OnExtBanCheck); return MOD_RES_PASSTHRU; }
-ModResult      Module::OnStats(char, User*, string_list&) { DetachEvent(I_OnStats); return MOD_RES_PASSTHRU; }
+ModResult      Module::OnStats(Stats::Context&) { DetachEvent(I_OnStats); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnChangeLocalUserHost(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserHost); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnChangeLocalUserGECOS(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserGECOS); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnPreTopicChange(User*, Channel*, const std::string&) { DetachEvent(I_OnPreTopicChange); return MOD_RES_PASSTHRU; }
@@ -135,7 +135,7 @@ void                Module::OnGarbageCollect() { DetachEvent(I_OnGarbageCollect); }
 ModResult      Module::OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { DetachEvent(I_OnSetConnectClass); return MOD_RES_PASSTHRU; }
 void           Module::OnText(User*, void*, int, const std::string&, char, CUList&) { DetachEvent(I_OnText); }
 ModResult      Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { DetachEvent(I_OnNamesListItem); return MOD_RES_PASSTHRU; }
-ModResult      Module::OnNumeric(User*, unsigned int, const std::string&) { DetachEvent(I_OnNumeric); return MOD_RES_PASSTHRU; }
+ModResult      Module::OnNumeric(User*, const Numeric::Numeric&) { DetachEvent(I_OnNumeric); return MOD_RES_PASSTHRU; }
 ModResult   Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { DetachEvent(I_OnAcceptConnection); return MOD_RES_PASSTHRU; }
 void           Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, Membership*, std::string&) { DetachEvent(I_OnSendWhoLine); }
 void           Module::OnSetUserIP(LocalUser*) { DetachEvent(I_OnSetUserIP); }
index d21a82149b423cbbe84fca796fff24f5dbddff5f..967c6a761f2c80a94058ca71381ad616a16768ca 100644 (file)
@@ -97,9 +97,9 @@ class ModuleGeoIP : public Module
                return MOD_RES_DENY;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'G')
+               if (stats.GetSymbol() != 'G')
                        return MOD_RES_PASSTHRU;
 
                unsigned int unknown = 0;
@@ -115,14 +115,13 @@ class ModuleGeoIP : public Module
                                unknown++;
                }
 
-               std::string p = "801 " + user->nick + " :GeoIPSTATS ";
                for (std::map<std::string, unsigned int>::const_iterator i = results.begin(); i != results.end(); ++i)
                {
-                       out.push_back(p + i->first + " " + ConvToStr(i->second));
+                       stats.AddRow(801, "GeoIPSTATS " + i->first + " " + ConvToStr(i->second));
                }
 
                if (unknown)
-                       out.push_back(p + "Unknown " + ConvToStr(unknown));
+                       stats.AddRow(801, "GeoIPSTATS Unknown " + ConvToStr(unknown));
 
                return MOD_RES_DENY;
        }
index d2fa09c4ebad1106a5f37776c50c85a5832ea6e7..85709080f8e1436c43ae1957d0b11c4366a8aee6 100644 (file)
@@ -49,7 +49,7 @@ class ModuleAbbreviation : public Module
                        {
                                if (matchlist.length() > 450)
                                {
-                                       user->WriteNumeric(420, ":Ambiguous abbreviation and too many possible matches.");
+                                       user->WriteNumeric(420, "Ambiguous abbreviation and too many possible matches.");
                                        return MOD_RES_DENY;
                                }
 
@@ -67,7 +67,7 @@ class ModuleAbbreviation : public Module
                /* Ambiguous command, list the matches */
                if (!matchlist.empty())
                {
-                       user->WriteNumeric(420, ":Ambiguous abbreviation, possible matches: %s%s", foundcommand.c_str(), matchlist.c_str());
+                       user->WriteNumeric(420, InspIRCd::Format("Ambiguous abbreviation, possible matches: %s%s", foundcommand.c_str(), matchlist.c_str()));
                        return MOD_RES_DENY;
                }
 
index 3a4bf5348c2de554d0323aaa62615cebc80f010c..9184b10af407ba83af17366e94a9db83a317ccb3 100644 (file)
@@ -253,14 +253,14 @@ class ModuleAlias : public Module
                        User* u = ServerInstance->FindNick(a->RequiredNick);
                        if (!u)
                        {
-                               user->WriteNumeric(ERR_NOSUCHNICK, a->RequiredNick + " :is currently unavailable. Please try again later.");
+                               user->WriteNumeric(ERR_NOSUCHNICK, a->RequiredNick, "is currently unavailable. Please try again later.");
                                return 1;
                        }
 
                        if ((a->ULineOnly) && (!u->server->IsULine()))
                        {
                                ServerInstance->SNO->WriteToSnoMask('a', "NOTICE -- Service "+a->RequiredNick+" required by alias "+a->AliasedCommand+" is not on a u-lined server, possibly underhanded antics detected!");
-                               user->WriteNumeric(ERR_NOSUCHNICK, a->RequiredNick + " :is an imposter! Please inform an IRC operator as soon as possible.");
+                               user->WriteNumeric(ERR_NOSUCHNICK, a->RequiredNick, "is an imposter! Please inform an IRC operator as soon as possible.");
                                return 1;
                        }
                }
index 05e76113affb7fda59fe3f0311c57d5d85961299..6a4db18227def74a42c5c3c8b8f0e546acf2ed72 100644 (file)
@@ -47,7 +47,7 @@ class ModuleAllowInvite : public Module
                        if (res == MOD_RES_DENY)
                        {
                                // Matching extban, explicitly deny /invite
-                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You are banned from using INVITE", channel->name.c_str());
+                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, "You are banned from using INVITE");
                                return res;
                        }
                        if (channel->IsModeSet(ni) || res == MOD_RES_ALLOW)
index 2b9c2e1c21c28edfaf62adc6d3513a1ffa0ee08f..8c7f300daba11b60cbcbd85d79de719edf69e425 100644 (file)
@@ -52,8 +52,7 @@ class AutoOpList : public ListModeBase
 
                if (adding && !mh)
                {
-                       source->WriteNumeric(415, "%s :Cannot find prefix mode '%s' for autoop",
-                               mid.c_str(), mid.c_str());
+                       source->WriteNumeric(415, mid, InspIRCd::Format("Cannot find prefix mode '%s' for autoop", mid.c_str()));
                        return MOD_RES_DENY;
                }
                else if (!mh)
@@ -64,8 +63,7 @@ class AutoOpList : public ListModeBase
                        return MOD_RES_DENY;
                if (mh->GetLevelRequired() > mylevel)
                {
-                       source->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be able to set mode '%s' to include it in an autoop",
-                               channel->name.c_str(), mid.c_str());
+                       source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to set mode '%s' to include it in an autoop", mid.c_str()));
                        return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index d3490acc062aab9eeb569ff4d4ebf9c4fd791916..c44a10f05c35896f0543b63d8635b6fbb5768eaf 100644 (file)
@@ -82,7 +82,7 @@ class BanRedirect : public ModeWatcher
                        ListModeBase::ModeList* list = banlm->GetList(channel);
                        if ((list) && (adding) && (maxbans <= list->size()))
                        {
-                               source->WriteNumeric(ERR_BANLISTFULL, "%s :Channel ban list for %s is full (maximum entries for this channel is %u)", channel->name.c_str(), channel->name.c_str(), maxbans);
+                               source->WriteNumeric(ERR_BANLISTFULL, channel->name, InspIRCd::Format("Channel ban list for %s is full (maximum entries for this channel is %u)", channel->name.c_str(), maxbans));
                                return false;
                        }
 
@@ -150,25 +150,25 @@ class BanRedirect : public ModeWatcher
                                {
                                        if (!ServerInstance->IsChannel(mask[CHAN]))
                                        {
-                                               source->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name in redirection (%s)", channel->name.c_str(), mask[CHAN].c_str());
+                                               source->WriteNumeric(ERR_NOSUCHCHANNEL, channel->name, InspIRCd::Format("Invalid channel name in redirection (%s)", mask[CHAN].c_str()));
                                                return false;
                                        }
 
                                        Channel *c = ServerInstance->FindChan(mask[CHAN]);
                                        if (!c)
                                        {
-                                               source->WriteNumeric(690, ":Target channel %s must exist to be set as a redirect.", mask[CHAN].c_str());
+                                               source->WriteNumeric(690, InspIRCd::Format("Target channel %s must exist to be set as a redirect.", mask[CHAN].c_str()));
                                                return false;
                                        }
                                        else if (adding && c->GetPrefixValue(source) < OP_VALUE)
                                        {
-                                               source->WriteNumeric(690, ":You must be opped on %s to set it as a redirect.", mask[CHAN].c_str());
+                                               source->WriteNumeric(690, InspIRCd::Format("You must be opped on %s to set it as a redirect.", mask[CHAN].c_str()));
                                                return false;
                                        }
 
                                        if (assign(channel->name) == mask[CHAN])
                                        {
-                                               source->WriteNumeric(690, "%s :You cannot set a ban redirection to the channel the ban is on", channel->name.c_str());
+                                               source->WriteNumeric(690, channel->name, "You cannot set a ban redirection to the channel the ban is on");
                                                return false;
                                        }
                                }
@@ -311,13 +311,13 @@ class ModuleBanRedirect : public Module
 
                                                if(destchan && destchan->IsModeSet(redirectmode) && !destlimit.empty() && (destchan->GetUserCounter() >= atoi(destlimit.c_str())))
                                                {
-                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Cannot join channel (You are banned)", chan->name.c_str());
+                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (You are banned)");
                                                        return MOD_RES_DENY;
                                                }
                                                else
                                                {
-                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Cannot join channel (You are banned)", chan->name.c_str());
-                                                       user->WriteNumeric(470, "%s %s :You are banned from this channel, so you are automatically transferred to the redirected channel.", chan->name.c_str(), redir->targetchan.c_str());
+                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (You are banned)");
+                                                       user->WriteNumeric(470, chan->name, redir->targetchan, "You are banned from this channel, so you are automatically transferred to the redirected channel.");
                                                        nofollow = true;
                                                        Channel::JoinUser(user, redir->targetchan);
                                                        nofollow = false;
index 57f86afd125b1f30e208b9f1fbc8086ed41d18f1..cd7698d69564d2104650e8710d701798d8c20ef2 100644 (file)
@@ -74,7 +74,7 @@ public:
 
                                if (((caps * 100) / text.length()) >= percent)
                                {
-                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Your message cannot contain %d%% or more capital letters if it's longer than %d characters", c->name.c_str(), percent, minlen);
+                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, InspIRCd::Format("Your message cannot contain %d%% or more capital letters if it's longer than %d characters", percent, minlen));
                                        return MOD_RES_DENY;
                                }
                        }
index a08ad7c6f0dabca419445a767703489070824139..567bdb24951e961f1ee304a9062ed6706faace86 100644 (file)
@@ -67,7 +67,7 @@ class ModuleBlockColor : public Module
                                                case 21:
                                                case 22:
                                                case 31:
-                                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Can't send colors to channel (+c set)", c->name.c_str());
+                                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send colors to channel (+c set)");
                                                        return MOD_RES_DENY;
                                                break;
                                        }
index 419af0153dfcc7264c45594638bcfdc105a35797..e0236bc17c4a8756b3a949bb537ee88b126c23df 100644 (file)
@@ -48,7 +48,7 @@ class ModuleBotMode : public Module, public Whois::EventListener
        {
                if (whois.GetTarget()->IsModeSet(bm))
                {
-                       whois.SendLine(335, ":is a bot on " + ServerInstance->Config->Network);
+                       whois.SendLine(335, "is a bot on " + ServerInstance->Config->Network);
                }
        }
 };
index 0eb208138276a6b7d4ee3673b2d3af18d4b3b776..e11b326de73a7941977946c086b83b92b6c7581f 100644 (file)
@@ -225,7 +225,7 @@ public:
                ACCEPTAction action = GetTargetAndAction(tok, user);
                if (!action.first)
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", tok.c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(tok));
                        return CMD_FAILURE;
                }
 
@@ -271,7 +271,7 @@ public:
                        for (callerid_data::UserSet::iterator i = dat->accepting.begin(); i != dat->accepting.end(); ++i)
                                user->WriteNumeric(RPL_ACCEPTLIST, (*i)->nick);
                }
-               user->WriteNumeric(RPL_ENDOFACCEPT, ":End of ACCEPT list");
+               user->WriteNumeric(RPL_ENDOFACCEPT, "End of ACCEPT list");
        }
 
        bool AddAccept(User* user, User* whotoadd)
@@ -280,12 +280,12 @@ public:
                callerid_data* dat = extInfo.get(user, true);
                if (dat->accepting.size() >= maxaccepts)
                {
-                       user->WriteNumeric(ERR_ACCEPTFULL, ":Accept list is full (limit is %d)", maxaccepts);
+                       user->WriteNumeric(ERR_ACCEPTFULL, InspIRCd::Format("Accept list is full (limit is %d)", maxaccepts));
                        return false;
                }
                if (!dat->accepting.insert(whotoadd).second)
                {
-                       user->WriteNumeric(ERR_ACCEPTEXIST, "%s :is already on your accept list", whotoadd->nick.c_str());
+                       user->WriteNumeric(ERR_ACCEPTEXIST, whotoadd->nick, "is already on your accept list");
                        return false;
                }
 
@@ -303,12 +303,12 @@ public:
                callerid_data* dat = extInfo.get(user, false);
                if (!dat)
                {
-                       user->WriteNumeric(ERR_ACCEPTNOT, "%s :is not on your accept list", whotoremove->nick.c_str());
+                       user->WriteNumeric(ERR_ACCEPTNOT, whotoremove->nick, "is not on your accept list");
                        return false;
                }
                if (!dat->accepting.erase(whotoremove))
                {
-                       user->WriteNumeric(ERR_ACCEPTNOT, "%s :is not on your accept list", whotoremove->nick.c_str());
+                       user->WriteNumeric(ERR_ACCEPTNOT, whotoremove->nick, "is not on your accept list");
                        return false;
                }
 
@@ -395,12 +395,12 @@ public:
                {
                        time_t now = ServerInstance->Time();
                        /* +g and *not* accepted */
-                       user->WriteNumeric(ERR_TARGUMODEG, "%s :is in +g mode (server-side ignore).", dest->nick.c_str());
+                       user->WriteNumeric(ERR_TARGUMODEG, dest->nick, "is in +g mode (server-side ignore).");
                        if (now > (dat->lastnotify + (time_t)notify_cooldown))
                        {
-                               user->WriteNumeric(RPL_TARGNOTIFY, "%s :has been informed that you messaged them.", dest->nick.c_str());
-                               dest->SendText(":%s %03d %s %s %s@%s :is messaging you, and you have umode +g. Use /ACCEPT +%s to allow.",
-                                               ServerInstance->Config->ServerName.c_str(), RPL_UMODEGMSG, dest->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str(), user->nick.c_str());
+                               user->WriteNumeric(RPL_TARGNOTIFY, dest->nick, "has been informed that you messaged them.");
+                               dest->WriteRemoteNumeric(RPL_UMODEGMSG, user->nick, InspIRCd::Format("%s@%s", user->ident.c_str(), user->dhost.c_str()), InspIRCd::Format("is messaging you, and you have umode +g. Use /ACCEPT +%s to allow.",
+                                               user->nick.c_str()));
                                dat->lastnotify = now;
                        }
                        return MOD_RES_DENY;
index 09d5e604dd12c3e617c3b88a9b799f503a4cdabb..e6e01570d83153a0aff3410041f9cca2a1a82260 100644 (file)
@@ -398,7 +398,7 @@ class CommandCap : public SplitCommand
                }
                else
                {
-                       user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, "%s :Invalid CAP subcommand", subcommand.c_str());
+                       user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, subcommand, "Invalid CAP subcommand");
                        return CMD_FAILURE;
                }
 
index 4fb0653a91b1014e6da68ff377f9d17dfa5947df..2a969bec7cb594666bd6d5d5b8680773fc241f24 100644 (file)
@@ -165,12 +165,12 @@ class ModuleCBan : public Module
                ServerInstance->XLines->UnregisterFactory(&f);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'C')
+               if (stats.GetSymbol() != 'C')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("CBAN", 210, user, out);
+               ServerInstance->XLines->InvokeStats("CBAN", 210, stats);
                return MOD_RES_DENY;
        }
 
@@ -181,7 +181,7 @@ class ModuleCBan : public Module
                if (rl)
                {
                        // Channel is banned.
-                       user->WriteNumeric(384, "%s :Cannot join channel, CBANed (%s)", cname.c_str(), rl->reason.c_str());
+                       user->WriteNumeric(384, cname, InspIRCd::Format("Cannot join channel, CBANed (%s)", rl->reason.c_str()));
                        ServerInstance->SNO->WriteGlobalSno('a', "%s tried to join %s which is CBANed (%s)",
                                 user->nick.c_str(), cname.c_str(), rl->reason.c_str());
                        return MOD_RES_DENY;
index da22b5153627745b2e44824406610123ca9df013..7d8c74024a8f0b5a5a877d6dcdabdbef0b0bb871 100644 (file)
@@ -79,7 +79,7 @@ class ModuleCensor : public Module
                        {
                                if (index->second.empty())
                                {
-                                       user->WriteNumeric(ERR_WORDFILTERED, "%s %s :Your message contained a censored word, and was blocked", ((Channel*)dest)->name.c_str(), index->first.c_str());
+                                       user->WriteNumeric(ERR_WORDFILTERED, ((Channel*)dest)->name, index->first, "Your message contained a censored word, and was blocked");
                                        return MOD_RES_DENY;
                                }
 
index 53428a5a871af08f19274155a4a7ebb31ba810bb..a7bc215570c221e54e6419ff2a623d55b8d99c33 100644 (file)
@@ -37,7 +37,7 @@ class ChanFilter : public ListModeBase
        {
                if (word.length() > 35)
                {
-                       user->WriteNumeric(935, "%s %s :word is too long for censor list", chan->name.c_str(), word.c_str());
+                       user->WriteNumeric(935, chan->name, word, "%word is too long for censor list");
                        return false;
                }
 
@@ -46,17 +46,17 @@ class ChanFilter : public ListModeBase
 
        void TellListTooLong(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(939, "%s %s :Channel spamfilter list is full", chan->name.c_str(), word.c_str());
+               user->WriteNumeric(939, chan->name, word, "Channel spamfilter list is full");
        }
 
        void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(937, "%s :The word %s is already on the spamfilter list", chan->name.c_str(), word.c_str());
+               user->WriteNumeric(937, chan->name, InspIRCd::Format("The word %s is already on the spamfilter list", word.c_str()));
        }
 
        void TellNotSet(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(938, "%s :No such spamfilter word is set", chan->name.c_str());
+               user->WriteNumeric(938, chan->name, "No such spamfilter word is set");
        }
 };
 
@@ -98,9 +98,9 @@ class ModuleChanFilter : public Module
                                if (InspIRCd::Match(text, i->mask))
                                {
                                        if (hidemask)
-                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (your message contained a censored word)", chan->name.c_str());
+                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word)");
                                        else
-                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s %s :Cannot send to channel (your message contained a censored word)", chan->name.c_str(), i->mask.c_str());
+                                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, i->mask, "Cannot send to channel (your message contained a censored word)");
                                        return MOD_RES_DENY;
                                }
                        }
index 43b2a323ba4fb84478d2e8c65de77a11f6052852..163f1f2ebf45abc60cea315a1ad32e2d751d9c91 100644 (file)
@@ -59,7 +59,7 @@ class CommandChghost : public Command
                // Allow services to change the host of unregistered users
                if ((!dest) || ((dest->registered != REG_ALL) && (!user->server->IsULine())))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
index c855216bfd4d91028e4df35e3134a2e9012bdded..0b4e78f127628362424e596f7df08082a34faf0a 100644 (file)
@@ -41,7 +41,7 @@ class CommandChgident : public Command
 
                if ((!dest) || (dest->registered != REG_ALL))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
index 830d5070b60c1b47ed50bfd0ac2031026663ce39..3ad9cede918b916084c1f076873fa128ace82855 100644 (file)
@@ -39,7 +39,7 @@ class CommandChgname : public Command
 
                if ((!dest) || (dest->registered != REG_ALL))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
index eab53b9bc92573a973e15bcbcc71be69d680cb3b..e04217e71f16d42ff45bb74bee97f78b4d0713d1 100644 (file)
@@ -47,7 +47,7 @@ class ModulePrivacyMode : public Module
                        User* t = (User*)dest;
                        if (!user->IsOper() && (t->IsModeSet(pm)) && (!user->server->IsULine()) && !user->SharesChannelWith(t))
                        {
-                               user->WriteNumeric(ERR_CANTSENDTOUSER, "%s :You are not permitted to send private messages to this user (+c set)", t->nick.c_str());
+                               user->WriteNumeric(ERR_CANTSENDTOUSER, t->nick, "You are not permitted to send private messages to this user (+c set)");
                                return MOD_RES_DENY;
                        }
                }
index b86bf1809182f6e7041c02b8a0b7d86c62e360ea..30c0aa4f2d5826093f7f98865b07f7b5f9a3cc7b 100644 (file)
@@ -82,16 +82,16 @@ class ModuleCustomTitle : public Module, public Whois::LineEventListener
        }
 
        // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
-       ModResult OnWhoisLine(Whois::Context& whois, unsigned int& numeric, std::string& text) CXX11_OVERRIDE
+       ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
                /* We use this and not OnWhois because this triggers for remote, too */
-               if (numeric == 312)
+               if (numeric.GetNumeric() == 312)
                {
                        /* Insert our numeric before 312 */
                        const std::string* ctitle = cmd.ctitle.get(whois.GetTarget());
                        if (ctitle)
                        {
-                               whois.SendLine(320, ":%s", ctitle->c_str());
+                               whois.SendLine(320, ctitle);
                        }
                }
                /* Don't block anything */
index c8b6bd8b4b82ec923e433c602a313da3ffa7d812..202cb123ffbff6aa1de368e5c0ecf5d8a6baab68 100644 (file)
@@ -44,7 +44,7 @@ class CommandCycle : public SplitCommand
 
                if (!channel)
                {
-                       user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :No such channel", parameters[0].c_str());
+                       user->WriteNumeric(ERR_NOSUCHCHANNEL, parameters[0], "No such channel");
                        return CMD_FAILURE;
                }
 
@@ -64,7 +64,7 @@ class CommandCycle : public SplitCommand
                }
                else
                {
-                       user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel", channel->name.c_str());
+                       user->WriteNumeric(ERR_NOTONCHANNEL, channel->name, "You're not on that channel");
                }
 
                return CMD_FAILURE;
index 45a2304651bf29e4ecb45fc08c60a7d899b3d272..21cc97aa5156198e1073d8c2b828405b87ffb67c 100644 (file)
@@ -120,7 +120,7 @@ class CommandDccallow : public Command
                                }
                                else
                                {
-                                       user->WriteNumeric(998, ":DCCALLOW command not understood. For help on DCCALLOW, type /DCCALLOW HELP");
+                                       user->WriteNumeric(998, "DCCALLOW command not understood. For help on DCCALLOW, type /DCCALLOW HELP");
                                        return CMD_FAILURE;
                                }
                        }
@@ -143,7 +143,7 @@ class CommandDccallow : public Command
                                                        if (i->nickname == target->nick)
                                                        {
                                                                dl->erase(i);
-                                                               user->WriteNumeric(995, "%s :Removed %s from your DCCALLOW list", user->nick.c_str(), target->nick.c_str());
+                                                               user->WriteNumeric(995, user->nick, InspIRCd::Format("Removed %s from your DCCALLOW list", target->nick.c_str()));
                                                                break;
                                                        }
                                                }
@@ -153,7 +153,7 @@ class CommandDccallow : public Command
                                {
                                        if (target == user)
                                        {
-                                               user->WriteNumeric(996, "%s :You cannot add yourself to your own DCCALLOW list!", user->nick.c_str());
+                                               user->WriteNumeric(996, user->nick, "You cannot add yourself to your own DCCALLOW list!");
                                                return CMD_FAILURE;
                                        }
 
@@ -168,7 +168,7 @@ class CommandDccallow : public Command
 
                                        if (dl->size() >= maxentries)
                                        {
-                                               user->WriteNumeric(996, "%s :Too many nicks on DCCALLOW list", user->nick.c_str());
+                                               user->WriteNumeric(996, user->nick, "Too many nicks on DCCALLOW list");
                                                return CMD_FAILURE;
                                        }
 
@@ -176,7 +176,7 @@ class CommandDccallow : public Command
                                        {
                                                if (k->nickname == target->nick)
                                                {
-                                                       user->WriteNumeric(996, "%s :%s is already on your DCCALLOW list", user->nick.c_str(), target->nick.c_str());
+                                                       user->WriteNumeric(996, user->nick, InspIRCd::Format("%s is already on your DCCALLOW list", target->nick.c_str()));
                                                        return CMD_FAILURE;
                                                }
                                        }
@@ -207,11 +207,11 @@ class CommandDccallow : public Command
 
                                        if (length > 0)
                                        {
-                                               user->WriteNumeric(993, "%s :Added %s to DCCALLOW list for %ld seconds", user->nick.c_str(), target->nick.c_str(), length);
+                                               user->WriteNumeric(993, user->nick, InspIRCd::Format("Added %s to DCCALLOW list for %ld seconds", target->nick.c_str(), length));
                                        }
                                        else
                                        {
-                                               user->WriteNumeric(994, "%s :Added %s to DCCALLOW list for this session", user->nick.c_str(), target->nick.c_str());
+                                               user->WriteNumeric(994, user->nick, InspIRCd::Format("Added %s to DCCALLOW list for this session", target->nick.c_str()));
                                        }
 
                                        /* route it. */
@@ -221,7 +221,7 @@ class CommandDccallow : public Command
                        else
                        {
                                // nick doesn't exist
-                               user->WriteNumeric(401, "%s :No such nick/channel", nick.c_str());
+                               user->WriteNumeric(Numerics::NoSuchNick(nick));
                                return CMD_FAILURE;
                        }
                }
@@ -236,8 +236,8 @@ class CommandDccallow : public Command
        void DisplayHelp(User* user)
        {
                for (size_t i = 0; i < sizeof(helptext)/sizeof(helptext[0]); i++)
-                       user->WriteNumeric(998, ":%s", helptext[i]);
-               user->WriteNumeric(999, ":End of DCCALLOW HELP");
+                       user->WriteNumeric(998, helptext[i]);
+               user->WriteNumeric(999, "End of DCCALLOW HELP");
 
                LocalUser* localuser = IS_LOCAL(user);
                if (localuser)
@@ -247,18 +247,18 @@ class CommandDccallow : public Command
        void DisplayDCCAllowList(User* user)
        {
                 // display current DCCALLOW list
-               user->WriteNumeric(990, ":Users on your DCCALLOW list:");
+               user->WriteNumeric(990, "Users on your DCCALLOW list:");
 
                dl = ext.get(user);
                if (dl)
                {
                        for (dccallowlist::const_iterator c = dl->begin(); c != dl->end(); ++c)
                        {
-                               user->WriteNumeric(991, "%s :%s (%s)", user->nick.c_str(), c->nickname.c_str(), c->hostmask.c_str());
+                               user->WriteNumeric(991, user->nick, InspIRCd::Format("%s (%s)", c->nickname.c_str(), c->hostmask.c_str()));
                        }
                }
 
-               user->WriteNumeric(992, ":End of DCCALLOW list");
+               user->WriteNumeric(992, "End of DCCALLOW list");
        }
 
 };
@@ -400,7 +400,7 @@ class ModuleDCCAllow : public Module
                                        {
                                                if (iter2->length != 0 && (iter2->set_on + iter2->length) <= ServerInstance->Time())
                                                {
-                                                       u->WriteNumeric(997, "%s :DCCALLOW entry for %s has expired", u->nick.c_str(), iter2->nickname.c_str());
+                                                       u->WriteNumeric(997, u->nick, InspIRCd::Format("DCCALLOW entry for %s has expired", iter2->nickname.c_str()));
                                                        iter2 = dl->erase(iter2);
                                                }
                                                else
@@ -435,7 +435,7 @@ class ModuleDCCAllow : public Module
                                                {
 
                                                        u->WriteNotice(i->nickname + " left the network or changed their nickname and has been removed from your DCCALLOW list");
-                                                       u->WriteNumeric(995, "%s :Removed %s from your DCCALLOW list", u->nick.c_str(), i->nickname.c_str());
+                                                       u->WriteNumeric(995, u->nick, InspIRCd::Format("Removed %s from your DCCALLOW list", i->nickname.c_str()));
                                                        dl->erase(i);
                                                        break;
                                                }
index f64297e15b8c678ce29d0969b8583400175e2ebf..1ad41cc57f23395199da3d5efe184b4ba5aca30f 100644 (file)
@@ -118,8 +118,7 @@ ModResult ModuleDelayMsg::OnUserPreMessage(User* user, void* dest, int target_ty
        {
                if (channel->GetPrefixValue(user) < VOICE_VALUE)
                {
-                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :You must wait %d seconds after joining to send to channel (+d)",
-                               channel->name.c_str(), len);
+                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, channel->name, InspIRCd::Format("You must wait %d seconds after joining to send to channel (+d)", len));
                        return MOD_RES_DENY;
                }
        }
index 6378ba2733c75b0f2aa23e283d31ec0896fd3a44..467c8a03b3dfe6f0c02a2ea18506cdc00949c941 100644 (file)
@@ -113,13 +113,13 @@ class ModuleDenyChannels : public Module
                                                Channel *newchan = ServerInstance->FindChan(redirect);
                                                if ((!newchan) || (!newchan->IsModeSet(redirectmode)))
                                                {
-                                                       user->WriteNumeric(926, "%s :Channel %s is forbidden, redirecting to %s: %s", cname.c_str(),cname.c_str(),redirect.c_str(), reason.c_str());
+                                                       user->WriteNumeric(926, cname, InspIRCd::Format("Channel %s is forbidden, redirecting to %s: %s", cname.c_str(), redirect.c_str(), reason.c_str()));
                                                        Channel::JoinUser(user, redirect);
                                                        return MOD_RES_DENY;
                                                }
                                        }
 
-                                       user->WriteNumeric(926, "%s :Channel %s is forbidden: %s", cname.c_str(),cname.c_str(),reason.c_str());
+                                       user->WriteNumeric(926, cname, InspIRCd::Format("Channel %s is forbidden: %s", cname.c_str(), reason.c_str()));
                                        return MOD_RES_DENY;
                                }
                        }
index 5eaa8c279abce71526b1ff611930d2e89f503163..44328480e3fe4bd54c4b74e28028f7bf7d64b94b 100644 (file)
@@ -117,13 +117,13 @@ class DNSBLResolver : public DNS::Request
                                {
                                        if (!ConfEntry->ident.empty())
                                        {
-                                               them->WriteNumeric(304, ":Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
+                                               them->WriteNumeric(304, "Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
                                                them->ChangeIdent(ConfEntry->ident);
                                        }
 
                                        if (!ConfEntry->host.empty())
                                        {
-                                               them->WriteNumeric(304, ":Your host has been set to " + ConfEntry->host + " because you matched " + reason);
+                                               them->WriteNumeric(304, "Your host has been set to " + ConfEntry->host + " because you matched " + reason);
                                                them->ChangeDisplayedHost(ConfEntry->host);
                                        }
 
@@ -406,9 +406,9 @@ class ModuleDNSBL : public Module
                return MOD_RES_PASSTHRU;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'd')
+               if (stats.GetSymbol() != 'd')
                        return MOD_RES_PASSTHRU;
 
                unsigned long total_hits = 0, total_misses = 0;
@@ -418,12 +418,12 @@ class ModuleDNSBL : public Module
                        total_hits += (*i)->stats_hits;
                        total_misses += (*i)->stats_misses;
 
-                       results.push_back("304 " + user->nick + " :DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " +
+                       stats.AddRow(304, "DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " +
                                        ConvToStr((*i)->stats_hits) + " hits and " + ConvToStr((*i)->stats_misses) + " misses");
                }
 
-               results.push_back("304 " + user->nick + " :DNSBLSTATS Total hits: " + ConvToStr(total_hits));
-               results.push_back("304 " + user->nick + " :DNSBLSTATS Total misses: " + ConvToStr(total_misses));
+               stats.AddRow(304, "DNSBLSTATS Total hits: " + ConvToStr(total_hits));
+               stats.AddRow(304, "DNSBLSTATS Total misses: " + ConvToStr(total_misses));
 
                return MOD_RES_PASSTHRU;
        }
index 076445644ba2bfa84644d94eadff7b170a3ea5ed..2884385fb6cec18b068640277791e928b56ee31c 100644 (file)
@@ -32,7 +32,7 @@ class ExemptChanOps : public ListModeBase
                std::string::size_type p = word.find(':');
                if (p == std::string::npos)
                {
-                       user->WriteNumeric(955, "%s %s :Invalid exemptchanops entry, format is <restriction>:<prefix>", chan->name.c_str(), word.c_str());
+                       user->WriteNumeric(955, chan->name, word, "Invalid exemptchanops entry, format is <restriction>:<prefix>");
                        return false;
                }
 
@@ -45,7 +45,7 @@ class ExemptChanOps : public ListModeBase
 
                if (!ServerInstance->Modes->FindMode(restriction, MODETYPE_CHANNEL))
                {
-                       user->WriteNumeric(955, "%s %s :Unknown restriction", chan->name.c_str(), restriction.c_str());
+                       user->WriteNumeric(955, chan->name, restriction, "Unknown restriction");
                        return false;
                }
 
@@ -54,17 +54,17 @@ class ExemptChanOps : public ListModeBase
 
        void TellListTooLong(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(959, "%s %s :Channel exemptchanops list is full", chan->name.c_str(), word.c_str());
+               user->WriteNumeric(959, chan->name, word, "Channel exemptchanops list is full");
        }
 
        void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(957, "%s :The word %s is already on the exemptchanops list", chan->name.c_str(), word.c_str());
+               user->WriteNumeric(957, chan->name, InspIRCd::Format("The word %s is already on the exemptchanops list", word.c_str()));
        }
 
        void TellNotSet(User* user, Channel* chan, std::string &word)
        {
-               user->WriteNumeric(958, "%s :No such exemptchanops word is set", chan->name.c_str());
+               user->WriteNumeric(958, chan->name, "No such exemptchanops word is set");
        }
 };
 
index 34d0bebb3cce91d865a14cde6f912b69ee4175b6..a3e30ecb463f4137f3cdbb09051a3c4bf5791ede 100644 (file)
@@ -187,7 +187,7 @@ class ModuleFilter : public Module
        FilterResult DecodeFilter(const std::string &data);
        void OnSyncNetwork(ProtocolInterface::Server& server) CXX11_OVERRIDE;
        void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) CXX11_OVERRIDE;
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE;
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE;
        ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE;
        void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
        bool AppliesToMe(User* user, FilterResult* filter, int flags);
@@ -343,14 +343,14 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, void* dest, int target_type
                {
                        ServerInstance->SNO->WriteGlobalSno('a', "FILTER: "+user->nick+" had their message filtered, target was "+target+": "+f->reason);
                        if (target_type == TYPE_CHANNEL)
-                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Message to channel blocked and opers notified (%s)", target.c_str(), f->reason.c_str());
+                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, target, InspIRCd::Format("Message to channel blocked and opers notified (%s)", f->reason.c_str()));
                        else
                                user->WriteNotice("Your message to "+target+" was blocked and opers notified: "+f->reason);
                }
                else if (f->action == FA_SILENT)
                {
                        if (target_type == TYPE_CHANNEL)
-                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Message to channel blocked (%s)", target.c_str(), f->reason.c_str());
+                               user->WriteNumeric(ERR_CANNOTSENDTOCHAN, target, InspIRCd::Format("Message to channel blocked (%s)", f->reason.c_str()));
                        else
                                user->WriteNotice("Your message to "+target+" was blocked: "+f->reason);
                }
@@ -693,21 +693,21 @@ void ModuleFilter::ReadFilters()
        }
 }
 
-ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results)
+ModResult ModuleFilter::OnStats(Stats::Context& stats)
 {
-       if (symbol == 's')
+       if (stats.GetSymbol() == 's')
        {
                for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); i++)
                {
-                       results.push_back("223 "+user->nick+" :"+RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
+                       stats.AddRow(223, RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
                }
                for (ExemptTargetSet::const_iterator i = exemptedchans.begin(); i != exemptedchans.end(); ++i)
                {
-                       results.push_back("223 "+user->nick+" :EXEMPT "+(*i));
+                       stats.AddRow(223, "EXEMPT "+(*i));
                }
                for (ExemptTargetSet::const_iterator i = exemptednicks.begin(); i != exemptednicks.end(); ++i)
                {
-                       results.push_back("223 "+user->nick+" :EXEMPT "+(*i));
+                       stats.AddRow(223, "EXEMPT "+(*i));
                }
        }
        return MOD_RES_PASSTHRU;
index 294187fa5c81bea51b6b8d775c0c72fa374861ac..b71f29fcccef6527c2fdc50b27ec5bfdbec867c0 100644 (file)
@@ -44,11 +44,11 @@ class CommandGloadmodule : public Command
                        if (ServerInstance->Modules->Load(parameters[0].c_str()))
                        {
                                ServerInstance->SNO->WriteToSnoMask('a', "NEW MODULE '%s' GLOBALLY LOADED BY '%s'",parameters[0].c_str(), user->nick.c_str());
-                               user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module successfully loaded.", parameters[0].c_str());
+                               user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "Module successfully loaded.");
                        }
                        else
                        {
-                               user->WriteNumeric(ERR_CANTLOADMODULE, "%s :%s", parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+                               user->WriteNumeric(ERR_CANTLOADMODULE, parameters[0], ServerInstance->Modules->LastError());
                        }
                }
                else
@@ -79,7 +79,7 @@ class CommandGunloadmodule : public Command
                if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") &&
                        InspIRCd::Match(parameters[0], "core_*.so", ascii_case_insensitive_map))
                {
-                       user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload core commands!", parameters[0].c_str());
+                       user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], "You cannot unload core commands!");
                        return CMD_FAILURE;
                }
 
@@ -93,16 +93,15 @@ class CommandGunloadmodule : public Command
                                if (ServerInstance->Modules->Unload(m))
                                {
                                        ServerInstance->SNO->WriteToSnoMask('a', "MODULE '%s' GLOBALLY UNLOADED BY '%s'",parameters[0].c_str(), user->nick.c_str());
-                                       user->SendText(":%s 973 %s %s :Module successfully unloaded.",
-                                               ServerInstance->Config->ServerName.c_str(), user->nick.c_str(), parameters[0].c_str());
+                                       user->WriteRemoteNumeric(973, parameters[0], "Module successfully unloaded.");
                                }
                                else
                                {
-                                       user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :%s", parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+                                       user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], ServerInstance->Modules->LastError());
                                }
                        }
                        else
-                               user->SendText(":%s %03d %s %s :No such module", ServerInstance->Config->ServerName.c_str(), ERR_CANTUNLOADMODULE, user->nick.c_str(), parameters[0].c_str());
+                               user->WriteRemoteNumeric(ERR_CANTUNLOADMODULE, parameters[0], "No such module");
                }
                else
                        ServerInstance->SNO->WriteToSnoMask('a', "MODULE '%s' GLOBAL UNLOAD BY '%s' (not unloaded here)",parameters[0].c_str(), user->nick.c_str());
@@ -140,7 +139,7 @@ class CommandGreloadmodule : public Command
                        }
                        else
                        {
-                               user->WriteNumeric(RPL_LOADEDMODULE, "%s :Could not find module by that name", parameters[0].c_str());
+                               user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "Could not find module by that name");
                                return CMD_FAILURE;
                        }
                }
index ef9ae5e22e8e7d8ffcccaa8396f9c04bd6723e54..95f69774bb0cad6cc543f7aa964b1688ac361342 100644 (file)
@@ -57,15 +57,15 @@ class CommandHelpop : public Command
                if (parameter == "index")
                {
                        /* iterate over all helpop items */
-                       user->WriteNumeric(290, ":HELPOP topic index");
+                       user->WriteNumeric(290, "HELPOP topic index");
                        for (HelpopMap::const_iterator iter = helpop_map.begin(); iter != helpop_map.end(); iter++)
-                               user->WriteNumeric(292, ":  %s", iter->first.c_str());
-                       user->WriteNumeric(292, ":*** End of HELPOP topic index");
+                               user->WriteNumeric(292, InspIRCd::Format("  %s", iter->first.c_str()));
+                       user->WriteNumeric(292, "*** End of HELPOP topic index");
                }
                else
                {
-                       user->WriteNumeric(290, ":*** HELPOP for %s", parameter.c_str());
-                       user->WriteNumeric(292, ": -");
+                       user->WriteNumeric(290, InspIRCd::Format("*** HELPOP for %s", parameter.c_str()));
+                       user->WriteNumeric(292, " -");
 
                        HelpopMap::const_iterator iter = helpop_map.find(parameter);
 
@@ -82,13 +82,13 @@ class CommandHelpop : public Command
                        {
                                // Writing a blank line will not work with some clients
                                if (token.empty())
-                                       user->WriteNumeric(292, ": ");
+                                       user->WriteNumeric(292, ' ');
                                else
-                                       user->WriteNumeric(292, ":%s", token.c_str());
+                                       user->WriteNumeric(292, token);
                        }
 
-                       user->WriteNumeric(292, ": -");
-                       user->WriteNumeric(292, ":*** End of HELPOP");
+                       user->WriteNumeric(292, " -");
+                       user->WriteNumeric(292, "*** End of HELPOP");
                }
                return CMD_SUCCESS;
        }
@@ -145,7 +145,7 @@ class ModuleHelpop : public Module, public Whois::EventListener
                {
                        if (whois.GetTarget()->IsModeSet(ho))
                        {
-                               whois.SendLine(310, ":is available for help.");
+                               whois.SendLine(310, "is available for help.");
                        }
                }
 
index 431b7b9688da80547a9c43d32d0faeaf47692593..08caae6b2c75e1fbcd229f0949eaf4e46800c827 100644 (file)
@@ -49,14 +49,14 @@ class ModuleHideChans : public Module, public Whois::LineEventListener
                AffectsOpers = ServerInstance->Config->ConfValue("hidechans")->getBool("affectsopers");
        }
 
-       ModResult OnWhoisLine(Whois::Context& whois, unsigned int& numeric, std::string& text) CXX11_OVERRIDE
+       ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
                /* always show to self */
                if (whois.IsSelfWhois())
                        return MOD_RES_PASSTHRU;
 
                /* don't touch anything except 319 */
-               if (numeric != 319)
+               if (numeric.GetNumeric() != 319)
                        return MOD_RES_PASSTHRU;
 
                /* don't touch if -I */
index cde8371fc6293d681fbb48774dd84931d3b5f2f8..97173c14b03513dbe8b67935a7cedbe9864f2043 100644 (file)
@@ -46,7 +46,7 @@ class ListWatcher : public ModeWatcher
                if (user->HasPrivPermission("channels/auspex"))
                        return true;
 
-               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You do not have access to view the %s list", chan->name.c_str(), GetModeName().c_str());
+               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, chan->name, InspIRCd::Format("You do not have access to view the %s list", GetModeName().c_str()));
                return false;
        }
 };
index 03f6745ee9796ed887b4ff843a3a10e9b2aa9d1b..0fa5206eaea2eb5b44c142534f900245d3863bde 100644 (file)
@@ -71,9 +71,9 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                        hm.opercount--;
        }
 
-       ModResult OnNumeric(User* user, unsigned int numeric, const std::string& text) CXX11_OVERRIDE
+       ModResult OnNumeric(User* user, const Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
-               if (numeric != 252 || active || user->HasPrivPermission("users/auspex"))
+               if (numeric.GetNumeric() != 252 || active || user->HasPrivPermission("users/auspex"))
                        return MOD_RES_PASSTHRU;
 
                // If there are no visible operators then we shouldn't send the numeric.
@@ -81,18 +81,18 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                if (opercount)
                {
                        active = true;
-                       user->WriteNumeric(252, "%lu :operator(s) online", opercount);
+                       user->WriteNumeric(252, opercount, "operator(s) online");
                        active = false;
                }
                return MOD_RES_DENY;
        }
 
-       ModResult OnWhoisLine(Whois::Context& whois, unsigned int& numeric, std::string& text) CXX11_OVERRIDE
+       ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
                /* Dont display numeric 313 (RPL_WHOISOPER) if they have +H set and the
                 * person doing the WHOIS is not an oper
                 */
-               if (numeric != 313)
+               if (numeric.GetNumeric() != 313)
                        return MOD_RES_PASSTHRU;
 
                if (!whois.GetTarget()->IsModeSet(hm))
@@ -122,9 +122,9 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                }
        }
 
-       ModResult OnStats(char symbol, User* user, string_list& results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'P')
+               if (stats.GetSymbol() != 'P')
                        return MOD_RES_PASSTHRU;
 
                unsigned int count = 0;
@@ -132,15 +132,15 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                for (UserManager::OperList::const_iterator i = opers.begin(); i != opers.end(); ++i)
                {
                        User* oper = *i;
-                       if (!oper->server->IsULine() && (user->IsOper() || !oper->IsModeSet(hm)))
+                       if (!oper->server->IsULine() && (stats.GetSource()->IsOper() || !oper->IsModeSet(hm)))
                        {
                                LocalUser* lu = IS_LOCAL(oper);
-                               results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
+                               stats.AddRow(249, oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
                                                (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable"));
                                count++;
                        }
                }
-               results.push_back("249 "+user->nick+" :"+ConvToStr(count)+" OPER(s)");
+               stats.AddRow(249, ConvToStr(count)+" OPER(s)");
 
                return MOD_RES_DENY;
        }
index 541e080f56a7ad999f4c7632fe85f88f5dfe5533..eb8e856acde4e150e28aab4917c916ed18673a31 100644 (file)
@@ -109,10 +109,12 @@ class ModuleHttpStats : public Module, public HTTPRequestEventListener
                                data << "<uptime><boot_time_t>" << ServerInstance->startup_time << "</boot_time_t></uptime>";
 
                                data << "<isupport>";
-                               const std::vector<std::string>& isupport = ServerInstance->ISupport.GetLines();
-                               for (std::vector<std::string>::const_iterator it = isupport.begin(); it != isupport.end(); it++)
+                               const std::vector<Numeric::Numeric>& isupport = ServerInstance->ISupport.GetLines();
+                               for (std::vector<Numeric::Numeric>::const_iterator i = isupport.begin(); i != isupport.end(); ++i)
                                {
-                                       data << Sanitize(*it) << std::endl;
+                                       const Numeric::Numeric& num = *i;
+                                       for (std::vector<std::string>::const_iterator j = num.GetParams().begin(); j != num.GetParams().end()-1; ++j)
+                                               data << "<token>" << Sanitize(*j) << "</token>" << std::endl;
                                }
                                data << "</isupport></general><xlines>";
                                std::vector<std::string> xltypes = ServerInstance->XLines->GetAllTypes();
index 52802f168884fd2a1783b2b41b0cae08b984b001..56e109c1a828697fc93f0510dfce336f35e7dcab 100644 (file)
@@ -95,7 +95,7 @@ class JoinFlood : public ParamMode<JoinFlood, SimpleExtItem<joinfloodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter",channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
@@ -104,7 +104,7 @@ class JoinFlood : public ParamMode<JoinFlood, SimpleExtItem<joinfloodsettings> >
                unsigned int nsecs = ConvToInt(parameter.substr(colon+1));
                if ((njoins<1) || (nsecs<1))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter",channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
@@ -136,7 +136,7 @@ class ModuleJoinFlood : public Module
                        joinfloodsettings *f = jf.ext.get(chan);
                        if (f && f->islocked())
                        {
-                               user->WriteNumeric(609, "%s :This channel is temporarily unavailable (+j). Please try again later.",chan->name.c_str());
+                               user->WriteNumeric(609, chan->name, "This channel is temporarily unavailable (+j). Please try again later.");
                                return MOD_RES_DENY;
                        }
                }
index e9c07f45fda18816a003a1017d8f3d150a7ff184..33b9bcd3567d4beb423ebce200ca131599376d1a 100644 (file)
@@ -116,7 +116,7 @@ class CommandJumpserver : public Command
                                        ++i;
                                        if (!t->IsOper())
                                        {
-                                               t->WriteNumeric(RPL_REDIR, "%s %d :Please use this Server/Port instead", parameters[0].c_str(), GetPort(t));
+                                               t->WriteNumeric(RPL_REDIR, parameters[0], GetPort(t), "Please use this Server/Port instead");
                                                ServerInstance->Users->QuitUser(t, reason);
                                                n_done++;
                                        }
@@ -160,8 +160,7 @@ class ModuleJumpServer : public Module
                if (js.redirect_new_users)
                {
                        int port = js.GetPort(user);
-                       user->WriteNumeric(RPL_REDIR, "%s %d :Please use this Server/Port instead",
-                               js.redirect_to.c_str(), port);
+                       user->WriteNumeric(RPL_REDIR, js.redirect_to, port, "Please use this Server/Port instead");
                        ServerInstance->Users->QuitUser(user, js.reason);
                        return MOD_RES_PASSTHRU;
                }
index b8a7766675e8e191ea0cb45331ba495058f695d9..ad8bfdcb6d1c60b283f8f604d8c341cb0f288907 100644 (file)
@@ -132,7 +132,7 @@ public:
                        const KickRejoinData* data = kr.ext.get(chan);
                        if ((data) && (!data->canjoin(user)))
                        {
-                               user->WriteNumeric(ERR_DELAYREJOIN, "%s :You must wait %u seconds after being kicked to rejoin (+J)", chan->name.c_str(), data->delay);
+                               user->WriteNumeric(ERR_DELAYREJOIN, chan, InspIRCd::Format("You must wait %u seconds after being kicked to rejoin (+J)", data->delay));
                                return MOD_RES_DENY;
                        }
                }
index 26397bc9c17f94e135e4f2604a173e30480bcd81..545c2dc14c11232202959ce7e3916a55578f15f9 100644 (file)
@@ -45,25 +45,25 @@ class CommandKnock : public Command
                Channel* c = ServerInstance->FindChan(parameters[0]);
                if (!c)
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
                if (c->HasUser(user))
                {
-                       user->WriteNumeric(ERR_KNOCKONCHAN, "%s :Can't KNOCK on %s, you are already on that channel.", c->name.c_str(), c->name.c_str());
+                       user->WriteNumeric(ERR_KNOCKONCHAN, c->name, InspIRCd::Format("Can't KNOCK on %s, you are already on that channel.", c->name.c_str()));
                        return CMD_FAILURE;
                }
 
                if (c->IsModeSet(noknockmode))
                {
-                       user->WriteNumeric(480, ":Can't KNOCK on %s, +K is set.", c->name.c_str());
+                       user->WriteNumeric(480, InspIRCd::Format("Can't KNOCK on %s, +K is set.", c->name.c_str()));
                        return CMD_FAILURE;
                }
 
                if (!c->IsModeSet(inviteonlymode))
                {
-                       user->WriteNumeric(ERR_CHANOPEN, "%s :Can't KNOCK on %s, channel is not invite only so knocking is pointless!", c->name.c_str(), c->name.c_str());
+                       user->WriteNumeric(ERR_CHANOPEN, c->name, InspIRCd::Format("Can't KNOCK on %s, channel is not invite only so knocking is pointless!", c->name.c_str()));
                        return CMD_FAILURE;
                }
 
index 65b9aa036349141cdcfe4164a37b1ae1f0a6b589..ffcc04682d639b94c6f9eeeb306e6a662fdda6d2 100644 (file)
@@ -44,7 +44,7 @@ class CommandLockserv : public Command
                }
 
                locked = true;
-               user->WriteNumeric(988, "%s :Closed for new connections", user->server->GetName().c_str());
+               user->WriteNumeric(988, user->server->GetName(), "Closed for new connections");
                ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used LOCKSERV to temporarily disallow new connections", user->nick.c_str());
                return CMD_SUCCESS;
        }
@@ -69,7 +69,7 @@ class CommandUnlockserv : public Command
                }
 
                locked = false;
-               user->WriteNumeric(989, "%s :Open for new connections", user->server->GetName().c_str());
+               user->WriteNumeric(989, user->server->GetName(), "Open for new connections");
                ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used UNLOCKSERV to allow new connections", user->nick.c_str());
                return CMD_SUCCESS;
        }
index 1faf3bfb99e5a1d04c449b9798201088f72edb6d..c5c872169ea1a2b360ff24d60a240e756a790b05 100644 (file)
@@ -73,7 +73,7 @@ class MsgFlood : public ParamMode<MsgFlood, SimpleExtItem<floodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter", channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
@@ -84,7 +84,7 @@ class MsgFlood : public ParamMode<MsgFlood, SimpleExtItem<floodsettings> >
 
                if ((nlines<2) || (nsecs<1))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter", channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
index 9b0fa8dab0b8438a49fe8e1b83f608bc936ea3ba..d3ab5b9fd2af0700fb6b26e2e95cad0b59183020 100644 (file)
@@ -50,8 +50,7 @@ class ModuleMLock : public Module
                std::string::size_type p = mlock_str->find(mode);
                if (p != std::string::npos)
                {
-                       source->WriteNumeric(742, "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy",
-                                            channel->name.c_str(), mode, mlock_str->c_str());
+                       source->WriteNumeric(742, channel->name, mode, *mlock_str, "MODE cannot be set due to channel having an active MLOCK restriction policy");
                        return MOD_RES_DENY;
                }
 
index 139c70e7646697016ac9faaadc08eda376fd73f5..b2e06f191df7858abced7d89bbe7fc9a4440135a 100644 (file)
@@ -285,7 +285,7 @@ class CommandMonitor : public SplitCommand
                        if (result == IRCv3::Monitor::Manager::WR_TOOMANY)
                        {
                                // List is full, send error which includes the remaining nicks that were not processed
-                               user->WriteNumeric(ERR_MONLISTFULL, "%u %s%s%s :Monitor list is full", maxmonitor, nick.c_str(), (ss.StreamEnd() ? "" : ","), ss.GetRemaining().c_str());
+                               user->WriteNumeric(ERR_MONLISTFULL, maxmonitor, InspIRCd::Format("%s%s%s", nick.c_str(), (ss.StreamEnd() ? "" : ","), ss.GetRemaining().c_str()), "Monitor list is full");
                                break;
                        }
                        else if (result != IRCv3::Monitor::Manager::WR_OK)
@@ -346,7 +346,7 @@ class CommandMonitor : public SplitCommand
                                out.Add(entry->GetNick());
                        }
                        out.Flush();
-                       user->WriteNumeric(RPL_ENDOFMONLIST, ":End of MONITOR list");
+                       user->WriteNumeric(RPL_ENDOFMONLIST, "End of MONITOR list");
                }
                else if (subcmd == 'S')
                {
index 72c4acd47ca12c57baf8f577880542dcab279f20..c9caf6a6ad8e7345b7e7949886091483505dc214 100644 (file)
@@ -36,7 +36,7 @@ class ModuleQuietBan : public Module
                Channel* chan = static_cast<Channel*>(dest);
                if (chan->GetExtBanStatus(user, 'm') == MOD_RES_DENY && chan->GetPrefixValue(user) < VOICE_VALUE)
                {
-                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're muted)", chan->name.c_str());
+                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're muted)");
                        return MOD_RES_DENY;
                }
 
index 617ee43b368f5a3f6f48e588e4ab15ea5f227b35..10bef981a3bee03425bbce9dfca8671103d1a277 100644 (file)
@@ -39,7 +39,7 @@ static void DisplayList(User* user, Channel* channel)
        }
        const std::string line = ":" + ServerInstance->Config->ServerName + " 961 " + user->nick + " " + channel->name;
        user->SendText(line, items);
-       user->WriteNumeric(960, "%s :End of mode list", channel->name.c_str());
+       user->WriteNumeric(960, channel->name, "End of mode list");
 }
 
 class CommandProp : public Command
@@ -55,7 +55,7 @@ class CommandProp : public Command
                Channel* const chan = ServerInstance->FindChan(parameters[0]);
                if (!chan)
                {
-                       src->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       src->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
index cade0b1db751ace5a5dd7829510b0d58275094e5..0af1041f913225757982c3fd544d0898a7de1ac6 100644 (file)
@@ -91,7 +91,7 @@ class NickFlood : public ParamMode<NickFlood, SimpleExtItem<nickfloodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter",channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
@@ -101,7 +101,7 @@ class NickFlood : public ParamMode<NickFlood, SimpleExtItem<nickfloodsettings> >
 
                if ((nnicks<1) || (nsecs<1))
                {
-                       source->WriteNumeric(608, "%s :Invalid flood parameter",channel->name.c_str());
+                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
                        return MODEACTION_DENY;
                }
 
@@ -142,7 +142,7 @@ class ModuleNickFlood : public Module
 
                                if (f->islocked())
                                {
-                                       user->WriteNumeric(ERR_CANTCHANGENICK, ":%s has been locked for nickchanges for 60 seconds because there have been more than %u nick changes in %u seconds", channel->name.c_str(), f->nicks, f->secs);
+                                       user->WriteNumeric(ERR_CANTCHANGENICK, InspIRCd::Format("%s has been locked for nickchanges for 60 seconds because there have been more than %u nick changes in %u seconds", channel->name.c_str(), f->nicks, f->secs));
                                        return MOD_RES_DENY;
                                }
 
index a99628bf1258396e1bb5d82f21935f4755a9a155..a517e95acb7080e5f14cc9515ce40aa6f47b0a3f 100644 (file)
@@ -55,7 +55,7 @@ class CommandNicklock : public Command
                                return CMD_FAILURE;
                        }
 
-                       user->WriteNumeric(947, "%s :Nickname now locked.", parameters[1].c_str());
+                       user->WriteNumeric(947, parameters[1], "Nickname now locked.");
                }
 
                /* If we made it this far, extend the user */
@@ -114,13 +114,11 @@ class CommandNickunlock : public Command
                        if (locked.set(target, 0))
                        {
                                ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used NICKUNLOCK on "+target->nick);
-                               user->SendText(":%s 945 %s %s :Nickname now unlocked.",
-                                       ServerInstance->Config->ServerName.c_str(),user->nick.c_str(),target->nick.c_str());
+                               user->WriteRemoteNumeric(945, target->nick, "Nickname now unlocked.");
                        }
                        else
                        {
-                               user->SendText(":%s 946 %s %s :This user's nickname is not locked.",
-                                       ServerInstance->Config->ServerName.c_str(),user->nick.c_str(),target->nick.c_str());
+                               user->WriteRemoteNumeric(946, target->nick, "This user's nickname is not locked.");
                                return CMD_FAILURE;
                        }
                }
@@ -159,7 +157,7 @@ class ModuleNickLock : public Module
        {
                if (locked.get(user))
                {
-                       user->WriteNumeric(ERR_CANTCHANGENICK, ":You cannot change your nickname (your nick is locked)");
+                       user->WriteNumeric(ERR_CANTCHANGENICK, "You cannot change your nickname (your nick is locked)");
                        return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index 953557d90ff165549acab2a3fd2a76734a8186cf..49b53ee950f93af1eccfc93fede8f4f96b0e51e8 100644 (file)
@@ -56,7 +56,7 @@ class ModuleNoCTCP : public Module
 
                        if (!c->GetExtBanStatus(user, 'C').check(!c->IsModeSet(nc)))
                        {
-                               user->WriteNumeric(ERR_NOCTCPALLOWED, "%s :Can't send CTCP to channel (+C set)", c->name.c_str());
+                               user->WriteNumeric(ERR_NOCTCPALLOWED, c->name, "Can't send CTCP to channel (+C set)");
                                return MOD_RES_DENY;
                        }
                }
index 0acf841187a7f3e91c0e4039fd377b25ed9040e1..fb3455567b53621ca12b1e7809e384601c980775 100644 (file)
@@ -48,7 +48,7 @@ class ModuleNoKicks : public Module
                if (!memb->chan->GetExtBanStatus(source, 'Q').check(!memb->chan->IsModeSet(nk)))
                {
                        // Can't kick with Q in place, not even opers with override, and founders
-                       source->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :Can't kick user %s from channel (+Q set)", memb->chan->name.c_str(), memb->user->nick.c_str());
+                       source->WriteNumeric(ERR_CHANOPRIVSNEEDED, memb->chan->name, InspIRCd::Format("Can't kick user %s from channel (+Q set)", memb->user->nick.c_str()));
                        return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index 63815f2bf7ef329675082187470e1ff14cbac773..d4da3e95139b251dc5f8b7add2321d5c55579c6c 100644 (file)
@@ -62,8 +62,8 @@ class ModuleNoNickChange : public Module
 
                        if (!curr->GetExtBanStatus(user, 'N').check(!curr->IsModeSet(nn)))
                        {
-                               user->WriteNumeric(ERR_CANTCHANGENICK, ":Can't change nickname while on %s (+N is set)",
-                                       curr->name.c_str());
+                               user->WriteNumeric(ERR_CANTCHANGENICK, InspIRCd::Format("Can't change nickname while on %s (+N is set)",
+                                       curr->name.c_str()));
                                return MOD_RES_DENY;
                        }
                }
index cab367ad9e6abe49e879a275911a1feb79d57c3a..3d6d0bb099422808e9f8af07c8fe385e50fbc2db 100644 (file)
@@ -55,7 +55,7 @@ class ModuleNoNotice : public Module
                                        return MOD_RES_PASSTHRU;
                                else
                                {
-                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Can't send NOTICE to channel (+T set)", c->name.c_str());
+                                       user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send NOTICE to channel (+T set)");
                                        return MOD_RES_DENY;
                                }
                        }
index 1444f93ad691a3ab37174b02e10f51e0dfdcf755..88b63bef25f405d0f25c3d2360566a04a961eb26 100644 (file)
@@ -146,7 +146,7 @@ class ModuleOjoin : public Module
                if (source == memb->user)
                        return MOD_RES_PASSTHRU;
 
-               source->WriteNumeric(ERR_RESTRICTED, memb->chan->name+" :Can't kick "+memb->user->nick+" as they're on official network business.");
+               source->WriteNumeric(ERR_RESTRICTED, memb->chan->name, "Can't kick "+memb->user->nick+" as they're on official network business.");
                return MOD_RES_DENY;
        }
 
index 3c6b4cd59c96f72de160d9a208da70b6ef9bc009..0b074ebab4247a183ea2360d7def1f986015a15b 100644 (file)
@@ -44,8 +44,7 @@ class ModuleOperChans : public Module
        {
                if (chan && chan->IsModeSet(oc) && !user->IsOper())
                {
-                       user->WriteNumeric(ERR_CANTJOINOPERSONLY, "%s :Only IRC operators may join %s (+O is set)",
-                               chan->name.c_str(), chan->name.c_str());
+                       user->WriteNumeric(ERR_CANTJOINOPERSONLY, chan->name, InspIRCd::Format("Only IRC operators may join %s (+O is set)", chan->name.c_str()));
                        return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index ac7178a93385ac12881ef467b481997d54e19a40..bf758b1f76812d894c2693a290110c83d8d46eaa 100644 (file)
@@ -44,7 +44,7 @@ class ModuleOperLevels : public Module
                                {
                                        if (IS_LOCAL(source)) ServerInstance->SNO->WriteGlobalSno('a', "Oper %s (level %ld) attempted to /kill a higher oper: %s (level %ld): Reason: %s",source->nick.c_str(),source_level,dest->nick.c_str(),dest_level,reason.c_str());
                                        dest->WriteNotice("*** Oper " + source->nick + " attempted to /kill you!");
-                                       source->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Oper %s is a higher level than you", dest->nick.c_str());
+                                       source->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Oper %s is a higher level than you", dest->nick.c_str()));
                                        return MOD_RES_DENY;
                                }
                        }
index bd1853d43da43a37a78739e1420aa9ddc47d6e97..010f4ae58a405c2e7df150962ab636e5b85dba90 100644 (file)
@@ -50,21 +50,20 @@ class CommandOpermotd : public Command
 
        void ShowOperMOTD(User* user)
        {
-               const std::string& servername = ServerInstance->Config->ServerName;
                if (opermotd.empty())
                {
-                       user->SendText(":%s 455 %s :OPERMOTD file is missing", servername.c_str(), user->nick.c_str());
+                       user->WriteRemoteNumeric(455, "OPERMOTD file is missing");
                        return;
                }
 
-               user->SendText(":%s 375 %s :- IRC Operators Message of the Day", servername.c_str(), user->nick.c_str());
+               user->WriteRemoteNumeric(375, "- IRC Operators Message of the Day");
 
                for (file_cache::const_iterator i = opermotd.begin(); i != opermotd.end(); ++i)
                {
-                       user->SendText(":%s 372 %s :- %s", servername.c_str(), user->nick.c_str(), i->c_str());
+                       user->WriteRemoteNumeric(372, InspIRCd::Format("- %s", i->c_str()));
                }
 
-               user->SendText(":%s 376 %s :- End of OPERMOTD", servername.c_str(), user->nick.c_str());
+               user->WriteRemoteNumeric(376, "- End of OPERMOTD");
        }
 };
 
index e822676bf7357c102233cbcd69f5768110a4daf7..b14de9ff91eeecda7d8eda473c4a858f2354db7f 100644 (file)
@@ -38,7 +38,7 @@ class Redirect : public ParamMode<Redirect, LocalStringExt>
                {
                        if (!ServerInstance->IsChannel(parameter))
                        {
-                               source->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name", parameter.c_str());
+                               source->WriteNumeric(ERR_NOSUCHCHANNEL, parameter, "Invalid channel name");
                                return MODEACTION_DENY;
                        }
                }
@@ -48,12 +48,12 @@ class Redirect : public ParamMode<Redirect, LocalStringExt>
                        Channel* c = ServerInstance->FindChan(parameter);
                        if (!c)
                        {
-                               source->WriteNumeric(690, ":Target channel %s must exist to be set as a redirect.",parameter.c_str());
+                               source->WriteNumeric(690, InspIRCd::Format("Target channel %s must exist to be set as a redirect.", parameter.c_str()));
                                return MODEACTION_DENY;
                        }
                        else if (c->GetPrefixValue(source) < OP_VALUE)
                        {
-                               source->WriteNumeric(690, ":You must be opped on %s to set it as a redirect.",parameter.c_str());
+                               source->WriteNumeric(690, InspIRCd::Format("You must be opped on %s to set it as a redirect.", parameter.c_str()));
                                return MODEACTION_DENY;
                        }
                }
@@ -119,19 +119,19 @@ class ModuleRedirect : public Module
                                        Channel* destchan = ServerInstance->FindChan(channel);
                                        if (destchan && destchan->IsModeSet(re))
                                        {
-                                               user->WriteNumeric(470, "%s * :You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.", cname.c_str());
+                                               user->WriteNumeric(470, cname, '*', "You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.");
                                                return MOD_RES_DENY;
                                        }
                                        /* We check the bool value here to make sure we have it enabled, if we don't then
                                                usermode +L might be assigned to something else. */
                                        if (UseUsermode && user->IsModeSet(re_u))
                                        {
-                                               user->WriteNumeric(470, "%s %s :Force redirection stopped.", cname.c_str(), channel.c_str());
+                                               user->WriteNumeric(470, cname, channel, "Force redirection stopped.");
                                                return MOD_RES_DENY;
                                        }
                                        else
                                        {
-                                               user->WriteNumeric(470, "%s %s :You may not join this channel, so you are automatically being transferred to the redirect channel.", cname.c_str(), channel.c_str());
+                                               user->WriteNumeric(470, cname, channel, "You may not join this channel, so you are automatically being transferred to the redirect channel.");
                                                Channel::JoinUser(user, channel);
                                                return MOD_RES_DENY;
                                        }
index 0ffe5e085010f43a62bdc846d4d2334e11c1f553..78b20ef6b9f96206c1711f65176431d59039218c 100644 (file)
@@ -49,7 +49,7 @@ class ModuleRegOnlyCreate : public Module
                        return MOD_RES_PASSTHRU;
 
                // XXX. there may be a better numeric for this..
-               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must have a registered nickname to create a new channel", cname.c_str());
+               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, cname, "You must have a registered nickname to create a new channel");
                return MOD_RES_DENY;
        }
 
index 8d0009d71330baca2816c421a412c102d7cbbadf..5b0efe2a27a6e14c095d06a7c92fbb4af6cafc6e 100644 (file)
@@ -76,7 +76,7 @@ class RemoveBase : public Command
                /* Fix by brain - someone needs to learn to validate their input! */
                if ((!target) || (target->registered != REG_ALL) || (!channel))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !channel ? channame.c_str() : username.c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(channel ? username.c_str() : channame.c_str()));
                        return CMD_FAILURE;
                }
 
@@ -88,7 +88,7 @@ class RemoveBase : public Command
 
                if (target->server->IsULine())
                {
-                       user->WriteNumeric(482, "%s :Only a u-line may remove a u-line from a channel.", channame.c_str());
+                       user->WriteNumeric(482, channame, "Only a u-line may remove a u-line from a channel.");
                        return CMD_FAILURE;
                }
 
@@ -144,7 +144,7 @@ class RemoveBase : public Command
                else
                {
                        /* m_nokicks.so was loaded and +Q was set, block! */
-                       user->WriteNumeric(ERR_RESTRICTED, "%s :Can't remove user %s from channel (nokicks mode is set)", channel->name.c_str(), target->nick.c_str());
+                       user->WriteNumeric(ERR_RESTRICTED, channel->name, InspIRCd::Format("Can't remove user %s from channel (nokicks mode is set)", target->nick.c_str()));
                        return CMD_FAILURE;
                }
 
index 9e660e8ed16f0d1843b480384ff5a6a772fdc212..9c7ed1213ee2cfdfa230ae0bc1d5af0c6ef831d7 100644 (file)
@@ -47,7 +47,7 @@ class ModuleRestrictChans : public Module
                        // user is not an oper and its not in the allow list
                        if ((!user->IsOper()) && (allowchans.find(cname) == allowchans.end()))
                        {
-                               user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Only IRC operators may create new channels", cname.c_str());
+                               user->WriteNumeric(ERR_BANNEDFROMCHAN, cname, "Only IRC operators may create new channels");
                                return MOD_RES_DENY;
                        }
                }
index 279775d480570621bb58a9f3464c390271a0d0b7..8ca531ed5ba5ee45942ab773ab3a97a3f1538db3 100644 (file)
@@ -39,7 +39,7 @@ class ModuleRestrictMsg : public Module
                        {
                                return MOD_RES_PASSTHRU;
                        }
-                       user->WriteNumeric(ERR_CANTSENDTOUSER, "%s :You are not permitted to send private messages to this user", u->nick.c_str());
+                       user->WriteNumeric(ERR_CANTSENDTOUSER, u->nick, "You are not permitted to send private messages to this user");
                        return MOD_RES_DENY;
                }
 
index 2aee89ad282b300053dbbf4aca3adb93a49c94bc..97fbf169a2b13247fb3511fefc38a50b8b846f76 100644 (file)
@@ -284,12 +284,12 @@ class ModuleRLine : public Module
                initing = false;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'R')
+               if (stats.GetSymbol() != 'R')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("R", 223, user, results);
+               ServerInstance->XLines->InvokeStats("R", 223, stats);
                return MOD_RES_DENY;
        }
 
index d1321947b2bb54979ecf8618a19556ae05581321..9696b08a1aaea186623b55afdbe894dd9442d89a 100644 (file)
@@ -53,7 +53,7 @@ class CommandSajoin : public Command
 
                        if (dest->server->IsULine())
                        {
-                               user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
+                               user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a u-lined client");
                                return CMD_FAILURE;
                        }
                        if (IS_LOCAL(user) && !ServerInstance->IsChannel(channel))
index 911b826dc0ac25190bd74b6a04c5a0199d185d31..8fc6e741be1fab8d66fdd9e25063978111ff6b23 100644 (file)
@@ -42,7 +42,7 @@ class CommandSakick : public Command
 
                        if (dest->server->IsULine())
                        {
-                               user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
+                               user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a u-lined client");
                                return CMD_FAILURE;
                        }
 
index 8b06118ee536f05b9a152879193cca98634209cc..bcb876d5b41906c5ca20383517b807852cd210a7 100644 (file)
@@ -42,7 +42,7 @@ class CommandSamode : public Command
                        User* target = ServerInstance->FindNickOnly(parameters[0]);
                        if ((!target) || (target->registered != REG_ALL))
                        {
-                               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                                return CMD_FAILURE;
                        }
 
index ba265fddd29acaeb2d9e7059f2d2d074634e081d..fd9a825dda7f58361ae56bc02fc3b11133648905 100644 (file)
@@ -42,7 +42,7 @@ class CommandSanick : public Command
                {
                        if (target && target->server->IsULine())
                        {
-                               user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
+                               user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a u-lined client");
                                return CMD_FAILURE;
                        }
 
index 730bf08234f4aba5c6e00d704355a1ab03ff08f9..65c32cd8aa71212550752e5fb3bb5fa62bfd1ce2 100644 (file)
@@ -48,7 +48,7 @@ class CommandSapart : public Command
 
                        if (dest->server->IsULine())
                        {
-                               user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
+                               user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a u-lined client");
                                return CMD_FAILURE;
                        }
 
index fb1c67564350144ae7acefc0ff27e146098b3773..4d5ac6e22a985904306ad6343e938384b1effe50 100644 (file)
@@ -39,7 +39,7 @@ class CommandSaquit : public Command
                {
                        if (dest->server->IsULine())
                        {
-                               user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
+                               user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a u-lined client");
                                return CMD_FAILURE;
                        }
 
index 6e308693073ec727f7b84ef2cad36c380ff8e34d..e749d16b475106abd71212636a7fdb5d713ac963 100644 (file)
@@ -142,7 +142,7 @@ class SaslAuthenticator
                                this->result = this->GetSaslResult(msg[3]);
                        }
                        else if (msg[2] == "M")
-                               this->user->WriteNumeric(908, "%s :are available SASL mechanisms", msg[3].c_str());
+                               this->user->WriteNumeric(908, msg[3], "are available SASL mechanisms");
                        else
                                ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Services sent an unknown SASL message \"%s\" \"%s\"", msg[2].c_str(), msg[3].c_str());
 
@@ -194,13 +194,13 @@ class SaslAuthenticator
                switch (this->result)
                {
                 case SASL_OK:
-                       this->user->WriteNumeric(903, ":SASL authentication successful");
+                       this->user->WriteNumeric(903, "SASL authentication successful");
                        break;
                 case SASL_ABORT:
-                       this->user->WriteNumeric(906, ":SASL authentication aborted");
+                       this->user->WriteNumeric(906, "SASL authentication aborted");
                        break;
                 case SASL_FAIL:
-                       this->user->WriteNumeric(904, ":SASL authentication failed");
+                       this->user->WriteNumeric(904, "SASL authentication failed");
                        break;
                 default:
                        break;
index 4a6f855369276dba2b3fb6fd865571e0454a9713..040d86b9a46b68cf1e9bf09b79d4d7043e7457c2 100644 (file)
@@ -46,7 +46,7 @@ class CommandSATopic : public Command
                }
                else
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
        }
index f4042b8f6299cbdfec0d51a9773b6e43a0c3b84d..b6c6ce174f046570fd34e634b6ea3bf105f0b63d 100644 (file)
@@ -66,8 +66,8 @@ class ModuleSecureList : public Module
                        /* Some crap clients (read: mIRC, various java chat applets) muck up if they don't
                         * receive these numerics whenever they send LIST, so give them an empty LIST to mull over.
                         */
-                       user->WriteNumeric(RPL_LISTSTART, "Channel :Users Name");
-                       user->WriteNumeric(RPL_LISTEND, ":End of channel list.");
+                       user->WriteNumeric(RPL_LISTSTART, "Channel", "Users Name");
+                       user->WriteNumeric(RPL_LISTEND, "End of channel list.");
                        return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index 48ab511f08c8a557cccbd1af4892ea425c488e26..559f28ea87cdde4d330fe6535aae07fa0313ad00 100644 (file)
@@ -46,7 +46,7 @@ class Channel_r : public ModeHandler
                }
                else
                {
-                       source->WriteNumeric(500, ":Only a server may modify the +r channel mode");
+                       source->WriteNumeric(500, "Only a server may modify the +r channel mode");
                }
                return MODEACTION_DENY;
        }
@@ -72,7 +72,7 @@ class User_r : public ModeHandler
                }
                else
                {
-                       source->WriteNumeric(500, ":Only a server may modify the +r user mode");
+                       source->WriteNumeric(500, "Only a server may modify the +r user mode");
                }
                return MODEACTION_DENY;
        }
@@ -128,8 +128,7 @@ class AccountExtItemImpl : public AccountExtItem
                        // Logged in
                        if (IS_LOCAL(user))
                        {
-                               user->WriteNumeric(900, "%s %s :You are now logged in as %s",
-                                       user->GetFullHost().c_str(), value.c_str(), value.c_str());
+                               user->WriteNumeric(900, user->GetFullHost(), value, InspIRCd::Format("You are now logged in as %s", value.c_str()));
                        }
                }
                // If value is empty then logged out
@@ -169,13 +168,13 @@ class ModuleServicesAccount : public Module, public Whois::EventListener
 
                if (account)
                {
-                       whois.SendLine(330, "%s :is logged in as", account->c_str());
+                       whois.SendLine(330, *account, "is logged in as");
                }
 
                if (whois.GetTarget()->IsModeSet(m5))
                {
                        /* user is registered */
-                       whois.SendLine(307, ":is a registered nick");
+                       whois.SendLine(307, "is a registered nick");
                }
        }
 
@@ -202,7 +201,7 @@ class ModuleServicesAccount : public Module, public Whois::EventListener
                        if (c->IsModeSet(m2) && !is_registered && res != MOD_RES_ALLOW)
                        {
                                // user messaging a +M channel and is not registered
-                               user->WriteNumeric(477, c->name+" :You need to be identified to a registered account to message this channel");
+                               user->WriteNumeric(477, c->name, "You need to be identified to a registered account to message this channel");
                                return MOD_RES_DENY;
                        }
                }
@@ -213,7 +212,7 @@ class ModuleServicesAccount : public Module, public Whois::EventListener
                        if (u->IsModeSet(m3) && !is_registered)
                        {
                                // user messaging a +R user and is not registered
-                               user->WriteNumeric(477, u->nick +" :You need to be identified to a registered account to message this user");
+                               user->WriteNumeric(477, u->nick, "You need to be identified to a registered account to message this user");
                                return MOD_RES_DENY;
                        }
                }
@@ -268,7 +267,7 @@ class ModuleServicesAccount : public Module, public Whois::EventListener
                                if (!is_registered)
                                {
                                        // joining a +R channel and not identified
-                                       user->WriteNumeric(477, chan->name + " :You need to be identified to a registered account to join this channel");
+                                       user->WriteNumeric(477, chan->name, "You need to be identified to a registered account to join this channel");
                                        return MOD_RES_DENY;
                                }
                        }
index 0445235dc795f6821de7853ee98c0fae38b5fc89..88bde9b57014137e8fe48ee698d8ee43c70a5129 100644 (file)
@@ -62,7 +62,7 @@ class ModuleServProtectMode : public Module, public Whois::EventListener, public
        {
                if (whois.GetTarget()->IsModeSet(bm))
                {
-                       whois.SendLine(310, ":is a Network Service on " + ServerInstance->Config->Network);
+                       whois.SendLine(310, "is a Network Service on " + ServerInstance->Config->Network);
                }
        }
 
@@ -86,7 +86,7 @@ class ModuleServProtectMode : public Module, public Whois::EventListener, public
                                if (u->IsModeSet(bm) && memb && memb->hasMode(mh->GetModeChar()))
                                {
                                        /* BZZZT, Denied! */
-                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You are not permitted to remove privileges from %s services", chan->name.c_str(), ServerInstance->Config->Network.c_str());
+                                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, chan->name, InspIRCd::Format("You are not permitted to remove privileges from %s services", ServerInstance->Config->Network.c_str()));
                                        return MOD_RES_DENY;
                                }
                        }
@@ -102,7 +102,7 @@ class ModuleServProtectMode : public Module, public Whois::EventListener, public
 
                if (dst->IsModeSet(bm))
                {
-                       src->WriteNumeric(485, ":You are not permitted to kill %s services!", ServerInstance->Config->Network.c_str());
+                       src->WriteNumeric(485, InspIRCd::Format("You are not permitted to kill %s services!", ServerInstance->Config->Network.c_str()));
                        ServerInstance->SNO->WriteGlobalSno('a', src->nick+" tried to kill service "+dst->nick+" ("+reason+")");
                        return MOD_RES_DENY;
                }
@@ -113,17 +113,16 @@ class ModuleServProtectMode : public Module, public Whois::EventListener, public
        {
                if (memb->user->IsModeSet(bm))
                {
-                       src->WriteNumeric(ERR_RESTRICTED, "%s :You are not permitted to kick services",
-                               memb->chan->name.c_str());
+                       src->WriteNumeric(ERR_RESTRICTED, memb->chan->name, "You are not permitted to kick services");
                        return MOD_RES_DENY;
                }
 
                return MOD_RES_PASSTHRU;
        }
 
-       ModResult OnWhoisLine(Whois::Context& whois, unsigned int& numeric, std::string& text) CXX11_OVERRIDE
+       ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
-               return ((numeric == 319) && whois.GetTarget()->IsModeSet(bm)) ? MOD_RES_DENY : MOD_RES_PASSTHRU;
+               return ((numeric.GetNumeric() == 319) && whois.GetTarget()->IsModeSet(bm)) ? MOD_RES_DENY : MOD_RES_PASSTHRU;
        }
 };
 
index dd82aef29ebf33f19247ebad525b5bf6138225d4..4a15fd0d5a050fff9c33f6694ae94d7909aba858 100644 (file)
@@ -36,7 +36,7 @@ class CommandSetidle : public SplitCommand
                int idle = InspIRCd::Duration(parameters[0]);
                if (idle < 1)
                {
-                       user->WriteNumeric(948, ":Invalid idle time.");
+                       user->WriteNumeric(948, "Invalid idle time.");
                        return CMD_FAILURE;
                }
                user->idle_lastmsg = (ServerInstance->Time() - idle);
@@ -44,7 +44,7 @@ class CommandSetidle : public SplitCommand
                if (user->signon > user->idle_lastmsg)
                        user->signon = user->idle_lastmsg;
                ServerInstance->SNO->WriteToSnoMask('a', user->nick+" used SETIDLE to set their idle time to "+ConvToStr(idle)+" seconds");
-               user->WriteNumeric(944, ":Idle time set.");
+               user->WriteNumeric(944, "Idle time set.");
 
                return CMD_SUCCESS;
        }
index cb51c4387cbf5e2a264d4120a015aaa63b01bc9f..9973bf2b6615819f34df647b1a3caae73c8034b4 100644 (file)
@@ -48,12 +48,12 @@ class CommandShowFile : public Command
                if (method == SF_NUMERIC)
                {
                        if (!introtext.empty())
-                               user->SendText(":%s %03d %s :%s %s", sn.c_str(), intronumeric, user->nick.c_str(), sn.c_str(), introtext.c_str());
+                               user->WriteRemoteNumeric(intronumeric, introtext);
 
                        for (file_cache::const_iterator i = contents.begin(); i != contents.end(); ++i)
-                               user->SendText(":%s %03d %s :- %s", sn.c_str(), textnumeric, user->nick.c_str(), i->c_str());
+                               user->WriteRemoteNumeric(textnumeric, InspIRCd::Format("- %s", i->c_str()));
 
-                       user->SendText(":%s %03d %s :%s", sn.c_str(), endnumeric, user->nick.c_str(), endtext.c_str());
+                       user->WriteRemoteNumeric(endnumeric, endtext.c_str());
                }
                else
                {
index a3a2909a08bb9427704d3b2eb3498da6070eb943..5388bb4856da5a2b078d3a9a8cce9c72a742956e 100644 (file)
@@ -194,12 +194,12 @@ class ModuleShun : public Module
                ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_BEFORE, alias);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list& out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'H')
+               if (stats.GetSymbol() != 'H')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("SHUN", 223, user, out);
+               ServerInstance->XLines->InvokeStats("SHUN", 223, stats);
                return MOD_RES_DENY;
        }
 
index f2ac26fb3692a8617cdb5fc19590b1903b5eee57..7d3b3f90ce091d20b2d07713a5664ad6c9fdc27d 100644 (file)
@@ -125,10 +125,10 @@ class CommandSilence : public Command
                                for (silencelist::const_iterator c = sl->begin(); c != sl->end(); c++)
                                {
                                        std::string decomppattern = DecompPattern(c->second);
-                                       user->WriteNumeric(271, "%s %s %s", user->nick.c_str(),c->first.c_str(), decomppattern.c_str());
+                                       user->WriteNumeric(271, user->nick, c->first, decomppattern);
                                }
                        }
-                       user->WriteNumeric(272, ":End of Silence List");
+                       user->WriteNumeric(272, "End of Silence List");
 
                        return CMD_SUCCESS;
                }
@@ -174,7 +174,7 @@ class CommandSilence : public Command
                                                if (listitem == mask && i->second == pattern)
                                                {
                                                        sl->erase(i);
-                                                       user->WriteNumeric(950, "%s :Removed %s %s from silence list", user->nick.c_str(), mask.c_str(), decomppattern.c_str());
+                                                       user->WriteNumeric(950, user->nick, InspIRCd::Format("Removed %s %s from silence list", mask.c_str(), decomppattern.c_str()));
                                                        if (!sl->size())
                                                        {
                                                                ext.unset(user);
@@ -183,7 +183,7 @@ class CommandSilence : public Command
                                                }
                                        }
                                }
-                               user->WriteNumeric(952, "%s :%s %s does not exist on your silence list", user->nick.c_str(), mask.c_str(), decomppattern.c_str());
+                               user->WriteNumeric(952, user->nick, InspIRCd::Format("%s %s does not exist on your silence list", mask.c_str(), decomppattern.c_str()));
                        }
                        else if (action == '+')
                        {
@@ -196,7 +196,7 @@ class CommandSilence : public Command
                                }
                                if (sl->size() > maxsilence)
                                {
-                                       user->WriteNumeric(952, "%s :Your silence list is full",user->nick.c_str());
+                                       user->WriteNumeric(952, user->nick, "Your silence list is full");
                                        return CMD_FAILURE;
                                }
 
@@ -206,7 +206,7 @@ class CommandSilence : public Command
                                        irc::string listitem = n->first.c_str();
                                        if (listitem == mask && n->second == pattern)
                                        {
-                                               user->WriteNumeric(952, "%s :%s %s is already on your silence list", user->nick.c_str(), mask.c_str(), decomppattern.c_str());
+                                               user->WriteNumeric(952, user->nick, InspIRCd::Format("%s %s is already on your silence list", mask.c_str(), decomppattern.c_str()));
                                                return CMD_FAILURE;
                                        }
                                }
@@ -218,7 +218,7 @@ class CommandSilence : public Command
                                {
                                        sl->push_back(silenceset(mask,pattern));
                                }
-                               user->WriteNumeric(951, "%s :Added %s %s to silence list", user->nick.c_str(), mask.c_str(), decomppattern.c_str());
+                               user->WriteNumeric(951, user->nick, InspIRCd::Format("Added %s %s to silence list", mask.c_str(), decomppattern.c_str()));
                                return CMD_SUCCESS;
                        }
                }
index 7263768443a4f7ab52fa2d9dbf6f6acdd931c360..ade8359ba4a85463ad714e1e7c40243544f553bc 100644 (file)
@@ -127,16 +127,15 @@ void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
        else if ((Current->Hidden) && (!user->IsOper()))
                return;
 
-       user->WriteNumeric(RPL_LINKS, "%s %s :%d %s",   Current->GetName().c_str(),
-                       (Utils->FlatLinks && (!user->IsOper())) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
-                       (Utils->FlatLinks && (!user->IsOper())) ? 0 : hops,
-                       Current->GetDesc().c_str());
+       user->WriteNumeric(RPL_LINKS, Current->GetName(),
+                       (((Utils->FlatLinks) && (!user->IsOper())) ? ServerInstance->Config->ServerName : Parent),
+                       InspIRCd::Format("%d %s", (((Utils->FlatLinks) && (!user->IsOper())) ? 0 : hops), Current->GetDesc().c_str()));
 }
 
 void ModuleSpanningTree::HandleLinks(const std::vector<std::string>& parameters, User* user)
 {
        ShowLinks(Utils->TreeRoot,user,0);
-       user->WriteNumeric(RPL_ENDOFLINKS, "* :End of /LINKS list.");
+       user->WriteNumeric(RPL_ENDOFLINKS, '*', "End of /LINKS list.");
 }
 
 std::string ModuleSpanningTree::TimeToStr(time_t secs)
@@ -304,11 +303,11 @@ ModResult ModuleSpanningTree::HandleVersion(const std::vector<std::string>& para
                // or the server is a 2.0 server and does not send a full version.
                bool showfull = ((user->IsOper()) && (!found->GetFullVersion().empty()));
                const std::string& Version = (showfull ? found->GetFullVersion() : found->GetVersion());
-               user->WriteNumeric(RPL_VERSION, ":%s", Version.c_str());
+               user->WriteNumeric(RPL_VERSION, Version);
        }
        else
        {
-               user->WriteNumeric(ERR_NOSUCHSERVER, "%s :No such server", parameters[0].c_str());
+               user->WriteNumeric(ERR_NOSUCHSERVER, parameters[0], "No such server");
        }
        return MOD_RES_DENY;
 }
index 3e02ce93f8ba119ae18a47a61e26049160e8df5b..2490c83ef65133252cc606af4f76b42063484ce5 100644 (file)
@@ -165,7 +165,7 @@ class ModuleSpanningTree : public Module
        void OnOper(User* user, const std::string &opertype) CXX11_OVERRIDE;
        void OnAddLine(User *u, XLine *x) CXX11_OVERRIDE;
        void OnDelLine(User *u, XLine *x) CXX11_OVERRIDE;
-       ModResult OnStats(char statschar, User* user, string_list &results) CXX11_OVERRIDE;
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE;
        ModResult OnSetAway(User* user, const std::string &awaymsg) CXX11_OVERRIDE;
        void OnLoadModule(Module* mod) CXX11_OVERRIDE;
        void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
index 612df80f3ef0802b9e8ee04f1d8c83ddf084893f..660d738e9b86fc423f9a6fcd183043f8a4d4f730 100644 (file)
@@ -172,7 +172,7 @@ CmdResult CommandMap::Handle(const std::vector<std::string>& parameters, User* u
                TreeServer* s = Utils->FindServerMask(parameters[0]);
                if (!s)
                {
-                       user->WriteNumeric(ERR_NOSUCHSERVER, "%s :No such server", parameters[0].c_str());
+                       user->WriteNumeric(ERR_NOSUCHSERVER, parameters[0], "No such server");
                        return CMD_FAILURE;
                }
 
@@ -199,17 +199,14 @@ CmdResult CommandMap::Handle(const std::vector<std::string>& parameters, User* u
 
        std::vector<std::string> map = GetMap(user, Utils->TreeRoot, max, 0);
        for (std::vector<std::string>::const_iterator i = map.begin(); i != map.end(); ++i)
-               user->SendText(":%s %03d %s :%s", ServerInstance->Config->ServerName.c_str(),
-                       RPL_MAP, user->nick.c_str(), i->c_str());
+               user->WriteRemoteNumeric(RPL_MAP, *i);
 
        size_t totusers = ServerInstance->Users->GetUsers().size();
        float avg_users = (float) totusers / Utils->serverlist.size();
 
-       user->SendText(":%s %03d %s :%u server%s and %u user%s, average %.2f users per server",
-               ServerInstance->Config->ServerName.c_str(), RPL_MAPUSERS, user->nick.c_str(),
-               (unsigned int)Utils->serverlist.size(), (Utils->serverlist.size() > 1 ? "s" : ""), (unsigned int)totusers, (totusers > 1 ? "s" : ""), avg_users);
-       user->SendText(":%s %03d %s :End of /MAP", ServerInstance->Config->ServerName.c_str(),
-               RPL_ENDMAP, user->nick.c_str());
+       user->WriteRemoteNumeric(RPL_MAPUSERS, InspIRCd::Format("%u server%s and %u user%s, average %.2f users per server",
+               (unsigned int)Utils->serverlist.size(), (Utils->serverlist.size() > 1 ? "s" : ""), (unsigned int)totusers, (totusers > 1 ? "s" : ""), avg_users));
+       user->WriteRemoteNumeric(RPL_ENDMAP, "End of /MAP");
 
        return CMD_SUCCESS;
 }
index 14b3f5ef74b10a6936eb26d9859d4eb6c78421db..b28c2d98436db9eae5b1a8c5c27e740be7739018 100644 (file)
 #include "utils.h"
 #include "link.h"
 
-ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &results)
+ModResult ModuleSpanningTree::OnStats(Stats::Context& stats)
 {
-       if ((statschar == 'c') || (statschar == 'n'))
+       if ((stats.GetSymbol() == 'c') || (stats.GetSymbol() == 'n'))
        {
                for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i != Utils->LinkBlocks.end(); ++i)
                {
                        Link* L = *i;
-                       results.push_back("213 "+user->nick+" "+statschar+" *@"+(L->HiddenFromStats ? "<hidden>" : L->IPAddr)+" * "+(*i)->Name.c_str()+" "+ConvToStr(L->Port)+" "+(L->Hook.empty() ? "plaintext" : L->Hook));
-                       if (statschar == 'c')
-                               results.push_back("244 "+user->nick+" H * * "+L->Name.c_str());
+                       std::string ipaddr = "*@";
+                       if (L->HiddenFromStats)
+                               ipaddr.append("<hidden>");
+                       else
+                               ipaddr.append(L->IPAddr);
+
+                       const std::string hook = (L->Hook.empty() ? "plaintext" : L->Hook);
+                       stats.AddRow(213, stats.GetSymbol(), ipaddr, '*', L->Name.c_str(), L->Port, hook);
+                       if (stats.GetSymbol() == 'c')
+                               stats.AddRow(244, 'H', '*', '*', L->Name.c_str());
                }
                return MOD_RES_DENY;
        }
-       else if (statschar == 'U')
+       else if (stats.GetSymbol() == 'U')
        {
                ConfigTagList tags = ServerInstance->Config->ConfTags("uline");
                for (ConfigIter i = tags.first; i != tags.second; ++i)
                {
                        std::string name = i->second->getString("server");
                        if (!name.empty())
-                               results.push_back("248 "+user->nick+" U "+name);
+                               stats.AddRow(248, 'U', name);
                }
                return MOD_RES_DENY;
        }
index 430467dc73319ad810978c2b4841e55d74ab85a5..7f718985436c5ff5af1b3e06da01f811cf5948c2 100644 (file)
@@ -31,8 +31,8 @@ ModResult ModuleSpanningTree::HandleRemoteWhois(const std::vector<std::string>&
        }
        else if (!remote)
        {
-               user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[1].c_str());
-               user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", parameters[1].c_str());
+               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
+               user->WriteNumeric(RPL_ENDOFWHOIS, parameters[0], "End of /WHOIS list.");
                return MOD_RES_DENY;
        }
        return MOD_RES_PASSTHRU;
index a3b80457927b5aacd6bce3e416328d34f4a9e5c0..01465670a4c1efc6b22ab175f9e8dc18ac3eb9d3 100644 (file)
@@ -50,7 +50,7 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::st
                // User that the incoming user is colliding with is not fully registered, we force nick change the
                // unregistered user to their uuid and tell them what happened
                collideswith->WriteFrom(collideswith, "NICK %s", collideswith->uuid.c_str());
-               collideswith->WriteNumeric(ERR_NICKNAMEINUSE, "%s :Nickname overruled.", collideswith->nick.c_str());
+               collideswith->WriteNumeric(ERR_NICKNAMEINUSE, collideswith->nick, "Nickname overruled.");
 
                // Clear the bit before calling User::ChangeNick() to make it NOT run the OnUserPostNick() hook
                collideswith->registered &= ~REG_NICK;
index 523d52abbc9cf21a3d2cde83c3f13deace7cc028..6a29d3bde913a731f97ee7c348a43b28d2924cd3 100644 (file)
@@ -95,7 +95,7 @@ class CommandSSLInfo : public Command
 
                if ((!target) || (target->registered != REG_ALL))
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nickname", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
                bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly");
@@ -162,10 +162,10 @@ class ModuleSSLInfo : public Module, public Whois::EventListener
                ssl_cert* cert = cmd.CertExt.get(whois.GetTarget());
                if (cert)
                {
-                       whois.SendLine(671, ":is using a secure connection");
+                       whois.SendLine(671, "is using a secure connection");
                        bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly");
                        if ((!operonlyfp || whois.IsSelfWhois() || whois.GetSource()->IsOper()) && !cert->fingerprint.empty())
-                               whois.SendLine(276, ":has client certificate fingerprint %s", cert->fingerprint.c_str());
+                               whois.SendLine(276, InspIRCd::Format("has client certificate fingerprint %s", cert->fingerprint.c_str()));
                }
        }
 
@@ -181,7 +181,7 @@ class ModuleSSLInfo : public Module, public Whois::EventListener
 
                                if (ifo->oper_block->getBool("sslonly") && !cert)
                                {
-                                       user->WriteNumeric(491, ":This oper login requires an SSL connection.");
+                                       user->WriteNumeric(491, "This oper login requires an SSL connection.");
                                        user->CommandFloodPenalty += 10000;
                                        return MOD_RES_DENY;
                                }
@@ -189,7 +189,7 @@ class ModuleSSLInfo : public Module, public Whois::EventListener
                                std::string fingerprint;
                                if (ifo->oper_block->readString("fingerprint", fingerprint) && (!cert || cert->GetFingerprint() != fingerprint))
                                {
-                                       user->WriteNumeric(491, ":This oper login requires a matching SSL certificate fingerprint.");
+                                       user->WriteNumeric(491, "This oper login requires a matching SSL certificate fingerprint.");
                                        user->CommandFloodPenalty += 10000;
                                        return MOD_RES_DENY;
                                }
index 1a596f5e0424b0332b344566e965ef9011132425..e499082ff81f5c821745597ca25744ec5961f573 100644 (file)
@@ -54,7 +54,7 @@ class SSLMode : public ModeHandler
                                                ssl_cert* cert = API->GetCertificate(i->first);
                                                if (!cert && !i->first->server->IsULine())
                                                {
-                                                       source->WriteNumeric(ERR_ALLMUSTSSL, "%s :all members of the channel must be connected via SSL", channel->name.c_str());
+                                                       source->WriteNumeric(ERR_ALLMUSTSSL, channel->name, "all members of the channel must be connected via SSL");
                                                        return MODEACTION_DENY;
                                                }
                                        }
@@ -107,7 +107,7 @@ class ModuleSSLModes : public Module
                        else
                        {
                                // Deny
-                               user->WriteNumeric(489, "%s :Cannot join channel; SSL users only (+z)", cname.c_str());
+                               user->WriteNumeric(489, cname, "Cannot join channel; SSL users only (+z)");
                                return MOD_RES_DENY;
                        }
                }
index 054f9c3344e7ffe46d739bbdf1a8ac88ef9d2327..b3cf5a26319d4772baa645921c0676417340aeeb 100644 (file)
@@ -44,23 +44,23 @@ class CommandStartTLS : public SplitCommand
        {
                if (!ssl)
                {
-                       user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not enabled");
+                       user->WriteNumeric(ERR_STARTTLS, "STARTTLS is not enabled");
                        return CMD_FAILURE;
                }
 
                if (user->registered == REG_ALL)
                {
-                       user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not permitted after client registration is complete");
+                       user->WriteNumeric(ERR_STARTTLS, "STARTTLS is not permitted after client registration is complete");
                        return CMD_FAILURE;
                }
 
                if (user->eh.GetIOHook())
                {
-                       user->WriteNumeric(ERR_STARTTLS, ":STARTTLS failure");
+                       user->WriteNumeric(ERR_STARTTLS, "STARTTLS failure");
                        return CMD_FAILURE;
                }
 
-               user->WriteNumeric(RPL_STARTTLS, ":STARTTLS successful, go ahead with TLS handshake");
+               user->WriteNumeric(RPL_STARTTLS, "STARTTLS successful, go ahead with TLS handshake");
                /* We need to flush the write buffer prior to adding the IOHook,
                 * otherwise we'll be sending this line inside the SSL session - which
                 * won't start its handshake until the client gets this line. Currently,
index a623e1553746021fdd53fac731e71140897287ce..ad6a4d1aaa15255020389a116cf86f047053be51 100644 (file)
@@ -183,12 +183,12 @@ class ModuleSVSHold : public Module
                silent = tag->getBool("silent", true);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if(symbol != 'S')
+               if (stats.GetSymbol() != 'S')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("SVSHOLD", 210, user, out);
+               ServerInstance->XLines->InvokeStats("SVSHOLD", 210, stats);
                return MOD_RES_DENY;
        }
 
@@ -198,7 +198,7 @@ class ModuleSVSHold : public Module
 
                if (rl)
                {
-                       user->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Services reserved nickname: %s", newnick.c_str(), rl->reason.c_str());
+                       user->WriteNumeric(ERR_ERRONEUSNICKNAME, newnick, InspIRCd::Format("Services reserved nickname: %s", rl->reason.c_str()));
                        return MOD_RES_DENY;
                }
 
index 80c7ddd3b13d8054dc5ddc587890c6d02b572489..9a433e154131c24b017c3a19251ad712cda2a734 100644 (file)
@@ -45,7 +45,7 @@ class CommandSwhois : public Command
 
                if (!dest) // allow setting swhois using SWHOIS before reg
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
 
@@ -93,16 +93,16 @@ class ModuleSWhois : public Module, public Whois::LineEventListener
        }
 
        // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
-       ModResult OnWhoisLine(Whois::Context& whois, unsigned int& numeric, std::string& text) CXX11_OVERRIDE
+       ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
        {
                /* We use this and not OnWhois because this triggers for remote, too */
-               if (numeric == 312)
+               if (numeric.GetNumeric() == 312)
                {
                        /* Insert our numeric before 312 */
                        std::string* swhois = cmd.swhois.get(whois.GetTarget());
                        if (swhois)
                        {
-                               whois.SendLine(320, ":%s", swhois->c_str());
+                               whois.SendLine(320, *swhois);
                        }
                }
 
index 8196d37ba6299a01f509c9ed70279a2a99fcec9c..8a627b9a6c1d9fcd02bae06b23e8dda4b2a6eb72 100644 (file)
@@ -72,14 +72,13 @@ class CommandTban : public Command
                Channel* channel = ServerInstance->FindChan(parameters[0]);
                if (!channel)
                {
-                       user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such channel", parameters[0].c_str());
+                       user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        return CMD_FAILURE;
                }
                int cm = channel->GetPrefixValue(user);
                if (cm < HALFOP_VALUE)
                {
-                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You do not have permission to set bans on this channel",
-                               channel->name.c_str());
+                       user->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, "You do not have permission to set bans on this channel");
                        return CMD_FAILURE;
                }
 
index 6053bc849cca9c6ad1c011dca25c9d5801c62653..eba2b33f0760088ce6197b8f256d40b47fcdd402 100644 (file)
@@ -150,7 +150,7 @@ class ModuleTopicLock : public Module
                // Only fired for local users currently, but added a check anyway
                if ((IS_LOCAL(user)) && (topiclock.get(chan)))
                {
-                       user->WriteNumeric(744, "%s :TOPIC cannot be changed due to topic lock being active on the channel", chan->name.c_str());
+                       user->WriteNumeric(744, chan->name, "TOPIC cannot be changed due to topic lock being active on the channel");
                        return MOD_RES_DENY;
                }
 
index e92688d1ddfff17171c06c64b2ce5d54f8ad25c3..d3045eadca806bbe4ef6fb396606382423d717df 100644 (file)
@@ -51,11 +51,11 @@ class CommandUninvite : public Command
                {
                        if (!c)
                        {
-                               user->WriteNumeric(401, "%s :No such nick/channel", parameters[1].c_str());
+                               user->WriteNumeric(Numerics::NoSuchNick(parameters[1]));
                        }
                        else
                        {
-                               user->WriteNumeric(401, "%s :No such nick/channel", parameters[0].c_str());
+                               user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
                        }
 
                        return CMD_FAILURE;
@@ -65,7 +65,7 @@ class CommandUninvite : public Command
                {
                        if (c->GetPrefixValue(user) < HALFOP_VALUE)
                        {
-                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be a channel %soperator", c->name.c_str(), c->GetPrefixValue(u) == HALFOP_VALUE ? "" : "half-");
+                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator", c->GetPrefixValue(u) == HALFOP_VALUE ? "" : "half-"));
                                return CMD_FAILURE;
                        }
                }
@@ -77,14 +77,23 @@ class CommandUninvite : public Command
                LocalUser* lu = IS_LOCAL(u);
                if (lu)
                {
+                       // XXX: The source of the numeric we send must be the server of the user doing the /UNINVITE,
+                       // so they don't see where the target user is connected to
                        if (!invapi->Remove(lu, c))
                        {
-                               user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server->GetName().c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
+                               Numeric::Numeric n(505);
+                               n.SetServer(user->server);
+                               n.push(u->nick).push(c->name).push(InspIRCd::Format("Is not invited to channel %s", c->name.c_str()));
+                               user->WriteRemoteNumeric(n);
                                return CMD_FAILURE;
                        }
 
-                       user->SendText(":%s 494 %s %s %s :Uninvited", user->server->GetName().c_str(), user->nick.c_str(), c->name.c_str(), u->nick.c_str());
-                       lu->WriteNumeric(493, ":You were uninvited from %s by %s", c->name.c_str(), user->nick.c_str());
+                       Numeric::Numeric n(494);
+                       n.SetServer(user->server);
+                       n.push(c->name).push(u->nick).push("Uninvited");
+                       user->WriteRemoteNumeric(n);
+
+                       lu->WriteNumeric(493, InspIRCd::Format("You were uninvited from %s by %s", c->name.c_str(), user->nick.c_str()));
 
                        std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
                        c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE " + c->name + " :" + msg);
index 04396739340c2dda7e680d48b06ae45e781ecafe..1b2ce9b1382e4f7580b005f572375331cd8da932 100644 (file)
@@ -52,7 +52,7 @@ class CommandUserip : public Command
                                                checked_privs = true;
                                                has_privs = user->HasPrivPermission("users/auspex");
                                                if (!has_privs)
-                                                       user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - You do not have the required operator privileges");
+                                                       user->WriteNumeric(ERR_NOPRIVILEGES, "Permission Denied - You do not have the required operator privileges");
                                        }
 
                                        if (!has_privs)
index bdd4b2b15414797720e20ac17fb94f24e73e787b..6e9a6f9ed716be97ee34dcf1953e8214bccce1f1 100644 (file)
@@ -53,12 +53,12 @@ class CommandWatch : public SplitCommand
                {
                        // The away state should only be sent if the client requests away notifications for a nick but 2.0 always sends them so we do that too
                        if (target->IsAway())
-                               user->WriteNumeric(RPL_NOWISAWAY, "%s %s %s %lu :is away", target->nick.c_str(), target->ident.c_str(), target->dhost.c_str(), (unsigned long)target->awaytime);
+                               user->WriteNumeric(RPL_NOWISAWAY, target->nick, target->ident, target->dhost, (unsigned long)target->awaytime, "is away");
                        else
-                               user->WriteNumeric(RPL_NOWON, "%s %s %s %lu :is online", target->nick.c_str(), target->ident.c_str(), target->dhost.c_str(), (unsigned long)target->age);
+                               user->WriteNumeric(RPL_NOWON, target->nick, target->ident, target->dhost, (unsigned long)target->age, "is online");
                }
                else if (show_offline)
-                       user->WriteNumeric(RPL_NOWOFF, "%s * * 0 :is offline", nick.c_str());
+                       user->WriteNumeric(RPL_NOWOFF, nick, "*", "*", "0", "is offline");
        }
 
        void HandlePlus(LocalUser* user, const std::string& nick)
@@ -67,12 +67,12 @@ class CommandWatch : public SplitCommand
                if (result == IRCv3::Monitor::Manager::WR_TOOMANY)
                {
                        // List is full, send error numeric
-                       user->WriteNumeric(ERR_TOOMANYWATCH, "%s :Too many WATCH entries", nick.c_str());
+                       user->WriteNumeric(ERR_TOOMANYWATCH, nick, "Too many WATCH entries");
                        return;
                }
                else if (result == IRCv3::Monitor::Manager::WR_INVALIDNICK)
                {
-                       user->WriteNumeric(942, "%s :Invalid nickname", nick.c_str());
+                       user->WriteNumeric(942, nick, "Invalid nickname");
                        return;
                }
                else if (result != IRCv3::Monitor::Manager::WR_OK)
@@ -88,9 +88,9 @@ class CommandWatch : public SplitCommand
 
                User* target = IRCv3::Monitor::Manager::FindNick(nick);
                if (target)
-                       user->WriteNumeric(RPL_WATCHOFF, "%s %s %s %lu :stopped watching", target->nick.c_str(), target->ident.c_str(), target->dhost.c_str(), (unsigned long)target->age);
+                       user->WriteNumeric(RPL_WATCHOFF, target->nick, target->ident, target->dhost, (unsigned long)target->age, "stopped watching");
                else
-                       user->WriteNumeric(RPL_WATCHOFF, "%s * * 0 :stopped watching", nick.c_str());
+                       user->WriteNumeric(RPL_WATCHOFF, nick, "*", "*", "0", "stopped watching");
        }
 
        void HandleList(LocalUser* user, bool show_offline)
@@ -102,7 +102,7 @@ class CommandWatch : public SplitCommand
                        const IRCv3::Monitor::Entry* entry = *i;
                        SendOnlineOffline(user, entry->GetNick(), show_offline);
                }
-               user->WriteNumeric(RPL_ENDOFWATCHLIST, ":End of WATCH list");
+               user->WriteNumeric(RPL_ENDOFWATCHLIST, "End of WATCH list");
        }
 
        void HandleStats(LocalUser* user)
@@ -111,7 +111,7 @@ class CommandWatch : public SplitCommand
 
                // Do not show how many clients are watching this nick, it's pointless
                const IRCv3::Monitor::WatchedList& list = manager.GetWatched(user);
-               user->WriteNumeric(RPL_WATCHSTAT, ":You have %lu and are on 0 WATCH entries", (unsigned long)list.size());
+               user->WriteNumeric(RPL_WATCHSTAT, InspIRCd::Format("You have %lu and are on 0 WATCH entries", (unsigned long)list.size()));
 
                Numeric::Builder<' '> out(user, RPL_WATCHLIST);
                for (IRCv3::Monitor::WatchedList::const_iterator i = list.begin(); i != list.end(); ++i)
@@ -120,7 +120,7 @@ class CommandWatch : public SplitCommand
                        out.Add(entry->GetNick());
                }
                out.Flush();
-               user->WriteNumeric(RPL_ENDOFWATCHLIST, ":End of WATCH S");
+               user->WriteNumeric(RPL_ENDOFWATCHLIST, "End of WATCH S");
        }
 
  public:
@@ -189,11 +189,12 @@ class ModuleWatch : public Module
                if (!list)
                        return;
 
-               std::string text = InspIRCd::Format("%s %s %s %lu :%s", nick.c_str(), user->ident.c_str(), user->dhost.c_str(), (unsigned long) shownts, numerictext);
+               Numeric::Numeric num(numeric);
+               num.push(nick).push(user->ident).push(user->dhost).push(ConvToStr(shownts)).push(numerictext);
                for (IRCv3::Monitor::WatcherList::const_iterator i = list->begin(); i != list->end(); ++i)
                {
                        LocalUser* curr = *i;
-                       curr->WriteNumeric(numeric, text);
+                       curr->WriteNumeric(num);
                }
        }
 
index 191a3d30ffd21812a8a0e596ac3399ddd34ea4df..f22cf1ad4a168f275a9c1d5e96a6debaea771616 100644 (file)
@@ -194,35 +194,34 @@ void ISupportManager::Build()
        }
 
        // Transform the map into a list of lines, ready to be sent to clients
-       std::string line;
+       Numeric::Numeric numeric(RPL_ISUPPORT);
        unsigned int token_count = 0;
        cachedlines.clear();
 
        for (std::map<std::string, std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
        {
-               line.append(it->first);
+               numeric.push(it->first);
+               std::string& token = numeric.GetParams().back();
 
                // If this token has a value then append a '=' char after the name and then the value itself
                if (!it->second.empty())
-                       line.append(1, '=').append(it->second);
+                       token.append(1, '=').append(it->second);
 
-               // Always append a space, even if it's the last token because all lines will be suffixed
-               line.push_back(' ');
                token_count++;
 
                if (token_count % 13 == 12 || it == --tokens.end())
                {
                        // Reached maximum number of tokens for this line or the current token
                        // is the last one; finalize the line and store it for later use
-                       line.append(":are supported by this server");
-                       cachedlines.push_back(line);
-                       line.clear();
+                       numeric.push("are supported by this server");
+                       cachedlines.push_back(numeric);
+                       numeric.GetParams().clear();
                }
        }
 }
 
 void ISupportManager::SendTo(LocalUser* user)
 {
-       for (std::vector<std::string>::const_iterator i = cachedlines.begin(); i != cachedlines.end(); ++i)
-               user->WriteNumeric(RPL_ISUPPORT, *i);
+       for (std::vector<Numeric::Numeric>::const_iterator i = cachedlines.begin(); i != cachedlines.end(); ++i)
+               user->WriteNumeric(*i);
 }
index ba6bbf36bb8e6a96bd1a2a3c6bd82211df21bf9d..fe052fcfc90f517c477772e8849f8aa15b8acb37 100644 (file)
@@ -127,7 +127,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
                        /* user banned */
                        ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Positive hit for " + New->GetIPString());
                        if (!ServerInstance->Config->XLineMessage.empty())
-                               New->WriteNumeric(ERR_YOUREBANNEDCREEP, ":" + ServerInstance->Config->XLineMessage);
+                               New->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage);
                        this->QuitUser(New, b->Reason);
                        return;
                }
index fd4afbcef7a643b7bd061ed07ca240ba266e63bc..f6cdcc769926d132a980051f8fb0ff8ad5cdf479 100644 (file)
@@ -348,7 +348,7 @@ void User::Oper(OperInfo* info)
 
        ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",
                nick.c_str(), ident.c_str(), host.c_str(), oper->name.c_str(), opername.c_str());
-       this->WriteNumeric(RPL_YOUAREOPER, ":You are now %s %s", strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->name.c_str());
+       this->WriteNumeric(RPL_YOUAREOPER, InspIRCd::Format("You are now %s %s", strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->name.c_str()));
 
        ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->name.c_str());
        ServerInstance->Users->all_opers.push_back(this);
@@ -524,12 +524,12 @@ void LocalUser::FullConnect()
        if (quitting)
                return;
 
-       this->WriteNumeric(RPL_WELCOME, ":Welcome to the %s IRC Network %s", ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str());
-       this->WriteNumeric(RPL_YOURHOSTIS, ":Your host is %s, running version %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH);
-       this->WriteNumeric(RPL_SERVERCREATED, ":This server was created %s %s", __TIME__, __DATE__);
+       this->WriteNumeric(RPL_WELCOME, InspIRCd::Format("Welcome to the %s IRC Network %s", ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str()));
+       this->WriteNumeric(RPL_YOURHOSTIS, InspIRCd::Format("Your host is %s, running version %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH));
+       this->WriteNumeric(RPL_SERVERCREATED, InspIRCd::Format("This server was created %s %s", __TIME__, __DATE__));
 
        const std::string& modelist = ServerInstance->Modes->GetModeListFor004Numeric();
-       this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH, modelist.c_str());
+       this->WriteNumeric(RPL_SERVERVERSION, ServerInstance->Config->ServerName, INSPIRCD_BRANCH, modelist);
 
        ServerInstance->ISupport.SendTo(this);
 
@@ -615,7 +615,7 @@ bool User::ChangeNick(const std::string& newnick, time_t newts)
                        {
                                /* force the camper to their UUID, and ask them to re-send a NICK. */
                                InUse->WriteFrom(InUse, "NICK %s", InUse->uuid.c_str());
-                               InUse->WriteNumeric(ERR_NICKNAMEINUSE, "%s :Nickname overruled.", InUse->nick.c_str());
+                               InUse->WriteNumeric(ERR_NICKNAMEINUSE, InUse->nick, "Nickname overruled.");
 
                                InUse->registered &= ~REG_NICK;
                                InUse->ChangeNick(InUse->uuid);
@@ -623,7 +623,7 @@ bool User::ChangeNick(const std::string& newnick, time_t newts)
                        else
                        {
                                /* No camping, tell the incoming user  to stop trying to change nick ;p */
-                               this->WriteNumeric(ERR_NICKNAMEINUSE, "%s :Nickname is already in use.", newnick.c_str());
+                               this->WriteNumeric(ERR_NICKNAMEINUSE, newnick, "Nickname is already in use.");
                                return false;
                        }
                }
@@ -786,25 +786,32 @@ void User::WriteCommand(const char* command, const std::string& text)
        this->WriteServ(command + (this->registered & REG_NICK ? " " + this->nick : " *") + " " + text);
 }
 
-void User::WriteNumeric(unsigned int numeric, const char* text, ...)
+namespace
 {
-       std::string textbuffer;
-       VAFORMAT(textbuffer, text, text);
-       this->WriteNumeric(numeric, textbuffer);
+       std::string BuildNumeric(const std::string& source, User* targetuser, unsigned int num, const std::vector<std::string>& params)
+       {
+               const char* const target = (targetuser->registered & REG_NICK ? targetuser->nick.c_str() : "*");
+               std::string raw = InspIRCd::Format(":%s %03u %s", source.c_str(), num, target);
+               if (!params.empty())
+               {
+                       for (std::vector<std::string>::const_iterator i = params.begin(); i != params.end()-1; ++i)
+                               raw.append(1, ' ').append(*i);
+                       raw.append(" :").append(params.back());
+               }
+               return raw;
+       }
 }
 
-void User::WriteNumeric(unsigned int numeric, const std::string &text)
+void User::WriteNumeric(const Numeric::Numeric& numeric)
 {
        ModResult MOD_RESULT;
 
-       FIRST_MOD_RESULT(OnNumeric, MOD_RESULT, (this, numeric, text));
+       FIRST_MOD_RESULT(OnNumeric, MOD_RESULT, (this, numeric));
 
        if (MOD_RESULT == MOD_RES_DENY)
                return;
 
-       const std::string message = InspIRCd::Format(":%s %03u %s %s", ServerInstance->Config->ServerName.c_str(),
-               numeric, this->registered & REG_NICK ? this->nick.c_str() : "*", text.c_str());
-       this->Write(message);
+       this->Write(BuildNumeric(ServerInstance->Config->ServerName, this, numeric.GetNumeric(), numeric.GetParams()));
 }
 
 void User::WriteFrom(User *user, const std::string &text)
@@ -947,6 +954,12 @@ void User::SendText(const std::string& linePrefix, std::stringstream& textStream
        SendText(linePrefix + line);
 }
 
+void User::WriteRemoteNumeric(const Numeric::Numeric& numeric)
+{
+       const std::string& servername = (numeric.GetServer() ? numeric.GetServer()->GetName() : ServerInstance->Config->ServerName);
+       SendText(BuildNumeric(servername, this, numeric.GetNumeric(), numeric.GetParams()));
+}
+
 /* return 0 or 1 depending if users u and u2 share one or more common channels
  * (used by QUIT, NICK etc which arent channel specific notices)
  *
@@ -1010,7 +1023,7 @@ bool User::ChangeDisplayedHost(const std::string& shost)
        this->InvalidateCache();
 
        if (IS_LOCAL(this))
-               this->WriteNumeric(RPL_YOURDISPLAYEDHOST, "%s :is now your displayed host", this->dhost.c_str());
+               this->WriteNumeric(RPL_YOURDISPLAYEDHOST, this->dhost, "is now your displayed host");
 
        return true;
 }
index dedf8c7a9c917a4c838ee31acce445d0eab3a57a..30a1d7c9cc97428904084c1115779c6f0fc2dce0 100644 (file)
@@ -447,7 +447,7 @@ void XLineManager::ApplyLines()
        pending_lines.clear();
 }
 
-void XLineManager::InvokeStats(const std::string &type, int numeric, User* user, string_list &results)
+void XLineManager::InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats)
 {
        ContainerIter n = lookup_lines.find(type);
 
@@ -468,7 +468,7 @@ void XLineManager::InvokeStats(const std::string &type, int numeric, User* user,
                                ExpireLine(n, i);
                        }
                        else
-                               results.push_back(ConvToStr(numeric)+" "+user->nick+" :"+i->second->Displayable()+" "+
+                               stats.AddRow(numeric, i->second->Displayable()+" "+
                                        ConvToStr(i->second->set_time)+" "+ConvToStr(i->second->duration)+" "+i->second->source+" :"+i->second->reason);
                        i = safei;
                }
@@ -531,7 +531,7 @@ void XLine::DefaultApply(User* u, const std::string &line, bool bancache)
        const std::string banReason = line + "-Lined: " + reason;
 
        if (!ServerInstance->Config->XLineMessage.empty())
-               u->WriteNumeric(ERR_YOUREBANNEDCREEP, ":" + ServerInstance->Config->XLineMessage);
+               u->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage);
 
        if (ServerInstance->Config->HideBans)
                ServerInstance->Users->QuitUser(u, line + "-Lined", &banReason);