summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/core/bs_assign.cpp8
-rw-r--r--modules/core/bs_badwords.cpp12
-rw-r--r--modules/core/bs_control.cpp4
-rw-r--r--modules/core/bs_info.cpp2
-rw-r--r--modules/core/bs_kick.cpp8
-rw-r--r--modules/core/bs_main.cpp4
-rw-r--r--modules/core/bs_set.cpp4
-rw-r--r--modules/core/cs_access.cpp408
-rw-r--r--modules/core/cs_akick.cpp31
-rw-r--r--modules/core/cs_ban.cpp9
-rw-r--r--modules/core/cs_clearusers.cpp5
-rw-r--r--modules/core/cs_clone.cpp6
-rw-r--r--modules/core/cs_drop.cpp4
-rw-r--r--modules/core/cs_flags.cpp455
-rw-r--r--modules/core/cs_getkey.cpp4
-rw-r--r--modules/core/cs_info.cpp3
-rw-r--r--modules/core/cs_invite.cpp2
-rw-r--r--modules/core/cs_kick.cpp9
-rw-r--r--modules/core/cs_main.cpp23
-rw-r--r--modules/core/cs_mode.cpp25
-rw-r--r--modules/core/cs_modes.cpp58
-rw-r--r--modules/core/cs_saset_noexpire.cpp2
-rw-r--r--modules/core/cs_set_bantype.cpp2
-rw-r--r--modules/core/cs_set_description.cpp2
-rw-r--r--modules/core/cs_set_founder.cpp4
-rw-r--r--modules/core/cs_set_keeptopic.cpp2
-rw-r--r--modules/core/cs_set_opnotice.cpp2
-rw-r--r--modules/core/cs_set_peace.cpp2
-rw-r--r--modules/core/cs_set_persist.cpp2
-rw-r--r--modules/core/cs_set_private.cpp2
-rw-r--r--modules/core/cs_set_restricted.cpp6
-rw-r--r--modules/core/cs_set_secure.cpp2
-rw-r--r--modules/core/cs_set_securefounder.cpp2
-rw-r--r--modules/core/cs_set_secureops.cpp2
-rw-r--r--modules/core/cs_set_signkick.cpp2
-rw-r--r--modules/core/cs_set_successor.cpp4
-rw-r--r--modules/core/cs_set_topiclock.cpp2
-rw-r--r--modules/core/cs_set_xop.cpp146
-rw-r--r--modules/core/cs_status.cpp75
-rw-r--r--modules/core/cs_topic.cpp4
-rw-r--r--modules/core/cs_unban.cpp2
-rw-r--r--modules/core/cs_xop.cpp417
-rw-r--r--modules/core/db_mysql.cpp51
-rw-r--r--modules/core/db_plain.cpp102
-rw-r--r--modules/core/ms_del.cpp2
-rw-r--r--modules/core/ms_ignore.cpp2
-rw-r--r--modules/core/ms_info.cpp2
-rw-r--r--modules/core/ms_list.cpp2
-rw-r--r--modules/core/ms_main.cpp4
-rw-r--r--modules/core/ms_read.cpp2
-rw-r--r--modules/core/ms_set.cpp2
-rw-r--r--modules/core/ns_ajoin.cpp4
-rw-r--r--modules/core/ns_alist.cpp123
-rw-r--r--modules/extra/cs_appendtopic.cpp4
-rw-r--r--modules/extra/cs_enforce.cpp7
-rw-r--r--modules/extra/cs_tban.cpp2
-rw-r--r--modules/extra/m_helpchan.cpp2
-rw-r--r--modules/extra/m_statusupdate.cpp52
58 files changed, 1331 insertions, 800 deletions
diff --git a/modules/core/bs_assign.cpp b/modules/core/bs_assign.cpp
index 0a08eec3b..803368994 100644
--- a/modules/core/bs_assign.cpp
+++ b/modules/core/bs_assign.cpp
@@ -49,7 +49,7 @@ class CommandBSAssign : public Command
return;
}
- if (ci->botflags.HasFlag(BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !u->HasPriv("botserv/administration")))
+ if (ci->botflags.HasFlag(BS_NOBOT) || (!ci->HasPriv(u, CA_ASSIGN) && !u->HasPriv("botserv/administration")))
{
source.Reply(ACCESS_DENIED);
return;
@@ -67,7 +67,7 @@ class CommandBSAssign : public Command
return;
}
- bool override = !check_access(u, ci, CA_ASSIGN);
+ bool override = !ci->HasPriv(u, CA_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") && !check_access(u, ci, CA_ASSIGN))
+ if (!u->HasPriv("botserv/administration") && !ci->HasPriv(u, CA_ASSIGN))
{
source.Reply(ACCESS_DENIED);
return;
@@ -129,7 +129,7 @@ class CommandBSUnassign : public Command
return;
}
- bool override = !check_access(u, ci, CA_ASSIGN);
+ bool override = !ci->HasPriv(u, CA_ASSIGN);
Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "for " << ci->bi->nick;
ci->bi->UnAssign(u, ci);
diff --git a/modules/core/bs_badwords.cpp b/modules/core/bs_badwords.cpp
index a272bdff9..a27dca2d4 100644
--- a/modules/core/bs_badwords.cpp
+++ b/modules/core/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 (!check_access(source.u, ci, CA_BADWORDS) && source.u->HasPriv("botserv/administration"))
+ if (!ci->HasPriv(source.u, CA_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 = !check_access(source.u, ci, CA_BADWORDS);
+ bool override = !ci->HasPriv(source.u, CA_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 = !check_access(source.u, ci, CA_BADWORDS);
+ bool override = !ci->HasPriv(source.u, CA_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 = !check_access(source.u, ci, CA_BADWORDS);
+ bool override = !ci->HasPriv(source.u, CA_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 = !check_access(source.u, ci, CA_BADWORDS);
+ bool override = !ci->HasPriv(source.u, CA_BADWORDS);
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "CLEAR";
ci->ClearBadWords();
@@ -254,7 +254,7 @@ class CommandBSBadwords : public Command
}
- if (!check_access(u, ci, CA_BADWORDS) && (!need_args || !u->HasPriv("botserv/administration")))
+ if (!ci->HasPriv(u, CA_BADWORDS) && (!need_args || !u->HasPriv("botserv/administration")))
{
source.Reply(ACCESS_DENIED);
return;
diff --git a/modules/core/bs_control.cpp b/modules/core/bs_control.cpp
index 431739693..16a5b372a 100644
--- a/modules/core/bs_control.cpp
+++ b/modules/core/bs_control.cpp
@@ -35,7 +35,7 @@ class CommandBSSay : public Command
return;
}
- if (!check_access(u, ci, CA_SAY))
+ if (!ci->HasPriv(u, CA_SAY))
{
source.Reply(ACCESS_DENIED);
return;
@@ -98,7 +98,7 @@ class CommandBSAct : public Command
return;
}
- if (!check_access(u, ci, CA_SAY))
+ if (!ci->HasPriv(u, CA_SAY))
{
source.Reply(ACCESS_DENIED);
return;
diff --git a/modules/core/bs_info.cpp b/modules/core/bs_info.cpp
index 38178a07b..b48a0b296 100644
--- a/modules/core/bs_info.cpp
+++ b/modules/core/bs_info.cpp
@@ -70,7 +70,7 @@ class CommandBSInfo : public Command
}
else if ((ci = cs_findchan(query)))
{
- if (!check_access(u, ci, CA_FOUNDER) && !u->HasPriv("botserv/administration"))
+ if (!ci->HasPriv(u, CA_FOUNDER) && !u->HasPriv("botserv/administration"))
{
source.Reply(ACCESS_DENIED);
return;
diff --git a/modules/core/bs_kick.cpp b/modules/core/bs_kick.cpp
index a8c34e5cd..3f433f773 100644
--- a/modules/core/bs_kick.cpp
+++ b/modules/core/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 (!check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration"))
+ else if (!ci->HasPriv(u, CA_SET) && !u->HasPriv("botserv/administration"))
source.Reply(ACCESS_DENIED);
else if (!ci->bi)
source.Reply(BOT_NOT_ASSIGNED);
else
{
- bool override = !check_access(u, ci, CA_SET);
+ bool override = !ci->HasPriv(u, CA_SET);
Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << option << " " << value;
if (option.equals_ci("BADWORDS"))
@@ -768,7 +768,7 @@ class BSKick : public Module
return;
bool Allow = true;
- if (check_access(u, ci, CA_NOKICK))
+ if (ci->HasPriv(u, CA_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;
@@ -993,7 +993,7 @@ class BSKick : public Module
Channel *chan = (*it)->chan;
++it;
- if (chan->ci != NULL && chan->ci->botflags.HasFlag(BS_KICK_AMSGS) && !check_access(u, chan->ci, CA_NOKICK))
+ if (chan->ci != NULL && chan->ci->botflags.HasFlag(BS_KICK_AMSGS) && !chan->ci->HasPriv(u, CA_NOKICK))
{
check_ban(chan->ci, u, TTB_AMSGS);
bot_kick(chan->ci, u, _("Don't use AMSGs!"));
diff --git a/modules/core/bs_main.cpp b/modules/core/bs_main.cpp
index 515b99ae0..69eab6040 100644
--- a/modules/core/bs_main.cpp
+++ b/modules/core/bs_main.cpp
@@ -81,7 +81,7 @@ class BotServCore : public Module
if (bi == NULL || !bi->commands.count(command))
return;
- if (check_access(u, c->ci, CA_FANTASIA))
+ if (c->ci->HasPriv(u, CA_FANTASIA))
{
this->fantasy_channel = c;
@@ -125,7 +125,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() && check_access(user, c->ci, 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->HasPriv(user, CA_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/core/bs_set.cpp b/modules/core/bs_set.cpp
index 0fbba874e..ccd1bb615 100644
--- a/modules/core/bs_set.cpp
+++ b/modules/core/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") && !check_access(u, ci, CA_SET))
+ else if (!u->HasPriv("botserv/administration") && !ci->HasPriv(u, CA_SET))
source.Reply(ACCESS_DENIED);
else
{
- bool override = !check_access(u, ci, CA_SET);
+ bool override = !ci->HasPriv(u, CA_SET);
Log(override ? LOG_ADMIN : LOG_COMMAND, u, this, ci) << option << " " << value;
if (option.equals_ci("DONTKICKOPS"))
diff --git a/modules/core/cs_access.cpp b/modules/core/cs_access.cpp
index 643292c38..777b0c176 100644
--- a/modules/core/cs_access.cpp
+++ b/modules/core/cs_access.cpp
@@ -13,6 +13,132 @@
#include "module.h"
+enum
+{
+ ACCESS_INVALID = -10000,
+ 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 void reset_levels(ChannelInfo *ci)
+{
+ for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i)
+ ci->levels[defaultLevels[i].priv] = defaultLevels[i].default_level;
+}
+
+class AccessChanAccess : public ChanAccess
+{
+ public:
+ int level;
+
+ AccessChanAccess(AccessProvider *p) : ChanAccess(p)
+ {
+ }
+
+ bool Matches(User *u, NickCore *nc)
+ {
+ if (u && (Anope::Match(u->nick, this->mask) || Anope::Match(u->GetMask(), this->mask)))
+ return true;
+ else if (nc && Anope::Match(nc->display, this->mask))
+ return true;
+ return false;
+ }
+
+ bool HasPriv(ChannelAccess priv)
+ {
+ for (int i = 0; defaultLevels[i].priv != CA_SIZE; ++i)
+ if (defaultLevels[i].priv == priv)
+ return DetermineLevel(this) >= this->ci->levels[priv];
+ return false;
+ }
+
+ Anope::string Serialize()
+ {
+ return stringify(this->level);
+ }
+
+ void Unserialize(const Anope::string &data)
+ {
+ this->level = convertTo<int>(data);
+ }
+
+ static int DetermineLevel(ChanAccess *access)
+ {
+ if (access->provider->name == "access/access")
+ {
+ AccessChanAccess *aaccess = debug_cast<AccessChanAccess *>(access);
+ return aaccess->level;
+ }
+ 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];
+ return highest;
+ }
+ }
+};
+
+class AccessAccessProvider : public AccessProvider
+{
+ public:
+ AccessAccessProvider(Module *o) : AccessProvider(o, "access/access")
+ {
+ }
+
+ ChanAccess *Create()
+ {
+ return new AccessChanAccess(this);
+ }
+};
+
class AccessListCallback : public NumberList
{
protected:
@@ -27,7 +153,7 @@ class AccessListCallback : public NumberList
~AccessListCallback()
{
if (SentHeader)
- source.Reply(_("End of access list."), ci->name.c_str());
+ source.Reply(_("End of access list."));
else
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
}
@@ -48,13 +174,7 @@ class AccessListCallback : public NumberList
static void DoList(CommandSource &source, ChannelInfo *ci, unsigned Number, ChanAccess *access)
{
- if (ci->HasFlag(CI_XOP))
- {
- Anope::string xop = get_xop_level(access->level);
- source.Reply(_(" %3d %s %s"), Number + 1, xop.c_str(), access->GetMask().c_str());
- }
- else
- source.Reply(_(" %3d %4d %s"), Number + 1, access->level, access->GetMask().c_str());
+ source.Reply(_(" %3d %4d %s"), Number + 1, AccessChanAccess::DetermineLevel(access), access->mask.c_str());
}
};
@@ -82,20 +202,19 @@ class AccessViewCallback : public AccessListCallback
static void DoList(CommandSource &source, ChannelInfo *ci, unsigned Number, ChanAccess *access)
{
Anope::string timebuf;
- if (ci->c && nc_on_chan(ci->c, access->nc))
- timebuf = "Now";
- else if (access->last_seen == 0)
- timebuf = "Never";
- else
- timebuf = do_strftime(access->last_seen);
-
- if (ci->HasFlag(CI_XOP))
+ if (ci->c)
+ for (CUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit)
+ if (access->Matches((*cit)->user, (*cit)->user->Account()))
+ timebuf = "Now";
+ if (timebuf.empty())
{
- Anope::string xop = get_xop_level(access->level);
- source.Reply(CHAN_ACCESS_VIEW_XOP_FORMAT, Number + 1, xop.c_str(), access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str());
+ if (access->last_seen == 0)
+ timebuf = "Never";
+ else
+ timebuf = do_strftime(access->last_seen);
}
- else
- source.Reply(CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, access->level, access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str());
+
+ source.Reply(CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, AccessChanAccess::DetermineLevel(access), access->mask.c_str(), access->creator.c_str(), timebuf.c_str());
}
};
@@ -111,7 +230,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 (!check_access(source.u, ci, CA_ACCESS_CHANGE) && source.u->HasPriv("chanserv/access/modify"))
+ if (!ci->HasPriv(source.u, CA_ACCESS_CHANGE) && source.u->HasPriv("chanserv/access/modify"))
this->override = true;
}
@@ -141,9 +260,10 @@ class AccessDelCallback : public NumberList
ChanAccess *access = ci->GetAccess(Number - 1);
- ChanAccess *u_access = ci->GetAccess(u);
- int16 u_level = u_access ? u_access->level : 0;
- if (u_level <= access->level && !u->HasPriv("chanserv/access/modify"))
+ AccessGroup u_access = ci->AccessFor(u);
+ ChanAccess *u_highest = u_access.Highest();
+
+ if (u_highest ? AccessChanAccess::DetermineLevel(u_highest) : 0 <= AccessChanAccess::DetermineLevel(access) && !u->HasPriv("chanserv/access/modify"))
{
Denied = true;
return;
@@ -151,9 +271,9 @@ class AccessDelCallback : public NumberList
++Deleted;
if (!Nicks.empty())
- Nicks += ", " + access->GetMask();
+ Nicks += ", " + access->mask;
else
- Nicks = access->GetMask();
+ Nicks = access->mask;
FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access));
@@ -176,17 +296,18 @@ class CommandCSAccess : public Command
}
catch (const ConvertException &) { }
- ChanAccess *u_access = ci->GetAccess(u);
- int16 u_level = u_access ? u_access->level : 0;
- if (level >= u_level && !u->HasPriv("chanserv/access/modify"))
+ if (!level)
{
- source.Reply(ACCESS_DENIED);
+ source.Reply(_("Access level must be non-zero."));
return;
}
- if (!level)
+ AccessGroup u_access = ci->AccessFor(u);
+ ChanAccess *highest = u_access.Highest();
+ int u_level = (highest ? AccessChanAccess::DetermineLevel(highest) : 0);
+ if (!ci->HasPriv(u, CA_FOUNDER) && level >= u_level && !u->HasPriv("chanserv/access/modify"))
{
- source.Reply(_("Access level must be non-zero."));
+ source.Reply(ACCESS_DENIED);
return;
}
else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER)
@@ -195,29 +316,22 @@ class CommandCSAccess : public Command
return;
}
- bool override = !check_access(u, ci, CA_ACCESS_CHANGE) || level >= u_level;
+ bool override = !ci->HasPriv(u, CA_ACCESS_CHANGE) || level >= u_level;
- ChanAccess *access = ci->GetAccess(mask, 0, false);
- if (access)
+ for (unsigned i = ci->GetAccessCount(); i > 0; --i)
{
- /* Don't allow lowering from a level >= u_level */
- if (access->level >= u_level && !u->HasPriv("chanserv/access/modify"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
- if (access->level == level)
+ ChanAccess *access = ci->GetAccess(i - 1);
+ if (mask.equals_ci(access->mask))
{
- source.Reply(_("Access level for \002%s\002 on %s unchanged from \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level);
- return;
+ /* Don't allow lowering from a level >= u_level */
+ if (AccessChanAccess::DetermineLevel(access) >= u_level && !u->HasPriv("chanserv/access/modify"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+ ci->EraseAccess(i - 1);
+ break;
}
- access->level = level;
-
- FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, access));
-
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level;
- source.Reply(_("Access level for \002%s\002 on %s changed to \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level);
- return;
}
if (ci->GetAccessCount() >= Config->CSAccessMax)
@@ -226,12 +340,25 @@ class CommandCSAccess : public Command
return;
}
- access = ci->AddAccess(mask, level, u->nick);
+ if (mask.find_first_of("!*@") == Anope::string::npos && findnick(mask) == NULL)
+ mask += "!*@*";
+
+ service_reference<AccessProvider> provider("access/access");
+ if (!provider)
+ return;
+ AccessChanAccess *access = debug_cast<AccessChanAccess *>(provider->Create());
+ access->ci = ci;
+ access->mask = mask;
+ access->creator = u->nick;
+ access->level = level;
+ access->last_seen = 0;
+ access->created = Anope::CurTime;
+ ci->AddAccess(access);
FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, access));
Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level;
- source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level);
+ source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->mask.c_str(), ci->name.c_str(), level);
return;
}
@@ -251,23 +378,32 @@ class CommandCSAccess : public Command
}
else
{
- ChanAccess *access = ci->GetAccess(mask, 0, false);
- ChanAccess *u_access = ci->GetAccess(u);
- int16 u_level = u_access ? u_access->level : 0;
- if (!access)
- source.Reply(_("\002%s\002 not found on %s access list."), mask.c_str(), ci->name.c_str());
- else if (access->nc != u->Account() && check_access(u, ci, CA_NOJOIN) && u_level <= access->level && !u->HasPriv("chanserv/access/modify"))
- source.Reply(ACCESS_DENIED);
- else
- {
- source.Reply(_("\002%s\002 deleted from %s access list."), access->GetMask().c_str(), ci->name.c_str());