anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

os_info.cpp (6661B)

      1 /* OperServ core functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  */
      8 
      9 #include "module.h"
     10 
     11 struct OperInfo : Serializable
     12 {
     13 	Anope::string target;
     14 	Anope::string info;
     15 	Anope::string adder;
     16 	time_t created;
     17 
     18 	OperInfo() : Serializable("OperInfo"), created(0) { }
     19 	OperInfo(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c) :
     20 		Serializable("OperInfo"), target(t), info(i), adder(a), created(c) { }
     21 
     22 	~OperInfo();
     23 
     24 	void Serialize(Serialize::Data &data) const anope_override
     25 	{
     26 		data["target"] << target;
     27 		data["info"] << info;
     28 		data["adder"] << adder;
     29 		data["created"] << created;
     30 	}
     31 
     32 	static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
     33 };
     34 
     35 struct OperInfos : Serialize::Checker<std::vector<OperInfo *> >
     36 {
     37 	OperInfos(Extensible *) : Serialize::Checker<std::vector<OperInfo *> >("OperInfo") { }
     38 
     39 	~OperInfos()
     40 	{
     41 		for (unsigned i = (*this)->size(); i > 0; --i)
     42 			delete (*this)->at(i - 1);
     43 	}
     44 
     45 	static Extensible *Find(const Anope::string &target)
     46 	{
     47 		NickAlias *na = NickAlias::Find(target);
     48 		if (na)
     49 			return na->nc;
     50 		return ChannelInfo::Find(target);
     51 	}
     52 };
     53 
     54 OperInfo::~OperInfo()
     55 {
     56 	Extensible *e = OperInfos::Find(target);
     57 	if (e)
     58 	{
     59 		OperInfos *op  = e->GetExt<OperInfos>("operinfo");
     60 		if (op)
     61 		{
     62 			std::vector<OperInfo *>::iterator it = std::find((*op)->begin(), (*op)->end(), this);
     63 			if (it != (*op)->end())
     64 				(*op)->erase(it);
     65 		}
     66 	}
     67 }
     68 
     69 Serializable *OperInfo::Unserialize(Serializable *obj, Serialize::Data &data)
     70 {
     71 	Anope::string starget;
     72 	data["target"] >> starget;
     73 
     74 	Extensible *e = OperInfos::Find(starget);
     75 	if (!e)
     76 		return NULL;
     77 
     78 	OperInfos *oi = e->Require<OperInfos>("operinfo");
     79 	OperInfo *o;
     80 	if (obj)
     81 		o = anope_dynamic_static_cast<OperInfo *>(obj);
     82 	else
     83 	{
     84 		o = new OperInfo();
     85 		o->target = starget;
     86 	}
     87 	data["info"] >> o->info;
     88 	data["adder"] >> o->adder;
     89 	data["created"] >> o->created;
     90 
     91 	if (!obj)
     92 		(*oi)->push_back(o);
     93 	return o;
     94 }
     95 
     96 class CommandOSInfo : public Command
     97 {
     98  public:
     99 	CommandOSInfo(Module *creator) : Command(creator, "operserv/info", 2, 3)
    100 	{
    101 		this->SetDesc(_("Associate oper info with a nick or channel"));
    102 		this->SetSyntax(_("ADD \037target\037 \037info\037"));
    103 		this->SetSyntax(_("DEL \037target\037 \037info\037"));
    104 		this->SetSyntax(_("CLEAR \037target\037"));
    105 	}
    106 
    107 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    108 	{
    109 		const Anope::string &cmd = params[0], target = params[1], info = params.size() > 2 ? params[2] : "";
    110 
    111 		Extensible *e;
    112 		if (IRCD->IsChannelValid(target))
    113 		{
    114 			ChannelInfo *ci = ChannelInfo::Find(target);
    115 			if (!ci)
    116 			{
    117 				source.Reply(CHAN_X_NOT_REGISTERED, target.c_str());
    118 				return;
    119 			}
    120 
    121 			e = ci;
    122 		}
    123 		else
    124 		{
    125 			NickAlias *na = NickAlias::Find(target);
    126 			if (!na)
    127 			{
    128 				source.Reply(NICK_X_NOT_REGISTERED, target.c_str());
    129 				return;
    130 			}
    131 
    132 			e = na->nc;
    133 		}
    134 
    135 		if (cmd.equals_ci("ADD"))
    136 		{
    137 			if (info.empty())
    138 			{
    139 				this->OnSyntaxError(source, cmd);
    140 				return;
    141 			}
    142 
    143 			OperInfos *oi = e->Require<OperInfos>("operinfo");
    144 
    145 			if ((*oi)->size() >= Config->GetModule(this->module)->Get<unsigned>("max", "10"))
    146 			{
    147 				source.Reply(_("The oper info list for \002%s\002 is full."), target.c_str());
    148 				return;
    149 			}
    150 
    151 			for (unsigned i = 0; i < (*oi)->size(); ++i)
    152 			{
    153 				OperInfo *o = (*oi)->at(i);
    154 
    155 				if (o->info.equals_ci(info))
    156 				{
    157 					source.Reply(_("The oper info already exists on \002%s\002."), target.c_str());
    158 					return;
    159 				}
    160 			}
    161 
    162 			(*oi)->push_back(new OperInfo(target, info, source.GetNick(), Anope::CurTime));
    163 
    164 			source.Reply(_("Added info to \002%s\002."), target.c_str());
    165 			Log(LOG_ADMIN, source, this) << "to add information to " << target;
    166 
    167 			if (Anope::ReadOnly)
    168 				source.Reply(READ_ONLY_MODE);
    169 		}
    170 		else if (cmd.equals_ci("DEL"))
    171 		{
    172 			if (info.empty())
    173 			{
    174 				this->OnSyntaxError(source, cmd);
    175 				return;
    176 			}
    177 
    178 			OperInfos *oi = e->GetExt<OperInfos>("operinfo");
    179 
    180 			if (!oi)
    181 			{
    182 				source.Reply(_("Oper info list for \002%s\002 is empty."), target.c_str());
    183 				return;
    184 			}
    185 
    186 			bool found = false;
    187 			for (unsigned i = (*oi)->size(); i > 0; --i)
    188 			{
    189 				OperInfo *o = (*oi)->at(i - 1);
    190 
    191 				if (o->info.equals_ci(info))
    192 				{
    193 					delete o;
    194 					found = true;
    195 					break;
    196 				}
    197 			}
    198 
    199 			if (!found)
    200 			{
    201 				source.Reply(_("No such info \"%s\" on \002%s\002."), info.c_str(), target.c_str());
    202 			}
    203 			else
    204 			{
    205 				if ((*oi)->empty())
    206 					e->Shrink<OperInfos>("operinfo");
    207 
    208 				source.Reply(_("Deleted info from \002%s\002."), target.c_str());
    209 				Log(LOG_ADMIN, source, this) << "to remove information from " << target;
    210 
    211 				if (Anope::ReadOnly)
    212 					source.Reply(READ_ONLY_MODE);
    213 			}
    214 		}
    215 		else if (cmd.equals_ci("CLEAR"))
    216 		{
    217 			OperInfos *oi = e->GetExt<OperInfos>("operinfo");
    218 
    219 			if (!oi)
    220 			{
    221 				source.Reply(_("Oper info list for \002%s\002 is empty."), target.c_str());
    222 				return;
    223 			}
    224 
    225 			e->Shrink<OperInfos>("operinfo");
    226 
    227 			source.Reply(_("Cleared info from \002%s\002."), target.c_str());
    228 			Log(LOG_ADMIN, source, this) << "to clear information for " << target;
    229 
    230 			if (Anope::ReadOnly)
    231 				source.Reply(READ_ONLY_MODE);
    232 		}
    233 		else
    234 		{
    235 			this->OnSyntaxError(source, cmd);
    236 		}
    237 	}
    238 
    239 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    240 	{
    241 		this->SendSyntax(source);
    242 		source.Reply(" ");
    243 		source.Reply(_("Add or delete oper information for a given nick or channel.\n"
    244 				"This will show to opers in the respective info command for\n"
    245 				"the nick or channel."));
    246 		return true;
    247 	}
    248 };
    249 
    250 class OSInfo : public Module
    251 {
    252 	CommandOSInfo commandosinfo;
    253 	ExtensibleItem<OperInfos> oinfo;
    254 	Serialize::Type oinfo_type;
    255 
    256 	void OnInfo(CommandSource &source, Extensible *e, InfoFormatter &info)
    257 	{
    258 		if (!source.IsOper())
    259 			return;
    260 
    261 		OperInfos *oi = oinfo.Get(e);
    262 		if (!oi)
    263 			return;
    264 
    265 		for (unsigned i = 0; i < (*oi)->size(); ++i)
    266 		{
    267 			OperInfo *o = (*oi)->at(i);
    268 			info[_("Oper Info")] = Anope::printf(_("(by %s on %s) %s"), o->adder.c_str(), Anope::strftime(o->created, source.GetAccount(), true).c_str(), o->info.c_str());
    269 		}
    270 	}
    271 
    272  public:
    273 	OSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    274 		commandosinfo(this), oinfo(this, "operinfo"), oinfo_type("OperInfo", OperInfo::Unserialize)
    275 	{
    276 
    277 	}
    278 
    279 	void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
    280 	{
    281 		OnInfo(source, na->nc, info);
    282 	}
    283 
    284 	void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
    285 	{
    286 		OnInfo(source, ci, info);
    287 	}
    288 };
    289 
    290 MODULE_INIT(OSInfo)