diff options
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<Privilege> 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<Privilege> &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<ChanAccess *> 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 @@ -259,6 +259,28 @@ namespace Anope } /** + * 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. */ inline string substr(size_type pos = 0, size_type n = npos) const { return string(this->_string.substr(pos, n)); } 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<Anope::string> &); /**** 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<ChannelInfoFlag, std::vector<ChanAccess *> access; /* List of authorized users */ std::vector<AutoKick *> akick; /* List of users to kickban */ std::vector<BadWord *> badwords; /* List of badwords */ + std::map<Anope::string, int16> levels; public: typedef std::multimap<ChannelModeName, ModeLock> ModeList; @@ -134,7 +135,6 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag, time_t last_topic_time; /* Time */ int16 bantype; - int16 levels[CA_SIZE]; MemoInfo memos; @@ -345,6 +345,28 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag, * and after uplink sync */ void RestoreTopic(); + + /** Get the level for a privilege + * @param priv The privilege name + * @return the level + * @throws CoreException if priv is not a valid privilege + */ + int16 GetLevel(const Anope::string &priv); + + /** Set the level for a privilege + * @param priv The privilege priv + * @param level The new level + */ + void SetLevel(const Anope::string &priv, int16 level); + + /** Remove a privilege from the channel + * @param priv The privilege + */ + void RemoveLevel(const Anope::string &priv); + + /** Clear all privileges from the channel + */ + void ClearLevels(); }; /** A timer used to keep the BotServ bot/ChanServ in the channel diff --git a/include/services.h b/include/services.h index d6db4e9ed..3a7ff65c2 100644 --- a/include/services.h +++ b/include/services.h @@ -98,6 +98,8 @@ extern int strncasecmp(const char *, const char *, size_t); #undef toupper #define tolower tolower_ #define toupper toupper_ +extern int toupper(char); +extern int tolower(char); /** This definition is used as shorthand for the various classes * and functions needed to make a module loadable by the OS. diff --git a/modules/commands/bs_assign.cpp b/modules/commands/bs_assign.cpp index 13f3e4403..64ae9064d 100644 --- a/modules/commands/bs_assign.cpp +++ b/modules/commands/bs_assign.cpp @@ -49,7 +49,7 @@ class CommandBSAssign : public Command return; } - if (ci->botflags.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<Anope::string, int16> 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<Anope::string, int16>::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<Privilege> &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<Anope::string> ¶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<Privilege> &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<Privilege> &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<Privilege> &privs = PrivilegeManager::GetPrivileges(); + std::map<Anope::string, int16> 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 <chanserv:level_" + p.name.lower() + "> 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<Anope::string, char> 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<Anope::string, char>::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<char> 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<Anope::string, char>::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<Anope::string, char>::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<Anope::string, char>::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<char, FlagLevels *, std::less<ci::string> > 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<char, FlagLevels *, std::less<ci::string> >::iterator it = levels.begin(), it_end = levels.end(); it != it_end; ++it) + typedef std::multimap<char, Anope::string, std::less<ci::string> > reverse_map; + reverse_map reverse; + for (std::map<Anope::string, char>::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<Privilege> &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<ChannelModeStatus *>(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..61c8c163b 100644 --- a/modules/commands/cs_set_misc.cpp +++ b/modules/commands/cs_set_misc.cpp @@ -28,7 +28,7 @@ class CommandCSSetMisc : public Command source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); return; } - else if (source.permission.empty() && !ci->AccessFor(source.u).HasPriv(CA_SET)) + else if (source.permission.empty() && !ci->AccessFor(source.u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_set_peace.cpp b/modules/commands/cs_set_peace.cpp index a5bdd7cd5..32a452ddd 100644 --- a/modules/commands/cs_set_peace.cpp +++ b/modules/commands/cs_set_peace.cpp @@ -32,7 +32,7 @@ class CommandCSSetPeace : 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_persist.cpp b/modules/commands/cs_set_persist.cpp index 000389ef1..22766d1f5 100644 --- a/modules/commands/cs_set_persist.cpp +++ b/modules/commands/cs_set_persist.cpp @@ -32,7 +32,7 @@ class CommandCSSetPersist : 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_private.cpp b/modules/commands/cs_set_private.cpp index 39fd8b414..9902e765d 100644 --- a/modules/commands/cs_set_private.cpp +++ b/modules/commands/cs_set_private.cpp @@ -32,7 +32,7 @@ class CommandCSSetPrivate : 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_restricted.cpp b/modules/commands/cs_set_restricted.cpp index bc04297f1..afddff5f9 100644 --- a/modules/commands/cs_set_restricted.cpp +++ b/modules/commands/cs_set_restricted.cpp @@ -31,7 +31,7 @@ class CommandCSSetRestricted : 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_secure.cpp b/modules/commands/cs_set_secure.cpp index 63671588b..1980a9d1e 100644 --- a/modules/commands/cs_set_secure.cpp +++ b/modules/commands/cs_set_secure.cpp @@ -32,7 +32,7 @@ class CommandCSSetSecure : 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_securefounder.cpp b/modules/commands/cs_set_securefounder.cpp index 746555814..5a41c8ec6 100644 --- a/modules/commands/cs_set_securefounder.cpp +++ b/modules/commands/cs_set_securefounder.cpp @@ -33,7 +33,7 @@ class CommandCSSetSecureFounder : public Command } - 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_secureops.cpp b/modules/commands/cs_set_secureops.cpp index 3dcc7b301..1a8b04807 100644 --- a/modules/commands/cs_set_secureops.cpp +++ b/modules/commands/cs_set_secureops.cpp @@ -32,7 +32,7 @@ class CommandCSSetSecureOps : 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_signkick.cpp b/modules/commands/cs_set_signkick.cpp index 3a4177b83..0eb372141 100644 --- a/modules/commands/cs_set_signkick.cpp +++ b/modules/commands/cs_set_signkick.cpp @@ -32,7 +32,7 @@ class CommandCSSetSignKick : 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_successor.cpp b/modules/commands/cs_set_successor.cpp index efd09bb6d..c670df15e 100644 --- a/modules/commands/cs_set_successor.cpp +++ b/modules/commands/cs_set_successor.cpp @@ -32,13 +32,13 @@ class CommandCSSetSuccessor : 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_topiclock.cpp b/modules/commands/cs_set_topiclock.cpp index 02f9151a0..67aa243e1 100644 --- a/modules/commands/cs_set_topiclock.cpp +++ b/modules/commands/cs_set_topiclock.cpp @@ -32,7 +32,7 @@ class CommandCSSetTopicLock : 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_tban.cpp b/modules/commands/cs_tban.cpp index 0e7b8978e..b7d1399fa 100644 --- a/modules/commands/cs_tban.cpp +++ b/modules/commands/cs_tban.cpp @@ -40,7 +40,7 @@ static bool CanBanUser(CommandSource &source, Channel *c, User *u2) User *u = source.u; ChannelInfo *ci = c->ci; bool ok = false; - if (!ci->AccessFor(u).HasPriv(CA_BAN)) + if (!ci->AccessFor(u).HasPriv("BAN")) source.Reply(ACCESS_DENIED); else if (matches_list(c, u2, CMODE_EXCEPT)) source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str()); diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp index a55c969f7..2210aed01 100644 --- a/modules/commands/cs_topic.cpp +++ b/modules/commands/cs_topic.cpp @@ -37,7 +37,7 @@ class CommandCSTopic : public Command if (!ci->c) source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - else if (!ci->AccessFor(u).HasPriv(CA_TOPIC) && !u->HasCommand("chanserv/topic")) + else if (!ci->AccessFor(u).HasPriv("TOPIC") && !u->HasCommand("chanserv/topic")) source.Reply(ACCESS_DENIED); else { @@ -47,7 +47,7 @@ class CommandCSTopic : public Command if (has_topiclock) ci->SetFlag(CI_TOPICLOCK); - bool override = !ci->AccessFor(u).HasPriv(CA_TOPIC); + bool override = !ci->AccessFor(u).HasPriv("TOPIC"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "to change the topic to " << (!topic.empty() ? topic : "No topic"); } return; diff --git a/modules/commands/cs_unban.cpp b/modules/commands/cs_unban.cpp index c78b3a7d1..8d6357745 100644 --- a/modules/commands/cs_unban.cpp +++ b/modules/commands/cs_unban.cpp @@ -39,7 +39,7 @@ class CommandCSUnban : public Command return; } - if (!ci->AccessFor(u).HasPriv(CA_UNBAN)) + if (!ci->AccessFor(u).HasPriv("UNBAN")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/cs_xop.cpp b/modules/commands/cs_xop.cpp index 27f200b9b..b2aaffde6 100644 --- a/modules/commands/cs_xop.cpp +++ b/modules/commands/cs_xop.cpp @@ -27,63 +27,63 @@ static struct XOPAccess { XOPType type; Anope::string name; - ChannelAccess access[CA_SIZE]; + Anope::string access[10]; } xopAccess[] = { { XOP_QOP, "QOP", { - CA_SIGNKICK, - CA_SET, - CA_AUTOOWNER, - CA_OWNERME, - CA_PROTECT, - CA_INFO, - CA_ASSIGN, - CA_TOPIC, - CA_SIZE + "SIGNKICK", + "SET", + "AUTOOWNER", + "OWNERME", + "PROTECT", + "INFO", + "ASSIGN", + "TOPIC", + "" } }, { XOP_SOP, "SOP", { - CA_AUTOPROTECT, - CA_AKICK, - CA_BADWORDS, - CA_MEMO, - CA_ACCESS_CHANGE, - CA_PROTECTME, - CA_OPDEOP, - CA_SIZE + "AUTOPROTECT", + "AKICK", + "BADWORDS", + "MEMO", + "ACCESS_CHANGE", + "PROTECTME", + "OPDEOP", + "" } }, { XOP_AOP, "AOP", { - CA_MODE, - CA_GETKEY, - CA_INVITE, - CA_UNBAN, - CA_AUTOOP, - CA_OPDEOPME, - CA_HALFOP, - CA_SAY, - CA_NOKICK, - CA_SIZE + "MODE", + "GETKEY", + "INVITE", + "UNBAN", + "AUTOOP", + "OPDEOPME", + "HALFOP", + "SAY", + "NOKICK", + "" } }, { XOP_HOP, "HOP", { - CA_AUTOHALFOP, - CA_HALFOPME, - CA_KICK, - CA_BAN, - CA_FANTASIA, - CA_SIZE + "AUTOHALFOP", + "HALFOPME", + "KICK", + "BAN", + "FANTASIA", + "" } }, { XOP_VOP, "VOP", { - CA_AUTOVOICE, - CA_VOICEME, - CA_ACCESS_LIST, - CA_SIZE + "AUTOVOICE", + "VOICEME", + "ACCESS_LIST", + "" } }, { XOP_UNKNOWN, "", { } @@ -108,7 +108,7 @@ class XOPChanAccess : public ChanAccess return false; } - bool HasPriv(ChannelAccess priv) + bool HasPriv(const Anope::string &priv) { for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i) { @@ -117,7 +117,7 @@ class XOPChanAccess : public ChanAccess if (this->type > x.type) continue; - for (int j = 0; x.access[j] != CA_SIZE; ++j) + for (int j = 0; !x.access[j].empty(); ++j) if (x.access[j] == priv) return true; } @@ -171,7 +171,7 @@ class XOPChanAccess : public ChanAccess { XOPAccess &x = xopAccess[i]; - for (int j = 0; x.access[j] != CA_SIZE; ++j) + for (int j = 0; !x.access[j].empty(); ++j) if (access->HasPriv(x.access[j])) ++count[x.type]; } @@ -316,7 +316,7 @@ class XOPBase : public Command ChanAccess *highest = access.Highest(); int u_level = (highest ? XOPChanAccess::DetermineLevel(highest) : 0); - if ((!access.Founder && !access.HasPriv(CA_ACCESS_CHANGE) && !u->HasPriv("chanserv/access/modify")) || (level <= u_level && !access.Founder)) + if ((!access.Founder && !access.HasPriv("ACCESS_CHANGE") && !u->HasPriv("chanserv/access/modify")) || (level <= u_level && !access.Founder)) { source.Reply(ACCESS_DENIED); return; @@ -360,7 +360,7 @@ class XOPBase : public Command acc->created = Anope::CurTime; ci->AddAccess(acc); - bool override = (level >= u_level && !access.Founder) || !access.HasPriv(CA_ACCESS_CHANGE); + bool override = (level >= u_level && !access.Founder) || !access.HasPriv("ACCESS_CHANGE"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask; FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, acc)); @@ -394,7 +394,7 @@ class XOPBase : public Command AccessGroup access = ci->AccessFor(u); ChanAccess *highest = access.Highest(); bool override = false; - if ((!mask.equals_ci(u->Account()->display) && !access.HasPriv(CA_ACCESS_CHANGE) && !access.Founder) || ((!highest || level <= XOPChanAccess::DetermineLevel(highest)) && !access.Founder)) + if ((!mask.equals_ci(u->Account()->display) && !access.HasPriv("ACCESS_CHANGE") && !access.Founder) || ((!highest || level <= XOPChanAccess::DetermineLevel(highest)) && !access.Founder)) { if (u->HasPriv("chanserv/access/modify")) override = true; @@ -443,7 +443,7 @@ class XOPBase : public Command AccessGroup access = ci->AccessFor(u); bool override = false; - if (!access.HasPriv(CA_ACCESS_LIST)) + if (!access.HasPriv("ACCESS_LIST")) { if (u->HasCommand("chanserv/access/list")) override = true; @@ -512,13 +512,13 @@ class XOPBase : public Command return; } - if (!ci->AccessFor(u).HasPriv(CA_FOUNDER) && !u->HasPriv("chanserv/access/modify")) + if (!ci->AccessFor(u).HasPriv("FOUNDER") && !u->HasPriv("chanserv/access/modify")) { source.Reply(ACCESS_DENIED); return; } - bool override = !ci->AccessFor(u).HasPriv(CA_FOUNDER); + bool override = !ci->AccessFor(u).HasPriv("FOUNDER"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "CLEAR"; for (unsigned i = ci->GetAccessCount(); i > 0; --i) diff --git a/modules/commands/ms_del.cpp b/modules/commands/ms_del.cpp index 8f75b0da9..d1aeaa4d1 100644 --- a/modules/commands/ms_del.cpp +++ b/modules/commands/ms_del.cpp @@ -70,7 +70,7 @@ class CommandMSDel : public Command source.Reply(READ_ONLY_MODE); return; } - else if (!ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (!ci->AccessFor(u).HasPriv("MEMO")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/ms_ignore.cpp b/modules/commands/ms_ignore.cpp index b0c6cfd4f..cfb863ebb 100644 --- a/modules/commands/ms_ignore.cpp +++ b/modules/commands/ms_ignore.cpp @@ -43,7 +43,7 @@ class CommandMSIgnore : public Command ChannelInfo *ci = cs_findchan(channel); if (!mi) source.Reply(ischan ? CHAN_X_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), channel.c_str()); - else if (ischan && !ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (ischan && !ci->AccessFor(u).HasPriv("MEMO")) source.Reply(ACCESS_DENIED); else if (command.equals_ci("ADD") && !param.empty()) { diff --git a/modules/commands/ms_info.cpp b/modules/commands/ms_info.cpp index 741be799a..03df6d973 100644 --- a/modules/commands/ms_info.cpp +++ b/modules/commands/ms_info.cpp @@ -50,7 +50,7 @@ class CommandMSInfo : public Command source.Reply(CHAN_X_NOT_REGISTERED, nname.c_str()); return; } - else if (!ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (!ci->AccessFor(u).HasPriv("MEMO")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/ms_list.cpp b/modules/commands/ms_list.cpp index e6d7a691d..9087ad2c5 100644 --- a/modules/commands/ms_list.cpp +++ b/modules/commands/ms_list.cpp @@ -74,7 +74,7 @@ class CommandMSList : public Command source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); return; } - else if (!ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (!ci->AccessFor(u).HasPriv("MEMO")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/ms_read.cpp b/modules/commands/ms_read.cpp index 87a5cb648..779a0c759 100644 --- a/modules/commands/ms_read.cpp +++ b/modules/commands/ms_read.cpp @@ -109,7 +109,7 @@ class CommandMSRead : public Command source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); return; } - else if (!ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (!ci->AccessFor(u).HasPriv("MEMO")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/ms_set.cpp b/modules/commands/ms_set.cpp index a4fef31a8..ef3480fd5 100644 --- a/modules/commands/ms_set.cpp +++ b/modules/commands/ms_set.cpp @@ -91,7 +91,7 @@ class CommandMSSet : public Command source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); return; } - else if (!is_servadmin && !ci->AccessFor(u).HasPriv(CA_MEMO)) + else if (!is_servadmin && !ci->AccessFor(u).HasPriv("MEMO")) { source.Reply(ACCESS_DENIED); return; diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp index ca7b656a6..bed0442d7 100644 --- a/modules/commands/ns_ajoin.cpp +++ b/modules/commands/ns_ajoin.cpp @@ -165,7 +165,7 @@ class NSAJoin : public Module Anope::string k; if (c->GetParam(CMODE_KEY, k)) { - if (ci->AccessFor(u).HasPriv(CA_GETKEY)) + if (ci->AccessFor(u).HasPriv("GETKEY")) key = k; else if (key != k) need_invite = true; @@ -190,7 +190,7 @@ class NSAJoin : public Module if (need_invite) { BotInfo *bi = findbot(Config->NickServ); - if (!bi || !ci->AccessFor(u).HasPriv(CA_INVITE)) + if (!bi || !ci->AccessFor(u).HasPriv("INVITE")) continue; ircdproto->SendInvite(bi, channels[i].first, u->nick); } diff --git a/modules/database/db_mysql.cpp b/modules/database/db_mysql.cpp index a90276274..163bb5a44 100644 --- a/modules/database/db_mysql.cpp +++ b/modules/database/db_mysql.cpp @@ -482,7 +482,7 @@ class DBMySQL : public Module continue; } - ci->levels[atoi(r.Get(i, "position").c_str())] = atoi(r.Get(i, "level").c_str()); + ci->SetLevel(r.Get(i, "name"), atoi(r.Get(i, "level").c_str())); } query = "SELECT * FROM `anope_cs_info_metadata`"; @@ -792,7 +792,7 @@ class DBMySQL : public Module ChannelInfo *ci = cs_findchan(params[0]); if (!ci) return; - if (!ci->AccessFor(u).HasPriv(CA_SET) && !u->HasPriv("botserv/administration")) + if (!ci->AccessFor(u).HasPriv("SET") && !u->HasPriv("botserv/administration")) return; if (params[1].equals_ci("BADWORDS") || params[1].equals_ci("BOLDS") || params[1].equals_ci("CAPS") || params[1].equals_ci("COLORS") || params[1].equals_ci("FLOOD") || params[1].equals_ci("REPEAT") || params[1].equals_ci("REVERSES") || params[1].equals_ci("UNDERLINES")) { @@ -843,7 +843,7 @@ class DBMySQL : public Module else if (command->name == "botserv/set" && params.size() > 1) { ChannelInfo *ci = cs_findchan(params[0]); - if (ci && !ci->AccessFor(u).HasPriv(CA_SET) && !u->HasPriv("botserv/administration")) + if (ci && !ci->AccessFor(u).HasPriv("SET") && !u->HasPriv("botserv/administration")) return; BotInfo *bi = NULL; if (!ci) @@ -880,7 +880,7 @@ class DBMySQL : public Module else { ci = cs_findchan(target); - if (!ci || !ci->AccessFor(u).HasPriv(CA_MEMO)) + if (!ci || !ci->AccessFor(u).HasPriv("MEMO")) return; } @@ -1029,27 +1029,27 @@ class DBMySQL : public Module this->RunQuery(query); } - void OnLevelChange(User *u, ChannelInfo *ci, int pos, int what) + void OnLevelChange(User *u, ChannelInfo *ci, const Anope::string &priv, int16 what) { - if (pos >= 0) - { - SQLQuery query("UPDATE `anope_cs_levels` SET `level` = @level WHERE `channel` = @channel AND `position` = @pos"); - query.setValue("level", what); - query.setValue("channel", ci->name); - query.setValue("pos", pos); - this->RunQuery(query); - } - else + SQLQuery query("UPDATE `anope_cs_levels` SET `level` = @level WHERE `channel` = @channel AND `name` = @name ON DUPLICATE KEY UPDATE level=VALUES(level), name=VALUES(name)"); + query.setValue("channel", ci->name); + if (priv == "ALL") { - SQLQuery query("INSERT INTO `anope_cs_levels` (level, channel, position) VALUES(@level, @channel, @pos) ON DUPLICATE KEY UPDATE level=VALUES(level), channel=VALUES(channel), position=VALUES(position)"); - query.setValue("channel", ci->name); - for (int i = 0; i < CA_SIZE; ++i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = 0; i < privs.size(); ++i) { - query.setValue("level", ci->levels[i]); - query.setValue("pos", i); + const Privilege &p = privs[i]; + query.setValue("level", ci->GetLevel(p.name)); + query.setValue("name", p.name); this->RunQuery(query); } } + else + { + query.setValue("level", what); + query.setValue("name", name); + this->RunQuery(query); + } } void OnChanForbidden(ChannelInfo *ci) @@ -1538,7 +1538,11 @@ static void SaveDatabases() me->OnAkickAdd(ci, ak); } +<<<<<<< HEAD me->OnLevelChange(NULL, ci, -1, -1); +======= + me->OnLevelChange(NULL, ci, "ALL", -1); +>>>>>>> 348a3db... Allow modules to add their own channel levels for (unsigned j = 0, end = ci->memos.memos.size(); j < end; ++j) { diff --git a/modules/database/db_plain.cpp b/modules/database/db_plain.cpp index 340775e0c..83098ced9 100644 --- a/modules/database/db_plain.cpp +++ b/modules/database/db_plain.cpp @@ -179,52 +179,6 @@ static void ReadDatabase(Module *m = NULL) db.close(); } -struct ChannelLevel -{ - ChannelAccess Level; - Anope::string Name; -}; - -ChannelLevel ChannelLevels[] = { - { CA_ACCESS_LIST, "ACCESS_LIST" }, - { CA_NOKICK, "NOKICK" }, - { CA_FANTASIA, "FANTASIA" }, - { CA_GREET, "GREET" }, - { CA_AUTOVOICE, "AUTOVOICE" }, - { CA_VOICEME, "VOICEME" }, - { CA_VOICE, "VOICE" }, - { CA_INFO, "INFO" }, - { CA_SAY, "SAY" }, - { CA_AUTOHALFOP, "AUTOHALFOP" }, - { CA_HALFOPME, "HALFOPME" }, - { CA_HALFOP, "HALFOP" }, - { CA_KICK, "KICK" }, - { CA_SIGNKICK, "SIGNKICK" }, - { CA_BAN, "BAN" }, - { CA_TOPIC, "TOPIC" }, - { CA_MODE, "MODE" }, - { CA_GETKEY, "GETKEY" }, - { CA_INVITE, "INVITE" }, - { CA_UNBAN, "UNBAN" }, - { CA_AUTOOP, "AUTOOP" }, - { CA_OPDEOPME, "OPDEOPME" }, - { CA_OPDEOP, "OPDEOP" }, - { CA_AUTOPROTECT, "AUTOPROTECT" }, - { CA_AKICK, "AKICK" }, - { CA_BADWORDS, "BADWORDS" }, - { CA_ASSIGN, "ASSIGN" }, - { CA_MEMO, "MEMO" }, - { CA_ACCESS_CHANGE, "ACCESS_CHANGE" }, - { CA_PROTECTME, "PROTECTME" }, - { CA_PROTECT, "PROTECT" }, - { CA_SET, "SET" }, - { CA_AUTOOWNER, "AUTOOWNER" }, - { CA_OWNERME, "OWNERME" }, - { CA_OWNER, "OWNER" }, - { CA_FOUNDER, "FOUNDER" }, - { CA_SIZE, "" } -}; - static Anope::string ToString(const std::vector<Anope::string> &strings) { Anope::string ret; @@ -532,9 +486,12 @@ class DBPlain : public Module else if (key.equals_ci("LEVELS")) { for (unsigned j = 0, end = params.size(); j < end; j += 2) - for (int i = 0; ChannelLevels[i].Level != CA_SIZE; ++i) - if (params[j].equals_ci(ChannelLevels[i].Name)) - ci->levels[ChannelLevels[i].Level] = params[j + 1].is_number_only() ? convertTo<int16>(params[j + 1]) : 0; + { + Privilege *p = PrivilegeManager::FindPrivilege(params[j]); + if (p == NULL) + continue; + ci->SetLevel(p->name, params[j + 1].is_number_only() ? convertTo<int16>(params[j + 1]) : 0); + } } else if (key.equals_ci("FLAGS")) ci->FromString(params); @@ -555,7 +512,7 @@ class DBPlain : public Module { service_reference<AccessProvider> provider("access/access"); if (!provider) - throw DatabaseException("Access entry for nonexistant provider " + params[0]); + throw DatabaseException("Old access entry for nonexistant provider"); ChanAccess *access = provider->Create(); access->ci = ci; @@ -799,8 +756,12 @@ class DBPlain : public Module if (!ci->last_topic.empty()) db_buffer << "MD TOPIC " << ci->last_topic_setter << " " << ci->last_topic_time << " :" << ci->last_topic << endl; db_buffer << "MD LEVELS"; - for (int j = 0; ChannelLevels[j].Level != CA_SIZE; ++j) - db_buffer << " " << ChannelLevels[j].Name << " " << ci->levels[ChannelLevels[j].Level]; + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = 0; i < privs.size(); ++i) + { + const Privilege &p = privs[i]; + db_buffer << p.name << " " << ci->GetLevel(p.name); + } db_buffer << endl; if (ci->FlagCount()) db_buffer << "MD FLAGS " << ToString(ci->ToString()) << endl; diff --git a/modules/extra/m_helpchan.cpp b/modules/extra/m_helpchan.cpp index 6efcea572..83477da94 100644 --- a/modules/extra/m_helpchan.cpp +++ b/modules/extra/m_helpchan.cpp @@ -28,7 +28,7 @@ class HelpChannel : public Module { User *u = finduser(param); - if (u && c->ci->AccessFor(u).HasPriv(CA_OPDEOPME)) + if (u && c->ci->AccessFor(u).HasPriv("OPDEOPME")) u->SetMode(findbot(Config->OperServ), UMODE_HELPOP); } diff --git a/modules/extra/m_statusupdate.cpp b/modules/extra/m_statusupdate.cpp index 6f98c1345..8fff6e4c3 100644 --- a/modules/extra/m_statusupdate.cpp +++ b/modules/extra/m_statusupdate.cpp @@ -9,15 +9,15 @@ static struct ModeInfo { - ChannelAccess priv; + Anope::string priv; ChannelModeName name; } modeInfo[] = { - { CA_AUTOOWNER, CMODE_OWNER }, - { CA_AUTOPROTECT, CMODE_PROTECT }, - { CA_AUTOOP, CMODE_OP }, - { CA_AUTOHALFOP, CMODE_HALFOP }, - { CA_AUTOVOICE, CMODE_VOICE }, - { CA_SIZE, CMODE_END } + { "AUTOOWNER", CMODE_OWNER }, + { "AUTOPROTECT", CMODE_PROTECT }, + { "AUTOOP", CMODE_OP }, + { "AUTOHALFOP", CMODE_HALFOP }, + { "AUTOVOICE", CMODE_VOICE }, + { "", CMODE_END } }; class StatusUpdate : public Module @@ -40,7 +40,7 @@ class StatusUpdate : public Module if (access->Matches(user, user->Account())) { - for (int i = 0; modeInfo[i].priv != CA_SIZE; ++i) + for (int i = 0; !modeInfo[i].priv.empty(); ++i) if (!access->HasPriv(modeInfo[i].priv)) ci->c->RemoveMode(NULL, modeInfo[i].name, user->nick); chan_set_correct_modes(user, ci->c, 1); @@ -57,7 +57,7 @@ class StatusUpdate : public Module if (access->Matches(user, user->Account())) { - for (int i = 0; modeInfo[i].priv != CA_SIZE; ++i) + for (int i = 0; !modeInfo[i].priv.empty(); ++i) if (access->HasPriv(modeInfo[i].priv)) ci->c->RemoveMode(NULL, modeInfo[i].name, user->nick); } diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp index a286c54e7..802e1e82e 100644 --- a/modules/pseudoclients/botserv.cpp +++ b/modules/pseudoclients/botserv.cpp @@ -81,7 +81,7 @@ class BotServCore : public Module if (bi == NULL || !bi->commands.count(command)) return; - if (c->ci->AccessFor(u).HasPriv(CA_FANTASIA)) + if (c->ci->AccessFor(u).HasPriv("FANTASIA")) { this->fantasy_channel = c; @@ -133,7 +133,7 @@ class BotServCore : public Module * to has synced, or we'll get greet-floods when the net * recovers from a netsplit. -GD */ - if (c->FindUser(c->ci->bi) && c->ci->botflags.HasFlag(BS_GREET) && user->Account() && !user->Account()->greet.empty() && c->ci->AccessFor(user).HasPriv(CA_GREET) && user->server->IsSynced()) + if (c->FindUser(c->ci->bi) && c->ci->botflags.HasFlag(BS_GREET) && user->Account() && !user->Account()->greet.empty() && c->ci->AccessFor(user).HasPriv("GREET") && user->server->IsSynced()) { ircdproto->SendPrivmsg(c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), user->Account()->greet.c_str()); c->ci->bi->lastmsg = Anope::CurTime; diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp index 987dec16b..ca131b0de 100644 --- a/modules/pseudoclients/memoserv.cpp +++ b/modules/pseudoclients/memoserv.cpp @@ -102,7 +102,7 @@ class MyMemoServService : public MemoServService { UserContainer *cu = *it; - if (ci->AccessFor(cu->user).HasPriv(CA_MEMO)) + if (ci->AccessFor(cu->user).HasPriv("MEMO")) { if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE)) cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), ci->name.c_str(), mi->memos.size()); @@ -181,7 +181,7 @@ class MemoServCore : public Module void OnJoinChannel(User *u, Channel *c) { - if (c->ci && c->ci->AccessFor(u).HasPriv(CA_MEMO) && c->ci->memos.memos.size() > 0) + if (c->ci && c->ci->AccessFor(u).HasPriv("MEMO") && c->ci->memos.memos.size() > 0) { if (c->ci->memos.memos.size() == 1) u->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos.size(), c->ci->name.c_str()); diff --git a/src/access.cpp b/src/access.cpp index b9b3e1e9a..49636cd04 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -19,6 +19,84 @@ enum ACCESS_FOUNDER = 10001 }; +Privilege::Privilege(const Anope::string &n, const Anope::string &d) : name(n), desc(d) +{ +} + +bool Privilege::operator==(const Privilege &other) +{ + return this->name == other.name; +} + +std::vector<Privilege> PrivilegeManager::privs; + +void PrivilegeManager::AddPrivilege(Privilege p, int pos, int def) +{ + if (pos < 0 || static_cast<size_t>(pos) > privs.size()) + pos = privs.size(); + privs.insert(privs.begin() + pos, p); + for (registered_channel_map::const_iterator cit = RegisteredChannelList.begin(), cit_end = RegisteredChannelList.end(); cit != cit_end; ++cit) + cit->second->SetLevel(p.name, def); +} + +void PrivilegeManager::RemovePrivilege(Privilege &p) +{ + std::vector<Privilege>::iterator it = std::find(privs.begin(), privs.end(), p); + if (it != privs.end()) + privs.erase(it); + for (registered_channel_map::const_iterator cit = RegisteredChannelList.begin(), cit_end = RegisteredChannelList.end(); cit != cit_end; ++cit) + cit->second->RemoveLevel(p.name); +} + +Privilege *PrivilegeManager::FindPrivilege(const Anope::string &name) +{ + for (unsigned i = privs.size(); i > 0; --i) + if (privs[i - 1].name == name) + return &privs[i - 1]; + return NULL; +} + +void PrivilegeManager::Init() +{ + AddPrivilege(Privilege("ACCESS_LIST", _("Allowed to view the access list"))); + AddPrivilege(Privilege("NOKICK", _("Prevents users being kicked by Services"))); + AddPrivilege(Privilege("FANTASIA", _("Allowed to use fantasy commands"))); + AddPrivilege(Privilege("FOUNDER", _("Allowed to issue commands restricted to channel founders"))); + AddPrivilege(Privilege("GREET", _("Greet message displayed"))); + AddPrivilege(Privilege("AUTOVOICE", _("Automatic mode +v"))); + AddPrivilege(Privilege("VOICEME", _("Allowed to (de)voice him/herself"))); + AddPrivilege(Privilege("VOICE", _("Allowed to (de)voice users"))); + AddPrivilege(Privilege("INFO", _("Allowed to use INFO command with ALL option"))); + AddPrivilege(Privilege("SAY", _("Allowed to use SAY and ACT commands"))); + AddPrivilege(Privilege("AUTOHALFOP", _("Automatic mode +h"))); + AddPrivilege(Privilege("HALFOPME", _("Allowed to (de)halfop him/herself"))); + AddPrivilege(Privilege("HALFOP", _("Allowed to (de)halfop users"))); + AddPrivilege(Privilege("KICK", _("Allowed to use the KICK command"))); + AddPrivilege(Privilege("SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used"))); + AddPrivilege(Privilege("BAN", _("Allowed to use ban users"))); + AddPrivilege(Privilege("TOPIC", _("Allowed to change channel topics"))); + AddPrivilege(Privilege("MODE", _("Allowed to change channel modes"))); + AddPrivilege(Privilege("GETKEY", _("Allowed to use GETKEY command"))); + AddPrivilege(Privilege("INVITE", _("Allowed to use the INVITE command"))); + AddPrivilege(Privilege("UNBAN", _("Allowed to unban users"))); + AddPrivilege(Privilege("AUTOOP", _("Automatic channel operator status"))); + AddPrivilege(Privilege("AUTOOWNER", _("Automatic mode +q"))); + AddPrivilege(Privilege("OPDEOPME", _("Allowed to (de)op him/herself"))); + AddPrivilege(Privilege("OPDEOP", _("Allowed to (de)op users"))); + AddPrivilege(Privilege("AUTOPROTECT", _("Automatic mode +a"))); + AddPrivilege(Privilege("AKICK", _("Allowed to use AKICK command"))); + AddPrivilege(Privilege("BADWORDS", _("Allowed to modify channel badwords list"))); + AddPrivilege(Privilege("ASSIGN", _("Allowed to assign/unassign a bot"))); + AddPrivilege(Privilege("MEMO", _("Allowed to read channel memos"))); + AddPrivilege(Privilege("ACCESS_CHANGE", _("Allowed to modify the access list"))); + AddPrivilege(Privilege("PROTECTME", _("Allowed to (de)protect him/herself"))); +} + +std::vector<Privilege> &PrivilegeManager::GetPrivileges() +{ + return privs; +} + AccessProvider::AccessProvider(Module *o, const Anope::string &n) : Service<AccessProvider>(o, n) { } @@ -37,26 +115,29 @@ ChanAccess::~ChanAccess() bool ChanAccess::operator>(ChanAccess &other) { - for (size_t i = CA_SIZE; i > 0; --i) - if (this->HasPriv(static_cast<ChannelAccess>(i - 1)) && !other.HasPriv(static_cast<ChannelAccess>(i - 1))) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) + if (this->HasPriv(privs[i - 1].name) && !other.HasPriv(privs[i - 1].name)) return true; return false; } bool ChanAccess::operator<(ChanAccess &other) { - for (size_t i = CA_SIZE; i > 0; --i) - if (!this->HasPriv(static_cast<ChannelAccess>(i - 1)) && other.HasPriv(static_cast<ChannelAccess>(i - 1))) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) + if (!this->HasPriv(privs[i - 1].name) && other.HasPriv(privs[i - 1].name)) return true; return false; } bool ChanAccess::operator>=(ChanAccess &other) { - for (size_t i = CA_SIZE; i > 0; --i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) { - bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), - other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + bool this_p = this->HasPriv(privs[i - 1].name), + other_p = other.HasPriv(privs[i - 1].name); if ((this_p && !other_p) || (this_p && other_p)) return true; @@ -67,10 +148,11 @@ bool ChanAccess::operator>=(ChanAccess &other) bool ChanAccess::operator<=(ChanAccess &other) { - for (size_t i = CA_SIZE; i > 0; --i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) { - bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), - other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + bool this_p = this->HasPriv(privs[i - 1].name), + other_p = other.HasPriv(privs[i - 1].name); if ((!this_p && other_p) || (this_p && other_p)) return true; @@ -86,23 +168,23 @@ AccessGroup::AccessGroup() : std::vector<ChanAccess *>() this->SuperAdmin = this->Founder = false; } -bool AccessGroup::HasPriv(ChannelAccess priv) const +bool AccessGroup::HasPriv(const Anope::string &name) const { if (this->SuperAdmin) return true; - else if (ci->levels[priv] == ACCESS_INVALID) + else if (ci->GetLevel(name) == ACCESS_INVALID) return false; else if (this->Founder) return true; EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnGroupCheckPriv, OnGroupCheckPriv(this, priv)); + FOREACH_RESULT(I_OnGroupCheckPriv, OnGroupCheckPriv(this, name)); if (MOD_RESULT != EVENT_CONTINUE) return MOD_RESULT == EVENT_ALLOW; for (unsigned i = this->size(); i > 0; --i) { ChanAccess *access = this->at(i - 1); - FOREACH_RESULT(I_OnCheckPriv, OnCheckPriv(access, priv)); - if (MOD_RESULT == EVENT_ALLOW || access->HasPriv(priv)) + FOREACH_RESULT(I_OnCheckPriv, OnCheckPriv(access, name)); + if (MOD_RESULT == EVENT_ALLOW || access->HasPriv(name)) return true; } return false; @@ -110,9 +192,10 @@ bool AccessGroup::HasPriv(ChannelAccess priv) const ChanAccess *AccessGroup::Highest() const { - for (size_t i = CA_SIZE; i > 0; --i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) for (unsigned j = this->size(); j > 0; --j) - if (this->at(j - 1)->HasPriv(static_cast<ChannelAccess>(i - 1))) + if (this->at(j - 1)->HasPriv(privs[ - 1].name)) return this->at(j - 1); return NULL; } @@ -127,8 +210,9 @@ bool AccessGroup::operator>(const AccessGroup &other) const return true; else if (!this->Founder && other.Founder) return false; - for (size_t i = CA_SIZE; i > 0; --i) - if (this->HasPriv(static_cast<ChannelAccess>(i - 1)) && !other.HasPriv(static_cast<ChannelAccess>(i - 1))) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) + if (this->HasPriv(privs[i - 1].name) && !other.HasPriv(privs[i - 1].name)) return true; return false; } @@ -143,8 +227,9 @@ bool AccessGroup::operator<(const AccessGroup &other) const return true; else if (this->Founder && !other.Founder) return false; - for (size_t i = CA_SIZE; i > 0; --i) - if (!this->HasPriv(static_cast<ChannelAccess>(i - 1)) && other.HasPriv(static_cast<ChannelAccess>(i - 1))) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) + if (!this->HasPriv(privs[i - 1].name) && other.HasPriv(privs[i - 1].name)) return true; return false; } @@ -159,10 +244,11 @@ bool AccessGroup::operator>=(const AccessGroup &other) const return true; else if (other.Founder) return false; - for (size_t i = CA_SIZE; i > 0; --i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) { - bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), - other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + bool this_p = this->HasPriv(privs[i - 1].name), + other_p = other.HasPriv(privs[i - 1].name); if ((this_p && !other_p) || (this_p && other_p)) return true; @@ -181,10 +267,11 @@ bool AccessGroup::operator<=(const AccessGroup &other) const return true; else if (this->Founder) return false; - for (size_t i = CA_SIZE; i > 0; --i) + const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); + for (unsigned i = privs.size(); i > 0; --i) { - bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), - other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + bool this_p = this->HasPriv(privs[i - 1].name), + other_p = other.HasPriv(privs[i - 1].name); if ((!this_p && other_p) || (this_p && other_p)) return true; diff --git a/src/botserv.cpp b/src/botserv.cpp index 1670283be..c388b8a94 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -71,7 +71,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, User *u, const Anope::string ci->c->SetMode(NULL, CMODE_BAN, mask); /* Check if we need to do a signkick or not -GD */ - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv(CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv("SIGNKICK"))) ci->c->Kick(ci->bi, u, "%s (%s)", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str(), requester->nick.c_str()); else ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); @@ -100,7 +100,7 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string if (ci->HasFlag(CI_PEACE) && requester != u && u_access >= req_access) return; - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv(CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv("SIGNKICK"))) ci->c->Kick(ci->bi, u, "%s (%s)", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str(), requester->nick.c_str()); else ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); diff --git a/src/channels.cpp b/src/channels.cpp index 52b0b86c5..1778b9f01 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -1091,31 +1091,31 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes) if (give_modes && (!user->Account() || user->Account()->HasFlag(NI_AUTOOP))) { - if (owner && u_access.HasPriv(CA_AUTOOWNER)) + if (owner && u_access.HasPriv("AUTOOWNER")) c->SetMode(NULL, CMODE_OWNER, user->nick); - else if (admin && u_access.HasPriv(CA_AUTOPROTECT)) + else if (admin && u_access.HasPriv("AUTOPROTECT")) c->SetMode(NULL, CMODE_PROTECT, user->nick); - if (op && u_access.HasPriv(CA_AUTOOP)) + if (op && u_access.HasPriv("AUTOOP")) c->SetMode(NULL, CMODE_OP, user->nick); - else if (halfop && u_access.HasPriv(CA_AUTOHALFOP)) + else if (halfop && u_access.HasPriv("AUTOHALFOP")) c->SetMode(NULL, CMODE_HALFOP, user->nick); - else if (voice && u_access.HasPriv(CA_AUTOVOICE)) + else if (voice && u_access.HasPriv("AUTOVOICE")) c->SetMode(NULL, CMODE_VOICE, user->nick); } /* If this channel has secureops or the channel is syncing and they are not ulined, check to remove modes */ if ((ci->HasFlag(CI_SECUREOPS) || (c->HasFlag(CH_SYNCING) && user->server->IsSynced())) && !user->server->IsULined()) { - if (owner && !u_access.HasPriv(CA_AUTOOWNER) && !u_access.HasPriv(CA_OWNERME)) + if (owner && !u_access.HasPriv("AUTOOWNER") && !u_access.HasPriv("OWNERME")) c->RemoveMode(NULL, CMODE_OWNER, user->nick); - if (admin && !u_access.HasPriv(CA_AUTOPROTECT) && !u_access.HasPriv(CA_PROTECTME)) + if (admin && !u_access.HasPriv("AUTOPROTECT") && !u_access.HasPriv("PROTECTME")) c->RemoveMode(NULL, CMODE_PROTECT, user->nick); - if (op && c->HasUserStatus(user, CMODE_OP) && !u_access.HasPriv(CA_AUTOOP) && !u_access.HasPriv(CA_OPDEOPME)) + if (op && c->HasUserStatus(user, CMODE_OP) && !u_access.HasPriv("AUTOOP") && !u_access.HasPriv("OPDEOPME")) c->RemoveMode(NULL, CMODE_OP, user->nick); - if (halfop && !u_access.HasPriv(CA_AUTOHALFOP) && !u_access.HasPriv(CA_HALFOPME)) + if (halfop && !u_access.HasPriv("AUTOHALFOP") && !u_access.HasPriv("HALFOPME")) c->RemoveMode(NULL, CMODE_HALFOP, user->nick); } diff --git a/src/init.cpp b/src/init.cpp index 4cff3fc91..76ba350bb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -355,6 +355,7 @@ void Init(int ac, char **av) /* Initialize the socket engine */ SocketEngine::Init(); + PrivilegeManager::Init(); /* Create me */ Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric); diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 882649d54..7eceb5942 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -49,9 +49,6 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Flags<ChannelInfoFlag, C this->memos.memomax = Config->MSMaxMemos; this->last_used = this->time_registered = Anope::CurTime; - for (int i = 0; i < CA_SIZE; ++i) - this->levels[i] = 0; - for (int i = 0; i < TTB_SIZE; ++i) this->ttb[i] = 0; @@ -781,3 +778,28 @@ void ChannelInfo::RestoreTopic() } } +int16 ChannelInfo::GetLevel(const Anope::string &priv) +{ + if (PrivilegeManager::FindPrivilege(priv) == NULL) + throw CoreException("Unknown privilege " + priv); + + if (this->levels.count(priv) == 0) + this->levels[priv] = 0; + return this->levels[priv]; +} + +void ChannelInfo::SetLevel(const Anope::string &priv, int16 level) +{ + this->levels[priv] = level; +} + +void ChannelInfo::RemoveLevel(const Anope::string &priv) +{ + this->levels.erase(priv); +} + +void ChannelInfo::ClearLevels() +{ + this->levels.clear(); +} + |