1
0
mirror of https://github.com/anope/anope.git synced 2026-06-17 07:04:46 +02:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Sadie Powell d4d2a4b4ce Release 2.0.12. 2022-12-09 08:30:43 +00:00
Sadie Powell e33b8d5f43 Update the changelogs. 2022-12-09 08:28:57 +00:00
PeGaSuS c2b154e1b1 Document cs_no_expire (#301). 2022-12-08 07:16:04 +00:00
Sadie Powell 4a2861ba3d Add a module that provides regex/pcre using PCRE2. 2022-12-07 15:43:39 +00:00
miwob 211bd80061 Update ircd-hybrid protocol module
* Add METADATA command handler which currently only allows to modify a client's certificate fingerprint
* Minor reformatting and style inconsistency fixes
2022-09-29 13:05:05 +01:00
Austin Ellis 32679a107a Add the ability to confirm accounts via webcpanel after logging in. 2022-09-22 17:38:07 +01:00
miwob bc101d10de Update hybrid protocol module to improve compatibility with the latest ircd-hybrid release.
* Remove support for deprecated channel mode `u`
* Add support for channel mode `N`
* Fixed the `UID` message handler requiring the correct amount of arguments
* Fixed the `SID` message handler requiring the correct amount of arguments
* Fixed the `SJOIN` message handler requiring the correct amount of arguments
* Minor documentation updates and style corrections
* Remove pointless return statement in the `JOIN` message handler
* Add support for the owner and admin channel prefix modes
* Add support for `MLOCK`
* Fixed SendChannel() so modes are prefixed with a `+`
* Change SendJoin() to actually use the mode stacker
* Add support for channel mode `Q`
* Add support for channel mode `Z`
* Add support for user mode `B` and `Z`
* Actually user mode `g` is not oper only. For some reason this mode got set to oper only in anope/anope@1e625b6
* Work properly with extended bans, e.g. don't normalize masks starting with a `$`
2022-09-15 14:13:24 +01:00
Sadie Powell 901a456132 Fix allowing spaces in some config fields that shouldn't contain them. 2022-09-12 17:56:45 +01:00
Sadie Powell 0c61915e31 Bahamut now has support for halfops. 2022-09-12 17:56:45 +01:00
Dragone2 d5e85c7f25 Fixe a typo in the Italian translation.
Ref: #298
2022-08-10 19:40:42 +01:00
Michael Stapelberg a5425e3bf3 database: write to temporary file and rename.
This decreases the likelihood of ending up with a zero-byte (or missing)
anope.db.

Co-authored-by: Michael Stapelberg <michael@robustirc.net>
2022-07-27 17:40:49 +01:00
18 changed files with 477 additions and 91 deletions
+2 -1
View File
@@ -22,6 +22,7 @@ jobs:
libgnutls28-dev \
libldap2-dev \
libmysqlclient-dev \
libpcre2-dev \
libpcre3-dev \
libsqlite3-dev \
libssl-dev \
@@ -29,7 +30,7 @@ jobs:
make
- name: Enable extras
run: |
for MODULE in m_ldap.cpp m_ldap_authentication.cpp m_ldap_oper.cpp m_mysql.cpp m_regex_pcre.cpp m_regex_posix.cpp m_regex_tre.cpp m_sql_authentication.cpp m_sql_log.cpp m_sql_oper.cpp m_sqlite.cpp m_ssl_gnutls.cpp m_ssl_openssl.cpp stats
for MODULE in m_ldap.cpp m_ldap_authentication.cpp m_ldap_oper.cpp m_mysql.cpp m_regex_pcre.cpp m_regex_pcre2.cpp m_regex_posix.cpp m_regex_tre.cpp m_sql_authentication.cpp m_sql_log.cpp m_sql_oper.cpp m_sqlite.cpp m_ssl_gnutls.cpp m_ssl_openssl.cpp stats
do
ln -s ${{ github.workspace }}/modules/extra/$MODULE ${{ github.workspace }}/modules
done
+1
View File
@@ -6,6 +6,7 @@ modules/m_ldap_authentication.cpp
modules/m_ldap_oper.cpp
modules/m_mysql.cpp
modules/m_regex_pcre.cpp
modules/m_regex_pcre2.cpp
modules/m_regex_posix.cpp
modules/m_regex_tre.cpp
modules/m_sql_authentication.cpp
+2
View File
@@ -89,6 +89,8 @@ module
* - noautoop: Disables autoop on the channel
* - cs_keep_modes: Enables keep modes on the channel, which retains modes when the channel is
* not in use.
* - cs_no_expire: Enables no expire. Needs founder, successor (if set) or anyone in the access list
* to be a registered nick, otherwise the channel will be dropped.
* - none: No defaults
*
* This directive is optional, if left blank, the options will default to keeptopic, cs_secure, securefounder,
+9 -1
View File
@@ -403,10 +403,18 @@ module { name = "help" }
/*
* m_regex_pcre [EXTRA]
*
* Provides the regex engine regex/pcre, which uses the Perl Compatible Regular Expressions library.
* Provides the regex engine regex/pcre, which uses version 1 of the Perl Compatible Regular
* Expressions library. This can not be loaded at the same time as the m_regex_pcre2 module.
*/
#module { name = "m_regex_pcre" }
/*
* m_regex_pcre2 [EXTRA]
*
* Provides the regex engine regex/pcre, which uses version 2 of the Perl Compatible Regular
* Expressions library. This can not be loaded at the same time as the m_regex_pcre module.
#module { name = "m_regex_pcre2" }
/*
* m_regex_posix [EXTRA]
*
+10
View File
@@ -1,3 +1,13 @@
Anope Version 2.0.12
--------------------
Added account confirmation to the web panel
Added the regex_pcre2 module which provides regex/pcre with PCRE2
Documented the cs_no_expire channel default
Fixed config validation mistakenly allowing spaces in some fields
Fixed the bahamut protocol module not knowing about halfops
Fixed writing a flatfile database not being atomic
Updated the hybrid protocol module for recent protocol changes
Anope Version 2.0.11
--------------------
Fixed ldap on OpenLDAP 2.5+
+4
View File
@@ -1,3 +1,7 @@
Anope Version 2.0.12
--------------------
Added the regex_pcre2 module
Anope Version 2.0.11
--------------------
No significant changes.
+1 -1
View File
@@ -7235,7 +7235,7 @@ msgstr "Limita l'accesso al canale"
#: modules/commands/cs_set.cpp:1291
msgid "Restricted access"
msgstr "Acesso limitato"
msgstr "Accesso limitato"
#: modules/commands/cs_set.cpp:661
#, c-format
+6 -8
View File
@@ -312,10 +312,7 @@ class DBFlatFile : public Module, public Pipe
else
db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
if (Anope::IsFile(db_name))
rename(db_name.c_str(), (db_name + ".tmp").c_str());
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream((db_name + ".tmp").c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
if (!fs->is_open())
Log(this) << "Unable to open " << db_name << " for writing";
@@ -349,14 +346,15 @@ class DBFlatFile : public Module, public Pipe
this->Write("Unable to write database " + db_name);
f->close();
if (Anope::IsFile((db_name + ".tmp").c_str()))
rename((db_name + ".tmp").c_str(), db_name.c_str());
}
else
{
f->close();
unlink((db_name + ".tmp").c_str());
#ifdef _WIN32
/* Windows rename() fails if the file already exists. */
remove(db_name.c_str());
#endif
rename((db_name + ".tmp").c_str(), db_name.c_str());
}
delete f;
+93
View File
@@ -0,0 +1,93 @@
/*
*
* (C) 2012-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
/* RequiredLibraries: pcre2-8 */
/* RequiredWindowsLibraries: libpcre2-8 */
#include "module.h"
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
class PCRERegex : public Regex
{
pcre2_code *regex;
public:
PCRERegex(const Anope::string &expr) : Regex(expr)
{
int errcode;
PCRE2_SIZE erroffset;
this->regex = pcre2_compile(reinterpret_cast<PCRE2_SPTR8>(expr.c_str()), expr.length(), PCRE2_CASELESS, &errcode, &erroffset, NULL);
if (!this->regex)
{
PCRE2_UCHAR error[128];
pcre2_get_error_message(errcode, error, sizeof error);
throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + reinterpret_cast<const char*>(error));
}
}
~PCRERegex()
{
pcre2_code_free(this->regex);
}
bool Matches(const Anope::string &str)
{
pcre2_match_data *unused = pcre2_match_data_create_from_pattern(this->regex, NULL);
int result = pcre2_match(regex, reinterpret_cast<PCRE2_SPTR8>(str.c_str()), str.length(), 0, 0, unused, NULL);
pcre2_match_data_free(unused);
return result >= 0;
}
};
class PCRERegexProvider : public RegexProvider
{
public:
PCRERegexProvider(Module *creator) : RegexProvider(creator, "regex/pcre") { }
Regex *Compile(const Anope::string &expression) anope_override
{
return new PCRERegex(expression);
}
};
class ModuleRegexPCRE : public Module
{
PCRERegexProvider pcre_regex_provider;
public:
ModuleRegexPCRE(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
pcre_regex_provider(this)
{
this->SetPermanent(true);
}
~ModuleRegexPCRE()
{
for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it)
{
XLineManager *xlm = *it;
const std::vector<XLine *> &xlines = xlm->GetList();
for (unsigned int i = 0; i < xlines.size(); ++i)
{
XLine *x = xlines[i];
if (x->regex && dynamic_cast<PCRERegex *>(x->regex))
{
delete x->regex;
x->regex = NULL;
}
}
}
}
};
MODULE_INIT(ModuleRegexPCRE)
+1
View File
@@ -524,6 +524,7 @@ class ProtoBahamut : public Module
/* v/h/o/a/q */
ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0));
ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1));
ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 1));
/* Add channel modes */
+241 -66
View File
@@ -1,7 +1,7 @@
/* ircd-hybrid protocol module. Minimum supported version of ircd-hybrid is 8.2.23.
*
* (C) 2003-2022 Anope Team <team@anope.org>
* (C) 2012-2020 ircd-hybrid development team
* (C) 2012-2022 ircd-hybrid development team
*
* Please read COPYING and README for further details.
*
@@ -10,6 +10,7 @@
*/
#include "module.h"
#include "modules/cs_mode.h"
static Anope::string UplinkSID;
static bool UseSVSAccount = false; // Temporary backwards compatibility hack until old proto is deprecated
@@ -22,7 +23,7 @@ class HybridProto : public IRCDProto
u->KillInternal(source, buf);
}
public:
public:
HybridProto(Module *creator) : IRCDProto(creator, "ircd-hybrid 8.2.23+")
{
DefaultPseudoclientModes = "+oi";
@@ -100,20 +101,32 @@ class HybridProto : public IRCDProto
void SendJoin(User *u, Channel *c, const ChannelStatus *status) anope_override
{
/*
* Note that we must send our modes with the SJOIN and can not add them to the
* mode stacker because ircd-hybrid does not allow *any* client to op itself
*/
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :"
<< (status != NULL ? status->BuildModePrefixList() : "") << u->GetUID();
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << u->GetUID();
/* And update our internal status for this user since this is not going through our mode handling system */
/*
* Note that we can send this with the SJOIN but choose not to
* because the mode stacker will handle this and probably will
* merge these modes with +nrt and other mlocked modes.
*/
if (status)
{
/* First save the channel status in case uc->status == status */
ChannelStatus cs = *status;
/*
* If the user is internally on the channel with flags, kill them so that
* the stacker will allow this.
*/
ChanUserContainer *uc = c->FindUser(u);
if (uc)
uc->status.Clear();
BotInfo *setter = BotInfo::Find(u->GetUID());
for (size_t i = 0; i < cs.Modes().length(); ++i)
c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), u->GetUID(), false);
if (uc)
uc->status = *status;
uc->status = cs;
}
}
@@ -171,15 +184,13 @@ class HybridProto : public IRCDProto
UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password;
/*
* As of October 02, 2020, ircd-hybrid-8 does support the following capabilities
* which are required to work with IRC-services:
*
* TBURST - Supports topic burst
* ENCAP - Supports ENCAP
* EOB - Supports End Of Burst message
* RHOST - Supports UID message with realhost information
* MLOCK - Supports MLOCK
*/
UplinkSocket::Message() << "CAPAB :ENCAP TBURST EOB RHOST";
UplinkSocket::Message() << "CAPAB :ENCAP TBURST EOB RHOST MLOCK";
SendServer(Me);
@@ -222,11 +233,7 @@ class HybridProto : public IRCDProto
void SendChannel(Channel *c) anope_override
{
Anope::string modes = c->GetModes(true, true);
if (modes.empty())
modes = "+";
Anope::string modes = "+" + c->GetModes(true, true);
UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " " << modes << " :";
}
@@ -275,6 +282,11 @@ class HybridProto : public IRCDProto
UplinkSocket::Message(Me) << "SVSHOST " << u->GetUID() << " " << u->timestamp << " " << u->host;
}
bool IsExtbanValid(const Anope::string &mask) anope_override
{
return mask.length() >= 4 && mask[0] == '$' && mask[2] == ':';
}
bool IsIdentValid(const Anope::string &ident) anope_override
{
if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
@@ -317,7 +329,7 @@ struct IRCDMessageBMask : IRCDMessage
{
IRCDMessageBMask(Module *creator) : IRCDMessage(creator, "BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* 0 1 2 3 */
/* :0MC BMASK 1350157102 #channel b :*!*@*.test.com */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
@@ -335,6 +347,46 @@ struct IRCDMessageBMask : IRCDMessage
}
};
struct IRCDMessageCapab : Message::Capab
{
IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 */
/* CAPAB :TBURST EOB MLOCK */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
spacesepstream sep(params[0]);
Anope::string capab;
while (sep.GetToken(capab))
{
if (capab.find("HOP") != Anope::string::npos || capab.find("RHOST") != Anope::string::npos)
ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1));
if (capab.find("AOP") != Anope::string::npos)
ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', 3));
if (capab.find("QOP") != Anope::string::npos)
ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', 4));
}
Message::Capab::Run(source, params);
}
};
struct IRCDMessageCertFP: IRCDMessage
{
IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
/* 0 */
/* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
User *u = source.GetUser();
u->fingerprint = params[0];
FOREACH_MOD(OnFingerprint, (u));
}
};
struct IRCDMessageEOB : IRCDMessage
{
IRCDMessageEOB(Module *creator) : IRCDMessage(creator, "EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
@@ -357,7 +409,58 @@ struct IRCDMessageJoin : Message::Join
std::vector<Anope::string> p = params;
p.erase(p.begin());
return Message::Join::Run(source, p);
Message::Join::Run(source, p);
}
};
struct IRCDMessageMetadata : IRCDMessage
{
IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* :0MC METADATA client 0MCAAAAAB certfp :4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
if (params[0].equals_cs("client"))
{
User *u = User::Find(params[1]);
if (!u)
{
Log(LOG_DEBUG) << "METADATA for nonexistent user " << params[1];
return;
}
if (params[2].equals_cs("certfp"))
{
u->fingerprint = params[3];
FOREACH_MOD(OnFingerprint, (u));
}
}
}
};
struct IRCDMessageMLock : IRCDMessage
{
IRCDMessageMLock(Module *creator) : IRCDMessage(creator, "MLOCK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* :0MC MLOCK 1350157102 #channel 1350158923 :nt */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
Channel *c = Channel::Find(params[1]);
if (c && c->ci)
{
ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
Anope::string modes;
if (modelocks)
modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
// Mode lock string is not what we say it is?
if (modes != params[3])
UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->name << " " << Anope::CurTime << " :" << modes;
}
}
};
@@ -400,7 +503,7 @@ struct IRCDMessageServer : IRCDMessage
{
IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 1 2 3 4 */
/* 0 1 2 3 4 */
/* SERVER hades.arpa 1 4XY + :ircd-hybrid test server */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
@@ -422,9 +525,9 @@ struct IRCDMessageServer : IRCDMessage
struct IRCDMessageSID : IRCDMessage
{
IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 1 2 3 4 */
/* 0 1 2 3 4 */
/* :0MC SID hades.arpa 2 4XY + :ircd-hybrid test server */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
@@ -437,15 +540,16 @@ struct IRCDMessageSID : IRCDMessage
struct IRCDMessageSJoin : IRCDMessage
{
IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 1 2 3 */
/* :0MC SJOIN 1654877335 #nether +nt :@0MCAAAAAB +0MCAAAAAC */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
Anope::string modes;
if (params.size() >= 3)
for (unsigned i = 2; i < params.size() - 1; ++i)
modes += " " + params[i];
for (unsigned i = 2; i < params.size() - 1; ++i)
modes += " " + params[i];
if (!modes.empty())
modes.erase(modes.begin());
@@ -485,11 +589,8 @@ struct IRCDMessageSVSMode : IRCDMessage
{
IRCDMessageSVSMode(Module *creator) : IRCDMessage(creator, "SVSMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/*
* parv[0] = nickname
* parv[1] = TS
* parv[2] = mode
*/
/* 0 1 2 */
/* :0MC SVSMODE 0MCAAAAAB 1350157102 +r */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
User *u = User::Find(params[0]);
@@ -508,6 +609,8 @@ struct IRCDMessageTBurst : IRCDMessage
{
IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TBURST", 5) { }
/* 0 1 2 3 4 */
/* :0MC TBURST 1654867975 #nether 1654877335 Steve!~steve@the.mines :Join the ghast nation */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
Anope::string setter;
@@ -524,6 +627,8 @@ struct IRCDMessageTMode : IRCDMessage
{
IRCDMessageTMode(Module *creator) : IRCDMessage(creator, "TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 1 2 */
/* :0MC TMODE 1654867975 #nether +ntR */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
time_t ts = 0;
@@ -547,14 +652,14 @@ struct IRCDMessageTMode : IRCDMessage
struct IRCDMessageUID : IRCDMessage
{
IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 10) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
/* 0 1 2 3 4 5 6 7 8 9 10 */
/* :0MC UID Steve 1 1350157102 +oi ~steve virtual.host real.host 10.0.0.1 0MCAAAAAB Steve :Mining all the time */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
NickAlias *na = NULL;
/* 0 1 2 3 4 5 6 7 8 9 10 */
/* :0MC UID Steve 1 1350157102 +oi ~steve virtual.host real.host 10.0.0.1 0MCAAAAAB Steve :Mining all the time */
if (params[9] != "*")
na = NickAlias::Find(params[9]);
@@ -565,28 +670,12 @@ struct IRCDMessageUID : IRCDMessage
}
};
struct IRCDMessageCertFP: IRCDMessage
{
IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
/* 0 */
/* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
{
User *u = source.GetUser();
u->fingerprint = params[0];
FOREACH_MOD(OnFingerprint, (u));
}
};
class ProtoHybrid : public Module
{
HybridProto ircd_proto;
/* Core message handlers */
Message::Away message_away;
Message::Capab message_capab;
Message::Error message_error;
Message::Invite message_invite;
Message::Kick message_kick;
@@ -607,8 +696,12 @@ class ProtoHybrid : public Module
/* Our message handlers */
IRCDMessageBMask message_bmask;
IRCDMessageCapab message_capab;
IRCDMessageCertFP message_certfp;
IRCDMessageEOB message_eob;
IRCDMessageJoin message_join;
IRCDMessageMetadata message_metadata;
IRCDMessageMLock message_mlock;
IRCDMessageNick message_nick;
IRCDMessagePass message_pass;
IRCDMessagePong message_pong;
@@ -619,13 +712,14 @@ class ProtoHybrid : public Module
IRCDMessageTBurst message_tburst;
IRCDMessageTMode message_tmode;
IRCDMessageUID message_uid;
IRCDMessageCertFP message_certfp;
bool use_server_side_mlock;
void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
ModeManager::AddUserMode(new UserModeOperOnly("CALLERID", 'g'));
ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l'));
ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
@@ -634,21 +728,22 @@ class ProtoHybrid : public Module
ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r'));
ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
ModeManager::AddUserMode(new UserMode("BOT", 'B'));
ModeManager::AddUserMode(new UserMode("DEAF", 'D'));
ModeManager::AddUserMode(new UserMode("SOFTCALLERID", 'G'));
ModeManager::AddUserMode(new UserModeOperOnly("HIDEOPER", 'H'));
ModeManager::AddUserMode(new UserMode("REGPRIV", 'R'));
ModeManager::AddUserMode(new UserModeNoone("SSL", 'S'));
ModeManager::AddUserMode(new UserModeNoone("WEBIRC", 'W'));
ModeManager::AddUserMode(new UserMode("SECUREONLY", 'Z'));
/* b/e/I */
ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
/* v/h/o */
/* v/o */
ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0));
ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1));
ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 2));
/* l/k */
@@ -664,28 +759,58 @@ class ProtoHybrid : public Module
ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r'));
ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
ModeManager::AddChannelMode(new ChannelMode("HIDEBMASKS", 'u'));
ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
ModeManager::AddChannelMode(new ChannelModeOperOnly("LBAN", 'L'));
ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O'));
ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
ModeManager::AddChannelMode(new ChannelMode("SSL", 'S'));
ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T'));
ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V'));
ModeManager::AddChannelMode(new ChannelModeNoone("ISSECURE", 'Z'));
}
public:
public:
ProtoHybrid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this),
message_kill(this), message_mode(this), message_motd(this), message_notice(this), message_part(this),
message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this),
message_time(this), message_topic(this), message_version(this), message_whois(this),
message_bmask(this), message_eob(this), message_join(this),
message_nick(this), message_pass(this), message_pong(this), message_server(this), message_sid(this),
message_sjoin(this), message_svsmode(this), message_tburst(this), message_tmode(this), message_uid(this),
message_certfp(this)
message_away(this),
message_error(this),
message_invite(this),
message_kick(this),
message_kill(this),
message_mode(this),
message_motd(this),
message_notice(this),
message_part(this),
message_ping(this),
message_privmsg(this),
message_quit(this),
message_squit(this),
message_stats(this),
message_time(this),
message_topic(this),
message_version(this),
message_whois(this),
message_bmask(this),
message_capab(this),
message_certfp(this),
message_eob(this),
message_join(this),
message_metadata(this),
message_mlock(this),
message_nick(this),
message_pass(this),
message_pong(this),
message_server(this),
message_sid(this),
message_sjoin(this),
message_svsmode(this),
message_tburst(this),
message_tmode(this),
message_uid(this)
{
if (Config->GetModule(this))
this->AddModes();
@@ -695,6 +820,56 @@ public:
{
u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
}
void OnReload(Configuration::Conf *conf) anope_override
{
use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
}
void OnChannelSync(Channel *c) anope_override
{
if (!c->ci)
return;
ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
if (use_server_side_mlock && modelocks && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->ci->name << " " << Anope::CurTime << " :" << modes;
}
}
void OnDelChan(ChannelInfo *ci) anope_override
{
if (use_server_side_mlock && ci->c && Servers::Capab.count("MLOCK"))
UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :";
}
EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes;
}
return EVENT_CONTINUE;
}
EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes;
}
return EVENT_CONTINUE;
}
};
MODULE_INIT(ProtoHybrid)
@@ -0,0 +1,26 @@
/*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#include "../../webcpanel.h"
WebCPanel::NickServ::Confirm::Confirm(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
}
bool WebCPanel::NickServ::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
{
std::vector<Anope::string> params;
params.push_back(message.post_data["code"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/confirm", params, replacements);
TemplateFileServer page("nickserv/confirm.html");
page.Serve(server, page_name, client, message, reply, replacements);
return true;
}
@@ -0,0 +1,24 @@
/*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
namespace WebCPanel
{
namespace NickServ
{
class Confirm : public WebPanelProtectedPage
{
public:
Confirm(const Anope::string &cat, const Anope::string &u);
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
};
}
}
@@ -0,0 +1,29 @@
{INCLUDE header.html}
<div class="panel-heading">Confirm your Email</div>
<div class="panel-body">
{FOR M IN MESSAGES}
<div class="alert alert-info">
{M}<br>
</div>
{END FOR}
<em>You can <strong>CONFIRM</strong> your registration by entering your confirmation code below.</em>
<hr>
<h4>Confirm your account</h4>
<form class="form-horizontal" method="post" action="/nickserv/confirm">
<div class="form-group">
<label class="control-label col-lg-2" for="confirm">Confirmation Code:</label>
<div class="col-lg-5">
<input class="form-control" type="text" name="code" id="code" placeholder="Code from Email">
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-5">
<button type="submit" class="btn btn-primary">Confirm Me!</button>
</div>
</div>
</form>
</div>
{INCLUDE footer.html}
+8 -1
View File
@@ -28,6 +28,7 @@ class ModuleWebCPanel : public Module
WebCPanel::NickServ::Cert nickserv_cert;
WebCPanel::NickServ::Access nickserv_access;
WebCPanel::NickServ::Alist nickserv_alist;
WebCPanel::NickServ::Confirm nickserv_confirm;
WebCPanel::ChanServ::Info chanserv_info;
WebCPanel::ChanServ::Set chanserv_set;
@@ -49,7 +50,7 @@ class ModuleWebCPanel : public Module
id(this, "webcpanel_id"), ip(this, "webcpanel_ip"), last_login(this, "webcpanel_last_login"),
style_css("style.css", "/static/style.css", "text/css"), logo_png("logo.png", "/static/logo.png", "image/png"), cubes_png("cubes.png", "/static/cubes.png", "image/png"), favicon_ico("favicon.ico", "/favicon.ico", "image/x-icon"),
index("/"), logout("/logout"), _register("/register"), confirm("/confirm"),
nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"),
nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"), nickserv_confirm("NickServ", "/nickserv/confirm"),
chanserv_info("ChanServ", "/chanserv/info"), chanserv_set("ChanServ", "/chanserv/set"), chanserv_access("ChanServ", "/chanserv/access"), chanserv_akick("ChanServ", "/chanserv/akick"),
chanserv_modes("ChanServ", "/chanserv/modes"), chanserv_drop("ChanServ", "/chanserv/drop"), memoserv_memos("MemoServ", "/memoserv/memos"), hostserv_request("HostServ", "/hostserv/request"),
operserv_akill("OperServ", "/operserv/akill")
@@ -107,6 +108,11 @@ class ModuleWebCPanel : public Module
s.subsections.push_back(ss);
provider->RegisterPage(&this->nickserv_alist);
ss.name = "Confirm";
ss.url = "/nickserv/confirm";
s.subsections.push_back(ss);
provider->RegisterPage(&this->nickserv_confirm);
panel.sections.push_back(s);
}
@@ -214,6 +220,7 @@ class ModuleWebCPanel : public Module
provider->UnregisterPage(&this->nickserv_cert);
provider->UnregisterPage(&this->nickserv_access);
provider->UnregisterPage(&this->nickserv_alist);
provider->UnregisterPage(&this->nickserv_confirm);
provider->UnregisterPage(&this->chanserv_info);
provider->UnregisterPage(&this->chanserv_set);
+1
View File
@@ -166,6 +166,7 @@ namespace WebPanel
#include "pages/nickserv/cert.h"
#include "pages/nickserv/access.h"
#include "pages/nickserv/alist.h"
#include "pages/nickserv/confirm.h"
#include "pages/chanserv/info.h"
#include "pages/chanserv/set.h"
+18 -12
View File
@@ -104,6 +104,12 @@ static void ValidateNoSpaces(const Anope::string &block, const Anope::string &na
throw ConfigException("The value for <" + block + ":" + name + "> may not contain spaces!");
}
static void ValidateNotEmptyOrSpaces(const Anope::string &block, const Anope::string &name, const Anope::string &value)
{
ValidateNotEmpty(block, name, value);
ValidateNoSpaces(block, name, value);
}
template<typename T> static void ValidateNotZero(const Anope::string &block, const Anope::string &name, T value)
{
if (!value)
@@ -159,7 +165,7 @@ Conf::Conf() : Block("")
const Anope::string &servername = serverinfo->Get<Anope::string>("name");
ValidateNotEmpty("serverinfo", "name", servername);
ValidateNotEmptyOrSpaces("serverinfo", "name", servername);
if (servername.find(' ') != Anope::string::npos || servername.find('.') == Anope::string::npos)
throw ConfigException("serverinfo:name is not a valid server name");
@@ -207,9 +213,9 @@ Conf::Conf() : Block("")
int port = uplink->Get<int>("port");
const Anope::string &password = uplink->Get<const Anope::string>("password");
ValidateNotEmpty("uplink", "host", host);
ValidateNotEmptyOrSpaces("uplink", "host", host);
ValidateNotZero("uplink", "port", port);
ValidateNotEmpty("uplink", "password", password);
ValidateNotEmptyOrSpaces("uplink", "password", password);
if (password.find(' ') != Anope::string::npos || password[0] == ':')
throw ConfigException("uplink:password is not valid");
@@ -223,7 +229,7 @@ Conf::Conf() : Block("")
const Anope::string &modname = module->Get<const Anope::string>("name");
ValidateNotEmpty("module", "name", modname);
ValidateNotEmptyOrSpaces("module", "name", modname);
this->ModulesAutoLoad.push_back(modname);
}
@@ -285,7 +291,7 @@ Conf::Conf() : Block("")
&vhost = oper->Get<const Anope::string>("vhost");
bool require_oper = oper->Get<bool>("require_oper");
ValidateNotEmpty("oper", "name", nname);
ValidateNotEmptyOrSpaces("oper", "name", nname);
ValidateNotEmpty("oper", "type", type);
OperType *ot = NULL;
@@ -318,9 +324,9 @@ Conf::Conf() : Block("")
&modes = service->Get<const Anope::string>("modes"),
&channels = service->Get<const Anope::string>("channels");
ValidateNotEmpty("service", "nick", nick);
ValidateNotEmpty("service", "user", user);
ValidateNotEmpty("service", "host", host);
ValidateNotEmptyOrSpaces("service", "nick", nick);
ValidateNotEmptyOrSpaces("service", "user", user);
ValidateNotEmptyOrSpaces("service", "host", host);
ValidateNotEmpty("service", "gecos", gecos);
ValidateNoSpaces("service", "channels", channels);
@@ -430,9 +436,9 @@ Conf::Conf() : Block("")
&group = command->Get<const Anope::string>("group");
bool hide = command->Get<bool>("hide");
ValidateNotEmpty("command", "service", service);
ValidateNotEmptyOrSpaces("command", "service", service);
ValidateNotEmpty("command", "name", nname);
ValidateNotEmpty("command", "command", cmd);
ValidateNotEmptyOrSpaces("command", "command", cmd);
BotInfo *bi = this->GetClient(service);
if (!bi)
@@ -466,8 +472,8 @@ Conf::Conf() : Block("")
bool hide = fantasy->Get<bool>("hide"),
prepend_channel = fantasy->Get<bool>("prepend_channel", "yes");
ValidateNotEmpty("fantasy", "name", nname);
ValidateNotEmpty("fantasy", "command", service);
ValidateNotEmptyOrSpaces("fantasy", "name", nname);
ValidateNotEmptyOrSpaces("fantasy", "command", service);
CommandInfo &c = this->Fantasy[nname];
c.name = service;
+1 -1
View File
@@ -2,5 +2,5 @@
VERSION_MAJOR=2
VERSION_MINOR=0
VERSION_PATCH=11
VERSION_PATCH=12
VERSION_EXTRA=""