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 { 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) { 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; } na->SetVhost(req->GetIdent(), req->GetHost(), source.GetNick(), req->GetTime()); EventManager::Get()->Dispatch(&Event::SetVhost::OnSetVhost, na); if (Config->GetModule(this->GetOwner())->Get<bool>("memouser") && memoserv) memoserv->Send(source.service->nick, na->GetNick(), _("[auto memo] Your requested vHost has been approved."), true); source.Reply(_("Vhost for \002{0}\002 has been activated."), na->GetNick()); Log(LOG_COMMAND, source, this) << "for " << na->GetNick() << " for vhost " << (!req->GetIdent().empty() ? req->GetIdent() + "@" : "") << req->GetHost(); req->Delete(); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { Log(LOG_ADMIN, source, this); Anope::QuitReason = source.command + " command received from " + source.GetNick(); Anope::Quitting = true; return; }
static void rsend_notify(CommandSource &source, MemoServ::MemoInfo *mi, MemoServ::Memo *m, const Anope::string &targ) { /* Only send receipt if memos are allowed */ if (MemoServ::service && !Anope::ReadOnly) { /* Get nick alias for sender */ NickServ::Nick *na = NickServ::FindNick(m->GetSender()); if (!na) return; /* Get nick core for sender */ NickServ::Account *nc = na->GetAccount(); if (!nc) return; /* Text of the memo varies if the recipient was a nick or channel */ Anope::string text = Anope::printf(Language::Translate(na->GetAccount(), _("\002[auto-memo]\002 The memo you sent to \002%s\002 has been viewed.")), targ.c_str()); /* Send notification */ MemoServ::service->Send(source.GetNick(), m->GetSender(), text, true); /* Notify recipient of the memo that a notification has been sent to the sender */ source.Reply(_("A notification memo has been sent to \002{0}\002 informing him/her you have read his/her memo."), nc->GetDisplay()); } /* Remove receipt flag from the original memo */ m->SetReceipt(false); }
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 { const Anope::string &nick = !params.empty() ? params[0] : source.GetNick(); const NickServ::Nick *na = NickServ::FindNick(nick); spacesepstream sep(nick); Anope::string nickbuf; while (sep.GetToken(nickbuf)) { #if 0 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->GetAccount() == u2->Account()) /* Nick is identified */ source.Reply("STATUS %s %d %s", nickbuf.c_str(), 3, u2->Account()->GetDisplay().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()->GetDisplay().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()->GetDisplay().c_str() : ""); #endif } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &chan = params[0]; const Anope::string &nick = params[1]; const Anope::string &s = params[2]; Channel *c; User *u2; if (!(c = Channel::Find(chan))) { source.Reply(_("Channel \002%s\002 doesn't exist."), chan); return; } if (c->bouncy_modes) { source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); return; } if (!(u2 = User::Find(nick, true))) { source.Reply(_("\002{0}\002 isn't currently online."), nick); return; } if (!c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str())) { source.Reply(_("Access denied.")); return; } Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")"; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &cmd = params[0]; const Anope::string &server = params[1]; Server *s = Server::Find(server, true); if (s == NULL) source.Reply(_("Server \002{0}\002 does not exist."), server); else if (s == Me || s->IsJuped() || s->IsULined()) source.Reply(_("You can not NOOP Services.")); else if (cmd.equals_ci("SET")) { /* Remove the O:lines */ IRCD->SendSVSNOOP(s, true); s->Extend<Anope::string>("noop", source.GetNick()); Log(LOG_ADMIN, source, this) << "SET on " << s->GetName(); source.Reply(_("All operators from \002{0}\002 have been removed."), s->GetName()); Anope::string reason = "NOOP command used by " + source.GetNick(); /* Kill all the IRCops of the server */ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) { User *u2 = it->second; if (u2->server == s && u2->HasMode("OPER")) u2->Kill(*source.service, reason); } } else if (cmd.equals_ci("REVOKE")) { s->Shrink<Anope::string>("noop"); IRCD->SendSVSNOOP(s, false); Log(LOG_ADMIN, source, this) << "REVOKE on " << s->GetName(); source.Reply(_("All O:lines of \002{0}\002 have been reset."), s->GetName()); } else this->OnSyntaxError(source, ""); }
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 &nick = !params.empty() ? params[0] : ""; const Anope::string ¶m = params.size() > 1 ? params[1] : ""; if (!source.IsServicesOper() && !nick.empty()) { this->OnSyntaxError(source); return; } User *u2 = !nick.empty() ? User::Find(nick, true) : source.GetUser(); if (!u2) { source.Reply(_("\002{0}\002 isn't currently online."), !nick.empty() ? nick : source.GetNick()); return; } if (!nick.empty() && u2->IsServicesOper()) { source.Reply(_("You can't logout \002{0}\002, they are a Services Operator."), nick); return; } #warning "revalidate" #if 0 if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE") && NickServ::service) NickServ::service->Validate(u2); #endif u2->super_admin = false; /* Dont let people logout and remain a SuperAdmin */ // XXX show account name here? logger.Command(LogType::COMMAND, source, _("{source} used {command} to logout {0}"), u2->nick); if (!nick.empty()) source.Reply(_("\002{0}\002 has been logged out."), nick); else source.Reply(_("You have been logged out.")); IRCD->Send<messages::Logout>(u2); u2->RemoveMode(source.service, "REGISTERED"); u2->Logout(); /* Send out an event */ EventManager::Get()->Dispatch(&Event::NickLogout::OnNickLogout, u2); }
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); } }
Anope::string Process(CommandSource &source, const std::vector<Anope::string> ¶ms) { spacesepstream sep(this->target_message); Anope::string token, message; while (sep.GetToken(token)) { if (token[0] != '$') message += " " + token; else if (token == "$me") message += " " + source.GetNick(); else { int num = -1, end = -1; try { Anope::string num_str = token.substr(1); size_t hy = num_str.find('-'); if (hy == Anope::string::npos) { num = convertTo<int>(num_str); end = num + 1; } else { num = convertTo<int>(num_str.substr(0, hy)); if (hy == num_str.length() - 1) end = params.size(); else end = convertTo<int>(num_str.substr(hy + 1)) + 1; } } catch (const ConvertException &) { continue; } for (int i = num; i < end && static_cast<unsigned>(i) < params.size(); ++i) message += " " + params[i]; } } message.trim(); return message; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &nick = params[0]; Anope::string reason = params.size() > 1 ? params[1] : ""; User *u2 = User::Find(nick, true); if (u2 == NULL) source.Reply(_("\002{0}\002 isn't currently online."), nick); else if (u2->IsProtected() || u2->server == Me) source.Reply(_("\002{0}\002 is protected and cannot be killed."), u2->nick); else { if (reason.empty()) reason = "No reason specified"; if (Config->GetModule("operserv")->Get<bool>("addakiller")) reason = "(" + source.GetNick() + ") " + reason; Log(LOG_ADMIN, source, this) << "on " << u2->nick << " for " << reason; u2->Kill(*source.service, reason); } }
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType ntype, const char **msgs) { const Anope::string text = params.size() > 1 ? params[1] : ""; if (text.empty()) { this->OnSyntaxError(source, "ADD"); return; } if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); NewsItem *ni = Serialize::New<NewsItem *>(); ni->SetNewsType(ntype); ni->SetText(text); ni->SetTime(Anope::CurTime); ni->SetWho(source.GetNick()); source.Reply(msgs[MSG_ADDED]); Log(LOG_ADMIN, source, this) << "to add a news item"; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &jserver = params[0]; const Anope::string &reason = params.size() > 1 ? params[1] : ""; Server *server = Server::Find(jserver, true); if (!IRCD->IsHostValid(jserver) || jserver.find('.') == Anope::string::npos) { source.Reply(_("\002{0}\002 is not a valid server name."), jserver); return; } if (server == Me || server == Servers::GetUplink() || server->IsULined()) { source.Reply(_("You can not jupe Servoces or its uplink server.")); return; } if (server && server->IsJuped()) { source.Reply(_("You can not jupe an already juped server.")); return; } Anope::string rbuf = "Juped by " + source.GetNick() + (!reason.empty() ? ": " + reason : ""); /* Generate the new sid before quitting the old server, so they can't collide */ Anope::string sid = IRCD->SID_Retrieve(); if (server) { IRCD->Send<messages::SQuit>(server, rbuf); server->Delete(rbuf); } Server *juped_server = new Server(Me, jserver, 1, rbuf, sid, true); IRCD->Send<messages::MessageServer>(juped_server); Log(LOG_ADMIN, source, this) << "on " << jserver << " (" << rbuf << ")"; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &cmd = params[0], target = params[1], info = params.size() > 2 ? params[2] : ""; Serialize::Object *e; if (IRCD->IsChannelValid(target)) { ChanServ::Channel *ci = ChanServ::Find(target); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), target); return; } e = ci; } else { NickServ::Nick *na = NickServ::FindNick(target); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), target); return; } e = na->GetAccount(); } if (cmd.equals_ci("ADD")) { if (info.empty()) { this->OnSyntaxError(source, cmd); return; } std::vector<OperInfo *> oinfos = e->GetRefs<OperInfo *>(operinfo); if (oinfos.size() >= Config->GetModule(this->module)->Get<unsigned int>("max", "10")) { source.Reply(_("The oper info list for \002{0}\002 is full."), target); return; } for (OperInfo *o : oinfos) if (o->GetInfo().equals_ci(info)) { source.Reply(_("The oper info already exists on \002{0}\002."), target); return; } OperInfo *o = operinfo.Create(); o->SetTarget(e); o->SetInfo(info); o->SetCreator(source.GetNick()); o->SetCreated(Anope::CurTime); source.Reply(_("Added info to \002{0}\002."), target); Log(LOG_ADMIN, source, this) << "to add information to " << target; if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); } else if (cmd.equals_ci("DEL")) { if (info.empty()) { this->OnSyntaxError(source, cmd); return; } std::vector<OperInfo *> oinfos = e->GetRefs<OperInfo *>(operinfo); if (oinfos.empty()) { source.Reply(_("Oper info list for \002{0}\002 is empty."), target); return; } for (OperInfo *o : oinfos) { if (o->GetInfo().equals_ci(info)) { o->Delete(); source.Reply(_("Deleted info from \002{0}\002."), target); Log(LOG_ADMIN, source, this) << "to remove information from " << target; if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); return; } } source.Reply(_("No such info \002{0}\002 on \002{1}\002."), info, target); } else if (cmd.equals_ci("CLEAR")) { std::vector<OperInfo *> oinfos = e->GetRefs<OperInfo *>(operinfo); if (oinfos.empty()) { source.Reply(_("Oper info list for \002{0}\002 is empty."), target); return; } for (OperInfo *o : oinfos) o->Delete(); source.Reply(_("Cleared info from \002{0}\002."), target); Log(LOG_ADMIN, source, this) << "to clear information for " << target; if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); } else { this->OnSyntaxError(source, cmd); } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &chan = params[0]; User *u = source.GetUser(); Channel *c = Channel::Find(chan); if (!c) { source.Reply(_("Channel \002{0}\002 doesn't exist."), chan); return; } ChanServ::Channel *ci = c->GetChannel(); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), c->name); return; } if (!source.AccessFor(ci).HasPriv("INVITE") && !source.HasOverrideCommand("chanserv/invite")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "INVITE", ci->GetName()); return; } User *u2; if (params.size() == 1) u2 = u; else u2 = User::Find(params[1], true); if (!u2) { source.Reply(_("\002{0}\002 isn't currently online."), params.size() > 1 ? params[1] : source.GetNick()); return; } if (c->FindUser(u2)) { if (u2 == u) source.Reply(_("You are already in \002{0}\002!"), c->name); else source.Reply(_("\002{0}\002 is already in \002{1}\002!"), u2->nick, c->name); return; } IRCD->Send<messages::Invite>(ci->WhoSends(), c, u2); if (u2 != u) { source.Reply(_("\002{0}\002 has been invited to \002{1}\002."), u2->nick, c->name); u2->SendMessage(ci->WhoSends(), _("You have been invited to \002{0}\002 by \002{1}\002."), c->name, source.GetNick()); logger.Command(source, ci, _("{source} used {command} on {channel} to invite {0}"), u2->nick); } else { u2->SendMessage(ci->WhoSends(), _("You have been invited to \002{0}\002."), c->name); logger.Command(source, ci, _("{source} used {command} on {channel}")); } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &target = params[0]; const Anope::string &modes = params[1]; User *u2 = User::Find(target, true); if (!u2) source.Reply(_("\002{0}\002 isn't currently online."), target); else { u2->SetModes(source.service, "%s", modes.c_str()); source.Reply(_("Changed usermodes of \002{0}\002 to \002{1}\002."), u2->nick.c_str(), modes.c_str()); u2->SendMessage(*source.service, _("\002{0}\002 changed your usermodes to \002{1}\002."), source.GetNick(), modes); Log(LOG_ADMIN, source, this) << modes << " on " << target; } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &nick = params[0]; Anope::string expiry = params[1]; Anope::string reason = params.size() > 2 ? params[2] : ""; time_t expiry_secs = Config->GetModule(this->GetOwner())->Get<time_t>("suspendexpire"); if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); if (expiry[0] != '+') { reason = expiry + " " + reason; reason.trim(); expiry.clear(); } else { expiry_secs = Anope::DoTime(expiry); if (expiry_secs == -1) { source.Reply(_("Invalid expiry time \002{0}\002."), expiry); return; } } NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } if (Config->GetModule("nickserv/main")->Get<bool>("secureadmins", "yes") && na->GetAccount()->GetOper()) { source.Reply(_("You may not suspend other Services Operators' nicknames.")); return; } NSSuspendInfo *si = na->GetAccount()->GetRef<NSSuspendInfo *>(); if (!si) { source.Reply(_("\002%s\002 is already suspended."), na->GetAccount()->GetDisplay().c_str()); return; } NickServ::Account *nc = na->GetAccount(); si = Serialize::New<NSSuspendInfo *>(); si->SetAccount(nc); si->SetBy(source.GetNick()); si->SetReason(reason); si->SetWhen(Anope::CurTime); si->SetExpires(expiry_secs ? expiry_secs + Anope::CurTime : 0); for (NickServ::Nick *na2 : nc->GetRefs<NickServ::Nick *>()) { na2->SetLastQuit(reason); User *u2 = User::Find(na2->GetNick(), true); if (u2) { u2->Logout(); if (NickServ::service) NickServ::service->Collide(u2, na2); } } Log(LOG_ADMIN, source, this) << "for " << nick << " (" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); source.Reply(_("\002{0}\002 is now suspended."), na->GetNick()); EventManager::Get()->Dispatch(&Event::NickSuspend::OnNickSuspend, na); }
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, ""); } }
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 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 &chan = params[0]; User *u = source.GetUser(); Channel *c = Channel::Find(chan); if (!c) { source.Reply(_("Channel \002{0}\002 doesn't exist."), chan); return; } ChanServ::Channel *ci = c->ci; if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), c->name); return; } if (!source.AccessFor(ci).HasPriv("INVITE") && !source.HasCommand("chanserv/invite")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "INVITE", ci->GetName()); return; } User *u2; if (params.size() == 1) u2 = u; else u2 = User::Find(params[1], true); if (!u2) { source.Reply(_("\002{0}\002 isn't currently online."), params.size() > 1 ? params[1] : source.GetNick()); return; } if (c->FindUser(u2)) { if (u2 == u) source.Reply(_("You are already in \002{0}\002!"), c->name); else source.Reply(_("\002{0}\002 is already in \002{1}\002!"), u2->nick, c->name); return; } bool override = !source.AccessFor(ci).HasPriv("INVITE"); IRCD->SendInvite(ci->WhoSends(), c, u2); if (u2 != u) { source.Reply(_("\002{0}\002 has been invited to \002{1}\002."), u2->nick, c->name); u2->SendMessage(ci->WhoSends(), _("You have been invited to \002{0}\002 by \002{1}\002."), c->name, source.GetNick()); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; }
void OnSuccess(NickServ::IdentifyRequest *) override { User *u = User::Find(user, true); if (!source.GetUser() || !source.service) return; NickServ::Nick *na = NickServ::FindNick(user); if (!na) return; Log(LOG_COMMAND, source, cmd) << "for " << na->GetNick(); /* Nick is being held by us, release it */ if (na->HasFieldS("HELD")) { NickServ::service->Release(na); source.Reply(_("Service's hold on \002{0}\002 has been released."), na->GetNick()); } else if (!u) { source.Reply(_("No one is using your nick, and services are not holding it.")); } // If the user being recovered is identified for the account of the nick then the user is the // same person that is executing the command, so kill them off (old GHOST command). else if (u->Account() == na->GetAccount()) { if (!source.GetAccount() && na->GetAccount()->HasFieldS("NS_SECURE")) { source.GetUser()->Login(u->Account()); Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->GetDisplay(); } if (Config->GetModule("ns_recover")->Get<bool>("restoreonrecover")) { if (!u->chans.empty()) { NSRecoverInfo i; for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) i[it->first->name] = it->second->status; source.GetUser()->Extend<NSRecoverInfo>("recover", i); } } u->SendMessage(*source.service, _("This nickname has been recovered by \002{0}\002. If you did not do this, then \002{0}\002 may have your password, and you should change it."), source.GetNick()); Anope::string buf = source.command.upper() + " command used by " + source.GetNick(); u->Kill(*source.service, buf); source.Reply(_("Ghost with your nick has been killed.")); if (IRCD->CanSVSNick) IRCD->SendForceNickChange(source.GetUser(), user, Anope::CurTime); } /* User is not identified or not identified to the same account as the person using this command */ else { if (!source.GetAccount() && na->GetAccount()->HasFieldS("NS_SECURE")) { source.GetUser()->Login(na->GetAccount()); // Identify the user using the command if they arent identified Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->GetNick() << " (" << na->GetAccount()->GetDisplay() << ")"; } u->SendMessage(*source.service, _("This nickname has been recovered by \002{0}\002."), source.GetNick()); if (NickServ::service) NickServ::service->Collide(u, na); if (IRCD->CanSVSNick) { /* If we can svsnick then release our hold and svsnick the user using the command */ if (NickServ::service) NickServ::service->Release(na); IRCD->SendForceNickChange(source.GetUser(), user, Anope::CurTime); source.Reply(_("You have regained control of \002%s\002 and are now identified as \002%s\002."), user, na->GetAccount()->GetDisplay().c_str()); } else source.Reply(_("The user with your nick has been removed. Use this command again to release services's hold on your nick.")); } }
void SendMemos(CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost) { Anope::string host; if (!vIdent.empty()) host = vIdent + "@" + vHost; else host = vHost; if (Config->GetModule(GetOwner())->Get<bool>("memooper") && memoserv) for (Oper *o : Serialize::GetObjects<Oper *>()) { NickServ::Nick *na = NickServ::FindNick(o->GetName()); if (!na) continue; Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str()); memoserv->Send(source.service->nick, na->GetNick(), message, true); } }
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); }
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) override { if (command->GetName() == "nickserv/info" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_NICK); if (d != NULL) { if (source.IsOper()) source.Reply(_("Nick \002%s\002 is forbidden by %s: %s"), params[0], d->GetCreator(), d->GetReason()); else source.Reply(_("Nick \002%s\002 is forbidden."), params[0]); return EVENT_STOP; } } else if (command->GetName() == "chanserv/info" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_CHAN); if (d != NULL) { if (source.IsOper()) source.Reply(_("Channel \002%s\002 is forbidden by %s: %s"), params[0], d->GetCreator(), d->GetReason()); else source.Reply(_("Channel \002%s\002 is forbidden."), params[0]); return EVENT_STOP; } } else if (source.IsOper()) return EVENT_CONTINUE; else if (command->GetName() == "nickserv/register" && params.size() > 1) { ForbidData *d = this->forbid_service.FindForbid(source.GetNick(), FT_REGISTER); if (d != NULL) { source.Reply(_("\002{0}\002 may not be registered."), source.GetNick()); return EVENT_STOP; } d = this->forbid_service.FindForbid(params[1], FT_EMAIL); if (d != NULL) { source.Reply(_("Your email address is not allowed, choose a different one.")); return EVENT_STOP; } } else if (command->GetName() == "nickserv/set/email" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_EMAIL); if (d != NULL) { source.Reply(_("Your email address is not allowed, choose a different one.")); return EVENT_STOP; } } else if (command->GetName() == "chanserv/register" && !params.empty()) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_REGISTER); if (d != NULL) { source.Reply(_("Channel \002{0}\002 is currently suspended."), params[0]); return EVENT_STOP; } } return EVENT_CONTINUE; }
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost) { Anope::string host; std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end; if (!vIdent.empty()) host = vIdent + "@" + vHost; else host = vHost; if (Config->GetModule(me)->Get<bool>("memooper") && MemoServ::service) for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) { NickServ::Nick *na = NickServ::FindNick(o->GetName()); if (!na) continue; Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str()); MemoServ::service->Send(source.service->nick, na->GetNick(), message, true); } }