summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp95
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp40
-rw-r--r--src/modules/m_blockamsg.cpp4
-rw-r--r--src/modules/m_chanhistory.cpp7
-rw-r--r--src/modules/m_chanlog.cpp20
-rw-r--r--src/modules/m_chgname.cpp4
-rw-r--r--src/modules/m_commonchans.cpp26
-rw-r--r--src/modules/m_connflood.cpp22
-rw-r--r--src/modules/m_cycle.cpp4
-rw-r--r--src/modules/m_halfop.cpp5
-rw-r--r--src/modules/m_helpop.cpp26
-rw-r--r--src/modules/m_hidechans.cpp26
-rw-r--r--src/modules/m_hideoper.cpp26
-rw-r--r--src/modules/m_hostchange.cpp96
-rw-r--r--src/modules/m_ident.cpp23
-rw-r--r--src/modules/m_messageflood.cpp152
-rw-r--r--src/modules/m_namesx.cpp14
-rw-r--r--src/modules/m_noctcp.cpp2
-rw-r--r--src/modules/m_nokicks.cpp4
-rw-r--r--src/modules/m_operchans.cpp25
-rw-r--r--src/modules/m_opermotd.cpp71
-rw-r--r--src/modules/m_sapart.cpp4
-rw-r--r--src/modules/m_satopic.cpp3
-rw-r--r--src/modules/m_services_account.cpp11
-rw-r--r--src/modules/m_servprotect.cpp4
-rw-r--r--src/modules/m_setname.cpp2
-rw-r--r--src/modules/m_showwhois.cpp26
-rw-r--r--src/modules/m_spanningtree/encap.cpp2
-rw-r--r--src/modules/m_spanningtree/protocolinterface.cpp28
-rw-r--r--src/modules/m_spanningtree/treesocket.h5
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp11
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp4
-rw-r--r--src/modules/m_uhnames.cpp3
-rw-r--r--src/modules/m_uninvite.cpp23
-rw-r--r--src/modules/m_xline_db.cpp28
35 files changed, 352 insertions, 494 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 6ca876d4c..7d8e9581e 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -28,8 +28,19 @@
#include "ssl.h"
#include "m_cap.h"
+#ifdef WINDOWS
+# pragma comment(lib, "libgnutls.lib")
+# pragma comment(lib, "libgcrypt.lib")
+# pragma comment(lib, "libgpg-error.lib")
+# pragma comment(lib, "user32.lib")
+# pragma comment(lib, "advapi32.lib")
+# pragma comment(lib, "libgcc.lib")
+# pragma comment(lib, "libmingwex.lib")
+# pragma comment(lib, "gdi32.lib")
+#endif
+
/* $ModDesc: Provides SSL support for clients */
-/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") */
+/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") -Wno-deprecated-declarations */
/* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") -lgcrypt */
enum issl_status { ISSL_NONE, ISSL_HANDSHAKING_READ, ISSL_HANDSHAKING_WRITE, ISSL_HANDSHAKEN, ISSL_CLOSING, ISSL_CLOSED };
@@ -151,6 +162,7 @@ class ModuleSSLGnuTLS : public Module
gnutls_certificate_credentials x509_cred;
gnutls_dh_params dh_params;
gnutls_digest_algorithm_t hash;
+ gnutls_priority_t priority;
std::string sslports;
int dh_bits;
@@ -172,6 +184,8 @@ class ModuleSSLGnuTLS : public Module
gnutls_global_init(); // This must be called once in the program
gnutls_x509_privkey_init(&x509_key);
+ // Init this here so it's always initialized, avoids an extra boolean
+ gnutls_priority_init(&priority, "NORMAL", NULL);
cred_alloc = false;
dh_alloc = false;
@@ -203,6 +217,10 @@ class ModuleSSLGnuTLS : public Module
if (Conf->getBool("showports", true))
{
+ sslports = Conf->getString("advertisedports");
+ if (!sslports.empty())
+ return;
+
for (size_t i = 0; i < ServerInstance->ports.size(); i++)
{
ListenSocket* port = ServerInstance->ports[i];
@@ -213,11 +231,20 @@ class ModuleSSLGnuTLS : public Module
ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %s", portid.c_str());
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
- sslports.append(portid).append(";");
+ {
+ /*
+ * Found an SSL port for clients that is not bound to 127.0.0.1 and handled by us, display
+ * the IP:port in ISUPPORT.
+ *
+ * We used to advertise all ports seperated by a ';' char that matched the above criteria,
+ * but this resulted in too long ISUPPORT lines if there were lots of ports to be displayed.
+ * To solve this by default we now only display the first IP:port found and let the user
+ * configure the exact value for the 005 token, if necessary.
+ */
+ sslports = portid;
+ break;
+ }
}
-
- if (!sslports.empty())
- sslports.erase(sslports.end() - 1);
}
}
@@ -241,6 +268,13 @@ class ModuleSSLGnuTLS : public Module
dh_bits = Conf->getInt("dhbits");
std::string hashname = Conf->getString("hash", "md5");
+ // The GnuTLS manual states that the gnutls_set_default_priority()
+ // call we used previously when initializing the session is the same
+ // as setting the "NORMAL" priority string.
+ // Thus if the setting below is not in the config we will behave exactly
+ // the same as before, when the priority setting wasn't available.
+ std::string priorities = Conf->getString("priority", "NORMAL");
+
if((dh_bits != 768) && (dh_bits != 1024) && (dh_bits != 2048) && (dh_bits != 3072) && (dh_bits != 4096))
dh_bits = 1024;
@@ -305,6 +339,21 @@ class ModuleSSLGnuTLS : public Module
if((ret = gnutls_certificate_set_x509_key(x509_cred, &x509_certs[0], certcount, x509_key)) < 0)
throw ModuleException("Unable to set GnuTLS cert/key pair: " + std::string(gnutls_strerror(ret)));
+ // It's safe to call this every time as we cannot have this uninitialized, see constructor and below.
+ gnutls_priority_deinit(priority);
+
+ // Try to set the priorities for ciphers, kex methods etc. to the user supplied string
+ // If the user did not supply anything then the string is already set to "NORMAL"
+ const char* priocstr = priorities.c_str();
+ const char* prioerror;
+
+ if ((ret = gnutls_priority_init(&priority, priocstr, &prioerror)) < 0)
+ {
+ // gnutls did not understand the user supplied string, log and fall back to the default priorities
+ ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to set priorities to \"%s\": %s Syntax error at position %d, falling back to default (NORMAL)", priorities.c_str(), gnutls_strerror(ret), (prioerror - priocstr));
+ gnutls_priority_init(&priority, "NORMAL", NULL);
+ }
+
gnutls_certificate_client_set_retrieve_function (x509_cred, cert_callback);
ret = gnutls_dh_params_init(&dh_params);
@@ -338,6 +387,7 @@ class ModuleSSLGnuTLS : public Module
gnutls_x509_crt_deinit(x509_certs[i]);
gnutls_x509_privkey_deinit(x509_key);
+ gnutls_priority_deinit(priority);
if (dh_alloc)
gnutls_dh_params_deinit(dh_params);
@@ -399,44 +449,39 @@ class ModuleSSLGnuTLS : public Module
}
}
- void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ void InitSession(StreamSocket* user, bool me_server)
{
- int fd = user->GetFd();
- issl_session* session = &sessions[fd];
-
- /* For STARTTLS: Don't try and init a session on a socket that already has a session */
- if (session->sess)
- return;
+ issl_session* session = &sessions[user->GetFd()];
- gnutls_init(&session->sess, GNUTLS_SERVER);
+ gnutls_init(&session->sess, me_server ? GNUTLS_SERVER : GNUTLS_CLIENT);
- gnutls_set_default_priority(session->sess); // Avoid calling all the priority functions, defaults are adequate.
+ gnutls_priority_set(session->sess, priority);
gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_dh_set_prime_bits(session->sess, dh_bits);
-
gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user));
gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
- gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any.
+ if (me_server)
+ gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any.
Handshake(session, user);
}
- void OnStreamSocketConnect(StreamSocket* user)
+ void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
{
issl_session* session = &sessions[user->GetFd()];
- gnutls_init(&session->sess, GNUTLS_CLIENT);
+ /* For STARTTLS: Don't try and init a session on a socket that already has a session */
+ if (session->sess)
+ return;
- gnutls_set_default_priority(session->sess); // Avoid calling all the priority functions, defaults are adequate.
- gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
- gnutls_dh_set_prime_bits(session->sess, dh_bits);
- gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user));
- gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
- gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
+ InitSession(user, true);
+ }
- Handshake(session, user);
+ void OnStreamSocketConnect(StreamSocket* user)
+ {
+ InitSession(user, false);
}
void OnStreamSocketClose(StreamSocket* user)
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 0a5a76792..a8020bba1 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -159,20 +159,34 @@ class ModuleSSLOpenSSL : public Module
if (Conf->getBool("showports", true))
{
+ sslports = Conf->getString("advertisedports");
+ if (!sslports.empty())
+ return;
+
for (size_t i = 0; i < ServerInstance->ports.size(); i++)
{
ListenSocket* port = ServerInstance->ports[i];
if (port->bind_tag->getString("ssl") != "openssl")
continue;
- std::string portid = port->bind_desc;
+ const std::string& portid = port->bind_desc;
ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %s", portid.c_str());
+
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
- sslports.append(portid).append(";");
+ {
+ /*
+ * Found an SSL port for clients that is not bound to 127.0.0.1 and handled by us, display
+ * the IP:port in ISUPPORT.
+ *
+ * We used to advertise all ports seperated by a ';' char that matched the above criteria,
+ * but this resulted in too long ISUPPORT lines if there were lots of ports to be displayed.
+ * To solve this by default we now only display the first IP:port found and let the user
+ * configure the exact value for the 005 token, if necessary.
+ */
+ sslports = portid;
+ break;
+ }
}
-
- if (!sslports.empty())
- sslports.erase(sslports.end() - 1);
}
}
@@ -198,6 +212,16 @@ class ModuleSSLOpenSSL : public Module
throw ModuleException("Unknown hash type " + hash);
use_sha = (hash == "sha1");
+ std::string ciphers = conf->getString("ciphers", "");
+
+ if (!ciphers.empty())
+ {
+ if ((!SSL_CTX_set_cipher_list(ctx, ciphers.c_str())) || (!SSL_CTX_set_cipher_list(clictx, ciphers.c_str())))
+ {
+ ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't set cipher list to %s.", ciphers.c_str());
+ ERR_print_errors_cb(error_callback, this);
+ }
+ }
/* Load our keys and certificates
* NOTE: OpenSSL's error logging API sucks, don't blame us for this clusterfuck.
@@ -262,8 +286,10 @@ class ModuleSSLOpenSSL : public Module
if (sessions[user->eh.GetFd()].sess)
{
if (!sessions[user->eh.GetFd()].cert->fingerprint.empty())
- user->WriteServ("NOTICE %s :*** You are connected using SSL fingerprint %s",
- user->nick.c_str(), sessions[user->eh.GetFd()].cert->fingerprint.c_str());
+ user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\""
+ " and your SSL fingerprint is %s", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess), sessions[user->eh.GetFd()].cert->fingerprint.c_str());
+ else
+ user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess));
}
}
}
diff --git a/src/modules/m_blockamsg.cpp b/src/modules/m_blockamsg.cpp
index 1d26b7639..8160fcf54 100644
--- a/src/modules/m_blockamsg.cpp
+++ b/src/modules/m_blockamsg.cpp
@@ -98,8 +98,8 @@ class ModuleBlockAmsg : public Module
virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- // Don't do anything with unregistered users, or remote ones.
- if(!user || (user->registered != REG_ALL) || !IS_LOCAL(user))
+ // Don't do anything with unregistered users
+ if (user->registered != REG_ALL)
return MOD_RES_PASSTHRU;
// We want case insensitive command comparison.
diff --git a/src/modules/m_chanhistory.cpp b/src/modules/m_chanhistory.cpp
index 482d526eb..16eba953f 100644
--- a/src/modules/m_chanhistory.cpp
+++ b/src/modules/m_chanhistory.cpp
@@ -129,12 +129,7 @@ class ModuleChanHistory : public Module
{
ConfigTag* tag = ServerInstance->Config->ConfValue("chanhistory");
m.maxlines = tag->getInt("maxlines", 50);
- sendnotice = tag->getInt("notice", true);
- }
-
- ~ModuleChanHistory()
- {
- ServerInstance->Modes->DelMode(&m);
+ sendnotice = tag->getBool("notice", true);
}
void OnUserMessage(User* user,void* dest,int target_type, const std::string &text, char status, const CUList&)
diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp
index ed5063fad..29385b8e2 100644
--- a/src/modules/m_chanlog.cpp
+++ b/src/modules/m_chanlog.cpp
@@ -28,7 +28,8 @@ class ModuleChanLog : public Module
/*
* Multimap so people can redirect a snomask to multiple channels.
*/
- std::multimap<char, std::string> logstreams;
+ typedef std::multimap<char, std::string> ChanLogTargets;
+ ChanLogTargets logstreams;
public:
ModuleChanLog() {
@@ -72,30 +73,21 @@ class ModuleChanLog : public Module
virtual ModResult OnSendSnotice(char &sno, std::string &desc, const std::string &msg)
{
- std::multimap<char, std::string>::const_iterator it = logstreams.find(sno);
- char buf[MAXBUF];
-
- if (it == logstreams.end())
+ std::pair<ChanLogTargets::const_iterator, ChanLogTargets::const_iterator> itpair = logstreams.equal_range(sno);
+ if (itpair.first == itpair.second)
return MOD_RES_PASSTHRU;
+ char buf[MAXBUF];
snprintf(buf, MAXBUF, "\2%s\2: %s", desc.c_str(), msg.c_str());
- while (it != logstreams.end())
+ for (ChanLogTargets::const_iterator it = itpair.first; it != itpair.second; ++it)
{
- if (it->first != sno)
- {
- it++;
- continue;
- }
-
Channel *c = ServerInstance->FindChan(it->second);
if (c)
{
c->WriteChannelWithServ(ServerInstance->Config->ServerName.c_str(), "PRIVMSG %s :%s", c->name.c_str(), buf);
ServerInstance->PI->SendChannelPrivmsg(c, 0, buf);
}
-
- it++;
}
return MOD_RES_PASSTHRU;
diff --git a/src/modules/m_chgname.cpp b/src/modules/m_chgname.cpp
index 667ddd928..2ac24c5d5 100644
--- a/src/modules/m_chgname.cpp
+++ b/src/modules/m_chgname.cpp
@@ -52,14 +52,14 @@ class CommandChgname : public Command
if (parameters[1].length() > ServerInstance->Config->Limits.MaxGecos)
{
- user->WriteServ("NOTICE %s :*** GECOS too long", user->nick.c_str());
+ user->WriteServ("NOTICE %s :*** CHGNAME: GECOS too long", user->nick.c_str());
return CMD_FAILURE;
}
if (IS_LOCAL(dest))
{
dest->ChangeName(parameters[1].c_str());
- ServerInstance->SNO->WriteGlobalSno('a', "%s used CHGNAME to change %s's real name to '%s'", user->nick.c_str(), dest->nick.c_str(), dest->fullname.c_str());
+ ServerInstance->SNO->WriteGlobalSno('a', "%s used CHGNAME to change %s's GECOS to '%s'", user->nick.c_str(), dest->nick.c_str(), dest->fullname.c_str());
}
return CMD_SUCCESS;
diff --git a/src/modules/m_commonchans.cpp b/src/modules/m_commonchans.cpp
index ac8a7ba29..877ba87d7 100644
--- a/src/modules/m_commonchans.cpp
+++ b/src/modules/m_commonchans.cpp
@@ -23,32 +23,10 @@
/** Handles user mode +c
*/
-class PrivacyMode : public ModeHandler
+class PrivacyMode : public SimpleUserModeHandler
{
public:
- PrivacyMode(Module* Creator) : ModeHandler(Creator, "deaf_commonchan", 'c', PARAM_NONE, MODETYPE_USER) { }
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (adding)
- {
- if (!dest->IsModeSet('c'))
- {
- dest->SetMode('c',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet('c'))
- {
- dest->SetMode('c',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
- }
+ PrivacyMode(Module* Creator) : SimpleUserModeHandler(Creator, "deaf_commonchan", 'c') { }
};
class ModulePrivacyMode : public Module
diff --git a/src/modules/m_connflood.cpp b/src/modules/m_connflood.cpp
index d0e925716..9d7c9cb2c 100644
--- a/src/modules/m_connflood.cpp
+++ b/src/modules/m_connflood.cpp
@@ -23,27 +23,25 @@
/* $ModDesc: Connection throttle */
-int conns = 0, throttled = 0;
-
class ModuleConnFlood : public Module
{
private:
- int seconds, maxconns, timeout, boot_wait;
+ int seconds, timeout, boot_wait;
+ unsigned int conns;
+ unsigned int maxconns;
+ bool throttled;
time_t first;
std::string quitmsg;
public:
- ModuleConnFlood() {
-
+ ModuleConnFlood()
+ : conns(0), throttled(false)
+ {
InitConf();
Implementation eventlist[] = { I_OnRehash, I_OnUserRegister };
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleConnFlood()
- {
- }
-
virtual Version GetVersion()
{
return Version("Connection throttle", VF_VENDOR);
@@ -78,12 +76,12 @@ public:
/* increase connection count */
conns++;
- if (throttled == 1)
+ if (throttled)
{
if (tdiff > seconds + timeout)
{
/* expire throttle */
- throttled = 0;
+ throttled = false;
ServerInstance->SNO->WriteGlobalSno('a', "Connection throttle deactivated");
return MOD_RES_PASSTHRU;
}
@@ -96,7 +94,7 @@ public:
{
if (conns >= maxconns)
{
- throttled = 1;
+ throttled = true;
ServerInstance->SNO->WriteGlobalSno('a', "Connection throttle activated");
ServerInstance->Users->QuitUser(user, quitmsg);
return MOD_RES_DENY;
diff --git a/src/modules/m_cycle.cpp b/src/modules/m_cycle.cpp
index b28edde83..1eb3c1899 100644
--- a/src/modules/m_cycle.cpp
+++ b/src/modules/m_cycle.cpp
@@ -20,7 +20,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style CYCLE command. */
+/* $ModDesc: Provides command CYCLE, acts as a server-side HOP command to part and rejoin a channel. */
/** Handle /CYCLE
*/
@@ -97,7 +97,7 @@ class ModuleCycle : public Module
virtual Version GetVersion()
{
- return Version("Provides support for unreal-style CYCLE command.", VF_VENDOR);
+ return Version("Provides command CYCLE, acts as a server-side HOP command to part and rejoin a channel.", VF_VENDOR);
}
};
diff --git a/src/modules/m_halfop.cpp b/src/modules/m_halfop.cpp
index f0eda3e56..7a43f0241 100644
--- a/src/modules/m_halfop.cpp
+++ b/src/modules/m_halfop.cpp
@@ -92,11 +92,6 @@ class ModuleHalfop : public Module
throw ModuleException("Could not add new modes!");
}
- ~ModuleHalfop()
- {
- ServerInstance->Modes->DelMode(&mh);
- }
-
Version GetVersion()
{
return Version("Channel half-operator mode provider", VF_VENDOR);
diff --git a/src/modules/m_helpop.cpp b/src/modules/m_helpop.cpp
index bbc7ae3ac..60c23f45b 100644
--- a/src/modules/m_helpop.cpp
+++ b/src/modules/m_helpop.cpp
@@ -29,35 +29,13 @@ static std::map<irc::string, std::string> helpop_map;
/** Handles user mode +h
*/
-class Helpop : public ModeHandler
+class Helpop : public SimpleUserModeHandler
{
public:
- Helpop(Module* Creator) : ModeHandler(Creator, "helpop", 'h', PARAM_NONE, MODETYPE_USER)
+ Helpop(Module* Creator) : SimpleUserModeHandler(Creator, "helpop", 'h')
{
oper = true;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (adding)
- {
- if (!dest->IsModeSet('h'))
- {
- dest->SetMode('h',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet('h'))
- {
- dest->SetMode('h',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
- }
};
/** Handles /HELPOP
diff --git a/src/modules/m_hidechans.cpp b/src/modules/m_hidechans.cpp
index 17e2e8605..9c582551b 100644
--- a/src/modules/m_hidechans.cpp
+++ b/src/modules/m_hidechans.cpp
@@ -24,32 +24,10 @@
/** Handles user mode +I
*/
-class HideChans : public ModeHandler
+class HideChans : public SimpleUserModeHandler
{
public:
- HideChans(Module* Creator) : ModeHandler(Creator, "hidechans", 'I', PARAM_NONE, MODETYPE_USER) { }
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (adding)
- {
- if (!dest->IsModeSet('I'))
- {
- dest->SetMode('I',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet('I'))
- {
- dest->SetMode('I',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
- }
+ HideChans(Module* Creator) : SimpleUserModeHandler(Creator, "hidechans", 'I') { }
};
class ModuleHideChans : public Module
diff --git a/src/modules/m_hideoper.cpp b/src/modules/m_hideoper.cpp
index cde50b1a9..998a57bb3 100644
--- a/src/modules/m_hideoper.cpp
+++ b/src/modules/m_hideoper.cpp
@@ -25,35 +25,13 @@
/** Handles user mode +H
*/
-class HideOper : public ModeHandler
+class HideOper : public SimpleUserModeHandler
{
public:
- HideOper(Module* Creator) : ModeHandler(Creator, "hideoper", 'H', PARAM_NONE, MODETYPE_USER)
+ HideOper(Module* Creator) : SimpleUserModeHandler(Creator, "hideoper", 'H')
{
oper = true;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (adding)
- {
- if (!dest->IsModeSet('H'))
- {
- dest->SetMode('H',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet('H'))
- {
- dest->SetMode('H',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
- }
};
class ModuleHideOper : public Module
diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp
index 2635015c7..e63c61631 100644
--- a/src/modules/m_hostchange.cpp
+++ b/src/modules/m_hostchange.cpp
@@ -28,12 +28,22 @@
class Host
{
public:
- std::string action;
+ enum HostChangeAction
+ {
+ HCA_SET,
+ HCA_SUFFIX,
+ HCA_ADDNICK
+ };
+
+ HostChangeAction action;
std::string newhost;
std::string ports;
+
+ Host(HostChangeAction Action, const std::string& Newhost, const std::string& Ports) :
+ action(Action), newhost(Newhost), ports(Ports) {}
};
-typedef std::map<std::string,Host*> hostchanges_t;
+typedef std::vector<std::pair<std::string, Host> > hostchanges_t;
class ModuleHostChange : public Module
{
@@ -51,44 +61,39 @@ class ModuleHostChange : public Module
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleHostChange()
- {
- for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++)
- {
- delete i->second;
- }
- hostchanges.clear();
- }
-
- void Prioritize()
- {
- Module* cloak = ServerInstance->Modules->Find("m_cloaking.so");
- ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_AFTER, &cloak);
- }
-
-
virtual void OnRehash(User* user)
{
ConfigReader Conf;
MySuffix = Conf.ReadValue("host","suffix",0);
MyPrefix = Conf.ReadValue("host","prefix","",0);
MySeparator = Conf.ReadValue("host","separator",".",0);
- for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++)
- {
- delete i->second;
- }
hostchanges.clear();
- for (int index = 0; index < Conf.Enumerate("hostchange"); index++)
+
+ std::set<std::string> dupecheck;
+ ConfigTagList tags = ServerInstance->Config->ConfTags("hostchange");
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
{
- std::string mask = Conf.ReadValue("hostchange", "mask", index);
- std::string ports = Conf.ReadValue("hostchange", "ports", index);
- std::string action = Conf.ReadValue("hostchange", "action", index);
- std::string newhost = Conf.ReadValue("hostchange", "value", index);
- Host* x = new Host;
- x->action = action;
- x->ports = ports;
- x->newhost = newhost;
- hostchanges[mask] = x;
+ ConfigTag* tag = i->second;
+ std::string mask = tag->getString("mask");
+ if (!dupecheck.insert(mask).second)
+ throw ModuleException("Duplicate hostchange entry: " + mask);
+
+ Host::HostChangeAction act;
+ std::string newhost;
+ std::string action = tag->getString("action");
+ if (!strcasecmp(action.c_str(), "set"))
+ {
+ act = Host::HCA_SET;
+ newhost = tag->getString("newhost");
+ }
+ else if (!strcasecmp(action.c_str(), "suffix"))
+ act = Host::HCA_SUFFIX;
+ else if (!strcasecmp(action.c_str(), "addnick"))
+ act = Host::HCA_ADDNICK;
+ else
+ throw ModuleException("Invalid hostchange action: " + action);
+
+ hostchanges.push_back(std::make_pair(mask, Host(act, tag->getString("ports"), newhost)));
}
}
@@ -105,11 +110,11 @@ class ModuleHostChange : public Module
{
if (((InspIRCd::MatchCIDR(user->MakeHost(), i->first)) || (InspIRCd::MatchCIDR(user->MakeHostIP(), i->first))))
{
- Host* h = i->second;
+ const Host& h = i->second;
- if (!h->ports.empty())
+ if (!h.ports.empty())
{
- irc::portparser portrange(h->ports, false);
+ irc::portparser portrange(h.ports, false);
long portno = -1;
bool foundany = false;
@@ -123,27 +128,26 @@ class ModuleHostChange : public Module
// host of new user matches a hostchange tag's mask
std::string newhost;
- if (h->action == "set")
+ if (h.action == Host::HCA_SET)
{
- newhost = h->newhost;
+ newhost = h.newhost;
}
- else if (h->action == "suffix")
+ else if (h.action == Host::HCA_SUFFIX)
{
newhost = MySuffix;
}
- else if (h->action == "addnick")
+ else if (h.action == Host::HCA_ADDNICK)
{
// first take their nick and strip out non-dns, leaving just [A-Z0-9\-]
std::string complete;
- std::string old = user->nick;
- for (unsigned int j = 0; j < old.length(); j++)
+ for (std::string::const_iterator j = user->nick.begin(); j != user->nick.end(); ++j)
{
- if (((old[j] >= 'A') && (old[j] <= 'Z')) ||
- ((old[j] >= 'a') && (old[j] <= 'z')) ||
- ((old[j] >= '0') && (old[j] <= '9')) ||
- (old[j] == '-'))
+ if (((*j >= 'A') && (*j <= 'Z')) ||
+ ((*j >= 'a') && (*j <= 'z')) ||
+ ((*j >= '0') && (*j <= '9')) ||
+ (*j == '-'))
{
- complete = complete + old[j];
+ complete = complete + *j;
}
}
if (complete.empty())
diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp
index b7c9c1cfd..c30e4d200 100644
--- a/src/modules/m_ident.cpp
+++ b/src/modules/m_ident.cpp
@@ -216,15 +216,17 @@ class IdentRequestSocket : public EventHandler
char ibuf[MAXBUF];
int recvresult = ServerInstance->SE->Recv(this, ibuf, MAXBUF-1, 0);
+ /* Close (but don't delete from memory) our socket
+ * and flag as done since the ident lookup has finished
+ */
+ Close();
+ done = true;
+
/* Cant possibly be a valid response shorter than 3 chars,
* because the shortest possible response would look like: '1,1'
*/
if (recvresult < 3)
- {
- Close();
- done = true;
return;
- }
ServerInstance->Logs->Log("m_ident",DEBUG,"ReadResponse()");
@@ -263,13 +265,6 @@ class IdentRequestSocket : public EventHandler
break;
}
-
- /* Close (but dont delete from memory) our socket
- * and flag as done
- */
- Close();
- done = true;
- return;
}
};
@@ -388,7 +383,11 @@ class ModuleIdent : public Module
{
/* Module unloading, tidy up users */
if (target_type == TYPE_USER)
- OnUserDisconnect((LocalUser*)item);
+ {
+ LocalUser* user = IS_LOCAL((User*) item);
+ if (user)
+ OnUserDisconnect(user);
+ }
}
virtual void OnUserDisconnect(LocalUser *user)
diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp
index f3045cf52..ff92fcaa3 100644
--- a/src/modules/m_messageflood.cpp
+++ b/src/modules/m_messageflood.cpp
@@ -33,47 +33,30 @@ class floodsettings
{
public:
bool ban;
- int secs;
- int lines;
+ unsigned int secs;
+ unsigned int lines;
time_t reset;
- std::map<User*,int> counters;
+ std::map<User*, unsigned int> counters;
floodsettings(bool a, int b, int c) : ban(a), secs(b), lines(c)
{
reset = ServerInstance->Time() + secs;
- };
+ }
- void addmessage(User* who)
+ bool addmessage(User* who)
{
- std::map<User*,int>::iterator iter = counters.find(who);
- if (iter != counters.end())
- {
- iter->second++;
- }
- else
- {
- counters[who] = 1;
- }
if (ServerInstance->Time() > reset)
{
counters.clear();
reset = ServerInstance->Time() + secs;
}
- }
- bool shouldkick(User* who)
- {
- std::map<User*,int>::iterator iter = counters.find(who);
- if (iter != counters.end())
- {
- return (iter->second >= this->lines);
- }
- else return false;
+ return (++counters[who] >= this->lines);
}
void clear(User* who)
{
- std::map<User*,int>::iterator iter = counters.find(who);
+ std::map<User*, unsigned int>::iterator iter = counters.find(who);
if (iter != counters.end())
{
counters.erase(iter);
@@ -92,101 +75,45 @@ class MsgFlood : public ModeHandler
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
- floodsettings *f = ext.get(channel);
-
if (adding)
{
- char ndata[MAXBUF];
- char* data = ndata;
- strlcpy(ndata,parameter.c_str(),MAXBUF);
- char* lines = data;
- char* secs = NULL;
- bool ban = false;
- if (*data == '*')
- {
- ban = true;
- lines++;
- }
- else
+ std::string::size_type colon = parameter.find(':');
+ if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
{
- ban = false;
- }
- while (*data)
- {
- if (*data == ':')
- {
- *data = 0;
- data++;
- secs = data;
- break;
- }
- else data++;
- }
- if (secs)
- {
- /* Set up the flood parameters for this channel */
- int nlines = atoi(lines);
- int nsecs = atoi(secs);
- if ((nlines<2) || (nsecs<1))
- {
- source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
- parameter.clear();
- return MODEACTION_DENY;
- }
- else
- {
- if (!f)
- {
- parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" +ConvToStr(nsecs);
- f = new floodsettings(ban,nsecs,nlines);
- ext.set(channel, f);
- channel->SetModeParam('f', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- std::string cur_param = channel->GetModeParameter('f');
- parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" +ConvToStr(nsecs);
- if (cur_param == parameter)
- {
- // mode params match
- return MODEACTION_DENY;
- }
- else
- {
- if ((((nlines != f->lines) || (nsecs != f->secs) || (ban != f->ban))) && (((nsecs > 0) && (nlines > 0))))
- {
- floodsettings *fs = new floodsettings(ban,nsecs,nlines);
- ext.set(channel, fs);
- channel->SetModeParam('f', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- return MODEACTION_DENY;
- }
- }
- }
- }
+ source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
+ return MODEACTION_DENY;
}
- else
+
+ /* Set up the flood parameters for this channel */
+ bool ban = (parameter[0] == '*');
+ unsigned int nlines = ConvToInt(parameter.substr(ban ? 1 : 0, ban ? colon-1 : colon));
+ unsigned int nsecs = ConvToInt(parameter.substr(colon+1));
+
+ if ((nlines<2) || (nsecs<1))
{
source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
- parameter.clear();
return MODEACTION_DENY;
}
+
+ floodsettings* f = ext.get(channel);
+ if ((f) && (nlines == f->lines) && (nsecs == f->secs) && (ban == f->ban))
+ // mode params match
+ return MODEACTION_DENY;
+
+ ext.set(channel, new floodsettings(ban, nsecs, nlines));
+ parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" + ConvToStr(nsecs);
+ channel->SetModeParam('f', parameter);
+ return MODEACTION_ALLOW;
}
else
{
- if (f)
- {
- ext.unset(channel);
- channel->SetModeParam('f', "");
- return MODEACTION_ALLOW;
- }
- }
+ if (!channel->IsModeSet('f'))
+ return MODEACTION_DENY;
- return MODEACTION_DENY;
+ ext.unset(channel);
+ channel->SetModeParam('f', "");
+ return MODEACTION_ALLOW;
+ }
}
};
@@ -208,15 +135,16 @@ class ModuleMsgFlood : public Module
ModResult ProcessMessages(User* user,Channel* dest, const std::string &text)
{
- ModResult res = ServerInstance->OnCheckExemption(user,dest,"flood");
- if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
+ if ((!IS_LOCAL(user)) || !dest->IsModeSet('f'))
+ return MOD_RES_PASSTHRU;
+
+ if (ServerInstance->OnCheckExemption(user,dest,"flood") == MOD_RES_ALLOW)
return MOD_RES_PASSTHRU;
floodsettings *f = mf.ext.get(dest);
if (f)
{
- f->addmessage(user);
- if (f->shouldkick(user))
+ if (f->addmessage(user))
{
/* Youre outttta here! */
f->clear(user);
@@ -230,7 +158,7 @@ class ModuleMsgFlood : public Module
}
char kickmessage[MAXBUF];
- snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %d lines in %d secs)", f->lines, f->secs);
+ snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %u lines in %u secs)", f->lines, f->secs);
dest->KickUser(ServerInstance->FakeClient, user, kickmessage);
diff --git a/src/modules/m_namesx.cpp b/src/modules/m_namesx.cpp
index 2603b0ce5..535f6ec10 100644
--- a/src/modules/m_namesx.cpp
+++ b/src/modules/m_namesx.cpp
@@ -52,13 +52,12 @@ class ModuleNamesX : public Module
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- irc::string c = command.c_str();
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
* Therefore, we just hook its as an unvalidated command therefore we
* can capture it even if it doesnt exist! :-)
*/
- if (c == "PROTOCTL")
+ if (command == "PROTOCTL")
{
if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"NAMESX")))
{
@@ -83,13 +82,16 @@ class ModuleNamesX : public Module
void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
{
- if (!cap.ext.get(source) || line.empty())
+ if (!cap.ext.get(source))
return;
- std::string::size_type pos = line.find(':');
- if (pos == std::string::npos || pos < 2)
+ // Channel names can contain ":", and ":" as a 'start-of-token' delimiter is
+ // only ever valid after whitespace, so... find the actual delimiter first!
+ // Thanks to FxChiP for pointing this out.
+ std::string::size_type pos = line.find(" :");
+ if (pos == std::string::npos || pos == 0)
return;
- pos -= 2;
+ pos--;
// Don't do anything if the user has no prefixes
if ((line[pos] == 'H') || (line[pos] == 'G') || (line[pos] == '*'))
return;
diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp
index 8c8e1c473..d6db7a7f7 100644
--- a/src/modules/m_noctcp.cpp
+++ b/src/modules/m_noctcp.cpp
@@ -67,7 +67,7 @@ class ModuleNoCTCP : public Module
if (!c->IsModeSet('C'))
return MOD_RES_PASSTHRU;
- if ((text.empty()) || (text[0] != '\001') || (strncmp(text.c_str(),"\1ACTION ",8)))
+ if ((text.empty()) || (text[0] != '\001') || (!strncmp(text.c_str(),"\1ACTION ",8)))
return MOD_RES_PASSTHRU;
ModResult res = ServerInstance->OnCheckExemption(user,c,"noctcp");
diff --git a/src/modules/m_nokicks.cpp b/src/modules/m_nokicks.cpp
index 2e598dafe..58e6fbea1 100644
--- a/src/modules/m_nokicks.cpp
+++ b/src/modules/m_nokicks.cpp
@@ -22,7 +22,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style channel mode +Q */
+/* $ModDesc: Provides channel mode +Q to prevent kicks on the channel. */
class NoKicks : public SimpleChannelModeHandler
{
@@ -74,7 +74,7 @@ class ModuleNoKicks : public Module
Version GetVersion()
{
- return Version("Provides support for unreal-style channel mode +Q", VF_VENDOR);
+ return Version("Provides channel mode +Q to prevent kicks on the channel.", VF_VENDOR);
}
};
diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp
index 074c644e1..2e6fad79f 100644
--- a/src/modules/m_operchans.cpp
+++ b/src/modules/m_operchans.cpp
@@ -24,32 +24,13 @@
/* $ModDesc: Provides support for oper-only chans via the +O channel mode */
-class OperChans : public ModeHandler
+class OperChans : public SimpleChannelModeHandler
{
public:
/* This is an oper-only mode */
- OperChans(Module* Creator) : ModeHandler(Creator, "operonly", 'O', PARAM_NONE, MODETYPE_CHANNEL) { oper = true; }
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
+ OperChans(Module* Creator) : SimpleChannelModeHandler(Creator, "operonly", 'O')
{
- if (adding)
- {
- if (!channel->IsModeSet('O'))
- {
- channel->SetMode('O',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (channel->IsModeSet('O'))
- {
- channel->SetMode('O',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
+ oper = true;
}
};
diff --git a/src/modules/m_opermotd.cpp b/src/modules/m_opermotd.cpp
index 3a05fbd56..5c107b6b1 100644
--- a/src/modules/m_opermotd.cpp
+++ b/src/modules/m_opermotd.cpp
@@ -24,42 +24,47 @@
/* $ModDesc: Shows a message to opers after oper-up, adds /opermotd */
-static FileReader* opermotd;
-
-CmdResult ShowOperMOTD(User* user)
-{
- if(!opermotd->FileSize())
- {
- user->WriteServ(std::string("425 ") + user->nick + std::string(" :OPERMOTD file is missing"));
- return CMD_FAILURE;
- }
-
- user->WriteServ(std::string("375 ") + user->nick + std::string(" :- IRC Operators Message of the Day"));
-
- for(int i=0; i != opermotd->FileSize(); i++)
- {
- user->WriteServ(std::string("372 ") + user->nick + std::string(" :- ") + opermotd->GetLine(i));
- }
-
- user->WriteServ(std::string("376 ") + user->nick + std::string(" :- End of OPERMOTD"));
-
- /* don't route me */
- return CMD_SUCCESS;
-}
-
/** Handle /OPERMOTD
*/
class CommandOpermotd : public Command
{
public:
- CommandOpermotd(Module* Creator) : Command(Creator,"OPERMOTD", 0)
+ FileReader opermotd;
+
+ CommandOpermotd(Module* Creator) : Command(Creator,"OPERMOTD", 0, 1)
{
flags_needed = 'o'; syntax = "[<servername>]";
}
CmdResult Handle (const std::vector<std::string>& parameters, User* user)
{
- return ShowOperMOTD(user);
+ if ((parameters.empty()) || (parameters[0] == ServerInstance->Config->ServerName))
+ ShowOperMOTD(user);
+ return CMD_SUCCESS;
+ }
+
+ RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
+ {
+ if (!parameters.empty())
+ return ROUTE_OPT_UCAST(parameters[0]);
+ return ROUTE_LOCALONLY;
+ }
+
+ void ShowOperMOTD(User* user)
+ {
+ const std::string& servername = ServerInstance->Config->ServerName;
+ if (!opermotd.FileSize())
+ {
+ user->SendText(":%s 455 %s :OPERMOTD file is missing", servername.c_str(), user->nick.c_str());
+ return;
+ }
+
+ user->SendText(":%s 375 %s :- IRC Operators Message of the Day", servername.c_str(), user->nick.c_str());
+
+ for (int i=0; i != opermotd.FileSize(); i++)
+ user->SendText(":%s 372 %s :- %s", servername.c_str(), user->nick.c_str(), opermotd.GetLine(i).c_str());
+
+ user->SendText(":%s 376 %s :- End of OPERMOTD", servername.c_str(), user->nick.c_str());
}
};
@@ -73,36 +78,28 @@ class ModuleOpermotd : public Module
void LoadOperMOTD()
{
ConfigTag* conf = ServerInstance->Config->ConfValue("opermotd");
- opermotd->LoadFile(conf->getString("file","opermotd"));
+ cmd.opermotd.LoadFile(conf->getString("file","opermotd"));
onoper = conf->getBool("onoper", true);
}
ModuleOpermotd()
: cmd(this)
{
- opermotd = NULL;
ServerInstance->AddCommand(&cmd);
- opermotd = new FileReader;
LoadOperMOTD();
Implementation eventlist[] = { I_OnRehash, I_OnOper };
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleOpermotd()
- {
- delete opermotd;
- opermotd = NULL;
- }
-
virtual Version GetVersion()
{
- return Version("Shows a message to opers after oper-up, adds /opermotd", VF_VENDOR);
+ return Version("Shows a message to opers after oper-up, adds /opermotd", VF_VENDOR | VF_OPTCOMMON);
}
virtual void OnOper(User* user, const std::string &opertype)
{
- if (onoper)
- ShowOperMOTD(user);
+ if (onoper && IS_LOCAL(user))
+ cmd.ShowOperMOTD(user);
}
virtual void OnRehash(User* user)
diff --git a/src/modules/m_sapart.cpp b/src/modules/m_sapart.cpp
index 1a19c6645..c1e6f6c08 100644
--- a/src/modules/m_sapart.cpp
+++ b/src/modules/m_sapart.cpp
@@ -21,7 +21,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style SAPART command */
+/* $ModDesc: Provides command SAPART to force-part users from a channel. */
/** Handle /SAPART
*/
@@ -116,7 +116,7 @@ class ModuleSapart : public Module
virtual Version GetVersion()
{
- return Version("Provides support for unreal-style SAPART command", VF_OPTCOMMON | VF_VENDOR);
+ return Version("Provides command SAPART to force-part users from a channel.", VF_OPTCOMMON | VF_VENDOR);
}
};
diff --git a/src/modules/m_satopic.cpp b/src/modules/m_satopic.cpp
index bf65cc5d5..a0e3319af 100644
--- a/src/modules/m_satopic.cpp
+++ b/src/modules/m_satopic.cpp
@@ -44,8 +44,7 @@ class CommandSATopic : public Command
// 3rd parameter overrides access checks
target->SetTopic(user, newTopic, true);
- ServerInstance->SNO->WriteToSnoMask('a', user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic);
- ServerInstance->PI->SendSNONotice("A", user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic);
+ ServerInstance->SNO->WriteGlobalSno('a', user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic);
return CMD_SUCCESS;
}
diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp
index 57a08ada4..08986d53c 100644
--- a/src/modules/m_services_account.cpp
+++ b/src/modules/m_services_account.cpp
@@ -40,19 +40,17 @@ class Channel_r : public ModeHandler
if (!IS_LOCAL(source) || ServerInstance->ULine(source->nick.c_str()) || ServerInstance->ULine(source->server))
{
// Only change the mode if it's not redundant
- if ((adding && !channel->IsModeSet('r')) || (!adding && channel->IsModeSet('r')))
+ if ((adding != channel->IsModeSet('r')))
{
channel->SetMode('r',adding);
return MODEACTION_ALLOW;
}
-
- return MODEACTION_DENY;
}
else
{
source->WriteNumeric(500, "%s :Only a server may modify the +r channel mode", source->nick.c_str());
- return MODEACTION_DENY;
}
+ return MODEACTION_DENY;
}
};
@@ -68,18 +66,17 @@ class User_r : public ModeHandler
{
if (!IS_LOCAL(source) || ServerInstance->ULine(source->nick.c_str()) || ServerInstance->ULine(source->server))
{
- if ((adding && !dest->IsModeSet('r')) || (!adding && dest->IsModeSet('r')))
+ if ((adding != dest->IsModeSet('r')))
{
dest->SetMode('r',adding);
return MODEACTION_ALLOW;
}
- return MODEACTION_DENY;
}
else
{
source->WriteNumeric(500, "%s :Only a server may modify the +r user mode", source->nick.c_str());
- return MODEACTION_DENY;
}
+ return MODEACTION_DENY;
}
};
diff --git a/src/modules/m_servprotect.cpp b/src/modules/m_servprotect.cpp
index 7df9effcc..c98eebec3 100644
--- a/src/modules/m_servprotect.cpp
+++ b/src/modules/m_servprotect.cpp
@@ -21,7 +21,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for Austhex style +k / UnrealIRCD +S services mode */
+/* $ModDesc: Provides usermode +k to protect services from kicks, kills and mode changes. */
/** Handles user mode +k
*/
@@ -64,7 +64,7 @@ class ModuleServProtectMode : public Module
Version GetVersion()
{
- return Version("Provides support for Austhex style +k / UnrealIRCD +S services mode", VF_VENDOR);
+ return Version("Provides usermode +k to protect services from kicks, kills, and mode changes.", VF_VENDOR);
}
void OnWhois(User* src, User* dst)
diff --git a/src/modules/m_setname.cpp b/src/modules/m_setname.cpp
index 3b8d4d149..32c1d5dc3 100644
--- a/src/modules/m_setname.cpp
+++ b/src/modules/m_setname.cpp
@@ -50,7 +50,7 @@ class CommandSetname : public Command
if (user->ChangeName(parameters[0].c_str()))
{
- ServerInstance->SNO->WriteGlobalSno('a', "%s used SETNAME to change their GECOS to %s", user->nick.c_str(), parameters[0].c_str());
+ ServerInstance->SNO->WriteGlobalSno('a', "%s used SETNAME to change their GECOS to '%s'", user->nick.c_str(), parameters[0].c_str());
}
return CMD_SUCCESS;
diff --git a/src/modules/m_showwhois.cpp b/src/modules/m_showwhois.cpp
index 6eec64bd5..d81dd553d 100644
--- a/src/modules/m_showwhois.cpp
+++ b/src/modules/m_showwhois.cpp
@@ -27,35 +27,13 @@
/** Handle user mode +W
*/
-class SeeWhois : public ModeHandler
+class SeeWhois : public SimpleUserModeHandler
{
public:
- SeeWhois(Module* Creator, bool IsOpersOnly) : ModeHandler(Creator, "showwhois", 'W', PARAM_NONE, MODETYPE_USER)
+ SeeWhois(Module* Creator, bool IsOpersOnly) : SimpleUserModeHandler(Creator, "showwhois", 'W')
{
oper = IsOpersOnly;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (adding)
- {
- if (!dest->IsModeSet('W'))
- {
- dest->SetMode('W',true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet('W'))
- {
- dest->SetMode('W',false);
- return MODEACTION_ALLOW;
- }
- }
-
- return MODEACTION_DENY;
- }
};
class WhoisNoticeCmd : public Command
diff --git a/src/modules/m_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp
index 51194e6d7..0cc293fa5 100644
--- a/src/modules/m_spanningtree/encap.cpp
+++ b/src/modules/m_spanningtree/encap.cpp
@@ -38,7 +38,7 @@ void TreeSocket::Encap(User* who, parameterlist &params)
params[params.size() - 1] = ":" + params[params.size() - 1];
- if (params[0].find('*') != std::string::npos)
+ if (params[0].find_first_of("*?") != std::string::npos)
{
Utils->DoOneToAllButSender(who->uuid, "ENCAP", params, who->server);
}
diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp
index efc00334d..3ab5dae9d 100644
--- a/src/modules/m_spanningtree/protocolinterface.cpp
+++ b/src/modules/m_spanningtree/protocolinterface.cpp
@@ -48,7 +48,7 @@ void SpanningTreeProtocolInterface::GetServerList(ProtoServerList &sl)
bool SpanningTreeProtocolInterface::SendEncapsulatedData(const parameterlist &encap)
{
- if (encap[0].find('*') != std::string::npos)
+ if (encap[0].find_first_of("*?") != std::string::npos)
{
Utils->DoOneToMany(ServerInstance->Config->GetSID(), "ENCAP", encap);
return true;
@@ -164,26 +164,16 @@ void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char stat
void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
{
- TreeServer* serv = Utils->FindServer(target->server);
- if (serv)
- {
- TreeSocket* sock = serv->GetSocket();
- if (sock)
- {
- sock->WriteLine(":" + ServerInstance->Config->GetSID() + " PRIVMSG " + target->nick + " :"+text);
- }
- }
+ parameterlist p;
+ p.push_back(target->uuid);
+ p.push_back(":" + text);
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PRIVMSG", p, target->server);
}
void SpanningTreeProtocolInterface::SendUserNotice(User* target, const std::string &text)
{
- TreeServer* serv = Utils->FindServer(target->server);
- if (serv)
- {
- TreeSocket* sock = serv->GetSocket();
- if (sock)
- {
- sock->WriteLine(":" + ServerInstance->Config->GetSID() + " NOTICE " + target->nick + " :"+text);
- }
- }
+ parameterlist p;
+ p.push_back(target->uuid);
+ p.push_back(":" + text);
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "NOTICE", p, target->server);
}
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index be5455bce..aebc7e03b 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -94,6 +94,7 @@ class TreeSocket : public BufferedSocket
time_t NextPing; /* Time when we are due to ping this server */
bool LastPingWasGood; /* Responded to last ping we sent? */
int proto_version; /* Remote protocol version */
+ bool ConnectionFailureShown; /* Set to true if a connection failure message was shown */
public:
time_t age;
@@ -315,6 +316,10 @@ class TreeSocket : public BufferedSocket
/** Handle server quit on close
*/
virtual void Close();
+
+ /** Returns true if this server was introduced to the rest of the network
+ */
+ bool Introduced();
};
#endif
diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp
index dcb35af31..3e916544b 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -49,6 +49,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, Link* link, Autoconnect* mya
capab->capab_phase = 0;
MyRoot = NULL;
proto_version = 0;
+ ConnectionFailureShown = false;
LinkState = CONNECTING;
if (!link->Hook.empty())
{
@@ -78,6 +79,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, ListenSocket* via
age = ServerInstance->Time();
LinkState = WAIT_AUTH_1;
proto_version = 0;
+ ConnectionFailureShown = false;
linkID = "inbound from " + client->addr();
FOREACH_MOD(I_OnHookIO, OnHookIO(this, via));
@@ -134,7 +136,7 @@ void TreeSocket::OnConnected()
void TreeSocket::OnError(BufferedSocketError e)
{
- ServerInstance->SNO->WriteGlobalSno('l', "Connection to \002%s\002 failed with error: %s",
+ ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\002%s\002' failed with error: %s",
linkID.c_str(), getError().c_str());
LinkState = DYING;
}
@@ -183,7 +185,7 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason)
{
DelServerEvent(Utils->Creator, Current->GetName());
- if (!Current->GetSocket() || Current->GetSocket()->GetLinkState() == CONNECTED)
+ if (!Current->GetSocket() || Current->GetSocket()->Introduced())
{
parameterlist params;
params.push_back(Current->GetName());
@@ -245,3 +247,8 @@ void TreeSocket::OnDataReady()
SendError("RecvQ overrun (line too long)");
Utils->Creator->loopCall = false;
}
+
+bool TreeSocket::Introduced()
+{
+ return (capab == NULL);
+}
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index e6fbad4c6..0a0c22e39 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -484,13 +484,13 @@ void TreeSocket::Close()
if (MyRoot)
Squit(MyRoot,getError());
- if (!linkID.empty())
+ if (!ConnectionFailureShown)
{
+ ConnectionFailureShown = true;
ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\2%s\2' failed.",linkID.c_str());
time_t server_uptime = ServerInstance->Time() - this->age;
if (server_uptime)
ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\2%s\2' was established for %s", linkID.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
- linkID.clear();
}
}
diff --git a/src/modules/m_uhnames.cpp b/src/modules/m_uhnames.cpp
index 37bd67440..5693eb807 100644
--- a/src/modules/m_uhnames.cpp
+++ b/src/modules/m_uhnames.cpp
@@ -51,13 +51,12 @@ class ModuleUHNames : public Module
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- irc::string c = command.c_str();
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
* Therefore, we just hook its as an unvalidated command therefore we
* can capture it even if it doesnt exist! :-)
*/
- if (c == "PROTOCTL")
+ if (command == "PROTOCTL")
{
if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"UHNAMES")))
{
diff --git a/src/modules/m_uninvite.cpp b/src/modules/m_uninvite.cpp
index 6c392fe49..9287589bb 100644
--- a/src/modules/m_uninvite.cpp
+++ b/src/modules/m_uninvite.cpp
@@ -63,22 +63,27 @@ class CommandUninvite : public Command
}
}
- irc::string xname(c->name.c_str());
-
- if (IS_LOCAL(u))
+ /* Servers remember invites only for their local users, so act
+ * only if the target is local. Otherwise the command will be
+ * passed to the target users server.
+ */
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu)
{
- // TODO send messages & such out to remote servers
- LocalUser* lu = IS_LOCAL(u);
+ irc::string xname(c->name.c_str());
if (!lu->IsInvited(xname))
{
- user->WriteNumeric(505, "%s %s %s :Is not invited to channel %s", user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
+ user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server.c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
return CMD_FAILURE;
}
- user->WriteNumeric(494, "%s %s %s :Uninvited", user->nick.c_str(), c->name.c_str(), u->nick.c_str());
+
+ user->SendText(":%s 494 %s %s %s :Uninvited", user->server.c_str(), user->nick.c_str(), c->name.c_str(), u->nick.c_str());
lu->RemoveInvite(xname);
lu->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s uninvited %s.",
- c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+
+ std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE " + c->name + " :" + msg);
+ ServerInstance->PI->SendChannelNotice(c, 0, msg);
}
return CMD_SUCCESS;
diff --git a/src/modules/m_xline_db.cpp b/src/modules/m_xline_db.cpp
index 1918f3fc5..683c14afa 100644
--- a/src/modules/m_xline_db.cpp
+++ b/src/modules/m_xline_db.cpp
@@ -25,6 +25,7 @@
class ModuleXLineDB : public Module
{
+ std::vector<XLine *> xlines;
bool reading_db; // If this is true, addlines are as a result of db reading, so don't bother flushing the db to disk.
// DO REMEMBER TO SET IT, otherwise it's annoying :P
public:
@@ -49,6 +50,7 @@ class ModuleXLineDB : public Module
void OnAddLine(User* source, XLine* line)
{
ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Adding a line");
+ xlines.push_back(line);
if (!reading_db)
{
@@ -74,6 +76,15 @@ class ModuleXLineDB : public Module
void RemoveLine(XLine *line)
{
ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Removing a line");
+ for (std::vector<XLine *>::iterator i = xlines.begin(); i != xlines.end(); i++)
+ {
+ if ((*i) == line)
+ {
+ xlines.erase(i);
+ break;
+ }
+ }
+
WriteDatabase();
}
@@ -108,19 +119,12 @@ class ModuleXLineDB : public Module
fprintf(f, "VERSION 1\n");
// Now, let's write.
- std::vector<std::string> types = ServerInstance->XLines->GetAllTypes();
- for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it)
+ XLine *line;
+ for (std::vector<XLine *>::iterator i = xlines.begin(); i != xlines.end(); i++)
{
- XLineLookup* lookup = ServerInstance->XLines->GetAll(*it);
- if (!lookup)
- continue;
-
- for (LookupIter i = lookup->begin(); i != lookup->end(); ++i)
- {
- XLine *line = i->second;
- fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(),
- ServerInstance->Config->ServerName.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str());
- }
+ line = (*i);
+ fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(),
+ ServerInstance->Config->ServerName.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str());
}
ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Finished writing XLines. Checking for error..");