const Anope::string BufferedSocket::GetLine() { size_t s = this->read_buffer.find('\n'); if (s == Anope::string::npos) return ""; Anope::string str = this->read_buffer.substr(0, s + 1); this->read_buffer.erase(0, s + 1); this->read_buffer.ltrim("\r\n"); return str.trim("\r\n"); }
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); }
Anope::string operator()(Anope::string s) const { return s.trim(); }
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); }