mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 18:49:03 -04:00
Merge branch 'insp3' into master.
This commit is contained in:
commit
4f68d162cc
4
.github/SECURITY.md
vendored
4
.github/SECURITY.md
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Currently the v2 (old stable) and v3 (stable) branches are actively receiving security fixes. Support for v2 will end on 2021-01-01.
|
||||
Currently the v3 (stable) branch is actively receiving security fixes. Support for v2 ended at the end of 2020.
|
||||
|
||||
The v4 branch is still early in development and only receives security fixes when they are synced from the v3 branch.
|
||||
|
||||
@ -10,7 +10,7 @@ Version | Supported
|
||||
------- | ---------
|
||||
4.x.y | :warning:
|
||||
3.x.y | :white_check_mark:
|
||||
2.0.x | :warning:
|
||||
2.0.x | :x:
|
||||
1.2.y | :x:
|
||||
1.1.y | :x:
|
||||
1.0.y | :x:
|
||||
|
@ -132,13 +132,17 @@
|
||||
# to this bind section.
|
||||
type="clients"
|
||||
|
||||
# ssl: If you want the port(s) in this bind tag to use TLS (SSL), set this to
|
||||
# the name of a custom <sslprofile> tag that you have defined. See the
|
||||
# docs page for the TLS (SSL) module you are using for more details.
|
||||
# ssl: If you want the port(s) in this bind tag to use TLS (SSL), set this
|
||||
# to the name of a custom <sslprofile> tag that you have defined. See the
|
||||
# docs page for the TLS (SSL) module you are using for more details:
|
||||
#
|
||||
# GnuTLS: https://docs.inspircd.org/3/modules/ssl_gnutls#sslprofile
|
||||
# mbedTLS: https://docs.inspircd.org/3/modules/ssl_mbedtls#sslprofile
|
||||
# OpenSSL: https://docs.inspircd.org/3/modules/ssl_openssl#sslprofile
|
||||
#
|
||||
# You will need to load the ssl_openssl module for OpenSSL, ssl_gnutls
|
||||
# for GnuTLS and ssl_mbedtls for mbedTLS.
|
||||
ssl="gnutls"
|
||||
ssl="Clients"
|
||||
|
||||
# defer: When this is non-zero, connections will not be handed over to
|
||||
# the daemon from the operating system before data is ready.
|
||||
|
@ -10,7 +10,7 @@
|
||||
<bind address="1.2.3.4"
|
||||
port="7005"
|
||||
type="servers"
|
||||
ssl="gnutls">
|
||||
ssl="Servers">
|
||||
|
||||
# Plaintext listener that binds on a TCP/IP endpoint:
|
||||
<bind address=""
|
||||
@ -56,14 +56,18 @@
|
||||
# failover (see above).
|
||||
timeout="5m"
|
||||
|
||||
# ssl: If defined, this states the name of the TLS (SSL) profile that will
|
||||
# be used when making an outbound connection to the server. See the docs
|
||||
# page for the TLS (SSL) module you are using for more details.
|
||||
# ssl: If defined, this states the TLS (SSL) profile that will be used
|
||||
# when making an outbound connection to the server. See the docs page for
|
||||
# the TLS (SSL) module you are using for more details:
|
||||
#
|
||||
# GnuTLS: https://docs.inspircd.org/3/modules/ssl_gnutls#sslprofile
|
||||
# mbedTLS: https://docs.inspircd.org/3/modules/ssl_mbedtls#sslprofile
|
||||
# OpenSSL: https://docs.inspircd.org/3/modules/ssl_openssl#sslprofile
|
||||
#
|
||||
# You will need to load the ssl_openssl module for OpenSSL, ssl_gnutls
|
||||
# for GnuTLS and ssl_mbedtls for mbedTLS. The server port that you
|
||||
# connect to must be capable of accepting this type of connection.
|
||||
ssl="gnutls"
|
||||
ssl="Servers"
|
||||
|
||||
# fingerprint: If defined, this option will force servers to be
|
||||
# authenticated using TLS (SSL) certificate fingerprints. See
|
||||
@ -96,7 +100,7 @@
|
||||
port="7000"
|
||||
allowmask="203.0.113.0/24 127.0.0.0/8 2001:db8::/32"
|
||||
timeout="5m"
|
||||
ssl="gnutls"
|
||||
ssl="Servers"
|
||||
bind="1.2.3.4"
|
||||
statshidden="no"
|
||||
hidden="no"
|
||||
|
@ -343,14 +343,14 @@
|
||||
# message to the server on connection. For more details please read the
|
||||
# IRCv3 WebIRC specification at: https://ircv3.net/specs/extensions/webirc.html
|
||||
#
|
||||
# When using this method you must specify a wildcard mask or CIDR range
|
||||
# to allow gateway connections from and at least one of either a TLS (SSL)
|
||||
# client certificate fingerprint for the gateway or a password to be
|
||||
# sent in the WEBIRC command.
|
||||
# When using this method you must specify one or more wildcard masks
|
||||
# or CIDR ranges to allow gateway connections from and at least one of
|
||||
# either a TLS (SSL) client certificate fingerprint for the gateway or
|
||||
# a password to be sent in the WEBIRC command.
|
||||
#
|
||||
# <cgihost type="webirc"
|
||||
# fingerprint="bd90547b59c1942b85f382bc059318f4c6ca54c5"
|
||||
# mask="192.0.2.0/24">
|
||||
# mask="192.0.2.0/24 198.51.100.*">
|
||||
# <cgihost type="webirc"
|
||||
# password="$2a$10$WEUpX9GweJiEF1WxBDSkeODBstIBMlVPweQTG9cKM8/Vd58BeM5cW"
|
||||
# hash="bcrypt"
|
||||
@ -361,13 +361,14 @@
|
||||
# address in the ident sent by the user. This is not recommended as it
|
||||
# only works with IPv4 connections.
|
||||
#
|
||||
# When using this method you must specify a wildcard mask or CIDR range to allow
|
||||
# gateway connections from. You can also optionally configure the static value
|
||||
# that replaces the IP in the ident to avoid leaking the real IP address of
|
||||
# gateway clients (defaults to "gateway" if not set).
|
||||
# When using this method you must specify one or more wildcard masks
|
||||
# or CIDR ranges to allow gateway connections from. You can also
|
||||
# optionally configure the static value that replaces the IP in the
|
||||
# ident to avoid leaking the real IP address of gateway clients
|
||||
# (defaults to "gateway" if not set).
|
||||
#
|
||||
# <cgihost type="ident"
|
||||
# mask="198.51.100.0/24"
|
||||
# mask="198.51.100.0/24 203.0.113.*"
|
||||
# newident="wibble">
|
||||
# <cgihost type="ident"
|
||||
# mask="*.ident.gateway.example.com"
|
||||
@ -836,7 +837,17 @@
|
||||
#<module name="dnsbl">
|
||||
# #
|
||||
# For configuration options please see the docs page for dnsbl at #
|
||||
# https://docs.inspircd.org/3/modules/dnsbl #
|
||||
# https://docs.inspircd.org/3/modules/dnsbl. You can also use one or #
|
||||
# more of the following example configs for popular DNSBLs: #
|
||||
# #
|
||||
# DroneBL (https://dronebl.org) #
|
||||
#<include file="examples/providers/dronebl.conf.example">
|
||||
# #
|
||||
# EFnet RBL (https://rbl.efnetrbl.org) #
|
||||
#<include file="examples/providers/efnet-rbl.conf.example">
|
||||
# #
|
||||
# dan.me.uk Tor exit node DNSBL (https://www.dan.me.uk/dnsbl) #
|
||||
#<include file="examples/providers/torexit.conf.example">
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# Exempt channel operators module: Provides support for allowing #
|
||||
@ -1953,8 +1964,6 @@
|
||||
# securelist blocking these sites from listing, define exception tags #
|
||||
# as shown below: #
|
||||
#<securehost exception="*@*.netsplit.de">
|
||||
#<securehost exception="*@*.ircdriven.com">
|
||||
#<securehost exception="*@*.ircs.me">
|
||||
# #
|
||||
# exemptregistered - Whether the waiting period applies to users who #
|
||||
# are logged in to a services account. #
|
||||
|
11
docs/conf/providers/dronebl.conf.example
Normal file
11
docs/conf/providers/dronebl.conf.example
Normal file
@ -0,0 +1,11 @@
|
||||
# This file contains configuration for using the dnsbl module with
|
||||
# the DroneBL DNSBL. See https://dronebl.org/ for more information on
|
||||
# DroneBL.
|
||||
|
||||
<dnsbl name="DroneBL"
|
||||
domain="dnsbl.dronebl.org"
|
||||
type="record"
|
||||
records="3,5,6,7,8,9,10,11,13,14,15,16,17,19"
|
||||
action="zline"
|
||||
duration="7d"
|
||||
reason="You are listed in DroneBL. Please visit https://dronebl.org/lookup.do?ip=%ip% for more information.">
|
11
docs/conf/providers/efnet-rbl.conf.example
Normal file
11
docs/conf/providers/efnet-rbl.conf.example
Normal file
@ -0,0 +1,11 @@
|
||||
# This file contains configuration for using the dnsbl module with
|
||||
# the EFnet RBL. See https://rbl.efnetrbl.org/ for more information
|
||||
# on the EFnet RBL.
|
||||
|
||||
<dnsbl name="EFnet RBL"
|
||||
domain="rbl.efnetrbl.org"
|
||||
type="record"
|
||||
records="1,2,3,4,5"
|
||||
action="zline"
|
||||
duration="7d"
|
||||
reason="You are listed in the EFnet RBL. Please visit https://rbl.efnetrbl.org/?i=%ip% for more information.">
|
11
docs/conf/providers/torexit.conf.example
Normal file
11
docs/conf/providers/torexit.conf.example
Normal file
@ -0,0 +1,11 @@
|
||||
# This file contains configuration for using the dnsbl module with
|
||||
# the dan.me.uk Tor exit node DNSBL. See https://www.dan.me.uk/dnsbl
|
||||
# for more information on the dan.me.uk Tor exit node DNSBL.
|
||||
|
||||
<dnsbl name="torexit.dan.me.uk"
|
||||
domain="torexit.dan.me.uk"
|
||||
type="record"
|
||||
records="100"
|
||||
action="zline"
|
||||
duration="7d"
|
||||
reason="Tor exit nodes are not allowed on this network. See https://metrics.torproject.org/rs.html#search/%ip% for more information.">
|
@ -33,9 +33,27 @@ struct ParseStack
|
||||
ParseStack(ServerConfig* conf)
|
||||
: output(conf->config_data), FilesOutput(conf->Files), errstr(conf->errstr)
|
||||
{
|
||||
vars["amp"] = "&";
|
||||
// Special character escapes.
|
||||
vars["newline"] = "\n";
|
||||
vars["nl"] = "\n";
|
||||
|
||||
// XML escapes.
|
||||
vars["amp"] = "&";
|
||||
vars["apos"] = "'";
|
||||
vars["gt"] = ">";
|
||||
vars["lt"] = "<";
|
||||
vars["quot"] = "\"";
|
||||
vars["newline"] = vars["nl"] = "\n";
|
||||
|
||||
// IRC formatting codes.
|
||||
vars["irc.bold"] = "\x02";
|
||||
vars["irc.color"] = "\x03";
|
||||
vars["irc.colour"] = "\x03";
|
||||
vars["irc.italic"] = "\x1D";
|
||||
vars["irc.monospace"] = "\x11";
|
||||
vars["irc.reset"] = "\x0F";
|
||||
vars["irc.reverse"] = "\x16";
|
||||
vars["irc.strikethrough"] = "\x1E";
|
||||
vars["irc.underline"] = "\x1F";
|
||||
}
|
||||
bool ParseFile(const std::string& name, int flags, const std::string& mandatory_tag = std::string(), bool isexec = false);
|
||||
void DoInclude(std::shared_ptr<ConfigTag> includeTag, int flags);
|
||||
|
@ -194,7 +194,7 @@ inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleE
|
||||
template<typename Class, typename... FunArgs, typename... FwdArgs>
|
||||
inline void Events::ModuleEventProvider::Call(void (Class::*function)(FunArgs...), FwdArgs&&... args) const
|
||||
{
|
||||
if (!GetModule() || GetModule()->dying)
|
||||
if (GetModule() && GetModule()->dying)
|
||||
return;
|
||||
|
||||
for (const auto& subscriber : subscribers)
|
||||
@ -211,7 +211,7 @@ inline void Events::ModuleEventProvider::Call(void (Class::*function)(FunArgs...
|
||||
template<typename Class, typename... FunArgs, typename... FwdArgs>
|
||||
inline ModResult Events::ModuleEventProvider::FirstResult(ModResult (Class::*function)(FunArgs...), FwdArgs&&... args) const
|
||||
{
|
||||
if (!GetModule() || GetModule()->dying)
|
||||
if (GetModule() && GetModule()->dying)
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
ModResult result;
|
||||
|
@ -49,6 +49,7 @@ enum
|
||||
RPL_MAP = 15, // ircu
|
||||
RPL_ENDMAP = 17, // ircu
|
||||
RPL_MAPUSERS = 18, // insp-specific
|
||||
RPL_SAVENICK = 43, // From irc2.
|
||||
|
||||
RPL_STATS = 210, // From aircd.
|
||||
RPL_UMODEIS = 221,
|
||||
|
@ -34,6 +34,7 @@ use File::Spec::Functions qw(rel2abs);
|
||||
|
||||
our @EXPORT = qw(command
|
||||
execute_command
|
||||
console_format
|
||||
print_format
|
||||
print_error
|
||||
print_warning
|
||||
@ -59,20 +60,23 @@ struct 'command' => {
|
||||
'description' => '$',
|
||||
};
|
||||
|
||||
sub __console_format($$) {
|
||||
my ($name, $data) = @_;
|
||||
return $data unless -t STDOUT;
|
||||
return $FORMAT_CODES{uc $name} . $data . $FORMAT_CODES{DEFAULT};
|
||||
sub console_format($) {
|
||||
my $message = shift;
|
||||
while ($message =~ /(<\|(\S+)\s(.*?)\|>)/) {
|
||||
my ($match, $type, $text) = ($1, uc $2, $3);
|
||||
if (-t STDOUT && exists $FORMAT_CODES{$type}) {
|
||||
$message =~ s/\Q$match\E/$FORMAT_CODES{$type}$text$FORMAT_CODES{DEFAULT}/;
|
||||
} else {
|
||||
$message =~ s/\Q$match\E/$text/;
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
sub print_format($;$) {
|
||||
my $message = shift;
|
||||
my $stream = shift // *STDOUT;
|
||||
while ($message =~ /(<\|(\S+)\s(.*?)\|>)/) {
|
||||
my $formatted = __console_format $2, $3;
|
||||
$message =~ s/\Q$1\E/$formatted/;
|
||||
}
|
||||
print { $stream } $message;
|
||||
print { $stream } console_format $message;
|
||||
}
|
||||
|
||||
sub print_error {
|
||||
|
@ -172,7 +172,7 @@ sub cmd_rehash()
|
||||
{
|
||||
if (getstatus() == 1) {
|
||||
my $pid = getprocessid();
|
||||
system("kill -HUP $pid >/dev/null 2>&1");
|
||||
kill HUP => $pid;
|
||||
print "InspIRCd rehashed (pid: $pid).\n";
|
||||
exit GENERIC_EXIT_SUCCESS;
|
||||
} else {
|
||||
|
@ -39,16 +39,19 @@ enum
|
||||
RPL_WHOISGATEWAY = 350
|
||||
};
|
||||
|
||||
// One or more hostmask globs or CIDR ranges.
|
||||
typedef std::vector<std::string> MaskList;
|
||||
|
||||
// Encapsulates information about an ident host.
|
||||
class IdentHost
|
||||
{
|
||||
private:
|
||||
std::string hostmask;
|
||||
MaskList hostmasks;
|
||||
std::string newident;
|
||||
|
||||
public:
|
||||
IdentHost(const std::string& mask, const std::string& ident)
|
||||
: hostmask(mask)
|
||||
IdentHost(const MaskList& masks, const std::string& ident)
|
||||
: hostmasks(masks)
|
||||
, newident(ident)
|
||||
{
|
||||
}
|
||||
@ -60,10 +63,19 @@ class IdentHost
|
||||
|
||||
bool Matches(LocalUser* user) const
|
||||
{
|
||||
if (!InspIRCd::Match(user->GetRealHost(), hostmask, ascii_case_insensitive_map))
|
||||
return false;
|
||||
for (MaskList::const_iterator iter = hostmasks.begin(); iter != hostmasks.end(); ++iter)
|
||||
{
|
||||
// Does the user's hostname match this hostmask?
|
||||
if (InspIRCd::Match(user->GetRealHost(), *iter, ascii_case_insensitive_map))
|
||||
return true;
|
||||
|
||||
return InspIRCd::MatchCIDR(user->GetIPString(), hostmask, ascii_case_insensitive_map);
|
||||
// Does the user's IP address match this hostmask?
|
||||
if (InspIRCd::MatchCIDR(user->GetIPString(), *iter, ascii_case_insensitive_map))
|
||||
return true;
|
||||
}
|
||||
|
||||
// The user didn't match any hostmasks.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@ -71,14 +83,14 @@ class IdentHost
|
||||
class WebIRCHost
|
||||
{
|
||||
private:
|
||||
std::string hostmask;
|
||||
MaskList hostmasks;
|
||||
std::string fingerprint;
|
||||
std::string password;
|
||||
std::string passhash;
|
||||
|
||||
public:
|
||||
WebIRCHost(const std::string& mask, const std::string& fp, const std::string& pass, const std::string& hash)
|
||||
: hostmask(mask)
|
||||
WebIRCHost(const MaskList& masks, const std::string& fp, const std::string& pass, const std::string& hash)
|
||||
: hostmasks(masks)
|
||||
, fingerprint(fp)
|
||||
, password(pass)
|
||||
, passhash(hash)
|
||||
@ -96,26 +108,22 @@ class WebIRCHost
|
||||
if (!fingerprint.empty() && !InspIRCd::TimingSafeCompare(fp, fingerprint))
|
||||
return false;
|
||||
|
||||
// Does the user's hostname match our hostmask?
|
||||
if (InspIRCd::Match(user->GetRealHost(), hostmask, ascii_case_insensitive_map))
|
||||
return true;
|
||||
for (MaskList::const_iterator iter = hostmasks.begin(); iter != hostmasks.end(); ++iter)
|
||||
{
|
||||
// Does the user's hostname match this hostmask?
|
||||
if (InspIRCd::Match(user->GetRealHost(), *iter, ascii_case_insensitive_map))
|
||||
return true;
|
||||
|
||||
// Does the user's IP address match our hostmask?
|
||||
return InspIRCd::MatchCIDR(user->GetIPString(), hostmask, ascii_case_insensitive_map);
|
||||
// Does the user's IP address match this hostmask?
|
||||
if (InspIRCd::MatchCIDR(user->GetIPString(), *iter, ascii_case_insensitive_map))
|
||||
return true;
|
||||
}
|
||||
|
||||
// The user didn't match any hostmasks.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* WEBIRC
|
||||
* This is used for the webirc method of CGIIRC auth, and is (really) the best way to do these things.
|
||||
* Syntax: WEBIRC password gateway hostname ip
|
||||
* Where password is a shared key, gateway is the name of the WebIRC gateway and version (e.g. cgiirc), hostname
|
||||
* is the resolved host of the client issuing the command and IP is the real IP of the client.
|
||||
*
|
||||
* How it works:
|
||||
* To tie in with the rest of cgiirc module, and to avoid race conditions, /webirc is only processed locally
|
||||
* and simply sets metadata on the user, which is later decoded on full connect to give something meaningful.
|
||||
*/
|
||||
class CommandWebIRC : public SplitCommand
|
||||
{
|
||||
public:
|
||||
@ -287,9 +295,13 @@ class ModuleCgiIRC
|
||||
|
||||
for (auto& [_, tag] : ServerInstance->Config->ConfTags("cgihost"))
|
||||
{
|
||||
MaskList masks;
|
||||
irc::spacesepstream maskstream(tag->getString("mask"));
|
||||
for (std::string mask; maskstream.GetToken(mask); )
|
||||
masks.push_back(mask);
|
||||
|
||||
// Ensure that we have the <cgihost:mask> parameter.
|
||||
const std::string mask = tag->getString("mask");
|
||||
if (mask.empty())
|
||||
if (masks.empty())
|
||||
throw ModuleException("<cgihost:mask> is a mandatory field, at " + tag->source.str());
|
||||
|
||||
// Determine what lookup type this host uses.
|
||||
@ -298,7 +310,7 @@ class ModuleCgiIRC
|
||||
{
|
||||
// The IP address should be looked up from the hex IP address.
|
||||
const std::string newident = tag->getString("newident", "gateway", ServerInstance->IsIdent);
|
||||
identhosts.push_back(IdentHost(mask, newident));
|
||||
identhosts.push_back(IdentHost(masks, newident));
|
||||
}
|
||||
else if (stdalgo::string::equalsci(type, "webirc"))
|
||||
{
|
||||
@ -317,7 +329,7 @@ class ModuleCgiIRC
|
||||
tag->source.str().c_str());
|
||||
}
|
||||
|
||||
webirchosts.push_back(WebIRCHost(mask, fingerprint, password, passwordhash));
|
||||
webirchosts.push_back(WebIRCHost(masks, fingerprint, password, passwordhash));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -24,16 +24,28 @@
|
||||
class ClassExtBan
|
||||
: public ExtBan::MatchingBase
|
||||
{
|
||||
private:
|
||||
std::string space;
|
||||
std::string underscore;
|
||||
|
||||
public:
|
||||
ClassExtBan(Module* Creator)
|
||||
: ExtBan::MatchingBase(Creator, "class", 'n')
|
||||
, space(" ")
|
||||
, underscore("_")
|
||||
{
|
||||
}
|
||||
|
||||
bool IsMatch(User* user, Channel* channel, const std::string& text) override
|
||||
{
|
||||
LocalUser* luser = IS_LOCAL(user);
|
||||
return luser && InspIRCd::Match(luser->GetClass()->name, text);
|
||||
if (!luser)
|
||||
return false;
|
||||
|
||||
// Replace spaces with underscores as they're prohibited in mode parameters.
|
||||
std::string classname(luser->GetClass()->name);
|
||||
stdalgo::string::replace_all(classname, space, underscore);
|
||||
return InspIRCd::Match(classname, text);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -76,6 +76,21 @@ class ModuleCodepage
|
||||
hashmap.swap(newhash);
|
||||
}
|
||||
|
||||
void CheckDuplicateNick()
|
||||
{
|
||||
insp::flat_set<std::string, irc::insensitive_swo> duplicates;
|
||||
const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
|
||||
for (UserManager::LocalList::const_iterator iter = list.begin(); iter != list.end(); ++iter)
|
||||
{
|
||||
LocalUser* user = *iter;
|
||||
if (user->nick != user->uuid && !duplicates.insert(user->nick).second)
|
||||
{
|
||||
user->WriteNumeric(RPL_SAVENICK, user->uuid, "Your nickname is no longer available.");
|
||||
user->ChangeNick(user->uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInvalidNick()
|
||||
{
|
||||
const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
|
||||
@ -83,7 +98,10 @@ class ModuleCodepage
|
||||
{
|
||||
LocalUser* user = *iter;
|
||||
if (user->nick != user->uuid && !ServerInstance->IsNick(user->nick))
|
||||
{
|
||||
user->WriteNumeric(RPL_SAVENICK, user->uuid, "Your nickname is no longer valid.");
|
||||
user->ChangeNick(user->uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,6 +131,7 @@ class ModuleCodepage
|
||||
|
||||
ServerInstance->Config->CaseMapping = origcasemapname;
|
||||
national_case_insensitive_map = origcasemap;
|
||||
CheckDuplicateNick();
|
||||
CheckRehash(casemap);
|
||||
}
|
||||
|
||||
|
@ -53,11 +53,7 @@ class OperExtBan
|
||||
if (!user->IsOper())
|
||||
return false;
|
||||
|
||||
// Check whether the oper's type matches the ban.
|
||||
if (InspIRCd::Match(user->oper->name, text))
|
||||
return true;
|
||||
|
||||
// If the oper's type contains spaces recheck with underscores.
|
||||
// Replace spaces with underscores as they're prohibited in mode parameters.
|
||||
std::string opername(user->oper->name);
|
||||
stdalgo::string::replace_all(opername, space, underscore);
|
||||
return InspIRCd::Match(opername, text);
|
||||
|
@ -36,6 +36,7 @@
|
||||
CommandMap::CommandMap(Module* Creator)
|
||||
: Command(Creator, "MAP", 0, 1)
|
||||
{
|
||||
allow_empty_last_param = false;
|
||||
Penalty = 2;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ CmdResult CommandSVSNick::Handle(User* user, Params& parameters)
|
||||
if (!u->ChangeNick(nick, NickTS))
|
||||
{
|
||||
// Changing to 'nick' failed (it may already be in use), change to the uuid
|
||||
u->WriteNumeric(RPL_SAVENICK, u->uuid, "Your nickname is in use by an older user on a new server.");
|
||||
u->ChangeNick(u->uuid);
|
||||
}
|
||||
}
|
||||
|
@ -661,6 +661,7 @@ bool QLine::Matches(User *u)
|
||||
void QLine::Apply(User* u)
|
||||
{
|
||||
/* Force to uuid on apply of Q-line, no need to disconnect anymore :) */
|
||||
u->WriteNumeric(RPL_SAVENICK, u->uuid, "Your nickname has been Q-lined.");
|
||||
u->ChangeNick(u->uuid);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user