void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } const Anope::string &mask = params[0]; std::vector<HostServ::VHost *> vhosts = source.GetAccount()->GetRefs<HostServ::VHost *>(); if (vhosts.empty()) { source.Reply(_("You do not have any vhosts associated with your account.")); return; } HostServ::VHost *vhost = HostServ::FindVHost(source.GetAccount(), mask); if (vhost == nullptr) { source.Reply(_("You do not have the vhost \002{0}\002."), mask); return; } /* Disable default on all vhosts */ for (HostServ::VHost *v : vhosts) v->SetDefault(false); /* Set default on chose vhost */ vhost->SetDefault(true); source.Reply(_("Your default vhost is now \002{0}\002."), vhost->Mask()); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &nick = !params.empty() ? params[0] : ""; NickServ::Account *nc; if (!nick.empty() && source.IsServicesOper()) { NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } nc = na->GetAccount(); } else nc = source.GetAccount(); ListFormatter list(source.GetAccount()); list.AddColumn(_("Nick")).AddColumn(_("Expires")); time_t nickserv_expire = Config->GetModule("nickserv")->Get<time_t>("expire", "21d"), unconfirmed_expire = Config->GetModule("nickserv")->Get<time_t>("unconfirmedexpire", "1d"); for (NickServ::Nick *na2 : nc->GetRefs<NickServ::Nick *>()) { Anope::string expires; if (na2->HasFieldS("NS_NO_EXPIRE")) expires = _("Does not expire"); else if (!nickserv_expire || Anope::NoExpire) ; else if (na2->GetAccount()->HasFieldS("UNCONFIRMED") && unconfirmed_expire) expires = Anope::strftime(na2->GetTimeRegistered() + unconfirmed_expire, source.GetAccount()); else expires = Anope::strftime(na2->GetLastSeen() + nickserv_expire, source.GetAccount()); ListFormatter::ListEntry entry; entry["Nick"] = na2->GetNick(); entry["Expires"] = expires; list.AddEntry(entry); } source.Reply(nc != source.GetAccount() ? _("List of nicknames in the group of \002%s\002:") : _("List of nicknames in your group:"), nc->GetDisplay().c_str()); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); source.Reply(_("%d nickname(s) in the group."), replies.size()); }
void DoList(CommandSource &source, NickServ::Account *nc) { std::vector<AutoJoin *> channels = nc->GetRefs<AutoJoin *>(); if (channels.empty()) { source.Reply(_("The auto join list of \002{0}\002 is empty."), nc->GetDisplay()); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Channel")).AddColumn(_("Key")); for (unsigned i = 0; i < channels.size(); ++i) { AutoJoin *aj = channels[i]; ListFormatter::ListEntry entry; entry["Number"] = stringify(i + 1); entry["Channel"] = aj->GetChannel(); entry["Key"] = aj->GetKey(); list.AddEntry(entry); } source.Reply(_("Auto join list of \002{0}\002:"), nc->GetDisplay()); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); }
void DoDel(CommandSource &source, NickServ::Account *nc, const Anope::string &mask) { if (mask.empty()) { this->OnSyntaxError(source, "DEL"); return; } if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } for (NickAccess *a : nc->GetRefs<NickAccess *>(nsaccess)) if (a->GetMask().equals_ci(mask)) { a->Delete(); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE mask " << mask << " from " << nc->GetDisplay(); source.Reply(_("\002{0}\002 deleted from the access list of \002{1}\002."), mask, nc->GetDisplay()); return; } source.Reply(_("\002{0}\002 not found on the access list of \002{1}\002."), mask, nc->GetDisplay()); }
void DoDel(CommandSource &source, NickServ::Account *nc, Anope::string certfp) { std::vector<NSCertEntry *> cl = nc->GetRefs<NSCertEntry *>(certentry); if (certfp.empty()) { User *u = source.GetUser(); if (u) certfp = u->fingerprint; } if (certfp.empty()) { this->OnSyntaxError(source, "DEL"); return; } NSCertEntry *cert = FindCert(cl, certfp); if (!cert) { source.Reply(_("\002{0}\002 not found on the certificate list of \002{1}\002."), certfp, nc->GetDisplay()); return; } cert->Delete(); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE certificate fingerprint " << certfp << " from " << nc->GetDisplay(); source.Reply(_("\002{0}\002 deleted from the access list of \002{1}\002."), certfp, nc->GetDisplay()); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (!MemoServ::service) return; const Anope::string &nick = params[0]; const Anope::string &text = params[1]; if (Anope::ReadOnly && !source.IsOper()) { source.Reply(_("Sorry, memo sending is temporarily disabled.")); return; } if (source.GetAccount()->HasFieldS("UNCONFIRMED")) { source.Reply(_("You must confirm your account before you may send a memo.")); return; } MemoServ::MemoServService::MemoResult result = MemoServ::service->Send(source.GetNick(), nick, text); if (result == MemoServ::MemoServService::MEMO_SUCCESS) { source.Reply(_("Memo sent to \002%s\002."), nick.c_str()); Log(LOG_COMMAND, source, this) << "to send a memo to " << nick; } else if (result == MemoServ::MemoServService::MEMO_INVALID_TARGET) source.Reply(_("\002{0}\002 is not a registered unforbidden nick or channel."), nick); else if (result == MemoServ::MemoServService::MEMO_TOO_FAST) source.Reply(_("Please wait \002{0}\002 seconds before using the \002{1}\002 command again."), Config->GetModule("memoserv")->Get<time_t>("senddelay"), source.command); else if (result == MemoServ::MemoServService::MEMO_TARGET_FULL) source.Reply(_("Sorry, \002{0}\002 currently has too many memos and cannot receive more."), nick); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { unsigned count = 0; ListFormatter list(source.GetAccount()); list.AddColumn(_("Nick")).AddColumn(_("Mask")); for (BotInfo *bi : Serialize::GetObjects<BotInfo *>()) { if (source.HasPriv("botserv/administration") || !bi->GetOperOnly()) { ++count; ListFormatter::ListEntry entry; entry["Nick"] = (bi->GetOperOnly() ? "* " : "") + bi->GetNick(); entry["Mask"] = bi->GetUser() + "@" + bi->GetHost(); list.AddEntry(entry); } } std::vector<Anope::string> replies; list.Process(replies); if (!count) { source.Reply(_("There are no bots available")); return; } source.Reply(_("Bot list:")); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); source.Reply(_("{0} bots available."), count); }
void DoList(CommandSource &source, NewsType ntype, const char **msgs) { std::vector<NewsItem *> list = Serialize::GetObjects<NewsItem *>(); if (list.empty()) { source.Reply(msgs[MSG_LIST_NONE]); return; } ListFormatter lflist(source.GetAccount()); lflist.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Text")); unsigned int i = 1; for (NewsItem *n : list) { ListFormatter::ListEntry entry; entry["Number"] = stringify(i++ + 1); entry["Creator"] = n->GetWho(); entry["Created"] = Anope::strftime(n->GetTime(), NULL, true); entry["Text"] = n->GetText(); lflist.AddEntry(entry); } source.Reply(msgs[MSG_LIST_HEADER]); std::vector<Anope::string> replies; lflist.Process(replies); for (i = 0; i < replies.size(); ++i) source.Reply(replies[i]); source.Reply(_("End of news list.")); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { unsigned counter = 0; unsigned display_counter = 0, listmax = Config->GetModule(this->GetOwner())->Get<unsigned>("listmax"); ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Created")); for (HostRequest *hr : Serialize::GetObjects<HostRequest *>()) { if (!listmax || display_counter < listmax) { ++display_counter; ListFormatter::ListEntry entry; entry["Number"] = stringify(display_counter); entry["Nick"] = hr->GetNick()->GetNick(); if (!hr->GetIdent().empty()) entry["Vhost"] = hr->GetIdent() + "@" + hr->GetHost(); else entry["Vhost"] = hr->GetHost(); entry["Created"] = Anope::strftime(hr->GetTime(), NULL, true); list.AddEntry(entry); } ++counter; } std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); source.Reply(_("Displayed \002{0}\002 records (\002{1}\002 total)."), display_counter, counter); }
void OnNickInfo(CommandSource &source, NickServ::Nick *na, InfoFormatter &info, bool show_hidden) override { NSSuspendInfo *s = na->GetAccount()->GetRef<NSSuspendInfo *>(); if (!s) return; if (show_hidden || Show(source, "suspended")) info[_("Suspended")] = _("This nickname is \002suspended\002."); if (!s->GetBy().empty() && (show_hidden || Show(source, "by"))) info[_("Suspended by")] = s->GetBy(); if (!s->GetReason().empty() && (show_hidden || Show(source, "reason"))) info[_("Suspend reason")] = s->GetReason(); if (s->GetWhen() && (show_hidden || Show(source, "on"))) info[_("Suspended on")] = Anope::strftime(s->GetWhen(), source.GetAccount()); if (s->GetExpires() && (show_hidden || Show(source, "expires"))) info[_("Suspension expires")] = Anope::strftime(s->GetExpires(), source.GetAccount()); }
void DoStatsUptime(CommandSource &source) { Stats *stats = Serialize::GetObject<Stats *>(); time_t uptime = Anope::CurTime - Anope::StartTime; source.Reply(_("Current users: \002{0}\002 (\002{1}\002 ops)"), UserListByNick.size(), OperCount); source.Reply(_("Maximum users: \002{0}\002 ({1})"), stats->GetMaxUserCount(), Anope::strftime(stats->GetMaxUserTime(), source.GetAccount())); source.Reply(_("Services up \002{0}\002."), Anope::Duration(uptime, source.GetAccount())); }
void DoAdd(CommandSource &source, NickServ::Account *nc, Anope::string certfp) { std::vector<NSCertEntry *> cl = nc->GetRefs<NSCertEntry *>(certentry); unsigned max = Config->GetModule(this->owner)->Get<unsigned>("max", "5"); if (cl.size() >= max) { source.Reply(_("Sorry, the maximum of \002{0}\002 certificate entries has been reached."), max); return; } if (source.GetAccount() == nc) { User *u = source.GetUser(); if (!u || u->fingerprint.empty()) { source.Reply(_("You are not using a client certificate.")); return; } certfp = u->fingerprint; } if (FindCert(cl, certfp)) { source.Reply(_("Fingerprint \002{0}\002 already present on the certificate list of \002{0}\002."), certfp, nc->GetDisplay()); return; } if (certmap.find(certfp) != certmap.end()) { source.Reply(_("Fingerprint \002{0}\002 is already in use."), certfp); return; } NSCertEntry *e = certentry.Create(); e->SetAccount(nc); e->SetCert(certfp); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD certificate fingerprint " << certfp << " to " << nc->GetDisplay(); source.Reply(_("\002{0}\002 added to the certificate list of \002{1}\002."), certfp, nc->GetDisplay()); }
void DoList(CommandSource &source) { std::vector<Ignore *> ignores = Serialize::GetObjects<Ignore *>(); for (Ignore *id : ignores) { if (id->GetTime() && !Anope::NoExpire && id->GetTime() <= Anope::CurTime) { Log(LOG_NORMAL, "expire/ignore", Config->GetClient("OperServ")) << "Expiring ignore entry " << id->GetMask(); id->Delete(); } } ignores = Serialize::GetObjects<Ignore *>(); if (ignores.empty()) { source.Reply(_("Ignore list is empty.")); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Reason")).AddColumn(_("Expires")); for (Ignore *ignore : ignores) { ListFormatter::ListEntry entry; entry["Mask"] = ignore->GetMask(); entry["Creator"] = ignore->GetCreator(); entry["Reason"] = ignore->GetReason(); entry["Expires"] = Anope::Expires(ignore->GetTime(), source.GetAccount()); list.AddEntry(entry); } source.Reply(_("Services ignore list:")); std::vector<Anope::string> replies; list.Process(replies); for (const Anope::string &r : replies) source.Reply(r); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &nick = params[0]; const Anope::string &pass = params.size() > 1 ? params[1] : ""; User *user = User::Find(nick, true); if (user && source.GetUser() == user) { source.Reply(_("You can't %s yourself!"), source.command.lower().c_str()); return; } NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } if (na->GetAccount()->HasFieldS("NS_SUSPENDED")) { source.Reply(_("\002{0}\002 is suspended."), na->GetNick()); return; } bool ok = false; if (source.GetAccount() == na->GetAccount()) ok = true; else if (!na->GetAccount()->HasFieldS("NS_SECURE") && source.GetUser() && na->GetAccount()->IsOnAccess(source.GetUser())) ok = true; if (certservice && source.GetUser() && certservice->Matches(source.GetUser(), na->GetAccount())) ok = true; if (ok == false && !pass.empty()) { NickServ::IdentifyRequest *req = NickServ::service->CreateIdentifyRequest(new NSRecoverRequestListener(source, this, na->GetNick(), pass), owner, na->GetNick(), pass); Event::OnCheckAuthentication(&Event::CheckAuthentication::OnCheckAuthentication, source.GetUser(), req); req->Dispatch(); } else { NSRecoverRequestListener req(source, this, na->GetNick(), pass); if (ok) req.OnSuccess(nullptr); else req.OnFail(nullptr); } }
void Command::SendSyntax(CommandSource &source) { Anope::string s = Language::Translate(source.GetAccount(), _("Syntax")); if (!this->syntax.empty()) { source.Reply("%s: \002%s %s\002", s.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[0].c_str())); Anope::string spaces(s.length(), ' '); for (unsigned i = 1, j = this->syntax.size(); i < j; ++i) source.Reply("%s \002%s %s\002", spaces.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[i].c_str())); } else source.Reply("%s: \002%s\002", s.c_str(), source.command.c_str()); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { #warning "this is completely disabled" #if 0 if (!MemoServ::service) return; if (Anope::ReadOnly && !source.IsOper()) { source.Reply(_("Sorry, memo sending is temporarily disabled.")); return; } const Anope::string &nick = params[0]; const Anope::string &text = params[1]; const NickServ::Nick *na = NULL; /* prevent user from rsend to themselves */ if ((na = NickServ::FindNick(nick)) && na->GetAccount() == source.GetAccount()) { source.Reply(_("You can not request a receipt when sending a memo to yourself.")); return; } if (Config->GetModule(this->GetOwner())->Get<bool>("operonly") && !source.IsServicesOper()) source.Reply(_("Access denied. This command is for operators only.")); else { MemoServ::MemoServService::MemoResult result = MemoServ::service->Send(source.GetNick(), nick, text); if (result == MemoServ::MemoServService::MEMO_INVALID_TARGET) source.Reply(_("\002{0}\002 isn't registered."), nick); else if (result == MemoServ::MemoServService::MEMO_TOO_FAST) source.Reply(_("Please wait \002{0}\002 seconds before using the \002{1}\002 command again."), Config->GetModule("memoserv/main")->Get<time_t>("senddelay"), source.command); else if (result == MemoServ::MemoServService::MEMO_TARGET_FULL) source.Reply(_("Sorry, \002{0}\002 currently has too many memos and cannot receive more."), nick); else { source.Reply(_("Memo sent to \002{0}\002."), nick); bool ischan, isregistered; MemoServ::MemoInfo *mi = MemoServ::service->GetMemoInfo(nick, ischan, isregistered, false); if (mi == NULL) throw CoreException("NULL mi in ms_rsend"); MemoServ::Memo *m = (mi->memos->size() ? mi->GetMemo(mi->memos->size() - 1) : NULL); if (m != NULL) m->receipt = true; } } #endif }
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] : ""; } NickServ::Account *nc; if (!nick.empty() && source.HasPriv("nickserv/access")) { NickServ::Nick *na = NickServ::FindNick(nick); if (na == NULL) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->GetAccount() && na->GetAccount()->IsServicesOper() && !cmd.equals_ci("LIST")) { source.Reply(_("You may view but not modify the access list of other Services Operators.")); return; } nc = na->GetAccount(); } else nc = source.nc; if (!mask.empty() && (mask.find('@') == Anope::string::npos || mask.find('!') != Anope::string::npos)) { source.Reply(_("Mask must be in the form \037user\037@\037host\037.")); source.Reply(_("\002%s%s HELP %s\002 for more information."), Config->StrictPrivmsg, source.service->nick, source.command); // XXX } else if (cmd.equals_ci("LIST")) return this->DoList(source, nc, mask); else if (nc->HasFieldS("NS_SUSPENDED")) source.Reply(_("\002{0}\002 is suspended."), nc->GetDisplay()); 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, ""); }
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) override { if (source.IsOper()) return EVENT_CONTINUE; if (command->GetName() == "nickserv/register") { if (this->CheckLimitReached(source, params.size() > 1 ? params[1] : "")) return EVENT_STOP; } else if (command->GetName() == "nickserv/set/email") { if (this->CheckLimitReached(source, params.size() > 0 ? params[0] : "")) return EVENT_STOP; } else if (command->GetName() == "nickserv/ungroup" && source.GetAccount()) { if (this->CheckLimitReached(source, source.GetAccount()->GetEmail())) return EVENT_STOP; } return EVENT_CONTINUE; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { User *u = source.GetUser(); NickServ::Nick *na = NickServ::FindNick(u->nick); if (!na || !na->HasVhost() || na->GetAccount() != source.GetAccount()) { source.Reply(_("There is no vhost assigned to this nickname.")); return; } u->vhost.clear(); IRCD->SendVhostDel(u); Log(LOG_COMMAND, source, this) << "to disable their vhost"; source.Reply(_("Your vhost was removed and the normal cloaking restored.")); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &cmd = params[0]; Anope::string nick, certfp; if (cmd.equals_ci("LIST")) nick = params.size() > 1 ? params[1] : ""; else { nick = params.size() == 3 ? params[1] : ""; certfp = params.size() > 1 ? params[params.size() - 1] : ""; } NickServ::Account *nc; if (!nick.empty() && source.HasPriv("nickserv/access")) { NickServ::Nick *na = NickServ::FindNick(nick); if (na == NULL) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->GetAccount() && na->GetAccount()->IsServicesOper() && !cmd.equals_ci("LIST")) { source.Reply(_("You may view, but not modify, the certificate list of other Services Operators.")); return; } nc = na->GetAccount(); } else nc = source.nc; if (cmd.equals_ci("LIST")) return this->DoList(source, nc); else if (nc->HasFieldS("NS_SUSPENDED")) source.Reply(_("\002{0}\002 is suspended."), nc->GetDisplay()); else if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode.")); else if (cmd.equals_ci("ADD")) return this->DoAdd(source, nc, certfp); else if (cmd.equals_ci("DEL")) return this->DoDel(source, nc, certfp); else this->OnSyntaxError(source, ""); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } const Anope::string &nick = params[0]; const Anope::string &reason = params.size() > 1 ? params[1] : ""; NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } HostRequest *req = na->GetExt<HostRequest>("hostrequest"); if (!req) { source.Reply(_("\002{0}\002 does not have a pending vhost request."), na->GetNick()); return; } req->Delete(); if (Config->GetModule(this->GetOwner())->Get<bool>("memouser") && memoserv) { Anope::string message; if (!reason.empty()) message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); else message = _("[auto memo] Your requested vHost has been rejected."); memoserv->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true); } source.Reply(_("Vhost for \002{0}\002 has been rejected."), na->GetNick()); Log(LOG_COMMAND, source, this) << "to reject vhost for " << nick << " (" << (!reason.empty() ? reason : "no reason") << ")"; }
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<bool>("hideprivilegedcommands"), hide_registered_commands = Config->GetBlock("options")->Get<bool>("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) { ServiceReference<Command> 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); } } 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); return true; }
void DoAdd(CommandSource &source, NickServ::Account *nc, const Anope::string &mask) { if (mask.empty()) { this->OnSyntaxError(source, "ADD"); return; } if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } std::vector<NickAccess *> access = nc->GetRefs<NickAccess *>(nsaccess); if (access.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax", "32")) { source.Reply(_("Sorry, the maximum of \002{0}\002 access entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); return; } for (NickAccess *a : access) if (a->GetMask().equals_ci(mask)) { source.Reply(_("Mask \002{0}\002 already present on the access list of \002{1}\002."), mask, nc->GetDisplay()); return; } NickAccess *a = nsaccess.Create(); a->SetAccount(nc); a->SetMask(mask); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD mask " << mask << " to " << nc->GetDisplay(); source.Reply(_("\002{0}\002 added to the access list of \002{1}\002."), mask, nc->GetDisplay()); }
void DoDel(CommandSource &source, NickServ::Account *nc, const Anope::string &chans) { std::vector<AutoJoin *> channels = nc->GetRefs<AutoJoin *>(); Anope::string delchans; Anope::string notfoundchans; commasepstream sep(chans); for (Anope::string chan; sep.GetToken(chan);) { unsigned i = 0; for (; i < channels.size(); ++i) if (channels[i]->GetChannel().equals_ci(chan)) break; if (i == channels.size()) notfoundchans += chan + ", "; else { delete channels[i]; delchans += chan + ", "; } } if (!notfoundchans.empty()) { notfoundchans = notfoundchans.substr(0, notfoundchans.length() - 2); source.Reply(_("\002{0}\002 was not found on the auto join list of \002{1}\002."), notfoundchans, nc->GetDisplay()); } if (delchans.empty()) return; delchans = delchans.substr(0, delchans.length() - 2); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE channel " << delchans << " from " << nc->GetDisplay(); source.Reply(_("\002{0}\002 was removed from the auto join list of \002{1}\002."), delchans, nc->GetDisplay()); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } 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")) { source.Reply(_("You must confirm your account before you may request a vhost.")); return; } Anope::string rawhostmask = params[0]; 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 (user.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen")) { source.Reply(_("The username \002{0}\002 is too long, please use a username shorter than %d characters."), Config->GetBlock("networkinfo")->Get<unsigned>("userlen")); return; } 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<unsigned>("hostlen")) { source.Reply(_("The requested vhost is too long, please use a hostname no longer than {0} characters."), Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")); return; } if (!IRCD->IsHostValid(host)) { source.Reply(_("The requested hostname is not valid.")); return; } time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay"); if (Config->GetModule(this->GetOwner())->Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime) { source.Reply(_("Please wait %d seconds before requesting a new vHost."), send_delay); u->lastmemosend = Anope::CurTime; return; } HostRequest *req = Serialize::New<HostRequest *>(); req->SetNick(na); req->SetIdent(user); req->SetHost(host); req->SetTime(Anope::CurTime); source.Reply(_("Your vhost has been requested.")); this->SendMemos(source, user, host); Log(LOG_COMMAND, source, this) << "to request new vhost " << (!user.empty() ? user + "@" : "") << host; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &channel = params[0]; ChanServ::Channel *ci = ChanServ::Find(channel); if (ci == NULL) { source.Reply(_("Channel \002{0}\002 isn't registered."), channel); return; } if (!source.AccessFor(ci).HasPriv("SET") && !source.HasOverridePriv("chanserv/administration")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "SET", ci->GetName()); return; } if (params.size() == 1) { std::vector<LogSetting *> ls = ci->GetRefs<LogSetting *>(); if (ls.empty()) { source.Reply(_("There currently are no logging configurations for \002{0}\002."), ci->GetName()); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method")).AddColumn(""); for (unsigned i = 0; i < ls.size(); ++i) { LogSetting *log = ls[i]; ListFormatter::ListEntry entry; entry["Number"] = stringify(i + 1); entry["Service"] = log->GetCommandService(); entry["Command"] = !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(); entry["Method"] = log->GetMethod(); entry[""] = log->GetExtra(); list.AddEntry(entry); } source.Reply(_("Log list for \002{0}\002:"), ci->GetName()); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); } else if (params.size() > 2) { if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } const Anope::string &command = params[1]; const Anope::string &method = params[2]; const Anope::string &extra = params.size() > 3 ? params[3] : ""; size_t sl = command.find('/'); if (sl == Anope::string::npos) { source.Reply(_("\002{0}\002 is not a valid command."), command); return; } Anope::string service = command.substr(0, sl), command_name = command.substr(sl + 1); ServiceBot *bi = ServiceBot::Find(service, true); Anope::string service_name; /* Allow either a command name or a service name. */ if (bi && bi->commands.count(command_name)) { /* Get service name from command */ service_name = bi->commands[command_name].name; } else if (ServiceReference<Command>(command.lower())) { /* This is the service name, don't use any specific command */ service_name = command; bi = NULL; command_name.clear(); } else { source.Reply(_("\002{0}\002 is not a valid command."), command); return; } if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO")) { source.Reply(_("\002%s\002 is not a valid logging method.")); return; } for (unsigned i = 0; i < extra.length(); ++i) if (ModeManager::GetStatusChar(extra[i]) == 0) { source.Reply(_("\002%c\002 is an unknown status mode."), extra[i]); return; } std::vector<LogSetting *> ls = ci->GetRefs<LogSetting *>(); for (unsigned i = ls.size(); i > 0; --i) { LogSetting *log = ls[i - 1]; if (log->GetServiceName() == service_name && log->GetMethod().equals_ci(method) && command_name.equals_ci(log->GetCommandName())) { if (log->GetExtra() == extra) { logger.Command(source, ci, _("{source} used {command} on {channel} to remove logging for {0} with method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging for command \002{0}\002 on \002{1}\002 with log method \002{2}{3}{4}\002 has been removed."), !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(), !log->GetCommandService().empty() ? log->GetCommandService() : "any service", method, extra.empty() ? "" : " ", extra); log->Delete(); } else { log->SetExtra(extra); logger.Command(source, ci, _("{source} used {command} on {channel} to change logging for {0} to method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging changed for command \002{0}\002 on \002{1}\002, now using log method \002{2}{3}{4]\002."), !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(), !log->GetCommandService().empty() ? log->GetCommandService() : "any service", method, extra.empty() ? "" : " ", extra); } return; } } LogSetting *log = Serialize::New<LogSetting *>(); log->SetChannel(ci); log->SetServiceName(service_name); if (bi) log->SetCommandService(bi->nick); log->SetCommandName(command_name); log->SetMethod(method); log->SetExtra(extra); log->SetCreated(Anope::CurTime); log->SetCreator(source.GetNick()); logger.Command(source, ci, _("{source} used {command} on {channel} to log {0} to method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging is now active for command \002{0}\002 on \002{1}\002, using log method \002{2}{3}{4}\002."), !command_name.empty() ? command_name : service_name, bi ? bi->nick : "any service", method, extra.empty() ? "" : " ", extra); } else { this->OnSyntaxError(source, ""); } }
static void DoRead(CommandSource &source, MemoServ::MemoInfo *mi, ChanServ::Channel *ci, unsigned index) { MemoServ::Memo *m = mi->GetMemo(index); if (!m) return; if (ci) source.Reply(_("Memo \002{0}\002 from \002{1}\002 (\002{2}\002)."), index + 1, m->GetSender(), Anope::strftime(m->GetTime(), source.GetAccount())); else source.Reply(_("Memo \002{0}\002 from \002{1}\002 (\002{2}\002)."), index + 1, m->GetSender(), Anope::strftime(m->GetTime(), source.GetAccount())); ServiceBot *bi; Anope::string cmd; if (Command::FindCommandFromService("memoserv/del", bi, cmd)) { if (ci) source.Reply(_("To delete, use \002{0}{1} {2} {3} {4}\002"), Config->StrictPrivmsg, bi->nick, cmd, ci->GetName(), index + 1); else source.Reply(_("To delete, use \002{0}{1} {2} {3}\002"), Config->StrictPrivmsg, bi->nick, cmd, index + 1); } source.Reply(m->GetText()); m->SetUnread(false); /* Check if a receipt notification was requested */ if (m->GetReceipt()) rsend_notify(source, mi, m, ci ? ci->GetName() : source.GetNick()); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { Anope::string param = !params.empty() ? params[0] : "", chan; ChanServ::Channel *ci = NULL; MemoServ::MemoInfo *mi; if (!param.empty() && param[0] == '#') { chan = param; param = params.size() > 1 ? params[1] : ""; ci = ChanServ::Find(chan); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), chan); return; } if (!source.AccessFor(ci).HasPriv("MEMO")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); return; } mi = ci->GetMemos(); } else { mi = source.nc->GetMemos(); } if (!param.empty() && !isdigit(param[0]) && !param.equals_ci("NEW")) { this->OnSyntaxError(source); return; } if (!mi) return; auto memos = mi->GetMemos(); if (!memos.size()) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no memos."), chan); else source.Reply(_("You have no memos.")); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Sender")).AddColumn(_("Date/Time")); if (!param.empty() && isdigit(param[0])) { NumberList(param, false, [&](unsigned int number) { if (!number || number > memos.size()) return; MemoServ::Memo *m = mi->GetMemo(number - 1); ListFormatter::ListEntry entry; entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(number); entry["Sender"] = m->GetSender(); entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); list.AddEntry(entry); }, []{}); } else { if (!param.empty()) { unsigned i, end; for (i = 0, end = memos.size(); i < end; ++i) if (mi->GetMemo(i)->GetUnread()) break; if (i == end) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no new memos."), chan); else source.Reply(_("You have no new memos.")); return; } } for (unsigned i = 0, end = memos.size(); i < end; ++i) { if (!param.empty() && !mi->GetMemo(i)->GetUnread()) continue; MemoServ::Memo *m = mi->GetMemo(i); ListFormatter::ListEntry entry; entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(i + 1); entry["Sender"] = m->GetSender(); entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); list.AddEntry(entry); } } std::vector<Anope::string> replies; list.Process(replies); source.Reply(_("Memos for \002{0}\002:"), ci ? ci->GetName().c_str() : source.GetNick().c_str()); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); }
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &time = params.size() > 1 ? params[1] : ""; const Anope::string &nick = params.size() > 2 ? params[2] : ""; const Anope::string &reason = params.size() > 3 ? params[3] : ""; if (time.empty() || nick.empty()) { this->OnSyntaxError(source, "ADD"); return; } time_t t = Anope::DoTime(time); if (t <= -1) { source.Reply(_("Invalid expiry time \002{0}\002."), time); return; } Anope::string mask = RealMask(nick); if (mask.empty()) { source.Reply(_("Mask must be in the form \037user\037@\037host\037.")); return; } if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); Ignore *ign = Serialize::New<Ignore *>(); ign->SetMask(mask); ign->SetCreator(source.GetNick()); ign->SetReason(reason); ign->SetTime(t ? Anope::CurTime + t : 0); if (!t) { source.Reply(_("\002{0}\002 will now permanently be ignored."), mask); Log(LOG_ADMIN, source, this) << "to add a permanent ignore for " << mask; } else { source.Reply(_("\002{0}\002 will now be ignored for \002{1}\002."), mask, Anope::Duration(t, source.GetAccount())); Log(LOG_ADMIN, source, this) << "to add an ignore on " << mask << " for " << Anope::Duration(t); } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (!this->fs) return; const Anope::string &command = params[0]; const Anope::string &subcommand = params.size() > 1 ? params[1] : ""; ForbidType ftype = FT_SIZE; if (subcommand.equals_ci("NICK")) ftype = FT_NICK; else if (subcommand.equals_ci("CHAN")) ftype = FT_CHAN; else if (subcommand.equals_ci("EMAIL")) ftype = FT_EMAIL; else if (subcommand.equals_ci("REGISTER")) ftype = FT_REGISTER; if (command.equals_ci("ADD") && params.size() > 3 && ftype != FT_SIZE) { const Anope::string &expiry = params[2][0] == '+' ? params[2] : ""; const Anope::string &entry = !expiry.empty() ? params[3] : params[2]; Anope::string reason; if (expiry.empty()) reason = params[3] + " "; if (params.size() > 4) reason += params[4]; reason.trim(); if (entry.replace_all_cs("?*", "").empty()) { source.Reply(_("The mask must contain at least one non wildcard character.")); return; } time_t expiryt = 0; if (!expiry.empty()) { expiryt = Anope::DoTime(expiry); if (expiryt == -1) { source.Reply(_("Invalid expiry time \002{0}\002."), expiry); return; } else if (expiryt) expiryt += Anope::CurTime; } NickServ::Nick *target = NickServ::FindNick(entry); if (target != NULL && Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && target->GetAccount()->IsServicesOper()) { source.Reply(_("Access denied.")); return; } ForbidData *d = this->fs->FindForbid(entry, ftype); bool created = false; if (d == NULL) { d = Serialize::New<ForbidData *>(); created = true; } d->SetMask(entry); d->SetCreator(source.GetNick()); d->SetReason(reason); d->SetCreated(Anope::CurTime); d->SetExpires(expiryt); d->SetType(ftype); if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); Log(LOG_ADMIN, source, this) << "to add a forbid on " << entry << " of type " << subcommand; source.Reply(_("Added a forbid on \002{0}\002 of type \002{1}\002 to expire on \002{2}\002."), entry, subcommand.lower(), expiryt ? Anope::strftime(expiryt, source.GetAccount()) : "never"); /* apply forbid */ switch (ftype) { case FT_NICK: { int na_matches = 0; for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) this->OnUserNickChange(it->second); for (auto it = NickServ::service->GetNickList().begin(); it != NickServ::service->GetNickList().end();) { NickServ::Nick *na = *it; ++it; d = this->fs->FindForbid(na->GetNick(), FT_NICK); if (d == NULL) continue; ++na_matches; delete na; } source.Reply(_("\002{0}\002 nickname(s) dropped."), na_matches); break; } case FT_CHAN: { int chan_matches = 0, ci_matches = 0; for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end;) { Channel *c = it->second; ++it; d = this->fs->FindForbid(c->name, FT_CHAN); if (d == NULL) continue; ServiceBot *OperServ = Config->GetClient("OperServ"); if (IRCD->CanSQLineChannel && OperServ) { time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s"); #warning "xline allocated on stack" #if 0 XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->GetReason()); IRCD->SendSQLine(NULL, &x); #endif } else if (ChanServ::service) { ChanServ::service->Hold(c); } ++chan_matches; for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end;) { User *u = cit->first; ++cit; if (u->server == Me || u->HasMode("OPER")) continue; reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: \002%s\002")), d->GetReason().c_str()); c->Kick(source.service, u, "%s", reason.c_str()); } } for (auto it = ChanServ::service->GetChannels().begin(); it != ChanServ::service->GetChannels().end();) { ChanServ::Channel *ci = it->second; ++it; d = this->fs->FindForbid(ci->GetName(), FT_CHAN); if (d == NULL) continue; ++ci_matches; delete ci; } source.Reply(_("\002{0}\002 channel(s) cleared, and \002{1}\002 channel(s) dropped."), chan_matches, ci_matches); break; } default: break; } } else if (command.equals_ci("DEL") && params.size() > 2 && ftype != FT_SIZE) { const Anope::string &entry = params[2]; ForbidData *d = this->fs->FindForbid(entry, ftype); if (d == nullptr) { source.Reply(_("Forbid on \002{0}\002 was not found."), entry); return; } if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); Log(LOG_ADMIN, source, this) << "to remove forbid on " << d->GetMask() << " of type " << subcommand; source.Reply(_("\002{0}\002 deleted from the \002{1}\002 forbid list."), d->GetMask(), subcommand); d->Delete(); } else if (command.equals_ci("LIST")) { const std::vector<ForbidData *> &forbids = this->fs->GetForbids(); if (forbids.empty()) { source.Reply(_("Forbid list is empty.")); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Mask")).AddColumn(_("Type")).AddColumn(_("Creator")).AddColumn(_("Expires")).AddColumn(_("Reason")); unsigned shown = 0; for (unsigned i = 0; i < forbids.size(); ++i) { ForbidData *d = forbids[i]; if (ftype != FT_SIZE && ftype != d->GetType()) continue; Anope::string stype; if (d->GetType() == FT_NICK) stype = "NICK"; else if (d->GetType() == FT_CHAN) stype = "CHAN"; else if (d->GetType() == FT_EMAIL) stype = "EMAIL"; else if (d->GetType() == FT_REGISTER) stype = "REGISTER"; else continue; ListFormatter::ListEntry entry; entry["Mask"] = d->GetMask(); entry["Type"] = stype; entry["Creator"] = d->GetCreator(); entry["Expires"] = d->GetExpires() ? Anope::strftime(d->GetExpires(), NULL, true).c_str() : Language::Translate(source.GetAccount(), _("Never")); entry["Reason"] = d->GetReason(); list.AddEntry(entry); ++shown; } if (!shown) { source.Reply(_("There are no forbids of type \002{0}\002."), subcommand.upper()); return; } source.Reply(_("Forbid list:")); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); if (shown >= forbids.size()) source.Reply(_("End of forbid list.")); else source.Reply(_("End of forbid list - \002{0}\002/\002{1}\002 entries shown."), shown, forbids.size()); } else this->OnSyntaxError(source, command); }