mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 10:39:02 -04:00
Merge branch 'insp3' into master.
This commit is contained in:
commit
7bdd72f634
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -35,5 +35,5 @@ Tick the boxes for the checks you have made.
|
||||
I have ensured that:
|
||||
|
||||
- [ ] This pull request does not introduce any incompatible API changes.
|
||||
- [ ] If ABI changes have been made I have incremented INSPIRCD_VERSION_API.
|
||||
- [ ] If ABI changes have been made I have incremented MODULE_ABI in `moduledefs.h`.
|
||||
- [ ] I have documented any features added by this pull request.
|
||||
|
6
.github/workflows/ci-macos.yml
vendored
6
.github/workflows/ci-macos.yml
vendored
@ -14,8 +14,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install pkg-config gnutls libmaxminddb libpq mbedtls mysql-client openssl@1.1 pcre re2 sqlite3 tre
|
||||
brew link --force libpq
|
||||
brew link --force mysql-client
|
||||
brew link --force --overwrite libpq
|
||||
brew link --force --overwrite mysql-client
|
||||
- name: Run test-build
|
||||
run: ./tools/test-build c++
|
||||
|
@ -4,7 +4,7 @@ InspIRCd is a modular C++ Internet Relay Chat (IRC) server for UNIX-like and Win
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
InspIRCd is supported on on the following platforms:
|
||||
InspIRCd is supported on the following platforms:
|
||||
|
||||
- Most recent BSD variants using the Clang 3.8+ or GCC 5+ compilers and the GNU toolchains (Make, etc).
|
||||
|
||||
|
2
configure
vendored
2
configure
vendored
@ -430,7 +430,7 @@ print_format <<"EOM";
|
||||
<|GREEN Execution User:|> $config{USER} ($config{UID})
|
||||
<|GREEN Socket Engine:|> $config{SOCKETENGINE}
|
||||
|
||||
To build with these settings run '<|GREEN make -j${\get_cpu_count} install|>' now.
|
||||
To build with these settings run '<|GREEN make -j${\get_cpu_count + 1} install|>' now.
|
||||
|
||||
EOM
|
||||
|
||||
|
@ -901,7 +901,7 @@
|
||||
# other modules that need it using the libMaxMindDB library. #
|
||||
# #
|
||||
# This module is in extras. Re-run configure with: #
|
||||
# ./configure --enable-extras=m_geo_maxmind.cpp
|
||||
# ./configure --enable-extras geo_maxmind
|
||||
# and run make install, then uncomment this module to enable it. #
|
||||
# #
|
||||
# This module requires libMaxMindDB to be installed on your system. #
|
||||
@ -1220,7 +1220,7 @@
|
||||
# LDAP module: Allows other SQL modules to access a LDAP database
|
||||
# through a unified API.
|
||||
# This modules is in extras. Re-run configure with:
|
||||
# ./configure --enable-extras=m_ldap.cpp
|
||||
# ./configure --enable-extras ldap
|
||||
# and run make install, then uncomment this module to enable it.
|
||||
#
|
||||
#<module name="ldap">
|
||||
@ -1364,7 +1364,7 @@
|
||||
# MySQL module: Allows other SQL modules to access MySQL databases
|
||||
# through a unified API.
|
||||
# This module is in extras. Re-run configure with:
|
||||
# ./configure --enable-extras=m_mysql.cpp
|
||||
# ./configure --enable-extras mysql
|
||||
# and run make install, then uncomment this module to enable it.
|
||||
#<module name="mysql">
|
||||
#
|
||||
@ -1655,7 +1655,7 @@
|
||||
# PostgreSQL module: Allows other SQL modules to access PgSQL databases
|
||||
# through a unified API.
|
||||
# This module is in extras. Re-run configure with:
|
||||
# ./configure --enable-extras=m_pgsql.cpp
|
||||
# ./configure --enable-extras pgsql
|
||||
# and run make install, then uncomment this module to enable it.
|
||||
#<module name="pgsql">
|
||||
#
|
||||
@ -2058,7 +2058,7 @@
|
||||
# SSL rehash signal module: Allows the SSL modules to be rehashed by
|
||||
# sending SIGUSR1 to a running InspIRCd process.
|
||||
# This modules is in extras. Re-run configure with:
|
||||
# ./configure --enable-extras=m_sslrehashsignal.cpp
|
||||
# ./configure --enable-extras sslrehashsignal
|
||||
# and run make install, then uncomment this module to enable it.
|
||||
#<module name="sslrehashsignal">
|
||||
|
||||
@ -2135,7 +2135,7 @@
|
||||
# SQLite3 module: Allows other SQL modules to access SQLite3 #
|
||||
# databases through a unified API. #
|
||||
# This module is in extras. Re-run configure with: #
|
||||
# ./configure --enable-extras=m_sqlite3.cpp
|
||||
# ./configure --enable-extras sqlite3
|
||||
# and run make install, then uncomment this module to enable it. #
|
||||
#
|
||||
#<module name="sqlite3">
|
||||
|
@ -52,6 +52,11 @@ class IRCv3::Replies::Reply
|
||||
user->Send(ev);
|
||||
}
|
||||
|
||||
void SendNoticeInternal(LocalUser* user, Command* command, const std::string& description)
|
||||
{
|
||||
user->WriteNotice(InspIRCd::Format("*** %s: %s", command->name.c_str(), description.c_str()));
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Initializes a new instance of the Reply class.
|
||||
* @param Creator The module which created this instance.
|
||||
@ -163,7 +168,57 @@ class IRCv3::Replies::Reply
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, description);
|
||||
else
|
||||
user->WriteNotice(InspIRCd::Format("*** %s: %s", command->name.c_str(), description.c_str()));
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
|
||||
const T1& p1, const std::string& description)
|
||||
{
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, p1, description);
|
||||
else
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
|
||||
const T1& p1, const T2& p2, const std::string& description)
|
||||
{
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, p1, p2, description);
|
||||
else
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
|
||||
const T1& p1, const T2& p2, const T3& p3, const std::string& description)
|
||||
{
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, p1, p2, p3, description);
|
||||
else
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
|
||||
const T1& p1, const T2& p2, const T3& p3, const T4& p4, const std::string& description)
|
||||
{
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, p1, p2, p3, p4, description);
|
||||
else
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code,
|
||||
const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const std::string& description)
|
||||
{
|
||||
if (cap.get(user))
|
||||
Send(user, command, code, p1, p2, p3, p4, p5, description);
|
||||
else
|
||||
SendNoticeInternal(user, command, description);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,7 @@ enum
|
||||
RPL_ENDMAP = 17, // ircu
|
||||
RPL_MAPUSERS = 18, // insp-specific
|
||||
|
||||
RPL_STATS = 210, // From aircd.
|
||||
RPL_UMODEIS = 221,
|
||||
|
||||
RPL_LUSERCLIENT = 251,
|
||||
@ -85,8 +86,6 @@ enum
|
||||
|
||||
RPL_USERIP = 340,
|
||||
RPL_INVITING = 341,
|
||||
RPL_INVITELIST = 346, // insp-specific (stolen from ircu)
|
||||
RPL_ENDOFINVITELIST = 347, // insp-specific (stolen from ircu)
|
||||
RPL_VERSION = 351,
|
||||
RPL_NAMREPLY = 353,
|
||||
RPL_LINKS = 364,
|
||||
|
@ -182,6 +182,9 @@ class CoreExport EventHandler : public classbase
|
||||
*/
|
||||
inline int GetFd() const { return fd; }
|
||||
|
||||
/** Checks if this event handler has a fd associated with it. */
|
||||
inline bool HasFd() const { return fd >= 0; }
|
||||
|
||||
inline int GetEventMask() const { return event_mask; }
|
||||
|
||||
/** Set a new file desciptor
|
||||
|
@ -528,14 +528,12 @@ class CoreExport XLineManager
|
||||
*/
|
||||
void ApplyLines();
|
||||
|
||||
/** Handle /STATS for a given type.
|
||||
* NOTE: Any items in the list for this particular line type which have expired
|
||||
* 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 stats Stats context
|
||||
/** Generates a /STATS response for the given X-line type.
|
||||
* @param type The type of X-line to look up.
|
||||
* @param context The stats context to respond with.
|
||||
* @return True if a response was sent; otherwise, false.
|
||||
*/
|
||||
void InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats);
|
||||
bool InvokeStats(const std::string& type, Stats::Context& context);
|
||||
|
||||
/** Expire X-lines which were added by the server configuration and have been removed. */
|
||||
void ExpireRemovedConfigLines(const std::string& type, const insp::flat_set<std::string>& configlines);
|
||||
|
@ -31,6 +31,13 @@
|
||||
#include "core_channel.h"
|
||||
#include "invite.h"
|
||||
|
||||
enum
|
||||
{
|
||||
// From ircd-hybrid.
|
||||
RPL_INVITELIST = 336,
|
||||
RPL_ENDOFINVITELIST = 337
|
||||
};
|
||||
|
||||
CommandInvite::CommandInvite(Module* parent, Invite::APIImpl& invapiimpl)
|
||||
: Command(parent, "INVITE", 0, 0)
|
||||
, invapi(invapiimpl)
|
||||
|
@ -50,6 +50,13 @@ namespace Invite
|
||||
};
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
// From RFC 1459.
|
||||
RPL_BANLIST = 367,
|
||||
RPL_ENDOFBANLIST = 368
|
||||
};
|
||||
|
||||
/** Handle /INVITE.
|
||||
*/
|
||||
class CommandInvite : public Command
|
||||
@ -164,7 +171,7 @@ class ModeChannelBan : public ListModeBase
|
||||
{
|
||||
public:
|
||||
ModeChannelBan(Module* Creator)
|
||||
: ListModeBase(Creator, "ban", 'b', "End of channel ban list", 367, 368, true)
|
||||
: ListModeBase(Creator, "ban", 'b', "End of channel ban list", RPL_BANLIST, RPL_ENDOFBANLIST, true)
|
||||
{
|
||||
syntax = "<mask>";
|
||||
}
|
||||
|
@ -701,7 +701,7 @@ class MyManager : public Manager, public Timer, public EventHandler
|
||||
|
||||
void Rehash(const std::string& dnsserver, std::string sourceaddr, unsigned int sourceport)
|
||||
{
|
||||
if (this->GetFd() > -1)
|
||||
if (this->HasFd())
|
||||
{
|
||||
SocketEngine::Shutdown(this, 2);
|
||||
SocketEngine::Close(this);
|
||||
|
@ -720,11 +720,9 @@ class ReloadAction : public ActionBase
|
||||
ReloadModule::DataKeeper datakeeper;
|
||||
datakeeper.Save(mod);
|
||||
|
||||
DLLManager* dll = mod->ModuleDLLManager;
|
||||
std::string name = mod->ModuleSourceFile;
|
||||
ServerInstance->Modules.DoSafeUnload(mod);
|
||||
ServerInstance->GlobalCulls.Apply();
|
||||
delete dll;
|
||||
bool result = ServerInstance->Modules.Load(name);
|
||||
|
||||
if (result)
|
||||
|
@ -195,19 +195,19 @@ void CommandStats::DoStats(Stats::Context& stats)
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
ServerInstance->XLines->InvokeStats("K",216,stats);
|
||||
ServerInstance->XLines->InvokeStats("K", stats);
|
||||
break;
|
||||
case 'g':
|
||||
ServerInstance->XLines->InvokeStats("G",223,stats);
|
||||
ServerInstance->XLines->InvokeStats("G", stats);
|
||||
break;
|
||||
case 'q':
|
||||
ServerInstance->XLines->InvokeStats("Q",217,stats);
|
||||
ServerInstance->XLines->InvokeStats("Q", stats);
|
||||
break;
|
||||
case 'Z':
|
||||
ServerInstance->XLines->InvokeStats("Z",223,stats);
|
||||
ServerInstance->XLines->InvokeStats("Z", stats);
|
||||
break;
|
||||
case 'e':
|
||||
ServerInstance->XLines->InvokeStats("E",223,stats);
|
||||
ServerInstance->XLines->InvokeStats("E", stats);
|
||||
break;
|
||||
case 'E':
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_t
|
||||
|
||||
ListenSocket::~ListenSocket()
|
||||
{
|
||||
if (this->GetFd() > -1)
|
||||
if (this->HasFd())
|
||||
{
|
||||
ServerInstance->Logs.Log("SOCKET", LOG_DEBUG, "Shut down listener on fd %d", this->fd);
|
||||
SocketEngine::Shutdown(this, 2);
|
||||
|
@ -57,6 +57,8 @@ Version::Version(const std::string &desc, int flags, const std::string& linkdata
|
||||
// These declarations define the behavours of the base class Module (which does nothing at all)
|
||||
CullResult Module::cull()
|
||||
{
|
||||
if (ModuleDLLManager)
|
||||
ServerInstance->GlobalCulls.AddItem(ModuleDLLManager);
|
||||
return classbase::cull();
|
||||
}
|
||||
|
||||
@ -441,11 +443,8 @@ namespace
|
||||
UnloadAction(Module* m) : mod(m) {}
|
||||
void Call() override
|
||||
{
|
||||
DLLManager* dll = mod->ModuleDLLManager;
|
||||
ServerInstance->Modules.DoSafeUnload(mod);
|
||||
ServerInstance->GlobalCulls.Apply();
|
||||
// In pure static mode this is always NULL
|
||||
delete dll;
|
||||
ServerInstance->GlobalCulls.AddItem(this);
|
||||
}
|
||||
};
|
||||
|
@ -24,13 +24,18 @@
|
||||
#include "inspircd.h"
|
||||
#include "listmode.h"
|
||||
|
||||
/** Handles +w channel mode
|
||||
*/
|
||||
enum
|
||||
{
|
||||
// InspIRCd-specific.
|
||||
RPL_ACCESSLIST = 910,
|
||||
RPL_ENDOFACCESSLIST = 911
|
||||
};
|
||||
|
||||
class AutoOpList : public ListModeBase
|
||||
{
|
||||
public:
|
||||
AutoOpList(Module* Creator)
|
||||
: ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", 910, 911, true)
|
||||
: ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", RPL_ACCESSLIST, RPL_ENDOFACCESSLIST, true)
|
||||
{
|
||||
ranktoset = ranktounset = OP_VALUE;
|
||||
syntax = "<prefix>:<mask>";
|
||||
|
@ -27,28 +27,23 @@
|
||||
#include "listmode.h"
|
||||
#include "modules/isupport.h"
|
||||
|
||||
/* Written by Om<om@inspircd.org>, April 2005. */
|
||||
/* Rewritten to use the listmode utility by Om, December 2005 */
|
||||
/* Adapted from m_exception, which was originally based on m_chanprotect and m_silence */
|
||||
enum
|
||||
{
|
||||
// From RFC 2812.
|
||||
RPL_EXCEPTLIST = 348,
|
||||
RPL_ENDOFEXCEPTLIST = 349
|
||||
};
|
||||
|
||||
// The +e channel mode takes a nick!ident@host, glob patterns allowed,
|
||||
// and if a user matches an entry on the +e list then they can join the channel, overriding any (+b) bans set on them
|
||||
// Now supports CIDR and IP addresses -- Brain
|
||||
|
||||
|
||||
/** Handles +e channel mode
|
||||
*/
|
||||
class BanException : public ListModeBase
|
||||
{
|
||||
public:
|
||||
BanException(Module* Creator)
|
||||
: ListModeBase(Creator, "banexception", 'e', "End of Channel Exception List", 348, 349, true)
|
||||
: ListModeBase(Creator, "banexception", 'e', "End of Channel Exception List", RPL_EXCEPTLIST, RPL_ENDOFEXCEPTLIST, true)
|
||||
{
|
||||
syntax = "<mask>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ModuleBanException
|
||||
: public Module
|
||||
, public ISupport::EventListener
|
||||
|
@ -188,7 +188,7 @@ class ModuleCBan : public Module, public Stats::EventListener
|
||||
if (stats.GetSymbol() != 'C')
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
ServerInstance->XLines->InvokeStats("CBAN", 210, stats);
|
||||
ServerInstance->XLines->InvokeStats("CBAN", stats);
|
||||
return MOD_RES_DENY;
|
||||
}
|
||||
|
||||
|
@ -27,15 +27,20 @@
|
||||
#include "listmode.h"
|
||||
#include "modules/exemption.h"
|
||||
|
||||
/** Handles channel mode +g
|
||||
*/
|
||||
enum
|
||||
{
|
||||
// InspIRCd-specific.
|
||||
RPL_ENDOFSPAMFILTER = 940,
|
||||
RPL_SPAMFILTER = 941
|
||||
};
|
||||
|
||||
class ChanFilter : public ListModeBase
|
||||
{
|
||||
public:
|
||||
unsigned long maxlen;
|
||||
|
||||
ChanFilter(Module* Creator)
|
||||
: ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", 941, 940, false)
|
||||
: ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", RPL_SPAMFILTER, RPL_ENDOFSPAMFILTER, false)
|
||||
{
|
||||
syntax = "<pattern>";
|
||||
}
|
||||
|
@ -154,6 +154,8 @@ class DCCAllowExt : public SimpleExtItem<dccallowlist>
|
||||
list->push_back(dccallow);
|
||||
}
|
||||
|
||||
// The value was well formed.
|
||||
set(user, list);
|
||||
}
|
||||
|
||||
std::string ToInternal(const Extensible* container, void* item) const override
|
||||
|
@ -25,13 +25,17 @@
|
||||
#include "listmode.h"
|
||||
#include "modules/exemption.h"
|
||||
|
||||
/** Handles channel mode +X
|
||||
*/
|
||||
enum
|
||||
{
|
||||
RPL_ENDOFEXEMPTIONLIST = 953,
|
||||
RPL_EXEMPTIONLIST = 954
|
||||
};
|
||||
|
||||
class ExemptChanOps : public ListModeBase
|
||||
{
|
||||
public:
|
||||
ExemptChanOps(Module* Creator)
|
||||
: ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", 954, 953, false)
|
||||
: ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", RPL_EXEMPTIONLIST, RPL_ENDOFEXEMPTIONLIST, false)
|
||||
{
|
||||
syntax = "<restriction>:<prefix>";
|
||||
}
|
||||
|
@ -897,7 +897,7 @@ ModResult ModuleFilter::OnStats(Stats::Context& stats)
|
||||
{
|
||||
for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); i++)
|
||||
{
|
||||
stats.AddRow(223, RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->duration)+" :"+i->reason);
|
||||
stats.AddRow(223, RegexEngine.GetProvider(), i->freeform, i->GetFlags(), FilterActionToString(i->action), i->duration, i->reason);
|
||||
}
|
||||
for (ExemptTargetSet::const_iterator i = exemptedchans.begin(); i != exemptedchans.end(); ++i)
|
||||
{
|
||||
|
@ -234,10 +234,12 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
|
||||
|
||||
void SendHTTPError(unsigned int response)
|
||||
{
|
||||
HTTPHeaders empty;
|
||||
static HTTPHeaders empty;
|
||||
std::string data = InspIRCd::Format(
|
||||
"<html><head></head><body>Server error %u: %s<br>"
|
||||
"<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>", response, http_status_str((http_status)response));
|
||||
"<html><head></head><body style='font-family: sans-serif; text-align: center'>"
|
||||
"<h1 style='font-size: 48pt'>Error %u</h1><h2 style='font-size: 24pt'>%s</h2><hr>"
|
||||
"<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>",
|
||||
response, http_status_str((http_status)response));
|
||||
|
||||
Page(data, response, &empty);
|
||||
}
|
||||
|
@ -103,7 +103,13 @@ class ModuleHTTPAccessList : public Module, public HTTPACLEventListener
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "BlockAccess (%u)", returnval);
|
||||
|
||||
std::stringstream data("Access to this resource is denied by an access control list. Please contact your IRC administrator.");
|
||||
std::stringstream data;
|
||||
data << "<html><head></head><body style='font-family: sans-serif; text-align: center'>"
|
||||
<< "<h1 style='font-size: 48pt'>Error " << returnval << "</h1>"
|
||||
<< "<h2 style='font-size: 24pt'>Access to this resource is denied by an access control list.</h2>"
|
||||
<< "<h2 style='font-size: 24pt'>Please contact your IRC administrator.</h2><hr>"
|
||||
<< "<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>";
|
||||
|
||||
HTTPDocumentResponse response(this, *http, &data, returnval);
|
||||
response.headers.SetHeader("X-Powered-By", MODNAME);
|
||||
if (!extraheaderkey.empty())
|
||||
|
@ -187,7 +187,7 @@ class IdentRequestSocket : public EventHandler
|
||||
/* Remove ident socket from engine, and close it, but dont detatch it
|
||||
* from its parent user class, or attempt to delete its memory.
|
||||
*/
|
||||
if (GetFd() > -1)
|
||||
if (HasFd())
|
||||
{
|
||||
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Close ident socket %d", GetFd());
|
||||
SocketEngine::Close(this);
|
||||
|
@ -27,23 +27,18 @@
|
||||
#include "listmode.h"
|
||||
#include "modules/isupport.h"
|
||||
|
||||
/*
|
||||
* Written by Om <om@inspircd.org>, April 2005.
|
||||
* Based on m_exception, which was originally based on m_chanprotect and m_silence
|
||||
*
|
||||
* The +I channel mode takes a nick!ident@host, glob patterns allowed,
|
||||
* and if a user matches an entry on the +I list then they can join the channel,
|
||||
* ignoring if +i is set on the channel
|
||||
* Now supports CIDR and IP addresses -- Brain
|
||||
*/
|
||||
enum
|
||||
{
|
||||
// From RFC 2812.
|
||||
RPL_INVEXLIST = 346,
|
||||
RPL_ENDOFINVEXLIST = 347
|
||||
};
|
||||
|
||||
/** Handles channel mode +I
|
||||
*/
|
||||
class InviteException : public ListModeBase
|
||||
{
|
||||
public:
|
||||
InviteException(Module* Creator)
|
||||
: ListModeBase(Creator, "invex", 'I', "End of Channel Invite Exception List", 346, 347, true)
|
||||
: ListModeBase(Creator, "invex", 'I', "End of Channel Invite Exception List", RPL_INVEXLIST, RPL_ENDOFINVEXLIST, true)
|
||||
{
|
||||
syntax = "<mask>";
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
|
||||
continue;
|
||||
|
||||
// Check that this user can actually see the cap.
|
||||
if (!cap->OnList(user))
|
||||
if (add && (!cap || !cap->OnList(user)))
|
||||
continue;
|
||||
|
||||
// If the cap is being added and the client supports cap values then show the value, if any
|
||||
|
@ -70,6 +70,7 @@ class STSCap : public Cap::Capability
|
||||
STSCap(Module* mod)
|
||||
: Cap::Capability(mod, "sts")
|
||||
{
|
||||
DisableAutoRegister();
|
||||
}
|
||||
|
||||
~STSCap()
|
||||
@ -173,6 +174,9 @@ class ModuleIRCv3STS : public Module
|
||||
unsigned long duration = tag->getDuration("duration", 60*60*24*30*2);
|
||||
bool preload = tag->getBool("preload");
|
||||
cap.SetPolicy(host, duration, port, preload);
|
||||
|
||||
if (!cap.IsRegistered())
|
||||
ServerInstance->Modules.AddService(cap);
|
||||
}
|
||||
|
||||
Version GetVersion() override
|
||||
|
@ -33,6 +33,8 @@ enum
|
||||
ERR_CANNOTKNOCK = 480,
|
||||
|
||||
// From ircd-ratbox.
|
||||
RPL_KNOCK = 710,
|
||||
RPL_KNOCKDLVR = 711,
|
||||
ERR_CHANOPEN = 713,
|
||||
ERR_KNOCKONCHAN = 714
|
||||
};
|
||||
@ -84,18 +86,22 @@ class CommandKnock : public Command
|
||||
}
|
||||
|
||||
if (sendnotice)
|
||||
{
|
||||
c->WriteNotice(InspIRCd::Format("User %s is KNOCKing on %s (%s)", user->nick.c_str(), c->name.c_str(), parameters[1].c_str()));
|
||||
user->WriteNotice("KNOCKing on " + c->name);
|
||||
}
|
||||
|
||||
if (sendnumeric)
|
||||
{
|
||||
Numeric::Numeric numeric(710);
|
||||
Numeric::Numeric numeric(RPL_KNOCK);
|
||||
numeric.push(c->name).push(user->GetFullHost()).push("is KNOCKing: " + parameters[1]);
|
||||
|
||||
ClientProtocol::Messages::Numeric numericmsg(numeric, c->name);
|
||||
c->Write(ServerInstance->GetRFCEvents().numeric, numericmsg);
|
||||
|
||||
user->WriteNumeric(RPL_KNOCKDLVR, c->name, "KNOCKing on channel");
|
||||
}
|
||||
|
||||
user->WriteNotice("KNOCKing on " + c->name);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ class ModuleRLine : public Module, public Stats::EventListener
|
||||
if (stats.GetSymbol() != 'R')
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
ServerInstance->XLines->InvokeStats("R", 223, stats);
|
||||
ServerInstance->XLines->InvokeStats("R", stats);
|
||||
return MOD_RES_DENY;
|
||||
}
|
||||
|
||||
|
@ -26,45 +26,58 @@
|
||||
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "modules/ircv3.h"
|
||||
#include "modules/ircv3_replies.h"
|
||||
|
||||
|
||||
|
||||
class CommandSetname : public Command
|
||||
class CommandSetName : public SplitCommand
|
||||
{
|
||||
private:
|
||||
IRCv3::Replies::Fail fail;
|
||||
|
||||
public:
|
||||
Cap::Capability cap;
|
||||
bool notifyopers;
|
||||
CommandSetname(Module* Creator) : Command(Creator,"SETNAME", 1, 1)
|
||||
|
||||
CommandSetName(Module* Creator)
|
||||
: SplitCommand(Creator, "SETNAME", 1, 1)
|
||||
, fail(Creator)
|
||||
, cap(Creator, "setname")
|
||||
{
|
||||
allow_empty_last_param = false;
|
||||
syntax = ":<realname>";
|
||||
}
|
||||
|
||||
CmdResult Handle(User* user, const Params& parameters) override
|
||||
CmdResult HandleLocal(LocalUser* user, const Params& parameters) override
|
||||
{
|
||||
if (parameters[0].size() > ServerInstance->Config->Limits.MaxReal)
|
||||
{
|
||||
user->WriteNotice("*** SETNAME: Real name is too long");
|
||||
fail.SendIfCap(user, cap, this, "INVALID_REALNAME", "Real name is too long");
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (user->ChangeRealName(parameters[0]))
|
||||
if (!user->ChangeRealName(parameters[0]))
|
||||
{
|
||||
if (notifyopers)
|
||||
ServerInstance->SNO.WriteGlobalSno('a', "%s used SETNAME to change their real name to '%s'",
|
||||
user->nick.c_str(), parameters[0].c_str());
|
||||
fail.SendIfCap(user, cap, this, "CANNOT_CHANGE_REALNAME", "Unable to change your real name");
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (notifyopers)
|
||||
ServerInstance->SNO.WriteGlobalSno('a', "%s used SETNAME to change their real name to '%s'",
|
||||
user->nick.c_str(), parameters[0].c_str());
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ModuleSetName : public Module
|
||||
{
|
||||
CommandSetname cmd;
|
||||
private:
|
||||
CommandSetName cmd;
|
||||
ClientProtocol::EventProvider setnameevprov;
|
||||
|
||||
public:
|
||||
ModuleSetName()
|
||||
: cmd(this)
|
||||
, setnameevprov(this, "SETNAME")
|
||||
{
|
||||
}
|
||||
|
||||
@ -80,6 +93,17 @@ class ModuleSetName : public Module
|
||||
cmd.notifyopers = tag->getBool("notifyopers", !operonly);
|
||||
}
|
||||
|
||||
void OnChangeRealName(User* user, const std::string& real) override
|
||||
{
|
||||
if (!(user->registered & REG_NICKUSER))
|
||||
return;
|
||||
|
||||
ClientProtocol::Message msg("SETNAME", user);
|
||||
msg.PushParamRef(real);
|
||||
ClientProtocol::Event protoev(setnameevprov, msg);
|
||||
IRCv3::WriteNeighborsWithCap(user, protoev, cmd.cap, true);
|
||||
}
|
||||
|
||||
Version GetVersion() override
|
||||
{
|
||||
return Version("Provides the SETNAME command", VF_VENDOR);
|
||||
|
@ -187,7 +187,7 @@ class ModuleShun : public Module, public Stats::EventListener
|
||||
if (stats.GetSymbol() != 'H')
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
ServerInstance->XLines->InvokeStats("SHUN", 223, stats);
|
||||
ServerInstance->XLines->InvokeStats("SHUN", stats);
|
||||
return MOD_RES_DENY;
|
||||
}
|
||||
|
||||
|
@ -219,11 +219,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
|
||||
{
|
||||
// Create a TreeServer object that will start connecting immediately in the background
|
||||
TreeSocket* newsocket = new TreeSocket(x, y, sa);
|
||||
if (newsocket->GetFd() > -1)
|
||||
{
|
||||
/* Handled automatically on success */
|
||||
}
|
||||
else
|
||||
if (!newsocket->HasFd())
|
||||
{
|
||||
ServerInstance->SNO.WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",
|
||||
x->Name.c_str(), newsocket->getError().c_str());
|
||||
|
@ -71,11 +71,7 @@ void ServernameResolver::OnLookupComplete(const DNS::Query *r)
|
||||
if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */
|
||||
{
|
||||
TreeSocket* newsocket = new TreeSocket(MyLink, myautoconnect, sa);
|
||||
if (newsocket->GetFd() > -1)
|
||||
{
|
||||
/* We're all OK */
|
||||
}
|
||||
else
|
||||
if (!newsocket->HasFd())
|
||||
{
|
||||
/* Something barfed, show the opers */
|
||||
ServerInstance->SNO.WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",
|
||||
|
@ -203,7 +203,7 @@ class ModuleSVSHold : public Module, public Stats::EventListener
|
||||
if (stats.GetSymbol() != 'S')
|
||||
return MOD_RES_PASSTHRU;
|
||||
|
||||
ServerInstance->XLines->InvokeStats("SVSHOLD", 210, stats);
|
||||
ServerInstance->XLines->InvokeStats("SVSHOLD", stats);
|
||||
return MOD_RES_DENY;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ bool InspIRCd::BindPort(ConfigTag* tag, const irc::sockets::sockaddrs& sa, std::
|
||||
}
|
||||
|
||||
ListenSocket* ll = new ListenSocket(tag, sa);
|
||||
if (ll->GetFd() < 0)
|
||||
if (!ll->HasFd())
|
||||
{
|
||||
ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Failed to listen on %s from tag at %s: %s",
|
||||
sa.str().c_str(), tag->getTagLocation().c_str(), strerror(errno));
|
||||
|
@ -180,11 +180,7 @@ EventHandler* SocketEngine::GetRef(int fd)
|
||||
|
||||
bool SocketEngine::BoundsCheckFd(EventHandler* eh)
|
||||
{
|
||||
if (!eh)
|
||||
return false;
|
||||
if (eh->GetFd() < 0)
|
||||
return false;
|
||||
return true;
|
||||
return eh && eh->HasFd();
|
||||
}
|
||||
|
||||
|
||||
|
@ -477,34 +477,30 @@ void XLineManager::ApplyLines()
|
||||
pending_lines.clear();
|
||||
}
|
||||
|
||||
void XLineManager::InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats)
|
||||
bool XLineManager::InvokeStats(const std::string& type, Stats::Context& context)
|
||||
{
|
||||
ContainerIter n = lookup_lines.find(type);
|
||||
ContainerIter citer = lookup_lines.find(type);
|
||||
if (citer == lookup_lines.end())
|
||||
return false;
|
||||
|
||||
time_t current = ServerInstance->Time();
|
||||
|
||||
LookupIter safei;
|
||||
|
||||
if (n != lookup_lines.end())
|
||||
for (LookupIter liter = citer->second.begin(); liter != citer->second.end(); )
|
||||
{
|
||||
XLineLookup& list = n->second;
|
||||
for (LookupIter i = list.begin(); i != list.end(); )
|
||||
// We might be about to expire the XLine so we have to increment the
|
||||
// iterator early to avoid doing that causing iterator invalidation.
|
||||
LookupIter current = liter++;
|
||||
|
||||
XLine* xline = current->second;
|
||||
if (xline->duration && xline->expiry <= ServerInstance->Time())
|
||||
{
|
||||
safei = i;
|
||||
safei++;
|
||||
|
||||
if (i->second->duration && current > i->second->expiry)
|
||||
{
|
||||
ExpireLine(n, i);
|
||||
}
|
||||
else
|
||||
stats.AddRow(numeric, i->second->Displayable()+" "+
|
||||
ConvToStr(i->second->set_time)+" "+ConvToStr(i->second->duration)+" "+i->second->source+" :"+i->second->reason);
|
||||
i = safei;
|
||||
// This XLine has expired so remove and skip it.
|
||||
ExpireLine(citer, current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.AddRow(RPL_STATS, context.GetSymbol(), xline->Displayable(), xline->set_time, xline->duration, xline->source, xline->reason);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
XLineManager::XLineManager()
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ foreach my $compiler (@compilers) {
|
||||
say "Failed to configure using the $compiler compiler and the $socketengine socket engine!";
|
||||
exit 1;
|
||||
}
|
||||
if (execute 'make', '--jobs', get_cpu_count, 'install') {
|
||||
if (execute 'make', '--jobs', get_cpu_count + 1, 'install') {
|
||||
say "Failed to compile using the $compiler compiler and the $socketengine socket engine!";
|
||||
exit 1;
|
||||
}
|
||||
|
2
vendor/README.md
vendored
2
vendor/README.md
vendored
@ -18,7 +18,7 @@ This directory contains vendored dependencies that are shipped with InspIRCd to
|
||||
|
||||
**License** — MIT License
|
||||
|
||||
**Version** — v2.9.2
|
||||
**Version** — v2.9.3
|
||||
|
||||
**Website** — [https://github.com/nodejs/http-parser](https://github.com/nodejs/http-parser)
|
||||
|
||||
|
85
vendor/http_parser/http_parser.c
vendored
85
vendor/http_parser/http_parser.c
vendored
@ -381,7 +381,10 @@ enum header_states
|
||||
, h_transfer_encoding
|
||||
, h_upgrade
|
||||
|
||||
, h_matching_transfer_encoding_token_start
|
||||
, h_matching_transfer_encoding_chunked
|
||||
, h_matching_transfer_encoding_token
|
||||
|
||||
, h_matching_connection_token_start
|
||||
, h_matching_connection_keep_alive
|
||||
, h_matching_connection_close
|
||||
@ -1335,6 +1338,7 @@ reexecute:
|
||||
parser->header_state = h_general;
|
||||
} else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
|
||||
parser->header_state = h_transfer_encoding;
|
||||
parser->flags |= F_TRANSFER_ENCODING;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1416,10 +1420,14 @@ reexecute:
|
||||
if ('c' == c) {
|
||||
parser->header_state = h_matching_transfer_encoding_chunked;
|
||||
} else {
|
||||
parser->header_state = h_general;
|
||||
parser->header_state = h_matching_transfer_encoding_token;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Multi-value `Transfer-Encoding` header */
|
||||
case h_matching_transfer_encoding_token_start:
|
||||
break;
|
||||
|
||||
case h_content_length:
|
||||
if (UNLIKELY(!IS_NUM(ch))) {
|
||||
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
|
||||
@ -1563,16 +1571,41 @@ reexecute:
|
||||
goto error;
|
||||
|
||||
/* Transfer-Encoding: chunked */
|
||||
case h_matching_transfer_encoding_token_start:
|
||||
/* looking for 'Transfer-Encoding: chunked' */
|
||||
if ('c' == c) {
|
||||
h_state = h_matching_transfer_encoding_chunked;
|
||||
} else if (STRICT_TOKEN(c)) {
|
||||
/* TODO(indutny): similar code below does this, but why?
|
||||
* At the very least it seems to be inconsistent given that
|
||||
* h_matching_transfer_encoding_token does not check for
|
||||
* `STRICT_TOKEN`
|
||||
*/
|
||||
h_state = h_matching_transfer_encoding_token;
|
||||
} else if (c == ' ' || c == '\t') {
|
||||
/* Skip lws */
|
||||
} else {
|
||||
h_state = h_general;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_transfer_encoding_chunked:
|
||||
parser->index++;
|
||||
if (parser->index > sizeof(CHUNKED)-1
|
||||
|| c != CHUNKED[parser->index]) {
|
||||
h_state = h_general;
|
||||
h_state = h_matching_transfer_encoding_token;
|
||||
} else if (parser->index == sizeof(CHUNKED)-2) {
|
||||
h_state = h_transfer_encoding_chunked;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_transfer_encoding_token:
|
||||
if (ch == ',') {
|
||||
h_state = h_matching_transfer_encoding_token_start;
|
||||
parser->index = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_connection_token_start:
|
||||
/* looking for 'Connection: keep-alive' */
|
||||
if (c == 'k') {
|
||||
@ -1631,7 +1664,7 @@ reexecute:
|
||||
break;
|
||||
|
||||
case h_transfer_encoding_chunked:
|
||||
if (ch != ' ') h_state = h_general;
|
||||
if (ch != ' ') h_state = h_matching_transfer_encoding_token;
|
||||
break;
|
||||
|
||||
case h_connection_keep_alive:
|
||||
@ -1765,12 +1798,17 @@ reexecute:
|
||||
REEXECUTE();
|
||||
}
|
||||
|
||||
/* Cannot use chunked encoding and a content-length header together
|
||||
per the HTTP specification. */
|
||||
if ((parser->flags & F_CHUNKED) &&
|
||||
/* Cannot us transfer-encoding and a content-length header together
|
||||
per the HTTP specification. (RFC 7230 Section 3.3.3) */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CONTENTLENGTH)) {
|
||||
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||
goto error;
|
||||
/* Allow it for lenient parsing as long as `Transfer-Encoding` is
|
||||
* not `chunked`
|
||||
*/
|
||||
if (!lenient || (parser->flags & F_CHUNKED)) {
|
||||
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
UPDATE_STATE(s_headers_done);
|
||||
@ -1845,8 +1883,31 @@ reexecute:
|
||||
UPDATE_STATE(NEW_MESSAGE());
|
||||
CALLBACK_NOTIFY(message_complete);
|
||||
} else if (parser->flags & F_CHUNKED) {
|
||||
/* chunked encoding - ignore Content-Length header */
|
||||
/* chunked encoding - ignore Content-Length header,
|
||||
* prepare for a chunk */
|
||||
UPDATE_STATE(s_chunk_size_start);
|
||||
} else if (parser->flags & F_TRANSFER_ENCODING) {
|
||||
if (parser->type == HTTP_REQUEST && !lenient) {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field
|
||||
* is present in a request and the chunked transfer coding is not
|
||||
* the final encoding, the message body length cannot be determined
|
||||
* reliably; the server MUST respond with the 400 (Bad Request)
|
||||
* status code and then close the connection.
|
||||
*/
|
||||
SET_ERRNO(HPE_INVALID_TRANSFER_ENCODING);
|
||||
RETURN(p - data); /* Error */
|
||||
} else {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field is present in a response and
|
||||
* the chunked transfer coding is not the final encoding, the
|
||||
* message body length is determined by reading the connection until
|
||||
* it is closed by the server.
|
||||
*/
|
||||
UPDATE_STATE(s_body_identity_eof);
|
||||
}
|
||||
} else {
|
||||
if (parser->content_length == 0) {
|
||||
/* Content-Length header given but zero: Content-Length: 0\r\n */
|
||||
@ -2100,6 +2161,12 @@ http_message_needs_eof (const http_parser *parser)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RFC 7230 3.3.3, see `s_headers_almost_done` */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CHUNKED) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
7
vendor/http_parser/http_parser.h
vendored
7
vendor/http_parser/http_parser.h
vendored
@ -27,7 +27,7 @@ extern "C" {
|
||||
/* Also update SONAME in the Makefile whenever you change these. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 9
|
||||
#define HTTP_PARSER_VERSION_PATCH 2
|
||||
#define HTTP_PARSER_VERSION_PATCH 3
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||
@ -225,6 +225,7 @@ enum flags
|
||||
, F_UPGRADE = 1 << 5
|
||||
, F_SKIPBODY = 1 << 6
|
||||
, F_CONTENTLENGTH = 1 << 7
|
||||
, F_TRANSFER_ENCODING = 1 << 8
|
||||
};
|
||||
|
||||
|
||||
@ -271,6 +272,8 @@ enum flags
|
||||
"unexpected content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_TRANSFER_ENCODING, \
|
||||
"request has invalid transfer-encoding") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
@ -293,11 +296,11 @@ enum http_errno {
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned int type : 2; /* enum http_parser_type */
|
||||
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned int state : 7; /* enum state from http_parser.c */
|
||||
unsigned int header_state : 7; /* enum header_state from http_parser.c */
|
||||
unsigned int index : 7; /* index into current matcher */
|
||||
unsigned int lenient_http_headers : 1;
|
||||
unsigned int flags : 16; /* F_* values from 'flags' enum; semi-public */
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user