From e7dd7159b1e1ab5b3edabc44ece5338672f8fbb4 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 9 Oct 2016 19:51:39 -0400 Subject: Make vhosts assignable to accounts, not nicks. Allow multiple vhosts per account. --- modules/hostserv/add.cpp | 135 ++++++++++++++++++++ modules/hostserv/del.cpp | 77 ++++------- modules/hostserv/group.cpp | 144 --------------------- modules/hostserv/list.cpp | 79 ++++++------ modules/hostserv/main/hostserv.cpp | 14 +- modules/hostserv/main/vhost.cpp | 14 +- modules/hostserv/main/vhost.h | 4 + modules/hostserv/main/vhosttype.cpp | 1 + modules/hostserv/main/vhosttype.h | 1 + modules/hostserv/off.cpp | 8 +- modules/hostserv/on.cpp | 44 ++++--- modules/hostserv/request.cpp | 42 +++--- modules/hostserv/set.cpp | 246 ++++++++---------------------------- 13 files changed, 324 insertions(+), 485 deletions(-) create mode 100644 modules/hostserv/add.cpp delete mode 100644 modules/hostserv/group.cpp (limited to 'modules/hostserv') diff --git a/modules/hostserv/add.cpp b/modules/hostserv/add.cpp new file mode 100644 index 000000000..42f457b25 --- /dev/null +++ b/modules/hostserv/add.cpp @@ -0,0 +1,135 @@ +/* + * Anope IRC Services + * + * Copyright (C) 2003-2016 Anope Team + * + * This file is part of Anope. Anope is free software; you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software + * Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see see . + */ + +#include "module.h" + +class CommandHSAdd : public Command +{ + public: + CommandHSAdd(Module *creator) : Command(creator, "hostserv/add", 2, 2) + { + this->SetDesc(_("Adds a vhost to an account")); + this->SetSyntax(_("\037account\037 \037hostmask\037")); + } + + void Execute(CommandSource &source, const std::vector ¶ms) override + { + if (Anope::ReadOnly) + { + source.Reply(_("Services are in read-only mode.")); + return; + } + + const Anope::string &nick = params[0]; + + NickServ::Nick *na = NickServ::FindNick(nick); + if (na == NULL) + { + source.Reply(_("\002{0}\002 isn't registered."), nick); + return; + } + + Anope::string rawhostmask = params[1]; + + Anope::string user, host; + size_t a = rawhostmask.find('@'); + + if (a == Anope::string::npos) + host = rawhostmask; + else + { + user = rawhostmask.substr(0, a); + host = rawhostmask.substr(a + 1); + } + + if (host.empty()) + { + this->OnSyntaxError(source, ""); + return; + } + + if (!user.empty()) + { + if (!IRCD->CanSetVIdent) + { + source.Reply(_("Vhosts may not contain a username.")); + return; + } + + if (!IRCD->IsIdentValid(user)) + { + source.Reply(_("The requested username is not valid.")); + return; + } + } + + if (host.length() > Config->GetBlock("networkinfo")->Get("hostlen")) + { + source.Reply(_("The requested vhost is too long, please use a hostname no longer than {0} characters."), Config->GetBlock("networkinfo")->Get("hostlen")); + return; + } + + if (!IRCD->IsHostValid(host)) + { + source.Reply(_("The requested hostname is not valid.")); + return; + } + + Anope::string mask = (!user.empty() ? user + "@" : "") + host; + Log(LOG_ADMIN, source, this) << "to add the vhost " << mask << " to " << na->GetAccount()->GetDisplay(); + + HostServ::VHost *vhost = Serialize::New(); + if (vhost == nullptr) + { + source.Reply(_("Unable to create vhost, is hostserv enabled?")); + return; + } + + vhost->SetOwner(na->GetAccount()); + vhost->SetIdent(user); + vhost->SetHost(host); + vhost->SetCreator(source.GetNick()); + vhost->SetCreated(Anope::CurTime); + +#warning "change event to broadcast account" + EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, na); + source.Reply(_("Vhost \002{0}\002 added to \002{1}\002."), mask, na->GetAccount()->GetDisplay()); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Adds the vhost \037hostmask\037 to \037account\037.")); + return true; + } +}; + +class HSAdd : public Module +{ + CommandHSAdd commandhsadd; + + public: + HSAdd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandhsadd(this) + { + if (!IRCD || !IRCD->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); + } +}; + +MODULE_INIT(HSAdd) diff --git a/modules/hostserv/del.cpp b/modules/hostserv/del.cpp index 48a1209fc..4d754ac1b 100644 --- a/modules/hostserv/del.cpp +++ b/modules/hostserv/del.cpp @@ -23,10 +23,10 @@ class CommandHSDel : public Command { public: - CommandHSDel(Module *creator) : Command(creator, "hostserv/del", 1, 1) + CommandHSDel(Module *creator) : Command(creator, "hostserv/del", 1, 2) { - this->SetDesc(_("Delete the vhost of another user")); - this->SetSyntax(_("\037user\037")); + this->SetDesc(_("Delete the vhost of a user")); + this->SetSyntax(_("\037user\037 [\037vhost\037]")); } void Execute(CommandSource &source, const std::vector ¶ms) override @@ -35,6 +35,8 @@ class CommandHSDel : public Command source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); const Anope::string &nick = params[0]; + const Anope::string &host = params.size() > 1 ? params[1] : ""; + NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { @@ -42,67 +44,42 @@ class CommandHSDel : public Command return; } - HostServ::VHost *vhost = na->GetVHost(); - if (vhost == nullptr) + if (!host.empty()) { - source.Reply(_("\002{0}\002 doesn't have a vhost."), na->GetNick()); - return; - } + HostServ::VHost *vhost = HostServ::FindVHost(na->GetAccount(), host); - Log(LOG_ADMIN, source, this) << "for user " << na->GetNick(); - EventManager::Get()->Dispatch(&Event::DeleteVhost::OnDeleteVhost, na); - vhost->Delete(); - source.Reply(_("Vhost for \002{0}\002 has been removed."), na->GetNick()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) override - { - source.Reply(_("Removes the vhost of \037user\037.")); - return true; - } -}; - -class CommandHSDelAll : public Command -{ - public: - CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1) - { - this->SetDesc(_("Delete the vhost for all nicks in a group")); - this->SetSyntax(_("\037group\037")); - } + if (vhost == nullptr) + { + source.Reply(_("\002{0}\002 doesn't have vhost \002{1}\002."), na->GetAccount()->GetDisplay(), host); + return; + } - void Execute(CommandSource &source, const std::vector ¶ms) override - { - if (Anope::ReadOnly) - source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); + Log(LOG_ADMIN, source, this) << "on " << na->GetAccount()->GetDisplay() << " to remove vhost " << vhost->Mask(); + source.Reply(_("Vhost \002{0}\002 for \002{1}\002 has been removed."), vhost->Mask(), na->GetAccount()->GetDisplay()); + vhost->Delete(); + return; + } - const Anope::string &nick = params[0]; - NickServ::Nick *na = NickServ::FindNick(nick); - if (!na) + std::vector vhosts = na->GetAccount()->GetRefs(); + if (vhosts.empty()) { - source.Reply(_("\002{0}\002 isn't registered."), nick); + source.Reply(_("\002{0}\002 doesn't have a vhost."), na->GetAccount()->GetDisplay()); return; } + Log(LOG_ADMIN, source, this) << "on " << na->GetAccount()->GetDisplay(); +#warning "send account" EventManager::Get()->Dispatch(&Event::DeleteVhost::OnDeleteVhost, na); - NickServ::Account *nc = na->GetAccount(); - for (NickServ::Nick *na2 : nc->GetRefs()) - { - HostServ::VHost *vhost = na2->GetVHost(); - if (vhost != nullptr) - { - vhost->Delete(); - } - } + for (HostServ::VHost *v : vhosts) + v->Delete(); - Log(LOG_ADMIN, source, this) << "for all nicks in group " << nc->GetDisplay(); - source.Reply(_("Vhosts for group \002{0}\002 have been removed."), nc->GetDisplay()); + source.Reply(_("Vhost(s) for \002{0}\002 has been removed."), na->GetAccount()->GetDisplay()); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { - source.Reply(_("Removes the vhost of all nicks in the group \037group\037.")); + source.Reply(_("Removes the vhost of \037user\037.")); return true; } }; @@ -110,12 +87,10 @@ class CommandHSDelAll : public Command class HSDel : public Module { CommandHSDel commandhsdel; - CommandHSDelAll commandhsdelall; public: HSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) , commandhsdel(this) - , commandhsdelall(this) { if (!IRCD || !IRCD->CanSetVHost) throw ModuleException("Your IRCd does not support vhosts"); diff --git a/modules/hostserv/group.cpp b/modules/hostserv/group.cpp deleted file mode 100644 index a41dc24db..000000000 --- a/modules/hostserv/group.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Anope IRC Services - * - * Copyright (C) 2003-2016 Anope Team - * - * This file is part of Anope. Anope is free software; you can - * redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software - * Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see see . - */ - -#include "module.h" -#include "modules/nickserv/group.h" - -class CommandHSGroup : public Command -{ - bool setting; - - public: - void Sync(NickServ::Nick *na) - { - if (setting) - return; - - HostServ::VHost *v = na->GetVHost(); - - if (v == nullptr) - return; - - setting = true; - for (NickServ::Nick *nick : na->GetAccount()->GetRefs()) - { - if (nick == na) - continue; - - HostServ::VHost *vhost = Serialize::New(); - if (vhost == nullptr) - continue; - - vhost->SetOwner(nick); - vhost->SetIdent(v->GetIdent()); - vhost->SetHost(v->GetHost()); - vhost->SetCreator(v->GetCreator()); - vhost->SetCreated(Anope::CurTime); - - nick->SetVHost(vhost); - - EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, nick); - } - setting = false; - } - - CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0), setting(false) - { - this->SetDesc(_("Syncs the vhost for all nicks in a group")); - } - - void Execute(CommandSource &source, const std::vector ¶ms) override - { - if (Anope::ReadOnly) - { - source.Reply(_("Services are in read-only mode.")); - return; - } - - NickServ::Nick *na = NickServ::FindNick(source.GetNick()); - if (!na || na->GetAccount() != source.GetAccount()) - { - source.Reply(_("Access denied.")); - return; - } - - HostServ::VHost *vhost = na->GetVHost(); - if (vhost == nullptr) - { - source.Reply(_("There is no vhost assigned to this nickname.")); - return; - } - - this->Sync(na); - if (!vhost->GetIdent().empty()) - source.Reply(_("All vhosts in the group \002{0}\002 have been set to \002{1}\002@\002{2}\002."), source.nc->GetDisplay(), vhost->GetIdent(), vhost->GetHost()); - else - source.Reply(_("All vhosts in the group \002{0}\002 have been set to \002{1}\002."), source.nc->GetDisplay(), vhost->GetHost()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) override - { - source.Reply(_("Sets the vhost of all nicks in your group to the vhost of your current nick.")); - return true; - } -}; - -class HSGroup : public Module - , public EventHook - , public EventHook -{ - CommandHSGroup commandhsgroup; - bool syncongroup; - bool synconset; - - public: - HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) - , EventHook(this) - , EventHook(this) - , commandhsgroup(this) - { - if (!IRCD || !IRCD->CanSetVHost) - throw ModuleException("Your IRCd does not support vhosts"); - } - - void OnSetVhost(NickServ::Nick *na) override - { - if (!synconset) - return; - - commandhsgroup.Sync(na); - } - - void OnNickGroup(User *u, NickServ::Nick *na) override - { - if (!syncongroup) - return; - - commandhsgroup.Sync(na); - } - - void OnReload(Configuration::Conf *conf) override - { - Configuration::Block *block = conf->GetModule(this); - syncongroup = block->Get("syncongroup"); - synconset = block->Get("synconset"); - } -}; - -MODULE_INIT(HSGroup) diff --git a/modules/hostserv/list.cpp b/modules/hostserv/list.cpp index 5a2b5238a..cbb69aa85 100644 --- a/modules/hostserv/list.cpp +++ b/modules/hostserv/list.cpp @@ -21,6 +21,14 @@ class CommandHSList : public Command { + bool VHostMatches(NickServ::Account *acc, const Anope::string &mask) + { + for (HostServ::VHost *vhost : acc->GetRefs()) + if (Anope::Match(vhost->GetHost(), mask)) + return true; + return false; + } + public: CommandHSList(Module *creator) : Command(creator, "hostserv/list", 0, 1) { @@ -63,55 +71,46 @@ class CommandHSList : public Command unsigned display_counter = 0, listmax = Config->GetModule(this->GetOwner())->Get("listmax", "50"); ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Creator")).AddColumn(_("Created")); + list.AddColumn(_("Number")).AddColumn(_("Account")).AddColumn(_("Vhost")).AddColumn(_("Creator")).AddColumn(_("Created")); - for (NickServ::Nick *na : NickServ::service->GetNickList()) + for (NickServ::Account *acc : NickServ::service->GetAccountList()) { - HostServ::VHost *vhost = na->GetVHost(); + std::vector vhosts = acc->GetRefs(); - if (vhost == nullptr) + if (vhosts.empty()) continue; - if (!key.empty() && key[0] != '#') - { - if ((Anope::Match(na->GetNick(), key) || Anope::Match(vhost->GetHost(), key)) && display_counter < listmax) - { - ++display_counter; + ++counter; - ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); - entry["Nick"] = na->GetNick(); - if (!vhost->GetIdent().empty()) - entry["Vhost"] = vhost->GetIdent() + "@" + vhost->GetHost(); - else - entry["Vhost"] = vhost->GetHost(); - entry["Creator"] = vhost->GetCreator(); - entry["Created"] = Anope::strftime(vhost->GetCreated(), NULL, true); - list.AddEntry(entry); - } - } - else + if (display_counter >= listmax) + continue; + + if (from && to && (counter < from || counter > to)) + continue; + + if (!key.empty() && !Anope::Match(acc->GetDisplay(), key) && !VHostMatches(acc, key)) + continue; + + ++display_counter; + + bool first = true; + for (HostServ::VHost *vhost : vhosts) { - /** - * List the host if its in the display range, and not more - * than NSListMax records have been displayed... - **/ - if (((counter >= from && counter <= to) || (!from && !to)) && display_counter < listmax) + ListFormatter::ListEntry entry; + + if (first) { - ++display_counter; - ListFormatter::ListEntry entry; entry["Number"] = stringify(display_counter); - entry["Nick"] = na->GetNick(); - if (!vhost->GetIdent().empty()) - entry["Vhost"] = vhost->GetIdent() + "@" + vhost->GetHost(); - else - entry["Vhost"] = vhost->GetHost(); - entry["Creator"] = vhost->GetCreator(); - entry["Created"] = Anope::strftime(vhost->GetCreated(), NULL, true); - list.AddEntry(entry); + entry["Account"] = acc->GetDisplay(); } + + entry["Vhost"] = vhost->Mask(); + entry["Creator"] = vhost->GetCreator(); + entry["Created"] = Anope::strftime(vhost->GetCreated(), NULL, true); + list.AddEntry(entry); + + first = false; } - ++counter; } if (!display_counter) @@ -139,12 +138,12 @@ class CommandHSList : public Command bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { - source.Reply(_("Lists all vhosts. If \037key\037 is specified, only entries whose nick or vhost match the pattern given in \037key\037 are displayed." + source.Reply(_("Lists all vhosts. If \037key\037 is specified, only entries whose account or vhost match the pattern given in \037key\037 are displayed." "If a \037#X-Y\037 style is used, only entries between the range of \002X\002 and \002Y\002 will be displayed.\n" "\n" "Examples:\n" " {0} Rob*\n" - " Lists all entries with the nick or vhost beginning with \"Rob\"\n" + " Lists all entries with the account or vhost beginning with \"Rob\"\n" "\n" " {0} #1-3\n" " Lists the first three entries."), diff --git a/modules/hostserv/main/hostserv.cpp b/modules/hostserv/main/hostserv.cpp index ab1617a85..b0c3d04f2 100644 --- a/modules/hostserv/main/hostserv.cpp +++ b/modules/hostserv/main/hostserv.cpp @@ -66,14 +66,7 @@ class HostServCore : public Module if (!IRCD->CanSetVHost) return; - NickServ::Nick *na = NickServ::FindNick(u->nick); - HostServ::VHost *vhost = nullptr; - - if (na && na->GetAccount() == u->Account()) - vhost = na->GetVHost(); - - if (vhost == nullptr) - vhost = NickServ::FindNick(u->Account()->GetDisplay())->GetVHost(); + HostServ::VHost *vhost = HostServ::FindVHost(u->Account()); if (vhost == nullptr) return; @@ -123,7 +116,10 @@ class HostServCore : public Module if (u && u->Account() == na->GetAccount()) { - HostServ::VHost *vhost = na->GetVHost(); + HostServ::VHost *vhost = HostServ::FindVHost(u->Account()); + + if (vhost == nullptr) + return; IRCD->SendVhost(u, vhost->GetIdent(), vhost->GetHost()); diff --git a/modules/hostserv/main/vhost.cpp b/modules/hostserv/main/vhost.cpp index f7878d53c..635e3a5b4 100644 --- a/modules/hostserv/main/vhost.cpp +++ b/modules/hostserv/main/vhost.cpp @@ -1,7 +1,7 @@ /* * Anope IRC Services * - * Copyright (C) 2015-2016 Anope Team + * Copyright (C) 2016 Anope Team * * This file is part of Anope. Anope is free software; you can * redistribute it and/or modify it under the terms of the GNU @@ -67,4 +67,14 @@ time_t VHostImpl::GetCreated() void VHostImpl::SetCreated(time_t created) { Set(&VHostType::created, created); -} \ No newline at end of file +} + +bool VHostImpl::IsDefault() +{ + return Get(&VHostType::default_); +} + +void VHostImpl::SetDefault(bool default_) +{ + Set(&VHostType::default_, default_); +} diff --git a/modules/hostserv/main/vhost.h b/modules/hostserv/main/vhost.h index e0b751899..90ac9140f 100644 --- a/modules/hostserv/main/vhost.h +++ b/modules/hostserv/main/vhost.h @@ -30,6 +30,7 @@ class VHostImpl : public HostServ::VHost Anope::string vhost; Anope::string creator; time_t created = 0; + bool default_ = false; public: using HostServ::VHost::VHost; @@ -48,5 +49,8 @@ class VHostImpl : public HostServ::VHost time_t GetCreated() override; void SetCreated(time_t) override; + + bool IsDefault() override; + void SetDefault(bool) override; }; diff --git a/modules/hostserv/main/vhosttype.cpp b/modules/hostserv/main/vhosttype.cpp index 3eae8eec3..ee73840bf 100644 --- a/modules/hostserv/main/vhosttype.cpp +++ b/modules/hostserv/main/vhosttype.cpp @@ -26,6 +26,7 @@ VHostType::VHostType(Module *me) : Serialize::Type(me) , vhost(this, "vhost", &VHostImpl::vhost) , creator(this, "creator", &VHostImpl::creator) , created(this, "created", &VHostImpl::created) + , default_(this, "default", &VHostImpl::default_) { } diff --git a/modules/hostserv/main/vhosttype.h b/modules/hostserv/main/vhosttype.h index 8306cae27..3be60f518 100644 --- a/modules/hostserv/main/vhosttype.h +++ b/modules/hostserv/main/vhosttype.h @@ -27,6 +27,7 @@ class VHostType : public Serialize::Type Serialize::Field vhost; Serialize::Field creator; Serialize::Field created; + Serialize::Field default_; VHostType(Module *); }; diff --git a/modules/hostserv/off.cpp b/modules/hostserv/off.cpp index 95c27532a..1d7d91876 100644 --- a/modules/hostserv/off.cpp +++ b/modules/hostserv/off.cpp @@ -31,14 +31,8 @@ class CommandHSOff : public Command void Execute(CommandSource &source, const std::vector ¶ms) override { User *u = source.GetUser(); - NickServ::Nick *na = NickServ::FindNick(u->nick); - HostServ::VHost *vhost = nullptr; - if (na && na->GetAccount() == source.GetAccount()) - vhost = na->GetVHost(); - - if (vhost == nullptr) - vhost = NickServ::FindNick(u->Account()->GetDisplay())->GetVHost(); + HostServ::VHost *vhost = HostServ::FindVHost(u->Account()); if (vhost == nullptr) { diff --git a/modules/hostserv/on.cpp b/modules/hostserv/on.cpp index c911ec206..c8f4211de 100644 --- a/modules/hostserv/on.cpp +++ b/modules/hostserv/on.cpp @@ -22,9 +22,10 @@ class CommandHSOn : public Command { public: - CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 0) + CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 1) { - this->SetDesc(_("Activates your assigned vhost")); + this->SetDesc(_("Activates a vhost")); + this->SetSyntax(_("[\037vhost\037]")); this->RequireUser(true); } @@ -34,27 +35,31 @@ class CommandHSOn : public Command return; // HostServ wouldn't even be loaded at this point User *u = source.GetUser(); - NickServ::Nick *na = NickServ::FindNick(u->nick); - HostServ::VHost *vhost = nullptr; + const Anope::string &v = params.empty() ? "" : params[0]; + HostServ::VHost *vhost; - if (na && na->GetAccount() == source.GetAccount()) - vhost = na->GetVHost(); - - if (vhost == nullptr) - vhost = NickServ::FindNick(u->Account()->GetDisplay())->GetVHost(); - - if (vhost == nullptr) + if (!v.empty()) { - source.Reply(_("There is no vhost assigned to this nickname.")); - return; + vhost = HostServ::FindVHost(u->Account(), v); + if (vhost == nullptr) + { + source.Reply(_("You do not have the vhost \002{0}\002."), v); + return; + } } - - if (!vhost->GetIdent().empty()) - source.Reply(_("Your vhost of \002{0}\002@\002{1}\002 is now activated."), vhost->GetIdent(), vhost->GetHost()); else - source.Reply(_("Your vhost of \002{0}\002 is now activated."), vhost->GetHost()); + { + vhost = HostServ::FindVHost(u->Account()); + if (vhost == nullptr) + { + source.Reply(_("You do not have any vhosts associated with your account."), vhost); + return; + } + } + + source.Reply(_("Your vhost of \002{0}\002 is now activated."), vhost->Mask()); - Log(LOG_COMMAND, source, this) << "to enable their vhost of " << (!vhost->GetIdent().empty() ? vhost->GetIdent() + "@" : "") << vhost->GetHost(); + Log(LOG_COMMAND, source, this) << "to enable their vhost of " << vhost->Mask(); IRCD->SendVhost(u, vhost->GetIdent(), vhost->GetHost()); u->vhost = vhost->GetHost(); if (IRCD->CanSetVIdent && !vhost->GetIdent().empty()) @@ -64,7 +69,8 @@ class CommandHSOn : public Command bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { - source.Reply(_("Activates your vhost.")); + source.Reply(_("Activates a vhost. If \037vhost\037 is specified, it must be a vhost assigned to your account." + " If \037vhost\037 is not specified, your default vhost will be activated.")); return true; } }; diff --git a/modules/hostserv/request.cpp b/modules/hostserv/request.cpp index 2bad26b48..2e9ccd41b 100644 --- a/modules/hostserv/request.cpp +++ b/modules/hostserv/request.cpp @@ -24,7 +24,7 @@ class HostRequest : public Serialize::Object { friend class HostRequestType; - NickServ::Nick *na = nullptr; + NickServ::Account *acc = nullptr; Anope::string ident, host; time_t time = 0; @@ -34,8 +34,8 @@ class HostRequest : public Serialize::Object HostRequest(Serialize::TypeBase *type) : Serialize::Object(type) { } HostRequest(Serialize::TypeBase *type, Serialize::ID id) : Serialize::Object(type, id) { } - NickServ::Nick *GetNick(); - void SetNick(NickServ::Nick *na); + NickServ::Account *GetAccount(); + void SetAccount(NickServ::Account *); Anope::string GetIdent(); void SetIdent(const Anope::string &i); @@ -50,12 +50,12 @@ class HostRequest : public Serialize::Object class HostRequestType : public Serialize::Type { public: - Serialize::ObjectField na; + Serialize::ObjectField acc; Serialize::Field ident, host; Serialize::Field time; HostRequestType(Module *me) : Serialize::Type(me) - , na(this, "na", &HostRequest::na, true) + , acc(this, "acc", &HostRequest::acc, true) , ident(this, "ident", &HostRequest::ident) , host(this, "host", &HostRequest::host) , time(this, "time", &HostRequest::time) @@ -63,14 +63,14 @@ class HostRequestType : public Serialize::Type } }; -NickServ::Nick *HostRequest::GetNick() +NickServ::Account *HostRequest::GetAccount() { - return Get(&HostRequestType::na); + return Get(&HostRequestType::acc); } -void HostRequest::SetNick(NickServ::Nick *na) +void HostRequest::SetAccount(NickServ::Account *acc) { - Set(&HostRequestType::na, na); + Set(&HostRequestType::acc, acc); } Anope::string HostRequest::GetIdent() @@ -145,12 +145,6 @@ class CommandHSRequest : public Command } User *u = source.GetUser(); - NickServ::Nick *na = NickServ::FindNick(source.GetNick()); - if (!na || na->GetAccount() != source.GetAccount()) - { - source.Reply(_("Access denied.")); //XXX with nonickownership this should be allowed. - return; - } if (source.GetAccount()->HasFieldS("UNCONFIRMED")) { @@ -218,8 +212,12 @@ class CommandHSRequest : public Command return; } - HostRequest *req = Serialize::New(); - req->SetNick(na); + HostRequest *req = u->Account()->GetRef(); + if (req != nullptr) + req->Delete(); // delete old request + + req = Serialize::New(); + req->SetAccount(u->Account()); req->SetIdent(user); req->SetHost(host); req->SetTime(Anope::CurTime); @@ -264,7 +262,7 @@ class CommandHSActivate : public Command return; } - HostRequest *req = na->GetExt("hostrequest"); + HostRequest *req = na->GetAccount()->GetRef(); if (!req) { source.Reply(_("\002{0}\002 does not have a pending vhost request."), na->GetNick()); @@ -278,14 +276,12 @@ class CommandHSActivate : public Command return; } - vhost->SetOwner(na); + vhost->SetOwner(na->GetAccount()); vhost->SetIdent(req->GetIdent()); vhost->SetHost(req->GetHost()); vhost->SetCreator(source.GetNick()); vhost->SetCreated(req->GetTime()); - na->SetVHost(vhost); - EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, na); if (Config->GetModule(this->GetOwner())->Get("memouser") && memoserv) @@ -335,7 +331,7 @@ class CommandHSReject : public Command return; } - HostRequest *req = na->GetExt("hostrequest"); + HostRequest *req = na->GetAccount()->GetRef(); if (!req) { source.Reply(_("\002{0}\002 does not have a pending vhost request."), na->GetNick()); @@ -393,7 +389,7 @@ class CommandHSWaiting : public Command ListFormatter::ListEntry entry; entry["Number"] = stringify(display_counter); - entry["Nick"] = hr->GetNick()->GetNick(); + entry["Nick"] = hr->GetAccount()->GetDisplay(); if (!hr->GetIdent().empty()) entry["Vhost"] = hr->GetIdent() + "@" + hr->GetHost(); else diff --git a/modules/hostserv/set.cpp b/modules/hostserv/set.cpp index 85769e0d2..f66c42d8a 100644 --- a/modules/hostserv/set.cpp +++ b/modules/hostserv/set.cpp @@ -1,7 +1,7 @@ /* * Anope IRC Services * - * Copyright (C) 2003-2016 Anope Team + * Copyright (C) 2016 Anope Team * * This file is part of Anope. Anope is free software; you can * redistribute it and/or modify it under the terms of the GNU @@ -22,142 +22,63 @@ class CommandHSSet : public Command { public: - CommandHSSet(Module *creator) : Command(creator, "hostserv/set", 2, 2) + CommandHSSet(Module *creator) : Command(creator, "hostserv/set", 2, 3) { - this->SetDesc(_("Set the vhost of another user")); - this->SetSyntax(_("\037user\037 \037hostmask\037")); + this->SetDesc(_("Set vhost options")); + this->SetSyntax(_("\037option\037 \037parameters\037")); } void Execute(CommandSource &source, const std::vector ¶ms) override { - if (Anope::ReadOnly) - { - source.Reply(_("Services are in read-only mode.")); - return; - } - - const Anope::string &nick = params[0]; - - NickServ::Nick *na = NickServ::FindNick(nick); - if (na == NULL) - { - source.Reply(_("\002{0}\002 isn't registered."), nick); - return; - } - - Anope::string rawhostmask = params[1]; - - Anope::string user, host; - size_t a = rawhostmask.find('@'); - - if (a == Anope::string::npos) - host = rawhostmask; - else - { - user = rawhostmask.substr(0, a); - host = rawhostmask.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - if (!user.empty()) - { - if (!IRCD->CanSetVIdent) - { - source.Reply(_("Vhosts may not contain a username.")); - return; - } + this->OnSyntaxError(source, ""); + } - if (!IRCD->IsIdentValid(user)) + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Available options:")); + // XXX this entire thing is dup + Anope::string this_name = source.command; + bool hide_privileged_commands = Config->GetBlock("options")->Get("hideprivilegedcommands"), + hide_registered_commands = Config->GetBlock("options")->Get("hideregisteredcommands"); + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) + { + const Anope::string &c_name = it->first; + const CommandInfo &info = it->second; + if (c_name.find_ci(this_name + " ") == 0) { - source.Reply(_("The requested username is not valid.")); - return; + ServiceReference c(info.name); + + // XXX dup + if (!c) + continue; + else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) + continue; + else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) + continue; + + source.command = it->first; + c->OnServHelp(source); } } - if (host.length() > Config->GetBlock("networkinfo")->Get("hostlen")) - { - source.Reply(_("The requested vhost is too long, please use a hostname no longer than {0} characters."), Config->GetBlock("networkinfo")->Get("hostlen")); - return; - } - - if (!IRCD->IsHostValid(host)) - { - source.Reply(_("The requested hostname is not valid.")); - return; - } - - Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->GetNick() << " to " << (!user.empty() ? user + "@" : "") << host; - - HostServ::VHost *vhost = Serialize::New(); - if (vhost == nullptr) - { - source.Reply(_("Unable to create vhost, is hostserv enabled?")); - return; - } - - vhost->SetOwner(na); - vhost->SetIdent(user); - vhost->SetHost(host); - vhost->SetCreator(source.GetNick()); - vhost->SetCreated(Anope::CurTime); - - na->SetVHost(vhost); - - EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, na); - if (!user.empty()) - source.Reply(_("Vhost for \002{0}\002 set to \002{1}\002@\002{2}\002."), na->GetNick(), user, host); - else - source.Reply(_("Vhost for \002{0}\002 set to \002{1}\002."), na->GetNick(), host); - } + CommandInfo *help = source.service->FindCommand("generic/help"); + if (help) + source.Reply(_("Type \002{0}{1} {2} {3} \037option\037\002 for more information on a particular option."), + Config->StrictPrivmsg, source.service->nick, help->cname, this_name); - bool OnHelp(CommandSource &source, const Anope::string &subcommand) override - { - source.Reply(_("Sets the vhost of the given \037user\037 to the given \037hostmask\037.")); return true; } }; -class CommandHSSetAll : public Command +class CommandHSSetDefault : public Command { - void Sync(NickServ::Nick *na) - { - if (!na) - return; - - HostServ::VHost *v = na->GetVHost(); - - if (v == nullptr) - return; - - for (NickServ::Nick *nick : na->GetAccount()->GetRefs()) - { - if (nick == na) - continue; - - HostServ::VHost *vhost = Serialize::New(); - if (vhost == nullptr) - continue; - - vhost->SetOwner(nick); - vhost->SetIdent(v->GetIdent()); - vhost->SetHost(v->GetHost()); - vhost->SetCreator(v->GetCreator()); - vhost->SetCreated(Anope::CurTime); - - nick->SetVHost(vhost); - } - } - public: - CommandHSSetAll(Module *creator) : Command(creator, "hostserv/setall", 2, 2) + CommandHSSetDefault(Module *creator, const Anope::string &cname = "hostserv/set/default") : Command(creator, cname, 1) { - this->SetDesc(_("Set the vhost for all nicks in a group")); - this->SetSyntax(_("\037user\037 \037hostmask\037")); + this->SetDesc(_("Sets your default vhost")); + this->SetSyntax(_("\037vhost\037")); } void Execute(CommandSource &source, const std::vector ¶ms) override @@ -168,88 +89,35 @@ class CommandHSSetAll : public Command return; } - const Anope::string &nick = params[0]; - NickServ::Nick *na = NickServ::FindNick(nick); - if (na == NULL) - { - source.Reply(_("\002{0}\002 isn't registered."), nick); - return; - } - - Anope::string rawhostmask = params[1]; - - Anope::string user, host; - size_t a = rawhostmask.find('@'); - - if (a == Anope::string::npos) - host = rawhostmask; - else - { - user = rawhostmask.substr(0, a); - host = rawhostmask.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - if (!user.empty()) - { - if (!IRCD->CanSetVIdent) - { - source.Reply(_("Vhosts may not contain a username.")); - return; - } + const Anope::string &mask = params[0]; + std::vector vhosts = source.GetAccount()->GetRefs(); - if (!IRCD->IsIdentValid(user)) - { - source.Reply(_("The requested username is not valid.")); - return; - } - } - - if (host.length() > Config->GetBlock("networkinfo")->Get("hostlen")) - { - source.Reply(_("The requested vhost is too long, please use a hostname no longer than {0} characters."), Config->GetBlock("networkinfo")->Get("hostlen")); - return; - } - - if (!IRCD->IsHostValid(host)) + if (vhosts.empty()) { - source.Reply(_("The requested hostname is not valid.")); + source.Reply(_("You do not have any vhosts associated with your account.")); return; } - Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->GetNick() << " to " << (!user.empty() ? user + "@" : "") << host; - - HostServ::VHost *vhost = Serialize::New(); + HostServ::VHost *vhost = HostServ::FindVHost(source.GetAccount(), mask); if (vhost == nullptr) { - source.Reply(_("Unable to create vhost, is hostserv enabled?")); + source.Reply(_("You do not have the vhost \002{0}\002."), mask); return; } - vhost->SetOwner(na); - vhost->SetIdent(user); - vhost->SetHost(host); - vhost->SetCreator(source.GetNick()); - vhost->SetCreated(Anope::CurTime); + /* Disable default on all vhosts */ + for (HostServ::VHost *v : vhosts) + v->SetDefault(false); - na->SetVHost(vhost); + /* Set default on chose vhost */ + vhost->SetDefault(true); - this->Sync(na); - EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, na); - if (!user.empty()) - source.Reply(_("Vhost for group \002{0}\002 set to \002{1}\002@\002{2}\002."), na->GetAccount()->GetDisplay(), user, host); - else - source.Reply(_("host for group \002{0}\002 set to \002{1}\002."), na->GetAccount()->GetDisplay(), host); + source.Reply(_("Your default vhost is now \002{0}\002."), vhost->Mask()); } - bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + bool OnHelp(CommandSource &source, const Anope::string &) override { - source.Reply(_("Sets the vhost for all nicknames in the group of \037user\037.")); + source.Reply(_("Sets your default vhost. Your default vhost is the vhost which is applied when you first login.")); return true; } }; @@ -257,15 +125,13 @@ class CommandHSSetAll : public Command class HSSet : public Module { CommandHSSet commandhsset; - CommandHSSetAll commandhssetall; + CommandHSSetDefault commandhssetdefault; public: HSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) , commandhsset(this) - , commandhssetall(this) + , commandhssetdefault(this) { - if (!IRCD || !IRCD->CanSetVHost) - throw ModuleException("Your IRCd does not support vhosts"); } }; -- cgit