mirror of
https://github.com/anope/anope.git
synced 2026-07-01 19:26:40 +02:00
Rip out ns_access and related code.
This is wildly insecure and has been disabled by default for at least a decade.
This commit is contained in:
@@ -116,12 +116,11 @@ public:
|
||||
|
||||
ChanServ = bi;
|
||||
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace cs_secure securefounder signkick")).GetTokens(defaults);
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace securefounder signkick")).GetTokens(defaults);
|
||||
if (defaults.empty())
|
||||
{
|
||||
defaults.emplace_back("KEEPTOPIC");
|
||||
defaults.emplace_back("PEACE");
|
||||
defaults.emplace_back("CS_SECURE");
|
||||
defaults.emplace_back("SECUREFOUNDER");
|
||||
defaults.emplace_back("SIGNKICK");
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
target_ci->last_topic_setter = source.service->nick;
|
||||
|
||||
const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED",
|
||||
"CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
|
||||
"SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
|
||||
|
||||
for (const auto &setting : settings)
|
||||
CopySetting(ci, target_ci, setting);
|
||||
|
||||
@@ -682,70 +682,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CommandCSSetSecure final
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandCSSetSecure(Module *creator, const Anope::string &cname = "chanserv/set/secure") : Command(creator, cname, 2, 2)
|
||||
{
|
||||
this->SetDesc(_("Activate security features"));
|
||||
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(params[0]);
|
||||
if (ci == NULL)
|
||||
{
|
||||
source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params[1].equals_ci("ON"))
|
||||
{
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure";
|
||||
ci->Extend<bool>("CS_SECURE");
|
||||
source.Reply(_("Secure option for %s is now \002on\002."), ci->name.c_str());
|
||||
}
|
||||
else if (params[1].equals_ci("OFF"))
|
||||
{
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure";
|
||||
ci->Shrink<bool>("CS_SECURE");
|
||||
source.Reply(_("Secure option for %s is now \002off\002."), ci->name.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "SECURE");
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Enables or disables security features for a\n"
|
||||
"channel. When \002SECURE\002 is set, only users who have\n"
|
||||
"identified to services, and are not only recognized, will be\n"
|
||||
"given access to channels from account-based access entries."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandCSSetSecureFounder final
|
||||
: public Command
|
||||
{
|
||||
@@ -1110,7 +1046,7 @@ class CSSet final
|
||||
: public Module
|
||||
{
|
||||
SerializableExtensibleItem<bool> noautoop, peace, securefounder,
|
||||
restricted, secure, secureops, signkick, signkick_level, noexpire,
|
||||
restricted, secureops, signkick, signkick_level, noexpire,
|
||||
persist;
|
||||
|
||||
struct KeepModes final
|
||||
@@ -1169,7 +1105,6 @@ class CSSet final
|
||||
CommandCSSetPeace commandcssetpeace;
|
||||
CommandCSSetPersist commandcssetpersist;
|
||||
CommandCSSetRestricted commandcssetrestricted;
|
||||
CommandCSSetSecure commandcssetsecure;
|
||||
CommandCSSetSecureFounder commandcssetsecurefounder;
|
||||
CommandCSSetSecureOps commandcssetsecureops;
|
||||
CommandCSSetSignKick commandcssetsignkick;
|
||||
@@ -1184,7 +1119,7 @@ public:
|
||||
CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
noautoop(this, "NOAUTOOP"), peace(this, "PEACE"),
|
||||
securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"),
|
||||
secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
|
||||
secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
|
||||
signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"),
|
||||
persist(this, "PERSIST"),
|
||||
keep_modes(this, "CS_KEEP_MODES"),
|
||||
@@ -1192,7 +1127,7 @@ public:
|
||||
commandcsset(this), commandcssetautoop(this), commandcssetbantype(this),
|
||||
commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this),
|
||||
commandcssetpeace(this), commandcssetpersist(this), commandcssetrestricted(this),
|
||||
commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
|
||||
commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
|
||||
commandcssetsuccessor(this), commandcssetnoexpire(this),
|
||||
|
||||
inhabit("inhabit")
|
||||
@@ -1304,8 +1239,6 @@ public:
|
||||
info.AddOption(_("Peace"));
|
||||
if (restricted.HasExt(ci))
|
||||
info.AddOption(_("Restricted access"));
|
||||
if (secure.HasExt(ci))
|
||||
info.AddOption(_("Security"));
|
||||
if (securefounder.HasExt(ci))
|
||||
info.AddOption(_("Secure founder"));
|
||||
if (secureops.HasExt(ci))
|
||||
|
||||
@@ -35,7 +35,6 @@ else \
|
||||
#define OLD_BI_PRIVATE 0x0001
|
||||
|
||||
#define OLD_NI_KILLPROTECT 0x00000001 /* Kill others who take this nick */
|
||||
#define OLD_NI_SECURE 0x00000002 /* Don't recognize unless IDENTIFY'd */
|
||||
#define OLD_NI_MSG 0x00000004 /* Use PRIVMSGs instead of NOTICEs */
|
||||
#define OLD_NI_MEMO_HARDMAX 0x00000008 /* Don't allow user to change memo limit */
|
||||
#define OLD_NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */
|
||||
@@ -60,7 +59,6 @@ else \
|
||||
#define OLD_CI_TOPICLOCK 0x00000008
|
||||
#define OLD_CI_RESTRICTED 0x00000010
|
||||
#define OLD_CI_PEACE 0x00000020
|
||||
#define OLD_CI_SECURE 0x00000040
|
||||
#define OLD_CI_VERBOTEN 0x00000080
|
||||
#define OLD_CI_ENCRYPTEDPW 0x00000100
|
||||
#define OLD_CI_NO_EXPIRE 0x00000200
|
||||
@@ -449,7 +447,7 @@ static void LoadNicks()
|
||||
READ(read_string(buffer, f));
|
||||
auto *nc = new NickCore(buffer);
|
||||
|
||||
const Anope::string settings[] = { "killprotect", "kill_quick", "ns_secure", "ns_private", "hide_email",
|
||||
const Anope::string settings[] = { "killprotect", "kill_quick", "ns_private", "hide_email",
|
||||
"hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "ns_keepmodes" };
|
||||
for (const auto &setting : settings)
|
||||
nc->Shrink<bool>(setting.upper());
|
||||
@@ -483,8 +481,6 @@ static void LoadNicks()
|
||||
READ(read_uint32(&u32, f));
|
||||
if (u32 & OLD_NI_KILLPROTECT)
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
if (u32 & OLD_NI_SECURE)
|
||||
nc->Extend<bool>("NS_SECURE");
|
||||
if (u32 & OLD_NI_MSG)
|
||||
nc->Extend<bool>("MSG");
|
||||
if (u32 & OLD_NI_MEMO_HARDMAX)
|
||||
@@ -571,7 +567,6 @@ static void LoadNicks()
|
||||
for (uint16_t j = 0; j < u16; ++j)
|
||||
{
|
||||
READ(read_string(buffer, f));
|
||||
nc->access.push_back(buffer);
|
||||
}
|
||||
|
||||
int16_t i16;
|
||||
@@ -752,7 +747,7 @@ static void LoadChannels()
|
||||
READ(read_buffer(namebuf, f));
|
||||
auto *ci = new ChannelInfo(namebuf);
|
||||
|
||||
const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "cs_secure", "secureops", "securefounder",
|
||||
const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "secureops", "securefounder",
|
||||
"signkick", "signkick_level", "topiclock", "persist", "noautoop", "cs_keepmodes" };
|
||||
for (const auto &setting : settings)
|
||||
ci->Shrink<bool>(setting.upper());
|
||||
@@ -801,8 +796,6 @@ static void LoadChannels()
|
||||
ci->Extend<bool>("RESTRICTED");
|
||||
if (tmpu32 & OLD_CI_PEACE)
|
||||
ci->Extend<bool>("PEACE");
|
||||
if (tmpu32 & OLD_CI_SECURE)
|
||||
ci->Extend<bool>("CS_SECURE");
|
||||
if (tmpu32 & OLD_CI_NO_EXPIRE)
|
||||
ci->Extend<bool>("CS_NO_EXPIRE");
|
||||
if (tmpu32 & OLD_CI_MEMO_HARDMAX)
|
||||
|
||||
@@ -190,27 +190,14 @@ public:
|
||||
else if (MOD_RESULT == EVENT_ALLOW)
|
||||
return;
|
||||
|
||||
if (!na->nc->HasExt("NS_SECURE") && u->IsRecognized())
|
||||
{
|
||||
na->last_seen = Anope::CurTime;
|
||||
na->last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
|
||||
na->last_realname = u->realname;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
|
||||
return;
|
||||
|
||||
bool on_access = u->IsRecognized(false);
|
||||
|
||||
if (on_access || !na->nc->HasExt("KILL_IMMED"))
|
||||
if (!na->nc->HasExt("KILL_IMMED"))
|
||||
{
|
||||
if (na->nc->HasExt("NS_SECURE"))
|
||||
u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
|
||||
else
|
||||
u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
|
||||
u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
|
||||
}
|
||||
if (na->nc->HasExt("KILLPROTECT") && !on_access)
|
||||
if (na->nc->HasExt("KILLPROTECT"))
|
||||
{
|
||||
if (na->nc->HasExt("KILL_IMMED"))
|
||||
{
|
||||
@@ -310,10 +297,9 @@ public:
|
||||
|
||||
NickServ = bi;
|
||||
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "ns_secure memo_signon memo_receive")).GetTokens(defaults);
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "memo_signon memo_receive")).GetTokens(defaults);
|
||||
if (defaults.empty())
|
||||
{
|
||||
defaults.emplace_back("NS_SECURE");
|
||||
defaults.emplace_back("MEMO_SIGNON");
|
||||
defaults.emplace_back("MEMO_RECEIVE");
|
||||
}
|
||||
@@ -523,7 +509,7 @@ public:
|
||||
|
||||
/* Update last quit and last seen for the user */
|
||||
NickAlias *na = NickAlias::Find(u->nick);
|
||||
if (na && !na->nc->HasExt("NS_SUSPENDED") && (u->IsRecognized() || u->IsIdentified(true)))
|
||||
if (na && !na->nc->HasExt("NS_SUSPENDED") && u->IsIdentified(true))
|
||||
{
|
||||
na->last_seen = Anope::CurTime;
|
||||
na->last_quit = msg;
|
||||
@@ -543,7 +529,7 @@ public:
|
||||
++it;
|
||||
|
||||
User *u = User::Find(na->nick, true);
|
||||
if (u && (u->IsIdentified(true) || u->IsRecognized()))
|
||||
if (u && u->IsIdentified(true))
|
||||
na->last_seen = Anope::CurTime;
|
||||
|
||||
bool expire = false;
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class CommandNSAccess final
|
||||
: public Command
|
||||
{
|
||||
private:
|
||||
void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask)
|
||||
{
|
||||
if (mask.empty())
|
||||
{
|
||||
this->OnSyntaxError(source, "ADD");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nc->access.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax", "32"))
|
||||
{
|
||||
source.Reply(_("Sorry, the maximum of %d access entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nc->FindAccess(mask))
|
||||
{
|
||||
source.Reply(_("Mask \002%s\002 already present on %s's access list."), mask.c_str(), nc->display.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
nc->AddAccess(mask);
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD mask " << mask << " to " << nc->display;
|
||||
source.Reply(_("\002%s\002 added to %s's access list."), mask.c_str(), nc->display.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask)
|
||||
{
|
||||
if (mask.empty())
|
||||
{
|
||||
this->OnSyntaxError(source, "DEL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nc->FindAccess(mask))
|
||||
{
|
||||
source.Reply(_("\002%s\002 not found on %s's access list."), mask.c_str(), nc->display.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
nc->EraseAccess(mask);
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE mask " << mask << " from " << nc->display;
|
||||
source.Reply(_("\002%s\002 deleted from %s's access list."), mask.c_str(), nc->display.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoList(CommandSource &source, NickCore *nc, const Anope::string &mask)
|
||||
{
|
||||
unsigned i, end;
|
||||
|
||||
if (nc->access.empty())
|
||||
{
|
||||
source.Reply(_("%s's access list is empty."), nc->display.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
source.Reply(_("Access list for %s:"), nc->display.c_str());
|
||||
for (i = 0, end = nc->access.size(); i < end; ++i)
|
||||
{
|
||||
Anope::string access = nc->GetAccess(i);
|
||||
if (!mask.empty() && !Anope::Match(access, mask))
|
||||
continue;
|
||||
source.Reply(" %s", access.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
public:
|
||||
CommandNSAccess(Module *creator) : Command(creator, "nickserv/access", 1, 3)
|
||||
{
|
||||
this->SetDesc(_("Modify the list of authorized addresses"));
|
||||
this->SetSyntax(_("ADD [\037nickname\037] \037mask\037"));
|
||||
this->SetSyntax(_("DEL [\037nickname\037] \037mask\037"));
|
||||
this->SetSyntax(_("LIST [\037nickname\037]"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
const Anope::string &cmd = params[0];
|
||||
Anope::string nick, mask;
|
||||
|
||||
if (cmd.equals_ci("LIST"))
|
||||
nick = params.size() > 1 ? params[1] : "";
|
||||
else
|
||||
{
|
||||
nick = params.size() == 3 ? params[1] : "";
|
||||
mask = params.size() > 1 ? params[params.size() - 1] : "";
|
||||
}
|
||||
|
||||
NickCore *nc;
|
||||
if (!nick.empty())
|
||||
{
|
||||
const NickAlias *na = NickAlias::Find(nick);
|
||||
if (na == NULL)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
return;
|
||||
}
|
||||
else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->nc && na->nc->IsServicesOper() && !cmd.equals_ci("LIST"))
|
||||
{
|
||||
source.Reply(_("You may view but not modify the access list of other Services Operators."));
|
||||
return;
|
||||
}
|
||||
|
||||
nc = na->nc;
|
||||
}
|
||||
else
|
||||
nc = source.nc;
|
||||
|
||||
if (!mask.empty() && (mask.find('@') == Anope::string::npos || mask.find('!') != Anope::string::npos))
|
||||
{
|
||||
source.Reply(BAD_USERHOST_MASK);
|
||||
source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
|
||||
}
|
||||
else if (cmd.equals_ci("LIST"))
|
||||
return this->DoList(source, nc, mask);
|
||||
else if (nc->HasExt("NS_SUSPENDED"))
|
||||
source.Reply(NICK_X_SUSPENDED, nc->display.c_str());
|
||||
else if (cmd.equals_ci("ADD"))
|
||||
return this->DoAdd(source, nc, mask);
|
||||
else if (cmd.equals_ci("DEL"))
|
||||
return this->DoDel(source, nc, mask);
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Modifies or displays the access list for your nick. This\n"
|
||||
"is the list of addresses which will be automatically\n"
|
||||
"recognized by %s as allowed to use the nick. If\n"
|
||||
"you want to use the nick from a different address, you\n"
|
||||
"need to send an \002IDENTIFY\002 command to make %s\n"
|
||||
"recognize you. Services Operators may provide a nick\n"
|
||||
"to modify other users' access lists.\n"
|
||||
" \n"
|
||||
"Examples:\n"
|
||||
" \n"
|
||||
" \002ACCESS ADD anyone@*.bepeg.com\002\n"
|
||||
" Allows access to user \002anyone\002 from any machine in\n"
|
||||
" the \002bepeg.com\002 domain.\n"
|
||||
" \n"
|
||||
" \002ACCESS DEL anyone@*.bepeg.com\002\n"
|
||||
" Reverses the previous command.\n"
|
||||
" \n"
|
||||
" \002ACCESS LIST\002\n"
|
||||
" Displays the current access list."), source.service->nick.c_str(), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class NSAccess final
|
||||
: public Module
|
||||
{
|
||||
CommandNSAccess commandnsaccess;
|
||||
|
||||
public:
|
||||
NSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandnsaccess(this)
|
||||
{
|
||||
}
|
||||
|
||||
void OnNickRegister(User *u, NickAlias *na, const Anope::string &) override
|
||||
{
|
||||
if (u && Config->GetModule(this)->Get<bool>("addaccessonreg"))
|
||||
na->nc->AddAccess(u->Mask());
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSAccess)
|
||||
@@ -299,7 +299,7 @@ public:
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
return;
|
||||
}
|
||||
else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access"))
|
||||
else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/cert"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
// same person that is executing the command, so kill them off (old GHOST command).
|
||||
else if (u->Account() == na->nc)
|
||||
{
|
||||
if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
|
||||
if (!source.GetAccount())
|
||||
{
|
||||
source.GetUser()->Login(u->Account());
|
||||
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->display;
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
/* User is not identified or not identified to the same account as the person using this command */
|
||||
else
|
||||
{
|
||||
if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
|
||||
if (!source.GetAccount())
|
||||
{
|
||||
source.GetUser()->Login(na->nc); // Identify the user using the command if they arent identified
|
||||
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->nick << " (" << na->nc->display << ")";
|
||||
@@ -182,8 +182,6 @@ public:
|
||||
bool ok = false;
|
||||
if (source.GetAccount() == na->nc)
|
||||
ok = true;
|
||||
else if (!na->nc->HasExt("NS_SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser()))
|
||||
ok = true;
|
||||
|
||||
NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
|
||||
if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl && cl->FindCert(source.GetUser()->fingerprint))
|
||||
|
||||
@@ -233,11 +233,7 @@ public:
|
||||
|
||||
Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
|
||||
|
||||
if (na->nc->GetAccessCount())
|
||||
source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str());
|
||||
else
|
||||
source.Reply(_("Nickname \002%s\002 registered."), u_nick.c_str());
|
||||
|
||||
source.Reply(_("Nickname \002%s\002 registered."), u_nick.c_str());
|
||||
if (nsregister.equals_ci("admin"))
|
||||
{
|
||||
nc->Extend<bool>("UNCONFIRMED");
|
||||
|
||||
+2
-105
@@ -1105,103 +1105,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSetSecure
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSSetSecure(Module *creator, const Anope::string &sname = "nickserv/set/secure", size_t min = 1) : Command(creator, sname, min, min + 1)
|
||||
{
|
||||
this->SetDesc(_("Turn nickname security on or off"));
|
||||
this->SetSyntax("{ON | OFF}");
|
||||
}
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable secure for " << nc->display;
|
||||
nc->Extend<bool>("NS_SECURE");
|
||||
source.Reply(_("Secure option is now \002on\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable secure for " << nc->display;
|
||||
nc->Shrink<bool>("NS_SECURE");
|
||||
source.Reply(_("Secure option is now \002off\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "SECURE");
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, source.nc->display, params[0]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns %s's security features on or off for your\n"
|
||||
"nick. With \002SECURE\002 set, you must enter your password\n"
|
||||
"before you will be recognized as the owner of the nick,\n"
|
||||
"regardless of whether your address is on the access\n"
|
||||
"list. However, if you are on the access list, %s\n"
|
||||
"will not auto-kill you regardless of the setting of the\n"
|
||||
"\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetSecure final
|
||||
: public CommandNSSetSecure
|
||||
{
|
||||
public:
|
||||
CommandNSSASetSecure(Module *creator) : CommandNSSetSecure(creator, "nickserv/saset/secure", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns %s's security features on or off for your\n"
|
||||
"nick. With \002SECURE\002 set, you must enter your password\n"
|
||||
"before you will be recognized as the owner of the nick,\n"
|
||||
"regardless of whether your address is on the access\n"
|
||||
"list. However, if you are on the access list, %s\n"
|
||||
"will not auto-kill you regardless of the setting of the\n"
|
||||
"\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetNoexpire final
|
||||
: public Command
|
||||
{
|
||||
@@ -1288,13 +1191,10 @@ class NSSet final
|
||||
CommandNSSetPassword commandnssetpassword;
|
||||
CommandNSSASetPassword commandnssasetpassword;
|
||||
|
||||
CommandNSSetSecure commandnssetsecure;
|
||||
CommandNSSASetSecure commandnssasetsecure;
|
||||
|
||||
CommandNSSASetNoexpire commandnssasetnoexpire;
|
||||
|
||||
SerializableExtensibleItem<bool> autoop, neverop, killprotect, kill_quick, kill_immed,
|
||||
message, secure, noexpire;
|
||||
message, noexpire;
|
||||
|
||||
struct KeepModes final
|
||||
: SerializableExtensibleItem<bool>
|
||||
@@ -1358,13 +1258,12 @@ public:
|
||||
commandnssetlanguage(this), commandnssasetlanguage(this),
|
||||
commandnssetmessage(this), commandnssasetmessage(this),
|
||||
commandnssetpassword(this), commandnssasetpassword(this),
|
||||
commandnssetsecure(this), commandnssasetsecure(this),
|
||||
commandnssasetnoexpire(this),
|
||||
|
||||
autoop(this, "AUTOOP"), neverop(this, "NEVEROP"),
|
||||
killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"),
|
||||
kill_immed(this, "KILL_IMMED"), message(this, "MSG"),
|
||||
secure(this, "NS_SECURE"), noexpire(this, "NS_NO_EXPIRE"),
|
||||
noexpire(this, "NS_NO_EXPIRE"),
|
||||
|
||||
keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email")
|
||||
{
|
||||
@@ -1420,8 +1319,6 @@ public:
|
||||
info.AddOption(_("Quick protection"));
|
||||
else if (killprotect.HasExt(na->nc))
|
||||
info.AddOption(_("Protection"));
|
||||
if (secure.HasExt(na->nc))
|
||||
info.AddOption(_("Security"));
|
||||
if (message.HasExt(na->nc))
|
||||
info.AddOption(_("Message mode"));
|
||||
if (autoop.HasExt(na->nc))
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class CommandNSStatus final
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSStatus(Module *creator) : Command(creator, "nickserv/status", 0, 16)
|
||||
{
|
||||
this->SetDesc(_("Returns the owner status of the given nickname"));
|
||||
this->SetSyntax(_("[\037nickname\037]"));
|
||||
this->AllowUnregistered(true);
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
const Anope::string &nick = !params.empty() ? params[0] : source.GetNick();
|
||||
const NickAlias *na = NickAlias::Find(nick);
|
||||
spacesepstream sep(nick);
|
||||
Anope::string nickbuf;
|
||||
|
||||
while (sep.GetToken(nickbuf))
|
||||
{
|
||||
User *u2 = User::Find(nickbuf, true);
|
||||
if (!u2) /* Nick is not online */
|
||||
source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, "");
|
||||
else if (u2->IsIdentified() && na && na->nc == u2->Account()) /* Nick is identified */
|
||||
source.Reply("STATUS %s %d %s", nickbuf.c_str(), 3, u2->Account()->display.c_str());
|
||||
else if (u2->IsRecognized()) /* Nick is recognised, but NOT identified */
|
||||
source.Reply("STATUS %s %d %s", nickbuf.c_str(), 2, u2->Account() ? u2->Account()->display.c_str() : "");
|
||||
else if (!na) /* Nick is online, but NOT a registered */
|
||||
source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, "");
|
||||
else
|
||||
/* Nick is not identified for the nick, but they could be logged into an account,
|
||||
* so we tell the user about it
|
||||
*/
|
||||
source.Reply("STATUS %s %d %s", nickbuf.c_str(), 1, u2->Account() ? u2->Account()->display.c_str() : "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Returns whether the user using the given nickname is\n"
|
||||
"recognized as the owner of the nickname. The response has\n"
|
||||
"this format:\n"
|
||||
" \n"
|
||||
" \037nickname\037 \037status-code\037 \037account\037\n"
|
||||
" \n"
|
||||
"where \037nickname\037 is the nickname sent with the command,\n"
|
||||
"\037status-code\037 is one of the following, and \037account\037\n"
|
||||
"is the account they are logged in as.\n"
|
||||
" \n"
|
||||
" 0 - no such user online \002or\002 nickname not registered\n"
|
||||
" 1 - user not recognized as nickname's owner\n"
|
||||
" 2 - user recognized as owner via access list only\n"
|
||||
" 3 - user recognized as owner via password identification\n"
|
||||
" \n"
|
||||
"If no nickname is given, your status will be returned."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class NSStatus final
|
||||
: public Module
|
||||
{
|
||||
CommandNSStatus commandnsstatus;
|
||||
|
||||
public:
|
||||
NSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandnsstatus(this)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSStatus)
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
" \n"
|
||||
"Sets read-only mode on or off. In read-only mode, normal\n"
|
||||
"users will not be allowed to modify any services data,\n"
|
||||
"including channel and nickname access lists, etc. IRCops\n"
|
||||
"including channel access lists, etc. Server operators\n"
|
||||
"with sufficient services privileges will be able to modify\n"
|
||||
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
|
||||
"suspend or forbid nicknames and channels, and manage news,\n"
|
||||
|
||||
@@ -76,14 +76,6 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
ci->Shrink<bool>("RESTRICTED");
|
||||
replacements["MESSAGES"] = "Restricted updated";
|
||||
}
|
||||
if (ci->HasExt("CS_SECURE") != message.post_data.count("secure"))
|
||||
{
|
||||
if (!ci->HasExt("CS_SECURE"))
|
||||
ci->Extend<bool>("CS_SECURE");
|
||||
else
|
||||
ci->Shrink<bool>("CS_SECURE");
|
||||
replacements["MESSAGES"] = "Secure updated";
|
||||
}
|
||||
if (ci->HasExt("SECUREOPS") != message.post_data.count("secureops"))
|
||||
{
|
||||
if (!ci->HasExt("SECUREOPS"))
|
||||
@@ -132,9 +124,6 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
|
||||
if (ci->HasExt("RESTRICTED"))
|
||||
replacements["RESTRICTED"];
|
||||
|
||||
if (ci->HasExt("CS_SECURE"))
|
||||
replacements["SECURE"];
|
||||
|
||||
if (ci->HasExt("SECUREOPS"))
|
||||
replacements["SECUREOPS"];
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#include "../../webcpanel.h"
|
||||
|
||||
WebCPanel::NickServ::Access::Access(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
|
||||
{
|
||||
}
|
||||
|
||||
bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
|
||||
{
|
||||
if (message.post_data.count("access") > 0)
|
||||
{
|
||||
std::vector<Anope::string> params;
|
||||
params.emplace_back("ADD");
|
||||
params.push_back(message.post_data["access"]);
|
||||
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
}
|
||||
else if (message.get_data.count("del") > 0 && message.get_data.count("mask") > 0)
|
||||
{
|
||||
std::vector<Anope::string> params;
|
||||
params.emplace_back("DEL");
|
||||
params.push_back(message.get_data["mask"]);
|
||||
|
||||
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
|
||||
}
|
||||
|
||||
for (const auto &access : na->nc->access)
|
||||
replacements["ACCESS"] = access;
|
||||
|
||||
TemplateFileServer page("nickserv/access.html");
|
||||
page.Serve(server, page_name, client, message, reply, replacements);
|
||||
return true;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* (C) 2003-2024 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace WebCPanel
|
||||
{
|
||||
|
||||
namespace NickServ
|
||||
{
|
||||
|
||||
class Access final
|
||||
: public WebPanelProtectedPage
|
||||
{
|
||||
public:
|
||||
Access(const Anope::string &cat, const Anope::string &u);
|
||||
|
||||
bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,14 +56,6 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
na->nc->Shrink<bool>("NS_PRIVATE");
|
||||
replacements["MESSAGES"] = "Private updated";
|
||||
}
|
||||
if (na->nc->HasExt("NS_SECURE") != message.post_data.count("secure"))
|
||||
{
|
||||
if (!na->nc->HasExt("NS_SECURE"))
|
||||
na->nc->Extend<bool>("NS_SECURE");
|
||||
else
|
||||
na->nc->Shrink<bool>("NS_SECURE");
|
||||
replacements["MESSAGES"] = "Secure updated";
|
||||
}
|
||||
if (message.post_data["kill"] == "on" && !na->nc->HasExt("KILLPROTECT"))
|
||||
{
|
||||
na->nc->Extend<bool>("KILLPROTECT");
|
||||
@@ -102,8 +94,6 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
|
||||
replacements["AUTOOP"];
|
||||
if (na->nc->HasExt("NS_PRIVATE"))
|
||||
replacements["PRIVATE"];
|
||||
if (na->nc->HasExt("NS_SECURE"))
|
||||
replacements["SECURE"];
|
||||
if (na->nc->HasExt("KILLPROTECT"))
|
||||
replacements["KILL_ON"];
|
||||
if (na->nc->HasExt("KILL_QUICK"))
|
||||
|
||||
@@ -64,10 +64,6 @@
|
||||
<td>Restricted</td>
|
||||
<td><input type="checkbox" name="restricted" value="on" {IF EXISTS RESTRICTED}checked{END IF}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secure</td>
|
||||
<td><input type="checkbox" name="secure" value="on" {IF EXISTS SECURE}checked{END IF}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secure Ops</td>
|
||||
<td><input type="checkbox" name="secureops" value="on" {IF EXISTS SECUREOPS}checked{END IF}></td>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
{INCLUDE header.html}
|
||||
<div class="panel-heading">Nick access list</div>
|
||||
<div class="panel-body">
|
||||
{FOR M IN MESSAGES}
|
||||
<div class="alert alert-info">
|
||||
{M}<br>
|
||||
</div>
|
||||
{END FOR}
|
||||
|
||||
{IF EXISTS ACCESS}
|
||||
<table id="tableNSAccess" class="table table-hover">
|
||||
<tbody>
|
||||
{FOR A IN ACCESS}
|
||||
<tr>
|
||||
<td class="col-lg-4">{A}</td>
|
||||
<td class="col-lg-8"><a href="/nickserv/access?mask={A}&del=1" class="btn btn-sm btn-danger">Delete</a></td>
|
||||
</tr>
|
||||
{END FOR}
|
||||
</tbody>
|
||||
</table>
|
||||
{ELSE}
|
||||
<em>Your access list is empty.</em>
|
||||
{END IF}
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Add an access entry</h4>
|
||||
<form class="form-horizontal" method="post" action="/nickserv/access">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-2" for="access">Hostmask:</label>
|
||||
<div class="col-lg-5">
|
||||
<input class="form-control" type="text" name="access" id="access" placeholder="Mask must be in the form user@host">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-5">
|
||||
<button type="submit" class="btn btn-primary">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{INCLUDE footer.html}
|
||||
@@ -48,10 +48,6 @@
|
||||
<td>Private:</td>
|
||||
<td><input type="checkbox" name="private" value="on" {IF EXISTS PRIVATE}checked{END IF}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secure:</td>
|
||||
<td><input type="checkbox" name="secure" value="on" {IF EXISTS SECURE}checked{END IF}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kill:</td>
|
||||
<td>
|
||||
|
||||
@@ -27,7 +27,6 @@ class ModuleWebCPanel final
|
||||
|
||||
WebCPanel::NickServ::Info nickserv_info;
|
||||
WebCPanel::NickServ::Cert nickserv_cert;
|
||||
WebCPanel::NickServ::Access nickserv_access;
|
||||
WebCPanel::NickServ::Alist nickserv_alist;
|
||||
WebCPanel::NickServ::Confirm nickserv_confirm;
|
||||
|
||||
@@ -51,7 +50,7 @@ public:
|
||||
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_confirm("NickServ", "/nickserv/confirm"),
|
||||
nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), 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")
|
||||
@@ -99,11 +98,6 @@ public:
|
||||
provider->RegisterPage(&this->nickserv_cert);
|
||||
}
|
||||
|
||||
ss.name = "Access";
|
||||
ss.url = "/nickserv/access";
|
||||
s.subsections.push_back(ss);
|
||||
provider->RegisterPage(&this->nickserv_access);
|
||||
|
||||
ss.name = "AList";
|
||||
ss.url = "/nickserv/alist";
|
||||
s.subsections.push_back(ss);
|
||||
@@ -219,7 +213,6 @@ public:
|
||||
|
||||
provider->UnregisterPage(&this->nickserv_info);
|
||||
provider->UnregisterPage(&this->nickserv_cert);
|
||||
provider->UnregisterPage(&this->nickserv_access);
|
||||
provider->UnregisterPage(&this->nickserv_alist);
|
||||
provider->UnregisterPage(&this->nickserv_confirm);
|
||||
|
||||
|
||||
@@ -170,7 +170,6 @@ namespace WebPanel
|
||||
|
||||
#include "pages/nickserv/info.h"
|
||||
#include "pages/nickserv/cert.h"
|
||||
#include "pages/nickserv/access.h"
|
||||
#include "pages/nickserv/alist.h"
|
||||
#include "pages/nickserv/confirm.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user