From 700a585b1bb38a9dc0ac3e749083250d405488f8 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 28 Aug 2011 15:46:15 -0400 Subject: Allow modules to add their own channel levels --- data/chanserv.example.conf | 8 +- data/tables.sql | 4 +- include/access.h | 59 +++------ include/anope.h | 22 +++ include/extern.h | 2 - include/modules.h | 8 +- include/regchannel.h | 24 +++- include/services.h | 2 + modules/commands/bs_assign.cpp | 8 +- modules/commands/bs_badwords.cpp | 12 +- modules/commands/bs_control.cpp | 4 +- modules/commands/bs_info.cpp | 2 +- modules/commands/bs_kick.cpp | 8 +- modules/commands/bs_set.cpp | 4 +- modules/commands/cs_access.cpp | 213 ++++++++++++------------------ modules/commands/cs_akick.cpp | 18 +-- modules/commands/cs_appendtopic.cpp | 4 +- modules/commands/cs_ban.cpp | 4 +- modules/commands/cs_clearusers.cpp | 2 +- modules/commands/cs_clone.cpp | 2 +- modules/commands/cs_drop.cpp | 4 +- modules/commands/cs_enforce.cpp | 2 +- modules/commands/cs_flags.cpp | 111 +++++----------- modules/commands/cs_getkey.cpp | 4 +- modules/commands/cs_info.cpp | 2 +- modules/commands/cs_invite.cpp | 2 +- modules/commands/cs_kick.cpp | 4 +- modules/commands/cs_mode.cpp | 6 +- modules/commands/cs_modes.cpp | 24 ++-- modules/commands/cs_saset_noexpire.cpp | 2 +- modules/commands/cs_set_bantype.cpp | 2 +- modules/commands/cs_set_description.cpp | 2 +- modules/commands/cs_set_founder.cpp | 4 +- modules/commands/cs_set_keeptopic.cpp | 2 +- modules/commands/cs_set_misc.cpp | 2 +- modules/commands/cs_set_peace.cpp | 2 +- modules/commands/cs_set_persist.cpp | 2 +- modules/commands/cs_set_private.cpp | 2 +- modules/commands/cs_set_restricted.cpp | 2 +- modules/commands/cs_set_secure.cpp | 2 +- modules/commands/cs_set_securefounder.cpp | 2 +- modules/commands/cs_set_secureops.cpp | 2 +- modules/commands/cs_set_signkick.cpp | 2 +- modules/commands/cs_set_successor.cpp | 4 +- modules/commands/cs_set_topiclock.cpp | 2 +- modules/commands/cs_tban.cpp | 2 +- modules/commands/cs_topic.cpp | 4 +- modules/commands/cs_unban.cpp | 2 +- modules/commands/cs_xop.cpp | 94 ++++++------- modules/commands/ms_del.cpp | 2 +- modules/commands/ms_ignore.cpp | 2 +- modules/commands/ms_info.cpp | 2 +- modules/commands/ms_list.cpp | 2 +- modules/commands/ms_read.cpp | 2 +- modules/commands/ms_set.cpp | 2 +- modules/commands/ns_ajoin.cpp | 4 +- modules/database/db_mysql.cpp | 42 +++--- modules/database/db_plain.cpp | 65 ++------- modules/extra/m_helpchan.cpp | 2 +- modules/extra/m_statusupdate.cpp | 18 +-- modules/pseudoclients/botserv.cpp | 4 +- modules/pseudoclients/memoserv.cpp | 4 +- src/access.cpp | 141 ++++++++++++++++---- src/botserv.cpp | 4 +- src/channels.cpp | 18 +-- src/init.cpp | 1 + src/regchannel.cpp | 28 +++- 67 files changed, 530 insertions(+), 520 deletions(-) diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index cc2bbaef6..d9bd6eb0c 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -184,8 +184,8 @@ chanserv * The level "disabled" is a special level that means the level is disabled, even from people * with founder level access. */ - level_change = 10 - level_list = 1 + level_access_change = 10 + level_access_list = 1 level_akick = 10 level_assign = "founder" level_autohalfop = 4 @@ -226,8 +226,8 @@ chanserv * * These flags are used by the chanserv/flags access system. */ - flag_change = "f" - flag_list = "l" + flag_access_change = "f" + flag_access_list = "l" flag_akick = "K" flag_assign = "s" flag_autohalfop = "H" diff --git a/data/tables.sql b/data/tables.sql index 69e694a32..ec99b7479 100644 --- a/data/tables.sql +++ b/data/tables.sql @@ -140,9 +140,9 @@ CREATE TABLE IF NOT EXISTS `anope_cs_info_metadata` ( CREATE TABLE IF NOT EXISTS `anope_cs_levels` ( `channel` varchar(255) NOT NULL DEFAULT '', - `position` int(11) NOT NULL DEFAULT '0', + `name` varchar(255) NOT NULL DEFAULT '', `level` int(11) NOT NULL DEFAULT '0', - UNIQUE KEY `channel` (`channel`,`position`) + UNIQUE KEY `channel` (`channel`,`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- diff --git a/include/access.h b/include/access.h index 0c730c9ff..6557d40c6 100644 --- a/include/access.h +++ b/include/access.h @@ -1,45 +1,24 @@ #ifndef ACCESS_H #define ACCESS_H -enum ChannelAccess +struct Privilege { - CA_ACCESS_LIST, - CA_NOKICK, - CA_FANTASIA, - CA_GREET, - CA_AUTOVOICE, - CA_VOICEME, - CA_VOICE, - CA_INFO, - CA_SAY, - CA_AUTOHALFOP, - CA_HALFOPME, - CA_HALFOP, - CA_KICK, - CA_SIGNKICK, - CA_BAN, - CA_TOPIC, - CA_MODE, - CA_GETKEY, - CA_INVITE, - CA_UNBAN, - CA_AUTOOP, - CA_OPDEOPME, - CA_OPDEOP, - CA_AUTOPROTECT, - CA_AKICK, - CA_BADWORDS, - CA_ASSIGN, - CA_MEMO, - CA_ACCESS_CHANGE, - CA_PROTECTME, - CA_PROTECT, - CA_SET, - CA_AUTOOWNER, - CA_OWNERME, - CA_OWNER, - CA_FOUNDER, - CA_SIZE + Anope::string name; + Anope::string desc; + + Privilege(const Anope::string &n, const Anope::string &d); + bool operator==(const Privilege &other); +}; + +class PrivilegeManager +{ + static std::vector privs; + public: + static void AddPrivilege(Privilege p, int pos = -1, int def = 0); + static void RemovePrivilege(Privilege &p); + static Privilege *FindPrivilege(const Anope::string &name); + static void Init(); + static std::vector &GetPrivileges(); }; class ChanAccess; @@ -65,7 +44,7 @@ class CoreExport ChanAccess ChanAccess(AccessProvider *p); virtual ~ChanAccess(); virtual bool Matches(User *u, NickCore *nc) = 0; - virtual bool HasPriv(ChannelAccess priv) = 0; + virtual bool HasPriv(const Anope::string &name) = 0; virtual Anope::string Serialize() = 0; virtual void Unserialize(const Anope::string &data) = 0; @@ -82,7 +61,7 @@ class CoreExport AccessGroup : public std::vector NickCore *nc; bool SuperAdmin, Founder; AccessGroup(); - bool HasPriv(ChannelAccess priv) const; + bool HasPriv(const Anope::string &priv) const; ChanAccess *Highest() const; bool operator>(const AccessGroup &other) const; bool operator<(const AccessGroup &other) const; diff --git a/include/anope.h b/include/anope.h index 5eeee0a04..3eec3d4e4 100644 --- a/include/anope.h +++ b/include/anope.h @@ -258,6 +258,28 @@ namespace Anope return new_string; } + /** + * Get the string in lowercase. + */ + inline string lower() + { + Anope::string new_string = *this; + for (size_type i = 0; i < new_string.length(); ++i) + new_string[i] = tolower(new_string[i]); + return new_string; + } + + /** + * Get the string in uppercase. + */ + inline string upper() + { + Anope::string new_string = *this; + for (size_type i = 0; i < new_string.length(); ++i) + new_string[i] = toupper(new_string[i]); + return new_string; + } + /** * Get a substring of the string. */ diff --git a/include/extern.h b/include/extern.h index b62997aad..4b15d81ac 100644 --- a/include/extern.h +++ b/include/extern.h @@ -152,8 +152,6 @@ E bool OnError(const Anope::string &, const std::vector &); /**** misc.c ****/ E bool IsFile(const Anope::string &filename); -E int toupper(char); -E int tolower(char); E time_t dotime(const Anope::string &s); E Anope::string duration(const time_t &seconds, NickCore *nc = NULL); diff --git a/include/modules.h b/include/modules.h index a34b7f64d..f76a1f58a 100644 --- a/include/modules.h +++ b/include/modules.h @@ -662,10 +662,10 @@ class CoreExport Module : public Extensible /** Called when a level for a channel is changed * @param u The user changing the level * @param ci The channel the level was changed on - * @param pos The level position, can be -1 for resetting levels + * @param priv The privilege changed * @param what The new level */ - virtual void OnLevelChange(User *u, ChannelInfo *ci, int pos, int what) { } + virtual void OnLevelChange(User *u, ChannelInfo *ci, const Anope::string &priv, int16 what) { } /** Called when a channel is dropped * @param chname The channel name @@ -751,14 +751,14 @@ class CoreExport Module : public Extensible * @param priv The privilege being checked for * @return EVENT_ALLOW for yes, EVENT_STOP to stop all processing */ - virtual EventReturn OnCheckPriv(ChanAccess *access, ChannelAccess priv) { return EVENT_CONTINUE; } + virtual EventReturn OnCheckPriv(ChanAccess *access, const Anope::string &priv) { return EVENT_CONTINUE; } /** Check whether an access group has a privilege * @param group The group * @param priv The privilege * @return MOD_ALLOW to allow, MOD_STOP to stop */ - virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, ChannelAccess priv) { return EVENT_CONTINUE; } + virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) { return EVENT_CONTINUE; } /** Called when a nick is dropped * @param u The user dropping the nick diff --git a/include/regchannel.h b/include/regchannel.h index 71136a73b..1d071fb0f 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -103,6 +103,7 @@ class CoreExport ChannelInfo : public Extensible, public Flags access; /* List of authorized users */ std::vector akick; /* List of users to kickban */ std::vector badwords; /* List of badwords */ + std::map levels; public: typedef std::multimap ModeList; @@ -134,7 +135,6 @@ class CoreExport ChannelInfo : public Extensible, public Flagsbotflags.HasFlag(BS_NOBOT) || (!ci->AccessFor(u).HasPriv(CA_ASSIGN) && !u->HasPriv("botserv/administration"))) + if (ci->botflags.HasFlag(BS_NOBOT) || (!ci->AccessFor(u).HasPriv("ASSIGN") && !u->HasPriv("botserv/administration"))) { source.Reply(ACCESS_DENIED); return; @@ -67,7 +67,7 @@ class CommandBSAssign : public Command return; } - bool override = !ci->AccessFor(u).HasPriv(CA_ASSIGN); + bool override = !ci->AccessFor(u).HasPriv("ASSIGN"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "for " << bi->nick; bi->Assign(u, ci); @@ -111,7 +111,7 @@ class CommandBSUnassign : public Command return; } - if (!u->HasPriv("botserv/administration") && !ci->AccessFor(u).HasPriv(CA_ASSIGN)) + if (!u->HasPriv("botserv/administration") && !ci->AccessFor(u).HasPriv("ASSIGN")) { source.Reply(ACCESS_DENIED); return; @@ -129,7 +129,7 @@ class CommandBSUnassign : public Command return; } - bool override = !ci->AccessFor(u).HasPriv(CA_ASSIGN); + bool override = !ci->AccessFor(u).HasPriv("ASSIGN"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "for " << ci->bi->nick; ci->bi->UnAssign(u, ci); diff --git a/modules/commands/bs_badwords.cpp b/modules/commands/bs_badwords.cpp index 15298d5eb..db3843cf4 100644 --- a/modules/commands/bs_badwords.cpp +++ b/modules/commands/bs_badwords.cpp @@ -60,7 +60,7 @@ class BadwordsDelCallback : public NumberList public: BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), Deleted(0), override(false) { - if (!ci->AccessFor(source.u).HasPriv(CA_BADWORDS) && source.u->HasPriv("botserv/administration")) + if (!ci->AccessFor(source.u).HasPriv("BADWORDS") && source.u->HasPriv("botserv/administration")) this->override = true; } @@ -90,7 +90,7 @@ class CommandBSBadwords : public Command private: void DoList(CommandSource &source, ChannelInfo *ci, const Anope::string &word) { - bool override = !ci->AccessFor(source.u).HasPriv(CA_BADWORDS); + bool override = !ci->AccessFor(source.u).HasPriv("BADWORDS"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "LIST"; if (!ci->GetBadWordCount()) @@ -167,7 +167,7 @@ class CommandBSBadwords : public Command } } - bool override = !ci->AccessFor(source.u).HasPriv(CA_BADWORDS); + bool override = !ci->AccessFor(source.u).HasPriv("BADWORDS"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "ADD " << realword; ci->AddBadWord(realword, type); @@ -203,7 +203,7 @@ class CommandBSBadwords : public Command return; } - bool override = !ci->AccessFor(source.u).HasPriv(CA_BADWORDS); + bool override = !ci->AccessFor(source.u).HasPriv("BADWORDS"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "DEL " << badword->word; source.Reply(_("\002%s\002 deleted from %s bad words list."), badword->word.c_str(), ci->name.c_str()); @@ -216,7 +216,7 @@ class CommandBSBadwords : public Command void DoClear(CommandSource &source, ChannelInfo *ci) { - bool override = !ci->AccessFor(source.u).HasPriv(CA_BADWORDS); + bool override = !ci->AccessFor(source.u).HasPriv("BADWORDS"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "CLEAR"; ci->ClearBadWords(); @@ -254,7 +254,7 @@ class CommandBSBadwords : public Command } - if (!ci->AccessFor(u).HasPriv(CA_BADWORDS) && (!need_args || !u->HasPriv("botserv/administration"))) + if (!ci->AccessFor(u).HasPriv("BADWORDS") && (!need_args || !u->HasPriv("botserv/administration"))) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/bs_control.cpp b/modules/commands/bs_control.cpp index b464a4520..164542daf 100644 --- a/modules/commands/bs_control.cpp +++ b/modules/commands/bs_control.cpp @@ -35,7 +35,7 @@ class CommandBSSay : public Command return; } - if (!ci->AccessFor(u).HasPriv(CA_SAY)) + if (!ci->AccessFor(u).HasPriv("SAY")) { source.Reply(ACCESS_DENIED); return; @@ -98,7 +98,7 @@ class CommandBSAct : public Command return; } - if (!ci->AccessFor(u).HasPriv(CA_SAY)) + if (!ci->AccessFor(u).HasPriv("SAY")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/bs_info.cpp b/modules/commands/bs_info.cpp index d6668184d..0dbec9e29 100644 --- a/modules/commands/bs_info.cpp +++ b/modules/commands/bs_info.cpp @@ -70,7 +70,7 @@ class CommandBSInfo : public Command } else if ((ci = cs_findchan(query))) { - if (!ci->AccessFor(u).HasPriv(CA_FOUNDER) && !u->HasPriv("botserv/administration")) + if (!ci->AccessFor(u).HasPriv("FOUNDER") && !u->HasPriv("botserv/administration")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index 107e78d64..74ccaf05c 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -41,13 +41,13 @@ class CommandBSKick : public Command this->OnSyntaxError(source, ""); else if (!value.equals_ci("ON") && !value.equals_ci("OFF")) this->OnSyntaxError(source, ""); - else if (!ci->AccessFor(u).HasPriv(CA_SET) && !u->HasPriv("botserv/administration")) + else if (!ci->AccessFor(u).HasPriv("SET") && !u->HasPriv("botserv/administration")) source.Reply(ACCESS_DENIED); else if (!ci->bi) source.Reply(BOT_NOT_ASSIGNED); else { - bool override = !ci->AccessFor(u).HasPriv(CA_SET); + bool override = !ci->AccessFor(u).HasPriv("SET"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << option << " " << value; if (option.equals_ci("BADWORDS")) @@ -767,7 +767,7 @@ class BSKick : public Module return; bool Allow = true; - if (ci->AccessFor(u).HasPriv(CA_NOKICK)) + if (ci->AccessFor(u).HasPriv("NOKICK")) Allow = false; else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (c->HasUserStatus(u, CMODE_HALFOP) || c->HasUserStatus(u, CMODE_OP) || c->HasUserStatus(u, CMODE_PROTECT) || c->HasUserStatus(u, CMODE_OWNER))) Allow = false; @@ -992,7 +992,7 @@ class BSKick : public Module Channel *chan = (*it)->chan; ++it; - if (chan->ci != NULL && chan->ci->botflags.HasFlag(BS_KICK_AMSGS) && !chan->ci->AccessFor(u).HasPriv(CA_NOKICK)) + if (chan->ci != NULL && chan->ci->botflags.HasFlag(BS_KICK_AMSGS) && !chan->ci->AccessFor(u).HasPriv("NOKICK")) { check_ban(chan->ci, u, TTB_AMSGS); bot_kick(chan->ci, u, _("Don't use AMSGs!")); diff --git a/modules/commands/bs_set.cpp b/modules/commands/bs_set.cpp index be699c3e8..b38c05d60 100644 --- a/modules/commands/bs_set.cpp +++ b/modules/commands/bs_set.cpp @@ -59,11 +59,11 @@ class CommandBSSet : public Command } else if (!(ci = cs_findchan(chan))) source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - else if (!u->HasPriv("botserv/administration") && !ci->AccessFor(u).HasPriv(CA_SET)) + else if (!u->HasPriv("botserv/administration") && !ci->AccessFor(u).HasPriv("SET")) source.Reply(ACCESS_DENIED); else { - bool override = !ci->AccessFor(u).HasPriv(CA_SET); + bool override = !ci->AccessFor(u).HasPriv("SET"); Log(override ? LOG_ADMIN : LOG_COMMAND, u, this, ci) << option << " " << value; if (option.equals_ci("DONTKICKOPS")) diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 2dd7da51c..8c3e1a1ca 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -19,57 +19,13 @@ enum ACCESS_FOUNDER = 10001 }; -static struct AccessLevels -{ - ChannelAccess priv; - int default_level; - Anope::string config_name; - Anope::string name; - Anope::string desc; -} defaultLevels[] = { - { CA_ACCESS_CHANGE, 10, "level_change", "ACC-CHANGE", _("Allowed to modify the access list") }, - { CA_ACCESS_LIST, 1, "level_list", "ACC-LIST", _("Allowed to view the access list") }, - { CA_AKICK, 10, "level_akick", "AKICK", _("Allowed to use AKICK command") }, - { CA_ASSIGN, ACCESS_FOUNDER, "level_assign", "ASSIGN", _("Allowed to assign/unassign a bot") }, - { CA_AUTOHALFOP, 4, "level_autohalfop", "AUTOHALFOP", _("Automatic mode +h") }, - { CA_AUTOOP, 5, "level_autoop", "AUTOOP", _("Automatic channel operator status") }, - { CA_AUTOOWNER, 10000, "level_autoowner", "AUTOOWNER", _("Automatic mode +q") }, - { CA_AUTOPROTECT, 10, "level_autoprotect", "AUTOPROTECT", _("Automatic mode +a") }, - { CA_AUTOVOICE, 3, "level_autovoice", "AUTOVOICE", _("Automatic mode +v") }, - { CA_BADWORDS, 10, "level_badwords", "BADWORDS", _("Allowed to modify channel badwords list") }, - { CA_BAN, 4, "level_ban", "BAN", _("Allowed to use ban users") }, - { CA_FANTASIA, 3, "level_fantasia", "FANTASIA", _("Allowed to use fantaisist commands") }, - { CA_FOUNDER, ACCESS_FOUNDER, "level_founder", "FOUNDER", _("Allowed to issue commands restricted to channel founders") }, - { CA_GETKEY, 5, "level_getkey", "GETKEY", _("Allowed to use GETKEY command") }, - { CA_GREET, 5, "level_greet", "GREET", _("Greet message displayed") }, - { CA_HALFOP, 5, "level_halfop", "HALFOP", _("Allowed to (de)halfop users") }, - { CA_HALFOPME, 4, "level_halfopme", "HALFOPME", _("Allowed to (de)halfop him/herself") }, - { CA_INFO, 10000, "level_info", "INFO", _("Allowed to use INFO command with ALL option") }, - { CA_INVITE, 5, "level_invite", "INVITE", _("Allowed to use the INVITE command") }, - { CA_KICK, 4, "level_kick", "KICK", _("Allowed to use the KICK command") }, - { CA_MEMO, 10, "level_memo", "MEMO", _("Allowed to read channel memos") }, - { CA_MODE, 5, "level_mode", "MODE", _("Allowed to change channel modes") }, - { CA_NOKICK, 1, "level_nokick", "NOKICK", _("Never kicked by the bot's kickers") }, - { CA_OPDEOP, 5, "level_opdeop", "OPDEOP", _("Allowed to (de)op users") }, - { CA_OPDEOPME, 5, "level_opdeopme", "OPDEOPME", _("Allowed to (de)op him/herself") }, - { CA_OWNER, ACCESS_FOUNDER, "level_owner", "OWNER", _("Allowed to use (de)owner users") }, - { CA_OWNERME, 10000, "level_ownerme", "OWNERME", _("Allowed to (de)owner him/herself") }, - { CA_PROTECT, 10000, "level_protect", "PROTECT", _("Allowed to (de)protect users") }, - { CA_PROTECTME, 10, "level_protectme", "PROTECTME", _("Allowed to (de)protect him/herself"), }, - { CA_SAY, 5, "level_say", "SAY", _("Allowed to use SAY and ACT commands") }, - { CA_SIGNKICK, ACCESS_FOUNDER, "level_signkick", "SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used") }, - { CA_SET, 10000, "level_set", "SET", _("Allowed to set channel settings") }, - { CA_TOPIC, 5, "level_topic", "TOPIC", _("Allowed to change channel topics") }, - { CA_UNBAN, 4, "level_unban", "UNBAN", _("Allowed to unban users") }, - { CA_VOICE, 4, "level_voice", "VOICE", _("Allowed to (de)voice users") }, - { CA_VOICEME, 3, "level_voiceme", "VOICEME", _("Allowed to (de)voice him/herself") }, - { CA_SIZE, -1, "", "", "" } -}; +static std::map defaultLevels; static void reset_levels(ChannelInfo *ci) { - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) - ci->levels[defaultLevels[i].priv] = defaultLevels[i].default_level; + ci->ClearLevels(); + for (std::map::iterator it = defaultLevels.begin(), it_end = defaultLevels.end(); it != it_end; ++it) + ci->SetLevel(it->first, it->second); } class AccessChanAccess : public ChanAccess @@ -90,12 +46,9 @@ class AccessChanAccess : public ChanAccess return false; } - bool HasPriv(ChannelAccess priv) + bool HasPriv(const Anope::string &name) { - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) - if (defaultLevels[i].priv == priv) - return this->ci->levels[priv] != ACCESS_INVALID && DetermineLevel(this) >= this->ci->levels[priv]; - return false; + return this->ci->GetLevel(name) != ACCESS_INVALID && this->level >= this->ci->GetLevel(name); } Anope::string Serialize() @@ -118,11 +71,18 @@ class AccessChanAccess : public ChanAccess else { int highest = 1; - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) - if (access->ci->levels[defaultLevels[i].priv] > highest && access->HasPriv(defaultLevels[i].priv)) - highest = access->ci->levels[defaultLevels[i].priv]; + const std::vector &privs = PrivilegeManager::GetPrivileges(); + + for (unsigned i = 0; i < privs.size(); ++i) + { + const Privilege &p = privs[i]; + if (access->ci->GetLevel(p.name) > highest && access->HasPriv(p.name)) + highest = access->ci->GetLevel(p.name); + } + if (highest >= ACCESS_FOUNDER) highest = ACCESS_FOUNDER - 1; + return highest; } } @@ -232,7 +192,7 @@ class AccessDelCallback : public NumberList public: AccessDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), Deleted(0), Denied(false) { - if (!ci->AccessFor(source.u).HasPriv(CA_ACCESS_CHANGE) && source.u->HasPriv("chanserv/access/modify")) + if (!ci->AccessFor(source.u).HasPriv("ACCESS_CHANGE") && source.u->HasPriv("chanserv/access/modify")) this->override = true; } @@ -318,7 +278,7 @@ class CommandCSAccess : public Command return; } - bool override = !ci->AccessFor(u).HasPriv(CA_ACCESS_CHANGE) || (level >= u_level && !u_access.Founder); + bool override = !ci->AccessFor(u).HasPriv("ACCESS_CHANGE") || (level >= u_level && !u_access.Founder); if (mask.find_first_of("!*@") == Anope::string::npos && findnick(mask) == NULL) mask += "!*@*"; @@ -395,7 +355,7 @@ class CommandCSAccess : public Command else { source.Reply(_("\002%s\002 deleted from %s access list."), access->mask.c_str(), ci->name.c_str()); - bool override = !u_access.Founder && !u_access.HasPriv(CA_ACCESS_CHANGE) && !access->mask.equals_ci(u->Account()->display); + bool override = !u_access.Founder && !u_access.HasPriv("ACCESS_CHANGE") && !access->mask.equals_ci(u->Account()->display); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << access->mask; FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access)); @@ -544,9 +504,9 @@ class CommandCSAccess : public Command bool has_access = false; if (u->HasPriv("chanserv/access/modify")) has_access = true; - else if (is_list && ci->AccessFor(u).HasPriv(CA_ACCESS_LIST)) + else if (is_list && ci->AccessFor(u).HasPriv("ACCESS_LIST")) has_access = true; - else if (ci->AccessFor(u).HasPriv(CA_ACCESS_CHANGE)) + else if (ci->AccessFor(u).HasPriv("ACCESS_CHANGE")) has_access = true; else if (is_del) { @@ -676,30 +636,23 @@ class CommandCSLevels : public Command source.Reply(_("Level must be between %d and %d inclusive."), ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); else { - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + Privilege *p = PrivilegeManager::FindPrivilege(what); + if (p == NULL) + source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + else { - AccessLevels &l = defaultLevels[i]; + ci->SetLevel(p->name, level); + FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, p->name, level)); - if (what.equals_ci(l.name)) - { - ci->levels[l.priv] = level; - FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, i, level)); - - bool override = !ci->AccessFor(u).HasPriv(CA_FOUNDER); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "SET " << l.name << " to " << level; + bool override = !ci->AccessFor(u).HasPriv("FOUNDER"); + Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "SET " << p->name << " to " << level; - if (level == ACCESS_FOUNDER) - source.Reply(_("Level for %s on channel %s changed to founder only."), l.name.c_str(), ci->name.c_str()); - else - source.Reply(_("Level for \002%s\002 on channel %s changed to \002%d\002."), l.name.c_str(), ci->name.c_str(), level); - return; - } + if (level == ACCESS_FOUNDER) + source.Reply(_("Level for %s on channel %s changed to founder only."), p->name.c_str(), ci->name.c_str()); + else + source.Reply(_("Level for \002%s\002 on channel %s changed to \002%d\002."), p->name.c_str(), ci->name.c_str(), level); } - - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); } - - return; } void DoDisable(CommandSource &source, ChannelInfo *ci, const std::vector ¶ms) @@ -710,22 +663,20 @@ class CommandCSLevels : public Command /* Don't allow disabling of the founder level. It would be hard to change it back if you dont have access to use this command */ if (!what.equals_ci("FOUNDER")) - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + { + Privilege *p = PrivilegeManager::FindPrivilege(what); + if (p != NULL) { - AccessLevels &l = defaultLevels[i]; - - if (what.equals_ci(l.name)) - { - ci->levels[l.priv] = ACCESS_INVALID; - FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, i, l.priv)); + ci->SetLevel(p->name, ACCESS_INVALID); + FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, p->name, ACCESS_INVALID)); - bool override = !ci->AccessFor(u).HasPriv(CA_FOUNDER); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DISABLE " << l.name; + bool override = !ci->AccessFor(u).HasPriv("FOUNDER"); + Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DISABLE " << p->name; - source.Reply(_("\002%s\002 disabled on channel %s."), l.name.c_str(), ci->name.c_str()); - return; - } + source.Reply(_("\002%s\002 disabled on channel %s."), p->name.c_str(), ci->name.c_str()); + return; } + } source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); @@ -736,30 +687,29 @@ class CommandCSLevels : public Command { source.Reply(_("Access level settings for channel %s:"), ci->name.c_str()); + const std::vector &privs = PrivilegeManager::GetPrivileges(); if (!levelinfo_maxwidth) - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - AccessLevels &l = defaultLevels[i]; + const Privilege &p = privs[i]; - int len = l.name.length(); + int len = p.name.length(); if (len > levelinfo_maxwidth) levelinfo_maxwidth = len; } - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - AccessLevels &l = defaultLevels[i]; - int j = ci->levels[l.priv]; + const Privilege &p = privs[i]; + int16 j = ci->GetLevel(p.name); if (j == ACCESS_INVALID) - source.Reply(_(" %-*s (disabled)"), levelinfo_maxwidth, l.name.c_str()); + source.Reply(_(" %-*s (disabled)"), levelinfo_maxwidth, p.name.c_str()); else if (j == ACCESS_FOUNDER) - source.Reply(_(" %-*s (founder only)"), levelinfo_maxwidth, l.name.c_str()); + source.Reply(_(" %-*s (founder only)"), levelinfo_maxwidth, p.name.c_str()); else - source.Reply(_(" %-*s %d"), levelinfo_maxwidth, l.name.c_str(), j); + source.Reply(_(" %-*s %d"), levelinfo_maxwidth, p.name.c_str(), j); } - - return; } void DoReset(CommandSource &source, ChannelInfo *ci) @@ -767,9 +717,9 @@ class CommandCSLevels : public Command User *u = source.u; reset_levels(ci); - FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, -1, 0)); + FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, "ALL", 0)); - bool override = !ci->AccessFor(u).HasPriv(CA_FOUNDER); + bool override = !ci->AccessFor(u).HasPriv("FOUNDER"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "RESET"; source.Reply(_("Access levels for \002%s\002 reset to defaults."), ci->name.c_str()); @@ -806,7 +756,7 @@ class CommandCSLevels : public Command */ if (cmd.equals_ci("SET") ? s.empty() : (cmd.substr(0, 3).equals_ci("DIS") ? (what.empty() || !s.empty()) : !what.empty())) this->OnSyntaxError(source, cmd); - else if (!ci->AccessFor(u).HasPriv(CA_FOUNDER) && !u->HasPriv("chanserv/access/modify")) + else if (!ci->AccessFor(u).HasPriv("FOUNDER") && !u->HasPriv("chanserv/access/modify")) source.Reply(ACCESS_DENIED); else if (cmd.equals_ci("SET")) this->DoSet(source, ci, params); @@ -827,19 +777,20 @@ class CommandCSLevels : public Command if (subcommand.equals_ci("DESC")) { source.Reply(_("The following feature/function names are understood.")); + const std::vector &privs = PrivilegeManager::GetPrivileges(); if (!levelinfo_maxwidth) - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - AccessLevels &l = defaultLevels[i]; + const Privilege &p = privs[i]; - int len = l.name.length(); + int len = p.name.length(); if (len > levelinfo_maxwidth) levelinfo_maxwidth = len; } - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - AccessLevels &l = defaultLevels[i]; - source.Reply(_(" %-*s %s"), levelinfo_maxwidth, l.name.c_str(), translate(source.u, l.desc.c_str())); + const Privilege &p = privs[i]; + source.Reply(_(" %-*s %s"), levelinfo_maxwidth, p.name.c_str(), translate(source.u, p.desc.c_str())); } } else @@ -883,33 +834,41 @@ class CSAccess : public Module this->SetAuthor("Anope"); - Implementation i[] = { I_OnReload, I_OnChanRegistered, I_OnCreateChan, I_OnGroupCheckPriv }; + Implementation i[] = { I_OnReload, I_OnCreateChan, I_OnGroupCheckPriv }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - this->OnReload(); + try + { + this->OnReload(); + } + catch (const ConfigException &ex) + { + throw ModuleException(ex.GetReason()); + } } void OnReload() { + std::vector &privs = PrivilegeManager::GetPrivileges(); + std::map tLevels; ConfigReader config; - for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - AccessLevels &l = defaultLevels[i]; + Privilege &p = privs[i]; - const Anope::string &value = config.ReadValue("chanserv", l.config_name, "", 0); - if (value.equals_ci("founder")) - l.default_level = ACCESS_FOUNDER; + const Anope::string &value = config.ReadValue("chanserv", "level_" + p.name.lower(), "", 0); + if (value.empty()) + throw ConfigException("The value for must not be empty!"); + else if (value.equals_ci("founder")) + tLevels[p.name] = ACCESS_FOUNDER; else if (value.equals_ci("disabled")) - l.default_level = ACCESS_INVALID; + tLevels[p.name] = ACCESS_INVALID; else - l.default_level = config.ReadInteger("chanserv", l.config_name, 0, false); + tLevels[p.name] = config.ReadInteger("chanserv", "level_" + p.name.lower(), 0, false); } - } - void OnChanRegistered(ChannelInfo *ci) - { - reset_levels(ci); + defaultLevels = tLevels; } void OnCreateChan(ChannelInfo *ci) @@ -917,12 +876,12 @@ class CSAccess : public Module reset_levels(ci); } - EventReturn OnGroupCheckPriv(const AccessGroup *group, ChannelAccess priv) + EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) { if (group->ci == NULL) return EVENT_CONTINUE; /* Special case. Allows a level of < 0 to match anyone, and a level of 0 to match anyone identified. */ - int16 level = group->ci->levels[priv]; + int16 level = group->ci->GetLevel(priv); if (level < 0) return EVENT_ALLOW; else if (level == 0 && group->nc) diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp index 594544e22..86c245059 100644 --- a/modules/commands/cs_akick.cpp +++ b/modules/commands/cs_akick.cpp @@ -134,7 +134,7 @@ class AkickDelCallback : public NumberList ~AkickDelCallback() { User *u = source.u; - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, c, ci) << "DEL on " << Deleted << " users"; if (!Deleted) @@ -213,7 +213,7 @@ class CommandCSAKick : public Command AccessGroup nc_access = ci->AccessFor(nc), u_access = ci->AccessFor(u); Entry entry_mask(CMODE_BEGIN, mask); - if ((ci->AccessFor(u2).HasPriv(CA_FOUNDER) || nc_access >= u_access) && entry_mask.Matches(u2)) + if ((ci->AccessFor(u2).HasPriv("FOUNDER") || nc_access >= u_access) && entry_mask.Matches(u2)) { source.Reply(ACCESS_DENIED); return; @@ -260,7 +260,7 @@ class CommandCSAKick : public Command else akick = ci->AddAkick(u->nick, mask, reason); - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << ": " << reason; FOREACH_MOD(I_OnAkickAdd, OnAkickAdd(u, ci, akick)); @@ -309,7 +309,7 @@ class CommandCSAKick : public Command return; } - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << mask; ci->EraseAkick(i); @@ -324,7 +324,7 @@ class CommandCSAKick : public Command const Anope::string &mask = params.size() > 2 ? params[2] : ""; - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "LIST"; if (!ci->GetAkickCount()) @@ -374,7 +374,7 @@ class CommandCSAKick : public Command const Anope::string &mask = params.size() > 2 ? params[2] : ""; - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "VIEW"; if (!ci->GetAkickCount()) @@ -438,7 +438,7 @@ class CommandCSAKick : public Command ++count; } - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ENFORCE, affects " << count << " users"; source.Reply(_("AKICK ENFORCE for \002%s\002 complete; \002%d\002 users were affected."), ci->name.c_str(), count); @@ -447,7 +447,7 @@ class CommandCSAKick : public Command void DoClear(CommandSource &source, ChannelInfo *ci) { User *u = source.u; - bool override = !ci->AccessFor(u).HasPriv(CA_AKICK); + bool override = !ci->AccessFor(u).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "CLEAR"; ci->ClearAkick(); @@ -483,7 +483,7 @@ class CommandCSAKick : public Command if (mask.empty() && (cmd.equals_ci("ADD") || cmd.equals_ci("DEL"))) this->OnSyntaxError(source, cmd); - else if (!ci->AccessFor(u).HasPriv(CA_AKICK) && !u->HasPriv("chanserv/access/modify")) + else if (!ci->AccessFor(u).HasPriv("AKICK") && !u->HasPriv("chanserv/access/modify")) source.Reply(ACCESS_DENIED); else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && readonly) source.Reply(_("Sorry, channel autokick list modification is temporarily disabled.")); diff --git a/modules/commands/cs_appendtopic.cpp b/modules/commands/cs_appendtopic.cpp index bc4db7cba..013e91046 100644 --- a/modules/commands/cs_appendtopic.cpp +++ b/modules/commands/cs_appendtopic.cpp @@ -58,7 +58,7 @@ class CommandCSAppendTopic : public Command source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); else if (!c->ci) source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); - else if (!c->ci->AccessFor(u).HasPriv(CA_TOPIC)) + else if (!c->ci->AccessFor(u).HasPriv("TOPIC")) source.Reply(ACCESS_DENIED); else { @@ -77,7 +77,7 @@ class CommandCSAppendTopic : public Command if (has_topiclock) c->ci->SetFlag(CI_TOPICLOCK); - bool override = c->ci->AccessFor(u).HasPriv(CA_TOPIC); + bool override = c->ci->AccessFor(u).HasPriv("TOPIC"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, c->ci) << "changed topic to " << topic; } return; diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp index 0aae3f9bd..cb4066aca 100644 --- a/modules/commands/cs_ban.cpp +++ b/modules/commands/cs_ban.cpp @@ -46,7 +46,7 @@ class CommandCSBan : public Command source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); else if (!u2) source.Reply(NICK_X_NOT_IN_USE, target.c_str()); - else if (!ci->AccessFor(u).HasPriv(CA_BAN)) + else if (!ci->AccessFor(u).HasPriv("BAN")) source.Reply(ACCESS_DENIED); else if (!is_same && ci->HasFlag(CI_PEACE) && u2_access >= u_access) source.Reply(ACCESS_DENIED); @@ -72,7 +72,7 @@ class CommandCSBan : public Command if (!c->FindUser(u2)) return; - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !ci->AccessFor(u).HasPriv(CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !ci->AccessFor(u).HasPriv("SIGNKICK"))) c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); else c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); diff --git a/modules/commands/cs_clearusers.cpp b/modules/commands/cs_clearusers.cpp index e8f47bac4..b89a68e6e 100644 --- a/modules/commands/cs_clearusers.cpp +++ b/modules/commands/cs_clearusers.cpp @@ -34,7 +34,7 @@ class CommandCSClearUsers : public Command source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); else if (!c->ci) source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); - else if (!c->ci->AccessFor(u).HasPriv(CA_FOUNDER)) + else if (!c->ci->AccessFor(u).HasPriv("FOUNDER")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index 8a242c532..6f67f01a0 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -36,7 +36,7 @@ public: return; } - if (!ci->AccessFor(u).HasPriv(CA_SET)) + if (!ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_drop.cpp b/modules/commands/cs_drop.cpp index 7056f5c35..dd7c9fa2e 100644 --- a/modules/commands/cs_drop.cpp +++ b/modules/commands/cs_drop.cpp @@ -47,7 +47,7 @@ class CommandCSDrop : public Command return; } - if ((ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv(CA_FOUNDER)) && !u->HasCommand("chanserv/drop")) + if ((ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv("FOUNDER")) && !u->HasCommand("chanserv/drop")) { source.Reply(ACCESS_DENIED); return; @@ -56,7 +56,7 @@ class CommandCSDrop : public Command if (ci->c && ModeManager::FindChannelModeByName(CMODE_REGISTERED)) ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); - bool override = (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv(CA_FOUNDER)); + bool override = (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv("FOUNDER")); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "none"); delete ci; diff --git a/modules/commands/cs_enforce.cpp b/modules/commands/cs_enforce.cpp index 78a2a9950..f64c7776d 100644 --- a/modules/commands/cs_enforce.cpp +++ b/modules/commands/cs_enforce.cpp @@ -129,7 +129,7 @@ class CommandCSEnforce : public Command source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); else if (!c->ci) source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); - else if (!c->ci->AccessFor(u).HasPriv(CA_AKICK)) + else if (!c->ci->AccessFor(u).HasPriv("AKICK")) source.Reply(ACCESS_DENIED); else { diff --git a/modules/commands/cs_flags.cpp b/modules/commands/cs_flags.cpp index 8bec73ae0..64ecb7323 100644 --- a/modules/commands/cs_flags.cpp +++ b/modules/commands/cs_flags.cpp @@ -13,51 +13,7 @@ #include "module.h" -static struct FlagLevels -{ - ChannelAccess priv; - char default_char; - Anope::string config_name; - Anope::string desc; -} flagLevels[] = { - { CA_ACCESS_CHANGE, 'f', "flag_change", _("Allowed to modify the access list") }, - { CA_ACCESS_LIST, 'l', "flag_list", _("Allowed to view the access list") }, - { CA_AKICK, 'K', "flag_akick", _("Allowed to use AKICK command") }, - { CA_ASSIGN, 's', "flag_assign", _("Allowed to assign/unassign a bot") }, - { CA_AUTOHALFOP, 'H', "flag_autohalfop", _("Automatic mode +h") }, - { CA_AUTOOP, 'O', "flag_autoop", _("Automatic channel operator status") }, - { CA_AUTOOWNER, 'Q', "flag_autoowner", _("Automatic mode +q") }, - { CA_AUTOPROTECT, 'A', "flag_autoprotect", _("Automatic mode +a") }, - { CA_AUTOVOICE, 'V', "flag_autovoice", _("Automatic mode +v") }, - { CA_BADWORDS, 'k', "flag_badwords", _("Allowed to modify channel badwords list") }, - { CA_BAN, 'b', "flag_ban", _("Allowed to use ban users") }, - { CA_FANTASIA, 'c', "flag_fantasia", _("Allowed to use fantasy commands") }, - { CA_FOUNDER, 'F', "flag_founder", _("Allowed to issue commands restricted to channel founders") }, - { CA_GETKEY, 'G', "flag_getkey", _("Allowed to use GETKEY command") }, - { CA_GREET, 'g', "flag_greet", _("Greet message displayed") }, - { CA_HALFOP, 'h', "flag_halfop", _("Allowed to (de)halfop users") }, - { CA_HALFOPME, 'h', "flag_halfopme", _("Allowed to (de)halfop him/herself") }, - { CA_INFO, 'I', "flag_info", _("Allowed to use INFO command with ALL option") }, - { CA_INVITE, 'i', "flag_invite", _("Allowed to use the INVITE command") }, - { CA_KICK, 'k', "flag_kick", _("Allowed to use the KICK command") }, - { CA_MEMO, 'm', "flag_memo", _("Allowed to read channel memos") }, - { CA_MODE, 's', "flag_mode", _("Allowed to change channel modes") }, - { CA_NOKICK, 'N', "flag_nokick", _("Prevents users being kicked by Services") }, - { CA_OPDEOP, 'o', "flag_opdeop", _("Allowed to (de)op users") }, - { CA_OPDEOPME, 'o', "flag_opdeopme", _("Allowed to (de)op him/herself") }, - { CA_OWNER, 'q', "flag_owner", _("Allowed to use (de)owner users") }, - { CA_OWNERME, 'q', "flag_ownerme", _("Allowed to (de)owner him/herself") }, - { CA_PROTECT, 'a', "flag_protect", _("Allowed to (de)protect users") }, - { CA_PROTECTME, 'a', "flag_protectme", _("Allowed to (de)protect him/herself"), }, - { CA_SAY, 'B', "flag_say", _("Allowed to use SAY and ACT commands") }, - { CA_SET, 's', "flag_set", _("Allowed to set channel settings") }, - { CA_SIGNKICK, 'K', "flag_signkick", _("Prevents kicks from being signed") }, - { CA_TOPIC, 't', "flag_topic", _("Allowed to change channel topics") }, - { CA_UNBAN, 'u', "flag_unban", _("Allowed to unban users") }, - { CA_VOICE, 'v', "flag_voice", _("Allowed to (de)voice users") }, - { CA_VOICEME, 'v', "flag_voiceme", _("Allowed to (de)voice him/herself") }, - { CA_SIZE, -1, "", "" } -}; +static std::map defaultFlags; class FlagsChanAccess : public ChanAccess { @@ -77,12 +33,11 @@ class FlagsChanAccess : public ChanAccess return false; } - bool HasPriv(ChannelAccess priv) + bool HasPriv(const Anope::string &priv) { - for (int i = 0; flagLevels[i].priv != CA_SIZE; ++i) - if (flagLevels[i].priv == priv) - return this->flags.count(flagLevels[i].default_char); - + std::map::iterator it = defaultFlags.find(priv); + if (it != defaultFlags.end() && this->flags.count(it->second) > 0) + return true; return false; } @@ -104,13 +59,9 @@ class FlagsChanAccess : public ChanAccess std::set buffer; - for (int i = 0; flagLevels[i].priv != CA_SIZE; ++i) - { - FlagLevels &l = flagLevels[i]; - - if (access->HasPriv(l.priv)) - buffer.insert(l.default_char); - } + for (std::map::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) + if (access->HasPriv(it->first)) + buffer.insert(it->second); return Anope::string(buffer.begin(), buffer.end()); } @@ -186,10 +137,9 @@ class CommandCSFlags : public Command case '*': if (add == -1) break; - for (int j = 0; flagLevels[j].priv != CA_SIZE; ++j) + for (std::map::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) { - FlagLevels &l = flagLevels[j]; - if (!u_access.HasPriv(l.priv)) + if (!u_access.HasPriv(it->first)) { if (u->HasPriv("chanserv/access/modify")) override = true; @@ -197,20 +147,19 @@ class CommandCSFlags : public Command continue; } if (add == 1) - current_flags.insert(l.default_char); + current_flags.insert(it->second); else if (add == 0) - current_flags.erase(l.default_char); + current_flags.erase(it->second); } break; default: if (add == -1) break; - for (int j = 0; flagLevels[j].priv != CA_SIZE; ++j) + for (std::map::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) { - FlagLevels &l = flagLevels[j]; - if (f != l.default_char) + if (f != it->second) continue; - else if (!u_access.HasPriv(l.priv)) + else if (!u_access.HasPriv(it->first)) { if (u->HasPriv("chanserv/access/modify")) override = true; @@ -361,9 +310,9 @@ class CommandCSFlags : public Command bool has_access = false; if (u->HasPriv("chanserv/access/modify")) has_access = true; - else if (is_list && ci->AccessFor(u).HasPriv(CA_ACCESS_LIST)) + else if (is_list && ci->AccessFor(u).HasPriv("ACCESS_LIST")) has_access = true; - else if (ci->AccessFor(u).HasPriv(CA_ACCESS_CHANGE)) + else if (ci->AccessFor(u).HasPriv("ACCESS_CHANGE")) has_access = true; if (!has_access) @@ -403,13 +352,17 @@ class CommandCSFlags : public Command source.Reply(" "); source.Reply(_("The available flags are:")); - std::multimap > levels; - for (int i = 0; flagLevels[i].priv != CA_SIZE; ++i) - levels.insert(std::make_pair(flagLevels[i].default_char, &flagLevels[i])); - for (std::multimap >::iterator it = levels.begin(), it_end = levels.end(); it != it_end; ++it) + typedef std::multimap > reverse_map; + reverse_map reverse; + for (std::map::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) + reverse.insert(std::make_pair(it->second, it->first)); + + for (reverse_map::iterator it = reverse.begin(), it_end = reverse.end(); it != it_end; ++it) { - FlagLevels *l = it->second; - source.Reply(" %c - %s", l->default_char, translate(source.u->Account(), l->desc.c_str())); + Privilege *p = PrivilegeManager::FindPrivilege(it->second); + if (p == NULL) + continue; + source.Reply(" %c - %s", it->first, translate(source.u->Account(), p->desc.c_str())); } return true; @@ -437,15 +390,15 @@ class CSFlags : public Module void OnReload() { ConfigReader config; + std::vector &privs = PrivilegeManager::GetPrivileges(); - for (int i = 0; flagLevels[i].priv != CA_SIZE; ++i) + for (unsigned i = 0; i < privs.size(); ++i) { - FlagLevels &l = flagLevels[i]; - - const Anope::string &value = config.ReadValue("chanserv", l.config_name, "", 0); + Privilege &p = privs[i]; + const Anope::string &value = config.ReadValue("chanserv", "flag_" + p.name, "", 0); if (value.empty()) continue; - l.default_char = value[0]; + defaultFlags[p.name] = value[0]; } } }; diff --git a/modules/commands/cs_getkey.cpp b/modules/commands/cs_getkey.cpp index cfb148134..680745170 100644 --- a/modules/commands/cs_getkey.cpp +++ b/modules/commands/cs_getkey.cpp @@ -35,7 +35,7 @@ class CommandCSGetKey : public Command } - if (!ci->AccessFor(u).HasPriv(CA_GETKEY) && !u->HasCommand("chanserv/getkey")) + if (!ci->AccessFor(u).HasPriv("GETKEY") && !u->HasCommand("chanserv/getkey")) { source.Reply(ACCESS_DENIED); return; @@ -48,7 +48,7 @@ class CommandCSGetKey : public Command return; } - bool override = !ci->AccessFor(u).HasPriv(CA_GETKEY); + bool override = !ci->AccessFor(u).HasPriv("GETKEY"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci); source.Reply(_("Key for channel \002%s\002 is \002%s\002."), chan.c_str(), key.c_str()); diff --git a/modules/commands/cs_info.cpp b/modules/commands/cs_info.cpp index 54f14cd0c..5fc85666a 100644 --- a/modules/commands/cs_info.cpp +++ b/modules/commands/cs_info.cpp @@ -50,7 +50,7 @@ class CommandCSInfo : public Command bool show_all = false; /* Should we show all fields? Only for sadmins and identified users */ - if (has_auspex || ci->AccessFor(u).HasPriv(CA_INFO)) + if (has_auspex || ci->AccessFor(u).HasPriv("INFO")) show_all = true; source.Reply(CHAN_INFO_HEADER, chan.c_str()); diff --git a/modules/commands/cs_invite.cpp b/modules/commands/cs_invite.cpp index f6ed44685..122171b90 100644 --- a/modules/commands/cs_invite.cpp +++ b/modules/commands/cs_invite.cpp @@ -42,7 +42,7 @@ class CommandCSInvite : public Command return; } - if (!ci->AccessFor(u).HasPriv(CA_INVITE)) + if (!ci->AccessFor(u).HasPriv("INVITE")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp index b9c0f7b41..c00025671 100644 --- a/modules/commands/cs_kick.cpp +++ b/modules/commands/cs_kick.cpp @@ -42,7 +42,7 @@ class CommandCSKick : public Command source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); else if (!u2) source.Reply(NICK_X_NOT_IN_USE, target.c_str()); - else if (!ci->AccessFor(u).HasPriv(CA_KICK)) + else if (!ci->AccessFor(u).HasPriv("KICK")) source.Reply(ACCESS_DENIED); else if (!is_same && (ci->HasFlag(CI_PEACE)) && u2_access >= u_access) source.Reply(ACCESS_DENIED); @@ -55,7 +55,7 @@ class CommandCSKick : public Command // XXX Log(LOG_COMMAND, u, this, ci) << "for " << u2->nick; - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !ci->AccessFor(u).HasPriv(CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !ci->AccessFor(u).HasPriv("SIGNKICK"))) ci->c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); else ci->c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index 3e4ed784c..a36e68690 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -20,13 +20,13 @@ class CommandCSMode : public Command if (!u || !ci || !cm || cm->Type != MODE_STATUS) return false; - const ChannelAccess accesses[] = { CA_VOICE, CA_HALFOP, CA_OPDEOP, CA_PROTECT, CA_OWNER, CA_SIZE }; + const Anope::string accesses[] = { "VOICE", "HALFOP", "OPDEOP", "PROTECT", "OWNER", "" }; const ChannelModeName modes[] = { CMODE_VOICE, CMODE_HALFOP, CMODE_OP, CMODE_PROTECT, CMODE_OWNER }; ChannelModeStatus *cms = debug_cast(cm); AccessGroup access = ci->AccessFor(u); unsigned short u_level = 0; - for (int i = 0; accesses[i] != CA_SIZE; ++i) + for (int i = 0; !accesses[i].empty(); ++i) if (access.HasPriv(accesses[i])) { ChannelMode *cm2 = ModeManager::FindChannelModeByName(modes[i]); @@ -319,7 +319,7 @@ class CommandCSMode : public Command if (!ci || !ci->c) source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); - else if (!ci->AccessFor(u).HasPriv(CA_MODE) && !u->HasCommand("chanserv/mode")) + else if (!ci->AccessFor(u).HasPriv("MODE") && !u->HasCommand("chanserv/mode")) source.Reply(ACCESS_DENIED); else if (subcommand.equals_ci("LOCK")) this->DoLock(source, ci, params); diff --git a/modules/commands/cs_modes.cpp b/modules/commands/cs_modes.cpp index fb2fcb727..a393ecaf9 100644 --- a/modules/commands/cs_modes.cpp +++ b/modules/commands/cs_modes.cpp @@ -15,7 +15,7 @@ class CommandModeBase : public Command { - void do_mode(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, ChannelAccess level, ChannelAccess levelself) + void do_mode(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, const Anope::string &level, const Anope::string &levelself) { User *u = source.u; User *u2 = finduser(nick); @@ -62,7 +62,7 @@ class CommandModeBase : public Command * @param level The acecss level required to set this mode on someone else * @param levelself The access level required to set this mode on yourself */ - void do_util(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, ChannelAccess level, ChannelAccess levelself) + void do_util(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, const Anope::string &level, const Anope::string &levelself) { User *u = source.u; @@ -94,7 +94,7 @@ class CommandCSOp : public CommandModeBase { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OP); - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_OPDEOP, CA_OPDEOPME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, "OPDEOP", "OPDEOPME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -123,7 +123,7 @@ class CommandCSDeOp : public CommandModeBase { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OP); - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_OPDEOP, CA_OPDEOPME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, "OPDEOP", "OPDEOPME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -152,7 +152,7 @@ class CommandCSVoice : public CommandModeBase { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_VOICE); - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_VOICE, CA_VOICEME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, "VOICE", "VOICEME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -182,7 +182,7 @@ class CommandCSDeVoice : public CommandModeBase { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_VOICE); - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_VOICE, CA_VOICEME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, "VOICE", "VOICEME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -215,7 +215,7 @@ class CommandCSHalfOp : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_HALFOP, CA_HALFOPME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, "HALFOP", "HALFOPME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -247,7 +247,7 @@ class CommandCSDeHalfOp : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_HALFOP, CA_HALFOPME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, "HALFOP", "HALFOPME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -280,7 +280,7 @@ class CommandCSProtect : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_PROTECT, CA_PROTECTME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, "PROTECT", "PROTECTME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -312,7 +312,7 @@ class CommandCSDeProtect : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_PROTECT, CA_PROTECTME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, "PROTECT", "PROTECTME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -343,7 +343,7 @@ class CommandCSOwner : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_OWNER, CA_OWNERME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, "OWNER", "OWNERME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -374,7 +374,7 @@ class CommandCSDeOwner : public CommandModeBase if (!cm) return; - return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_OWNER, CA_OWNERME); + return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, "OWNER", "OWNERME"); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) diff --git a/modules/commands/cs_saset_noexpire.cpp b/modules/commands/cs_saset_noexpire.cpp index 1f645304a..52754215a 100644 --- a/modules/commands/cs_saset_noexpire.cpp +++ b/modules/commands/cs_saset_noexpire.cpp @@ -32,7 +32,7 @@ class CommandCSSASetNoexpire : public Command return; } - if (source.permission.empty() && !ci->AccessFor(u).HasPriv(CA_SET)) + if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_bantype.cpp b/modules/commands/cs_set_bantype.cpp index 468a3cb86..afc15963b 100644 --- a/modules/commands/cs_set_bantype.cpp +++ b/modules/commands/cs_set_bantype.cpp @@ -32,7 +32,7 @@ class CommandCSSetBanType : public Command return; } - if (source.permission.empty() && !ci->AccessFor(u).HasPriv(CA_SET)) + if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_description.cpp b/modules/commands/cs_set_description.cpp index acd30e68b..d65731273 100644 --- a/modules/commands/cs_set_description.cpp +++ b/modules/commands/cs_set_description.cpp @@ -32,7 +32,7 @@ class CommandCSSetDescription : public Command return; } - if (source.permission.empty() && !ci->AccessFor(u).HasPriv(CA_SET)) + if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_founder.cpp b/modules/commands/cs_set_founder.cpp index ac7ece637..7ef553a78 100644 --- a/modules/commands/cs_set_founder.cpp +++ b/modules/commands/cs_set_founder.cpp @@ -32,13 +32,13 @@ class CommandCSSetFounder : public Command return; } - if (source.permission.empty() && !ci->AccessFor(u).HasPriv(CA_SET)) + if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; } - if (source.permission.empty() && (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv(CA_FOUNDER))) + if (source.permission.empty() && (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv("FOUNDER"))) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_keeptopic.cpp b/modules/commands/cs_set_keeptopic.cpp index 58c88a73c..5227cde21 100644 --- a/modules/commands/cs_set_keeptopic.cpp +++ b/modules/commands/cs_set_keeptopic.cpp @@ -32,7 +32,7 @@ class CommandCSSetKeepTopic : public Command return; } - if (source.permission.empty() && !ci->AccessFor(u).HasPriv(CA_SET)) + if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp index a64bbf6ea..