diff options
author | Adam <Adam@anope.org> | 2013-04-08 23:36:14 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2013-04-08 23:37:42 -0500 |
commit | 0a3d27a91f826db7c3bb639901450a5b00c80b64 (patch) | |
tree | c1045d56cd43ff6775221c897ab28e27faa56ad3 | |
parent | bcd85ca68281b8f10d4357d6f7daeced4b79a9b4 (diff) |
Made XOP privileges configurable
-rw-r--r-- | data/chanserv.example.conf | 55 | ||||
-rw-r--r-- | include/commands.h | 3 | ||||
-rw-r--r-- | modules/commands/cs_access.cpp | 48 | ||||
-rw-r--r-- | modules/commands/cs_xop.cpp | 545 | ||||
-rw-r--r-- | src/access.cpp | 47 | ||||
-rw-r--r-- | src/command.cpp | 4 |
6 files changed, 226 insertions, 476 deletions
diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index 1c0710f7b..d6d063ee0 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -228,6 +228,8 @@ chanserv * * If you loaded cs_flags, you may define a flag associated with that privilege for use in chanserv/flags. * + * If you loaded cs_xop, you may define a xop command to associate the privilege with. + * * Defining new privileges here is not useful unless you have a module (eg, a third party one) made to check for * the specific level you are defining. * @@ -247,6 +249,7 @@ privilege rank = 0 level = 10 flag = "f" + xop = "SOP" } /* @@ -262,6 +265,7 @@ privilege rank = 10 level = 3 flag = "f" + xop = "VOP" } /* @@ -277,6 +281,7 @@ privilege rank = 250 level = 10 flag = "K" + xop = "SOP" } /* @@ -292,6 +297,7 @@ privilege rank = 270 level = "founder" flag = "s" + xop = "QOP" } /* @@ -307,6 +313,7 @@ privilege rank = 100 level = 4 flag = "H" + xop = "HOP" } /* @@ -322,6 +329,7 @@ privilege rank = 210 level = 5 flag = "O" + xop = "AOP" } /* @@ -337,6 +345,7 @@ privilege rank = 330 level = 9999 flag = "Q" + xop = "QOP" } /* @@ -352,6 +361,7 @@ privilege rank = 240 level = 10 flag = "A" + xop = "SOP" } /* @@ -367,6 +377,7 @@ privilege rank = 50 level = 3 flag = "V" + xop = "VOP" } /* @@ -382,6 +393,7 @@ privilege rank = 260 level = 10 flag = "K" + xop = "SOP" } /* @@ -397,6 +409,7 @@ privilege rank = 150 level = 4 flag = "b" + xop = "HOP" } /* @@ -412,6 +425,7 @@ privilege rank = 30 level = 3 flag = "c" + xop = "VOP" } /* @@ -430,6 +444,7 @@ privilege rank = 360 level = "founder" flag = "F" + xop = "QOP" } /* @@ -446,6 +461,7 @@ privilege rank = 180 level = 5 flag = "G" + xop = "AOP" } /* @@ -461,6 +477,7 @@ privilege rank = 40 level = 5 flag = "g" + xop = "AOP" } /* @@ -477,6 +494,7 @@ privilege rank = 120 level = 5 flag = "h" + xop = "AOP" } /* @@ -493,6 +511,7 @@ privilege rank = 110 level = 4 flag = "h" + xop = "HOP" } /* @@ -509,6 +528,7 @@ privilege rank = 80 level = 9999 flag = "I" + xop = "QOP" } /* @@ -525,6 +545,7 @@ privilege rank = 190 level = 5 flag = "i" + xop = "AOP" } /* @@ -540,6 +561,7 @@ privilege rank = 130 level = 4 flag = "k" + xop = "HOP" } /* @@ -556,6 +578,7 @@ privilege rank = 280 level = 10 flag = "m" + xop = "SOP" } /* @@ -572,6 +595,7 @@ privilege rank = 170 level = 9999 flag = "s" + xop = "QOP" } /* @@ -587,6 +611,7 @@ privilege rank = 20 level = 1 flag = "N" + xop = "VOP" } /* @@ -603,6 +628,7 @@ privilege rank = 230 level = 5 flag = "o" + xop = "SOP" } /* @@ -619,6 +645,7 @@ privilege rank = 220 level = 5 flag = "o" + xop = "AOP" } /* @@ -635,6 +662,7 @@ privilege rank = 350 level = "founder" flag = "q" + xop = "QOP" } /* @@ -651,6 +679,7 @@ privilege rank = 340 level = 9999 flag = "q" + xop = "QOP" } /* @@ -667,6 +696,7 @@ privilege rank = 310 level = 9999 flag = "a" + xop = "QOP" } /* @@ -683,6 +713,7 @@ privilege rank = 300 level = 10 flag = "a" + xop = "AOP" } /* @@ -699,6 +730,7 @@ privilege rank = 90 level = 5 flag = "B" + xop = "AOP" } /* @@ -717,6 +749,7 @@ privilege rank = 320 level = 9999 flag = "s" + xop = "QOP" } /* @@ -733,6 +766,7 @@ privilege rank = 140 level = 9999 flag = "K" + xop = "QOP" } /* @@ -748,6 +782,7 @@ privilege rank = 160 level = 5 flag = "t" + xop = "AOP" } /* @@ -763,6 +798,7 @@ privilege rank = 200 level = 4 flag = "u" + xop = "HOP" } /* @@ -779,6 +815,7 @@ privilege rank = 70 level = 4 flag = "v" + xop = "HOP" } /* @@ -795,6 +832,7 @@ privilege rank = 60 level = 3 flag = "v" + xop = "VOP" } /* @@ -1181,17 +1219,20 @@ command { service = "ChanServ"; name = "UP"; command = "chanserv/up"; group = "c /* * cs_xop * - * Provides the commands chanserv/qop, chanserv/sop, chanserv/aop, chanserv/hop, and chanserv/vop. + * Provides the command chanserv/xop. * Provides the access system "XOP". * - * Used for giving users access in channels. + * Used for giving users access in channels. Many commands may be linked to chanserv/xop, but the + * privileges given by each is determined by the privilege:xop settings above. These commands should + * be ordered from highest to lowest, as each command inherits the privileges of the commands below + * it. */ module { name = "cs_xop" } -command { service = "ChanServ"; name = "QOP"; command = "chanserv/qop"; group = "chanserv/access"; } -command { service = "ChanServ"; name = "SOP"; command = "chanserv/sop"; group = "chanserv/access"; } -command { service = "ChanServ"; name = "AOP"; command = "chanserv/aop"; group = "chanserv/access"; } -command { service = "ChanServ"; name = "HOP"; command = "chanserv/hop"; group = "chanserv/access"; } -command { service = "ChanServ"; name = "VOP"; command = "chanserv/vop"; group = "chanserv/access"; } +command { service = "ChanServ"; name = "QOP"; command = "chanserv/xop"; group = "chanserv/access"; } +command { service = "ChanServ"; name = "SOP"; command = "chanserv/xop"; group = "chanserv/access"; } +command { service = "ChanServ"; name = "AOP"; command = "chanserv/xop"; group = "chanserv/access"; } +command { service = "ChanServ"; name = "HOP"; command = "chanserv/xop"; group = "chanserv/access"; } +command { service = "ChanServ"; name = "VOP"; command = "chanserv/xop"; group = "chanserv/access"; } /* Use m_rewrite to rewrite the op, deop, etc. commands (see modules.conf). */ diff --git a/include/commands.h b/include/commands.h index be800aa32..b74639a32 100644 --- a/include/commands.h +++ b/include/commands.h @@ -136,9 +136,10 @@ class CoreExport Command : public Service bool RequireUser() const; /** Get the command description + * @param source The source wanting the command description * @return The commands description */ - const Anope::string &GetDesc() const; + virtual const Anope::string GetDesc(CommandSource &source) const; /** Execute this command. * @param source The source diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 86ce37a51..e6f32d8d2 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -15,49 +15,6 @@ static std::map<Anope::string, int16_t, ci::less> defaultLevels; -static struct -{ - Anope::string name; - Anope::string desc; -} descriptions[] = { - {"ACCESS_CHANGE", _("Allowed to modify the access list")}, - {"ACCESS_LIST", _("Allowed to view the access list")}, - {"AKICK", _("Allowed to use the AKICK command")}, - {"ASSIGN", _("Allowed to assign/unassign a bot")}, - {"AUTOHALFOP", _("Automatic halfop upon join")}, - {"AUTOOP", _("Automatic channel operator status upon join")}, - {"AUTOOWNER", _("Automatic owner upon join")}, - {"AUTOPROTECT", _("Automatic protect upon join")}, - {"AUTOVOICE", _("Automatic voice on join")}, - {"BADWORDS", _("Allowed to modify channel badwords list")}, - {"BAN", _("Allowed to ban users")}, - {"FANTASIA", _("Allowed to use fantasy commands")}, - {"FOUNDER", _("Allowed to issue commands restricted to channel founders")}, - {"GETKEY", _("Allowed to use GETKEY command")}, - {"GREET", _("Greet message displayed on join")}, - {"HALFOP", _("Allowed to (de)halfop users")}, - {"HALFOPME", _("Allowed to (de)halfop him/herself")}, - {"INFO", _("Allowed to get full INFO output")}, - {"INVITE", _("Allowed to use the INVITE command")}, - {"KICK", _("Allowed to use the KICK command")}, - {"MEMO", _("Allowed to read channel memos")}, - {"MODE", _("Allowed to use the MODE command")}, - {"NOKICK", _("Prevents users being kicked by Services")}, - {"OPDEOP", _("Allowed to (de)op users")}, - {"OPDEOPME", _("Allowed to (de)op him/herself")}, - {"OWNER", _("Allowed to (de)owner users")}, - {"OWNERME", _("Allowed to (de)owner him/herself")}, - {"PROTECT", _("Allowed to (de)protect users")}, - {"PROTECTME", _("Allowed to (de)protect him/herself")}, - {"SAY", _("Allowed to use SAY and ACT commands")}, - {"SET", _("Allowed to set channel settings")}, - {"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")}, - {"TOPIC", _("Allowed to change channel topics")}, - {"UNBAN", _("Allowed to unban users")}, - {"VOICE", _("Allowed to (de)voice users")}, - {"VOICEME", _("Allowed to (de)voice him/herself")} -}; - static inline void reset_levels(ChannelInfo *ci) { ci->ClearLevels(); @@ -851,11 +808,6 @@ class CSAccess : public Module if (p == NULL) continue; - if (p->desc.empty()) - for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j) - if (descriptions[j].name == pname) - p->desc = descriptions[j].desc; - const Anope::string &value = config.ReadValue("privilege", "level", "", i); if (value.empty()) continue; diff --git a/modules/commands/cs_xop.cpp b/modules/commands/cs_xop.cpp index 546175e14..18a2789c7 100644 --- a/modules/commands/cs_xop.cpp +++ b/modules/commands/cs_xop.cpp @@ -9,93 +9,18 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" -enum XOPType +namespace { - XOP_QOP, - XOP_SOP, - XOP_AOP, - XOP_HOP, - XOP_VOP, - XOP_UNKNOWN -}; - -static struct XOPAccess -{ - XOPType type; - Anope::string name; - Anope::string access[10]; -} xopAccess[] = { - { XOP_QOP, "QOP", - { - "SIGNKICK", - "SET", - "MODE", - "AUTOOWNER", - "OWNERME", - "PROTECT", - "INFO", - "ASSIGN", - "" - } - }, - { XOP_SOP, "SOP", - { - "AUTOPROTECT", - "AKICK", - "BADWORDS", - "MEMO", - "ACCESS_CHANGE", - "PROTECTME", - "OPDEOP", - "" - } - }, - { XOP_AOP, "AOP", - { - "TOPIC", - "GETKEY", - "INVITE", - "AUTOOP", - "OPDEOPME", - "HALFOP", - "SAY", - "GREET", - "" - } - }, - { XOP_HOP, "HOP", - { - "AUTOHALFOP", - "HALFOPME", - "VOICE", - "KICK", - "BAN", - "UNBAN", - "" - } - }, - { XOP_VOP, "VOP", - { - "AUTOVOICE", - "VOICEME", - "ACCESS_LIST", - "FANTASIA", - "NOKICK", - "" - } - }, - { XOP_UNKNOWN, "", { } - } -}; + std::vector<Anope::string> order; + std::map<Anope::string, std::vector<Anope::string> > permissions; +} class XOPChanAccess : public ChanAccess { public: - XOPType type; + Anope::string type; XOPChanAccess(AccessProvider *p) : ChanAccess(p) { @@ -103,51 +28,26 @@ class XOPChanAccess : public ChanAccess bool HasPriv(const Anope::string &priv) const anope_override { - for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i) + for (std::vector<Anope::string>::iterator it = std::find(order.begin(), order.end(), this->type); it != order.end(); ++it) { - XOPAccess &x = xopAccess[i]; - - if (this->type > x.type) - continue; - - for (int j = 0; !x.access[j].empty(); ++j) - if (x.access[j] == priv) - return true; + const std::vector<Anope::string> &privs = permissions[*it]; + if (std::find(privs.begin(), privs.end(), priv) != privs.end()) + return true; } - return false; } Anope::string AccessSerialize() const { - for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i) - { - XOPAccess &x = xopAccess[i]; - - if (this->type == x.type) - return x.name; - } - - return ""; + return this->type; } void AccessUnserialize(const Anope::string &data) anope_override { - for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i) - { - XOPAccess &x = xopAccess[i]; - - if (data == x.name) - { - this->type = x.type; - return; - } - } - - this->type = XOP_UNKNOWN; + this->type = data; } - static XOPType DetermineLevel(const ChanAccess *access) + static Anope::string DetermineLevel(const ChanAccess *access) { if (access->provider->name == "access/xop") { @@ -156,26 +56,24 @@ class XOPChanAccess : public ChanAccess } else { - int count[XOP_UNKNOWN]; - for (int i = 0; i < XOP_UNKNOWN; ++i) - count[i] = 0; + std::map<Anope::string, int> count; - for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i) + for (std::map<Anope::string, std::vector<Anope::string> >::const_iterator it = permissions.begin(), it_end = permissions.end(); it != it_end; ++it) { - XOPAccess &x = xopAccess[i]; - - for (int j = 0; !x.access[j].empty(); ++j) - if (access->HasPriv(x.access[j])) - ++count[x.type]; + int &c = count[it->first]; + const std::vector<Anope::string> &perms = it->second; + for (unsigned i = 0; i < perms.size(); ++i) + if (access->HasPriv(perms[i])) + ++c; } - XOPType max = XOP_UNKNOWN; + Anope::string max; int maxn = 0; - for (int i = 0; i < XOP_UNKNOWN; ++i) - if (count[i] > maxn) + for (std::map<Anope::string, int>::iterator it = count.begin(), it_end = count.end(); it != it_end; ++it) + if (it->second > maxn) { - max = static_cast<XOPType>(i); - maxn = count[i]; + maxn = it->second; + max = it->first; } return max; @@ -196,12 +94,11 @@ class XOPAccessProvider : public AccessProvider } }; -class XOPBase : public Command +class CommandCSXOP : public Command { private: - void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level) + void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { - Anope::string mask = params.size() > 2 ? params[2] : ""; if (mask.empty()) @@ -218,7 +115,7 @@ class XOPBase : public Command XOPChanAccess tmp_access(NULL); tmp_access.ci = ci; - tmp_access.type = level; + tmp_access.type = source.command.upper(); AccessGroup access = source.AccessFor(ci); const ChanAccess *highest = access.Highest(); @@ -277,7 +174,7 @@ class XOPBase : public Command acc->ci = ci; acc->mask = mask; acc->creator = source.GetNick(); - acc->type = level; + acc->type = source.command.upper(); acc->last_seen = 0; acc->created = Anope::CurTime; ci->AddAccess(acc); @@ -288,7 +185,7 @@ class XOPBase : public Command source.Reply(_("\002%s\002 added to %s %s list."), acc->mask.c_str(), ci->name.c_str(), source.command.c_str()); } - void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level) + void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { NickCore *nc = source.nc; Anope::string mask = params.size() > 2 ? params[2] : ""; @@ -313,7 +210,7 @@ class XOPBase : public Command XOPChanAccess tmp_access(NULL); tmp_access.ci = ci; - tmp_access.type = level; + tmp_access.type = source.command.upper(); AccessGroup access = source.AccessFor(ci); const ChanAccess *highest = access.Highest(); @@ -353,9 +250,8 @@ class XOPBase : public Command unsigned deleted; Anope::string nicks; bool override; - XOPType type; public: - XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, XOPType _type, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), override(_override), type(_type) + XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), override(_override) { } @@ -381,7 +277,7 @@ class XOPBase : public Command ChanAccess *caccess = ci->GetAccess(number - 1); - if (this->type != XOPChanAccess::DetermineLevel(caccess)) + if (this->source.command.upper() != XOPChanAccess::DetermineLevel(caccess)) return; ++deleted; @@ -395,7 +291,7 @@ class XOPBase : public Command ci->EraseAccess(number - 1); } } - delcallback(source, ci, this, override, level, mask); + delcallback(source, ci, this, override, mask); delcallback.Process(); } else @@ -404,7 +300,7 @@ class XOPBase : public Command { ChanAccess *a = ci->GetAccess(i); - if (a->mask.equals_ci(mask) && XOPChanAccess::DetermineLevel(a) == level) + if (a->mask.equals_ci(mask) && XOPChanAccess::DetermineLevel(a) == source.command.upper()) { Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << a->mask; @@ -421,7 +317,7 @@ class XOPBase : public Command } } - void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level) + void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params.size() > 2 ? params[2] : ""; @@ -449,9 +345,9 @@ class XOPBase : public Command { ListFormatter &list; ChannelInfo *ci; - XOPType type; + CommandSource &source; public: - XOPListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist, XOPType _type) : NumberList(numlist, false), list(_list), ci(_ci), type(_type) + XOPListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist, CommandSource &src) : NumberList(numlist, false), list(_list), ci(_ci), source(src) { } @@ -462,7 +358,7 @@ class XOPBase : public Command const ChanAccess *a = ci->GetAccess(Number - 1); - if (this->type != XOPChanAccess::DetermineLevel(a)) + if (this->source.command.upper() != XOPChanAccess::DetermineLevel(a)) return; ListFormatter::ListEntry entry; @@ -470,7 +366,7 @@ class XOPBase : public Command entry["Mask"] = a->mask; this->list.AddEntry(entry); } - } nl_list(list, ci, nick, level); + } nl_list(list, ci, nick, source); nl_list.Process(); } else @@ -479,7 +375,7 @@ class XOPBase : public Command { const ChanAccess *a = ci->GetAccess(i); - if (XOPChanAccess::DetermineLevel(a) != level) + if (XOPChanAccess::DetermineLevel(a) != source.command.upper()) continue; else if (!nick.empty() && !Anope::Match(a->mask, nick)) continue; @@ -504,9 +400,8 @@ class XOPBase : public Command } } - void DoClear(CommandSource &source, ChannelInfo *ci, XOPType level) + void DoClear(CommandSource &source, ChannelInfo *ci) { - if (Anope::ReadOnly) { source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str()); @@ -531,19 +426,30 @@ class XOPBase : public Command for (unsigned i = ci->GetAccessCount(); i > 0; --i) { const ChanAccess *access = ci->GetAccess(i - 1); - if (XOPChanAccess::DetermineLevel(access) == level) + if (XOPChanAccess::DetermineLevel(access) == source.command.upper()) ci->EraseAccess(i - 1); } FOREACH_MOD(I_OnAccessClear, OnAccessClear(ci, source)); source.Reply(_("Channel %s %s list has been cleared."), ci->name.c_str(), source.command.c_str()); + } + + public: + CommandCSXOP(Module *modname) : Command(modname, "chanserv/xop", 2, 4) + { + this->SetSyntax("\037channel\037 ADD \037mask\037"); + this->SetSyntax("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}"); + this->SetSyntax("\037channel\037 LIST [\037mask\037 | \037list\037]"); + this->SetSyntax("\037channel\037 CLEAR"); + } - return; + const Anope::string GetDesc(CommandSource &source) const anope_override + { + return Anope::printf(_("Modify the list of %s users"), source.command.upper().c_str()); } - protected: - void DoXop(CommandSource &source, const std::vector<Anope::string> ¶ms, XOPType level) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelInfo *ci = ChannelInfo::Find(params[0]); if (ci == NULL) @@ -555,79 +461,68 @@ class XOPBase : public Command const Anope::string &cmd = params[1]; if (cmd.equals_ci("ADD")) - return this->DoAdd(source, ci, params, level); + return this->DoAdd(source, ci, params); else if (cmd.equals_ci("DEL")) - return this->DoDel(source, ci, params, level); + return this->DoDel(source, ci, params); else if (cmd.equals_ci("LIST")) - return this->DoList(source, ci, params, level); + return this->DoList(source, ci, params); else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source, ci, level); + return this->DoClear(source, ci); else this->OnSyntaxError(source, ""); - - return; - } - public: - XOPBase(Module *modname, const Anope::string &command) : Command(modname, command, 2, 4) - { - this->SetSyntax("\037channel\037 ADD \037mask\037"); - this->SetSyntax("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}"); - this->SetSyntax("\037channel\037 LIST [\037mask\037 | \037list\037]"); - this->SetSyntax("\037channel\037 CLEAR"); } - virtual ~XOPBase() - { - } - - virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; - - virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; -}; - -class CommandCSQOP : public XOPBase -{ - public: - CommandCSQOP(Module *creator) : XOPBase(creator, "chanserv/qop") - { - this->SetDesc(_("Modify the list of QOP users")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoXop(source, params, XOP_QOP); - } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override { + const Anope::string &cmd = source.command.upper(); + this->SendSyntax(source); source.Reply(" "); - source.Reply(_("Maintains the \002QOP\002 (AutoOwner) \002list\002 for a channel. The QOP\n" - "list gives users the right to be auto-owner on your channel,\n" - "which gives them almost (or potentially, total) access.\n" - " \n" - "The \002QOP ADD\002 command adds the given nickname to the\n" - "QOP list.\n" + source.Reply(_("Maintains the \2%s list\2 for a channel. Users who match an access entry\n" + "on the %s list receive the following privileges:\n" + " "), cmd.c_str(), cmd.c_str()); + + Anope::string buf; + for (unsigned i = 0; i < permissions[cmd].size(); ++i) + { + buf += ", " + permissions[cmd][i]; + if (buf.length() > 75) + { + source.Reply(" %s\n", buf.substr(2).c_str()); + buf.clear(); + } + } + if (!buf.empty()) + { + source.Reply(" %s\n", buf.substr(2).c_str()); + buf.clear(); + } + + source.Reply(_(" \n" + "The \002%s ADD\002 command adds the given nickname to the\n" + "%s list.\n" " \n" - "The \002QOP DEL\002 command removes the given nick from the\n" - "QOP list. If a list of entry numbers is given, those\n" + "The \002%s DEL\002 command removes the given nick from the\n" + "%s list. If a list of entry numbers is given, those\n" "entries are deleted. (See the example for LIST below.)\n" " \n" - "The \002QOP LIST\002 command displays the QOP list. If\n" + "The \002%s LIST\002 command displays the %s list. If\n" "a wildcard mask is given, only those entries matching the\n" "mask are displayed. If a list of entry numbers is given,\n" "only those entries are shown; for example:\n" - " \002QOP #channel LIST 2-5,7-9\002\n" - " Lists QOP entries numbered 2 through 5 and\n" + " \002%s #channel LIST 2-5,7-9\002\n" + " Lists %s entries numbered 2 through 5 and\n" " 7 through 9.\n" " \n" - "The \002QOP CLEAR\002 command clears all entries of the\n" - "QOP list.")); + "The \002%s CLEAR\002 command clears all entries of the\n" + "%s list."), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), + cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str()); source.Reply(_(" \n" - "The \002QOP\002 commands are limited to founders\n" + "The \002%s\002 commands are limited to founders\n" "(unless SECUREOPS is off). However, any user on the\n" - "VOP list or above may use the \002QOP LIST\002 command.\n" - " \n")); + "VOP list or above may use the \002%s LIST\002 command.\n" + " \n"), cmd.c_str(), cmd.c_str()); source.Reply(_("Alternative methods of modifying channel access lists are\n" "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" @@ -638,238 +533,52 @@ class CommandCSQOP : public XOPBase } }; -class CommandCSAOP : public XOPBase +class CSXOP : public Module { - public: - CommandCSAOP(Module *creator) : XOPBase(creator, "chanserv/aop") - { - this->SetDesc(_("Modify the list of AOP users")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoXop(source, params, XOP_AOP); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002AOP\002 (AutoOP) \002list\002 for a channel. The AOP\n" - "list gives users the right to be auto-opped on your channel,\n" - "to unban or invite themselves if needed, to have their\n" - "greet message showed on join, and so on.\n" - " \n" - "The \002AOP ADD\002 command adds the given nickname to the\n" - "AOP list.\n" - " \n" - "The \002AOP DEL\002 command removes the given nick from the\n" - "AOP list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002AOP LIST\002 command displays the AOP list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002AOP #channel LIST 2-5,7-9\002\n" - " Lists AOP entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002AOP CLEAR\002 command clears all entries of the\n" - "AOP list.")); - source.Reply(_(" \n" - "The \002AOP ADD\002 and \002AOP DEL\002 commands are limited to\n" - "SOPs or above, while the \002AOP CLEAR\002 command can only\n" - "be used by the channel founder. However, any user on the\n" - "VOP list or above may use the \002AOP LIST\002 command.\n" - " \n")); - source.Reply(_("Alternative methods of modifying channel access lists are\n" - "available. See \002%s%s HELP ACCESS\002 for information\n" - "about the access list, and \002%s%s HELP FLAGS\002 for\n" - "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); - return true; - } -}; + XOPAccessProvider accessprovider; + CommandCSXOP commandcsxop; -class CommandCSHOP : public XOPBase -{ public: - CommandCSHOP(Module *creator) : XOPBase(creator, "chanserv/hop") + CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + accessprovider(this), commandcsxop(this) { - this->SetDesc(_("Maintains the HOP (HalfOP) list for a channel")); - } + this->SetAuthor("Anope"); + this->SetPermanent(true); - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoXop(source, params, XOP_HOP); + this->OnReload(); } - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override + void OnReload() anope_override { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002HOP\002 (HalfOP) \002list\002 for a channel. The HOP\n" - "list gives users the right to be auto-halfopped on your\n" - "channel.\n" - " \n" - "The \002HOP ADD\002 command adds the given nickname to the\n" - "HOP list.\n" - " \n" - "The \002HOP DEL\002 command removes the given nick from the\n" - "HOP list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002HOP LIST\002 command displays the HOP list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002HOP #channel LIST 2-5,7-9\002\n" - " Lists HOP entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002HOP CLEAR\002 command clears all entries of the\n" - "HOP list.")); - source.Reply(_(" \n" - "The \002HOP ADD\002 and \002HOP DEL\002 commands are limited\n" - "to SOPs or above, while \002HOP LIST\002 is available to VOPs\n" - "and above. The \002HOP CLEAR\002 command can only be used by the\n" - "channel founder.\n" - " \n")); - source.Reply(_("Alternative methods of modifying channel access lists are\n" - "available. See \002%s%s HELP ACCESS\002 for information\n" - "about the access list, and \002%s%s HELP FLAGS\002 for\n" - "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); - return true; - } -}; + order.clear(); + permissions.clear(); -class CommandCSSOP : public XOPBase -{ - public: - CommandCSSOP(Module *creator) : XOPBase(creator, "chanserv/sop") - { - this->SetDesc(_("Modify the list of SOP users")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoXop(source, params, XOP_SOP); - } + ConfigReader config; - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002SOP\002 (SuperOP) \002list\002 for a channel. The SOP\n" - "list gives users all rights given by the AOP list, and adds\n" - "those needed to use the AutoKick and the BadWords lists,\n" - "to send and read channel memos, and so on.\n" - " \n" - "The \002SOP ADD\002 command adds the given nickname to the\n" - "SOP list.\n" - " \n" - "The \002SOP DEL\002 command removes the given nick from the\n" - "SOP list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002SOP LIST\002 command displays the SOP list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SOP #channel LIST 2-5,7-9\002\n" - " Lists SOP entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002SOP CLEAR\002 command clears all entries of the\n" - "SOP list.")); - source.Reply(_(" \n" - "The \002SOP ADD\002, \002SOP DEL\002 and \002SOP CLEAR\002 commands are\n" - "limited to the channel founder. However, any user on the\n" - "VOP list or above may use the \002SOP LIST\002 command.\n" - " \n")); - source.Reply(_("Alternative methods of modifying channel access lists are\n" - "available. See \002%s%s HELP ACCESS\002 for information\n" - "about the access list, and \002%s%s HELP FLAGS\002 for\n" - "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); - return true; - } -}; + for (int i = 0; i < config.Enumerate("privilege"); ++i) + { + const Anope::string &pname = config.ReadValue("privilege", "name", "", i); -class CommandCSVOP : public XOPBase -{ - public: - CommandCSVOP(Module *creator) : XOPBase(creator, "chanserv/vop") - { - this->SetDesc(_("Maintains the VOP (VOicePeople) list for a channel")); - } + Privilege *p = PrivilegeManager::FindPrivilege(pname); + if (p == NULL) + continue; - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoXop(source, params, XOP_VOP); - } + const Anope::string &xop = config.ReadValue("privilege", "xop", "", i); + if (xop.empty()) + continue; - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002VOP\002 (VOicePeople) \002list\002 for a channel.\n" - "The VOP list allows users to be auto-voiced and to voice\n" - "themselves if they aren't.\n" - " \n" - "The \002VOP ADD\002 command adds the given nickname to the\n" - "VOP list.\n" - " \n" - "The \002VOP DEL\002 command removes the given nick from the\n" - "VOP list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002VOP LIST\002 command displays the VOP list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002VOP #channel LIST 2-5,7-9\002\n" - " Lists VOP entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002VOP CLEAR\002 command clears all entries of the\n" - "VOP list.")); - source.Reply(_(" \n" - "The \002VOP ADD\002 and \002VOP DEL\002 commands are limited\n" - "to SOPs or above, while \002VOP LIST\002 is available to VOPs\n" - "and above. The \002VOP CLEAR\002 command can only be used by the\n" - "channel founder.\n" - " \n")); - source.Reply(_("Alternative methods of modifying channel access lists are\n" - "available. See \002%s%s HELP ACCESS\002 for information\n" - "about the access list, and \002%s%s HELP FLAGS\002 for\n" - "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); - return true; - } -}; + permissions[xop].push_back(pname); + } -class CSXOP : public Module -{ - XOPAccessProvider accessprovider; - CommandCSQOP commandcsqop; - CommandCSSOP commandcssop; - CommandCSAOP commandcsaop; - CommandCSHOP commandcshop; - CommandCSVOP commandcsvop; + for (int i = 0; i < config.Enumerate("command"); ++i) + { + const Anope::string &cname = config.ReadValue("command", "name", "", i), + &cserv = config.ReadValue("command", "command", "", i); + if (cname.empty() || cserv != "chanserv/xop") + continue; - public: - CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), - accessprovider(this), commandcsqop(this), commandcssop(this), commandcsaop(this), commandcshop(this), commandcsvop(this) - { - this->SetAuthor("Anope"); - this->SetPermanent(true); + order.push_back(cname); + } } }; diff --git a/src/access.cpp b/src/access.cpp index 7a178b446..6f9a8cd8f 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -16,8 +16,55 @@ #include "users.h" #include "account.h" +static struct +{ + Anope::string name; + Anope::string desc; +} descriptions[] = { + {"ACCESS_CHANGE", _("Allowed to modify the access list")}, + {"ACCESS_LIST", _("Allowed to view the access list")}, + {"AKICK", _("Allowed to use the AKICK command")}, + {"ASSIGN", _("Allowed to assign/unassign a bot")}, + {"AUTOHALFOP", _("Automatic halfop upon join")}, + {"AUTOOP", _("Automatic channel operator status upon join")}, + {"AUTOOWNER", _("Automatic owner upon join")}, + {"AUTOPROTECT", _("Automatic protect upon join")}, + {"AUTOVOICE", _("Automatic voice on join")}, + {"BADWORDS", _("Allowed to modify channel badwords list")}, + {"BAN", _("Allowed to ban users")}, + {"FANTASIA", _("Allowed to use fantasy commands")}, + {"FOUNDER", _("Allowed to issue commands restricted to channel founders")}, + {"GETKEY", _("Allowed to use GETKEY command")}, + {"GREET", _("Greet message displayed on join")}, + {"HALFOP", _("Allowed to (de)halfop users")}, + {"HALFOPME", _("Allowed to (de)halfop him/herself")}, + {"INFO", _("Allowed to get full INFO output")}, + {"INVITE", _("Allowed to use the INVITE command")}, + {"KICK", _("Allowed to use the KICK command")}, + {"MEMO", _("Allowed to read channel memos")}, + {"MODE", _("Allowed to use the MODE command")}, + {"NOKICK", _("Prevents users being kicked by Services")}, + {"OPDEOP", _("Allowed to (de)op users")}, + {"OPDEOPME", _("Allowed to (de)op him/herself")}, + {"OWNER", _("Allowed to (de)owner users")}, + {"OWNERME", _("Allowed to (de)owner him/herself")}, + {"PROTECT", _("Allowed to (de)protect users")}, + {"PROTECTME", _("Allowed to (de)protect him/herself")}, + {"SAY", _("Allowed to use SAY and ACT commands")}, + {"SET", _("Allowed to set channel settings")}, + {"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")}, + {"TOPIC", _("Allowed to change channel topics")}, + {"UNBAN", _("Allowed to unban users")}, + {"VOICE", _("Allowed to (de)voice users")}, + {"VOICEME", _("Allowed to (de)voice him/herself")} +}; + Privilege::Privilege(const Anope::string &n, const Anope::string &d, int r) : name(n), desc(d), rank(r) { + if (this->desc.empty()) + for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j) + if (descriptions[j].name == name) + this->desc = descriptions[j].desc; } bool Privilege::operator==(const Privilege &other) const diff --git a/src/command.cpp b/src/command.cpp index db30a25f3..9d058fefb 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -178,14 +178,14 @@ void Command::RequireUser(bool b) this->require_user = b; } -const Anope::string &Command::GetDesc() const +const Anope::string Command::GetDesc(CommandSource &) const { return this->desc; } void Command::OnServHelp(CommandSource &source) { - source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc().c_str())); + source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str())); } bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; } |