summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-11-30 03:02:33 -0500
committerAdam <Adam@anope.org>2010-12-12 19:37:02 -0500
commit0ba566491ea246fcc895862d0ef80bdf4ee43b4b (patch)
tree9852671d32476ddad58e264a8e074c41fef9f69f
parent2a4d57a1cacd22084abea5dd21c87dc733a7b5bf (diff)
Allowing adding hostmasks to channel access lists
-rw-r--r--include/extern.h5
-rw-r--r--include/language.h6
-rw-r--r--include/modules.h14
-rw-r--r--include/regchannel.h37
-rw-r--r--include/services.h3
-rw-r--r--modules/core/cs_access.cpp111
-rw-r--r--modules/core/cs_akick.cpp12
-rw-r--r--modules/core/cs_ban.cpp10
-rw-r--r--modules/core/cs_clone.cpp2
-rw-r--r--modules/core/cs_kick.cpp10
-rw-r--r--modules/core/cs_modes.cpp10
-rw-r--r--modules/core/cs_register.cpp4
-rw-r--r--modules/core/cs_status.cpp3
-rw-r--r--modules/core/cs_xop.cpp119
-rw-r--r--modules/core/db_plain.cpp12
-rw-r--r--modules/core/ms_staff.cpp1
-rw-r--r--modules/core/ns_access.cpp3
-rw-r--r--modules/core/ns_alist.cpp12
-rw-r--r--modules/extra/db_mysql.cpp23
-rw-r--r--src/botserv.cpp18
-rw-r--r--src/channels.cpp6
-rw-r--r--src/chanserv.cpp80
-rw-r--r--src/language.cpp50
-rw-r--r--src/regchannel.cpp124
24 files changed, 340 insertions, 335 deletions
diff --git a/include/extern.h b/include/extern.h
index de51742ab..24f12a84f 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -63,8 +63,6 @@ E Channel *findchan(const Anope::string &chan);
E User *nc_on_chan(Channel *c, const NickCore *nc);
-E int get_access_level(ChannelInfo *ci, NickAlias *na);
-E int get_access_level(ChannelInfo *ci, NickCore *nc);
E Anope::string get_xop_level(int level);
E void do_cmode(const Anope::string &source, const Anope::string &channel, const Anope::string &modes, const Anope::string &ts);
@@ -91,7 +89,7 @@ E void get_chanserv_stats(long *nrec, long *memuse);
E void reset_levels(ChannelInfo *ci);
E void cs_init();
E void expire_chans();
-E void cs_remove_nick(const NickCore *nc);
+E void cs_remove_nick(NickCore *nc);
E void check_modes(Channel *c);
E int check_valid_admin(User *user, Channel *chan, int servermode);
@@ -100,7 +98,6 @@ E int check_valid_op(User *user, Channel *chan, int servermode);
E ChannelInfo *cs_findchan(const Anope::string &chan);
E int check_access(User *user, ChannelInfo *ci, int what);
E bool IsFounder(User *user, ChannelInfo *ci);
-E int get_access(User *user, ChannelInfo *ci);
E void update_cs_lastseen(User *user, ChannelInfo *ci);
E int get_idealban(ChannelInfo *ci, User *u, Anope::string &ret);
diff --git a/include/language.h b/include/language.h
index 0b880a2f5..4b04028f9 100644
--- a/include/language.h
+++ b/include/language.h
@@ -392,7 +392,6 @@ enum LanguageString
CHAN_XOP_NOT_AVAILABLE,
CHAN_QOP_SYNTAX,
CHAN_QOP_DISABLED,
- CHAN_QOP_NICKS_ONLY,
CHAN_QOP_ADDED,
CHAN_QOP_MOVED,
CHAN_QOP_NO_SUCH_ENTRY,
@@ -406,7 +405,6 @@ enum LanguageString
CHAN_QOP_CLEAR,
CHAN_AOP_SYNTAX,
CHAN_AOP_DISABLED,
- CHAN_AOP_NICKS_ONLY,
CHAN_AOP_ADDED,
CHAN_AOP_MOVED,
CHAN_AOP_NO_SUCH_ENTRY,
@@ -420,7 +418,6 @@ enum LanguageString
CHAN_AOP_CLEAR,
CHAN_HOP_SYNTAX,
CHAN_HOP_DISABLED,
- CHAN_HOP_NICKS_ONLY,
CHAN_HOP_ADDED,
CHAN_HOP_MOVED,
CHAN_HOP_NO_SUCH_ENTRY,
@@ -434,7 +431,6 @@ enum LanguageString
CHAN_HOP_CLEAR,
CHAN_SOP_SYNTAX,
CHAN_SOP_DISABLED,
- CHAN_SOP_NICKS_ONLY,
CHAN_SOP_ADDED,
CHAN_SOP_MOVED,
CHAN_SOP_NO_SUCH_ENTRY,
@@ -448,7 +444,6 @@ enum LanguageString
CHAN_SOP_CLEAR,
CHAN_VOP_SYNTAX,
CHAN_VOP_DISABLED,
- CHAN_VOP_NICKS_ONLY,
CHAN_VOP_ADDED,
CHAN_VOP_MOVED,
CHAN_VOP_NO_SUCH_ENTRY,
@@ -466,7 +461,6 @@ enum LanguageString
CHAN_ACCESS_DISABLED,
CHAN_ACCESS_LEVEL_NONZERO,
CHAN_ACCESS_LEVEL_RANGE,
- CHAN_ACCESS_NICKS_ONLY,
CHAN_ACCESS_REACHED_LIMIT,
CHAN_ACCESS_LEVEL_UNCHANGED,
CHAN_ACCESS_LEVEL_CHANGED,
diff --git a/include/modules.h b/include/modules.h
index 12e7884f8..c96c1ae27 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -723,25 +723,23 @@ class CoreExport Module : public Extensible
/** Called when access is deleted from a channel
* @param ci The channel
* @param u The user who removed the access
- * @param nc The user who was deleted
+ * @param access The access entry being removed
*/
- virtual void OnAccessDel(ChannelInfo *ci, User *u, NickCore *nc) { }
+ virtual void OnAccessDel(ChannelInfo *ci, User *u, ChanAccess *access) { }
/** Called when access is changed
* @param ci The channel
* @param u The user who changed the access
- * @param nc The nick whos access was changed
- * @param level The level of the new access
+ * @param u access The access changed
*/
- virtual void OnAccessChange(ChannelInfo *ci, User *u, NickCore *nc, int level) { }
+ virtual void OnAccessChange(ChannelInfo *ci, User *u, ChanAccess *access) { }
/** Called when access is added
* @param ci The channel
* @param u The user who added the access
- * @para nc The nick who was added to access
- * @param level The level they were added at
+ * @param access The access changed
*/
- virtual void OnAccessAdd(ChannelInfo *ci, User *u, NickCore *nc, int level) { }
+ virtual void OnAccessAdd(ChannelInfo *ci, User *u, ChanAccess *access) { }
/** Called when the access list is cleared
* @param ci The channel
diff --git a/include/regchannel.h b/include/regchannel.h
index 760a91f5f..71deb1ce7 100644
--- a/include/regchannel.h
+++ b/include/regchannel.h
@@ -132,14 +132,15 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag,
/** Add an entry to the channel access list
*
- * @param nc The NickCore of the user that the access entry should be tied to
+ * @param mask The mask of the access entry
* @param level The channel access level the user has on the channel
* @param creator The user who added the access
* @param last_seen When the user was last seen within the channel
+ * @return The new access class
*
* Creates a new access list entry and inserts it into the access list.
*/
- void AddAccess(NickCore *nc, int16 level, const Anope::string &creator, int32 last_seen = 0);
+ ChanAccess *AddAccess(const Anope::string &mask, int16 level, const Anope::string &creator, int32 last_seen = 0);
/** Get an entry from the channel access list by index
*
@@ -150,15 +151,35 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag,
*/
ChanAccess *GetAccess(unsigned index);
+ /** Get an entry from the channel access list by User
+ *
+ * @param u The User to find within the access list vector
+ * @param level Optional channel access level to compare the access entries to
+ * @return A ChanAccess struct corresponding to the User, or NULL if not found
+ *
+ * Retrieves an entry from the access list that matches the given User, optionally also matching a certain level.
+ */
+ ChanAccess *GetAccess(User *u, int16 level = 0);
+
/** Get an entry from the channel access list by NickCore
*
- * @param nc The NickCore to find within the access list vector
+ * @param u The NickCore to find within the access list vector
* @param level Optional channel access level to compare the access entries to
* @return A ChanAccess struct corresponding to the NickCore, or NULL if not found
*
* Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level.
*/
- ChanAccess *GetAccess(const NickCore *nc, int16 level = 0);
+ ChanAccess *GetAccess(NickCore *nc, int16 level = 0);
+
+ /** Get an entry from the channel access list by mask
+ *
+ * @param u The mask to find within the access list vector
+ * @param level Optional channel access level to compare the access entries to
+ * @return A ChanAccess struct corresponding to the mask, or NULL if not found
+ *
+ * Retrieves an entry from the access list that matches the given mask, optionally also matching a certain level.
+ */
+ ChanAccess *GetAccess(const Anope::string &mask, int16 level = 0);
/** Get the size of the accss vector for this channel
* @return The access vector size
@@ -173,6 +194,14 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag,
*/
void EraseAccess(unsigned index);
+ /** Erase an entry from the channel access list
+ *
+ * @param access The access to remove
+ *
+ * Clears the memory used by the given access entry and removes it from the vector.
+ */
+ void EraseAccess(ChanAccess *access);
+
/** Clear the entire channel access list
*
* Clears the entire access list by deleting every item and then clearing the vector.
diff --git a/include/services.h b/include/services.h
index 16be4ebc7..2b4c13f7c 100644
--- a/include/services.h
+++ b/include/services.h
@@ -571,7 +571,8 @@ enum AccessLevel
struct ChanAccess
{
int16 level;
- NickCore *nc; /* Guaranteed to be non-NULL if in use, NULL if not */
+ Anope::string mask; /* Mask of the access entry */
+ NickCore *nc; /* NC of the entry, if the entry is a valid nickcore */
time_t last_seen;
Anope::string creator;
};
diff --git a/modules/core/cs_access.cpp b/modules/core/cs_access.cpp
index 96856da60..43cb58cf1 100644
--- a/modules/core/cs_access.cpp
+++ b/modules/core/cs_access.cpp
@@ -50,10 +50,10 @@ class AccessListCallback : public NumberList
if (source.ci->HasFlag(CI_XOP))
{
Anope::string xop = get_xop_level(access->level);
- source.Reply(CHAN_ACCESS_LIST_XOP_FORMAT, Number + 1, xop.c_str(), access->nc->display.c_str());
+ source.Reply(CHAN_ACCESS_LIST_XOP_FORMAT, Number + 1, xop.c_str(), access->mask.c_str());
}
else
- source.Reply(CHAN_ACCESS_LIST_AXS_FORMAT, Number + 1, access->level, access->nc->display.c_str());
+ source.Reply(CHAN_ACCESS_LIST_AXS_FORMAT, Number + 1, access->level, access->mask.c_str());
}
};
@@ -93,10 +93,10 @@ class AccessViewCallback : public AccessListCallback
if (ci->HasFlag(CI_XOP))
{
Anope::string xop = get_xop_level(access->level);
- source.Reply(CHAN_ACCESS_VIEW_XOP_FORMAT, Number + 1, xop.c_str(), access->nc->display.c_str(), access->creator.c_str(), timebuf.c_str());
+ source.Reply(CHAN_ACCESS_VIEW_XOP_FORMAT, Number + 1, xop.c_str(), access->mask.c_str(), access->creator.c_str(), timebuf.c_str());
}
else
- source.Reply(CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, access->level, access->nc->display.c_str(), access->creator.c_str(), timebuf.c_str());
+ source.Reply(CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, access->level, access->mask.c_str(), access->creator.c_str(), timebuf.c_str());
}
};
@@ -142,7 +142,9 @@ class AccessDelCallback : public NumberList
ChanAccess *access = ci->GetAccess(Number - 1);
- if (get_access(u, ci) <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
+ ChanAccess *u_access = ci->GetAccess(u);
+ int16 u_level = u_access ? u_access->level : 0;
+ if (u_level <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
{
Denied = true;
return;
@@ -150,11 +152,11 @@ class AccessDelCallback : public NumberList
++Deleted;
if (!Nicks.empty())
- Nicks += ", " + access->nc->display;
+ Nicks += ", " + access->mask;
else
- Nicks = access->nc->display;
+ Nicks = access->mask;
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access->nc));
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access));
ci->EraseAccess(Number - 1);
}
@@ -167,11 +169,12 @@ class CommandCSAccess : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
- const Anope::string &nick = params[2];
+ Anope::string mask = params[2];
int level = params[3].is_number_only() ? convertTo<int>(params[3]) : ACCESS_INVALID;
- int ulev = get_access(u, ci);
- if (level >= ulev && !u->Account()->HasPriv("chanserv/access/modify"))
+ ChanAccess *u_access = ci->GetAccess(u);
+ int16 u_level = u_access ? u_access->level : 0;
+ if (level >= u_level && !u->Account()->HasPriv("chanserv/access/modify"))
{
source.Reply(ACCESS_DENIED);
return MOD_CONT;
@@ -188,41 +191,37 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
- bool override = !check_access(u, ci, CA_ACCESS_CHANGE) || level >= ulev;
+ bool override = !check_access(u, ci, CA_ACCESS_CHANGE) || level >= u_level;
- NickAlias *na = findnick(nick);
- if (!na)
+ NickAlias *na = findnick(mask);
+ if (!na && mask.find_first_of("!@*") == Anope::string::npos)
+ mask += "!*@*";
+ else if (na && na->HasFlag(NS_FORBIDDEN))
{
- source.Reply(CHAN_ACCESS_NICKS_ONLY);
- return MOD_CONT;
- }
- else if (na->HasFlag(NS_FORBIDDEN))
- {
- source.Reply(NICK_X_FORBIDDEN, nick.c_str());
+ source.Reply(NICK_X_FORBIDDEN, mask.c_str());
return MOD_CONT;
}
- NickCore *nc = na->nc;
- ChanAccess *access = ci->GetAccess(nc);
+ ChanAccess *access = ci->GetAccess(mask);
if (access)
{
- /* Don't allow lowering from a level >= ulev */
- if (access->level >= ulev && !u->Account()->HasPriv("chanserv/access/modify"))
+ /* Don't allow lowering from a level >= u_level */
+ if (access->level >= u_level && !u->Account()->HasPriv("chanserv/access/modify"))
{
source.Reply(ACCESS_DENIED);
return MOD_CONT;
}
if (access->level == level)
{
- source.Reply(CHAN_ACCESS_LEVEL_UNCHANGED, access->nc->display.c_str(), ci->name.c_str(), level);
+ source.Reply(CHAN_ACCESS_LEVEL_UNCHANGED, access->mask.c_str(), ci->name.c_str(), level);
return MOD_CONT;
}
access->level = level;
- FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na->nc, level));
+ FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, access));
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << na->nick << " (group: " << nc->display << ") (level: " << level << ") as level " << ulev;
- source.Reply(CHAN_ACCESS_LEVEL_CHANGED, nc->display.c_str(), ci->name.c_str(), level);
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << na->nick << " (level: " << level << ") as level " << u_level;
+ source.Reply(CHAN_ACCESS_LEVEL_CHANGED, access->mask.c_str(), ci->name.c_str(), level);
return MOD_CONT;
}
@@ -232,12 +231,12 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
- ci->AddAccess(nc, level, u->nick);
+ access = ci->AddAccess(mask, level, u->nick);
- FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, nc, level));
+ FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, access));
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << na->nick << " (group: " << nc->display << ") (level: " << level << ") as level " << ulev;
- source.Reply(CHAN_ACCESS_ADDED, nc->display.c_str(), ci->name.c_str(), level);
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level;
+ source.Reply(CHAN_ACCESS_ADDED, access->mask.c_str(), ci->name.c_str(), level);
return MOD_CONT;
}
@@ -247,49 +246,33 @@ class CommandCSAccess : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
- const Anope::string &nick = params[2];
+ const Anope::string &mask = params[2];
if (!ci->GetAccessCount())
source.Reply(CHAN_ACCESS_LIST_EMPTY, ci->name.c_str());
- else if (isdigit(nick[0]) && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
+ else if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- AccessDelCallback list(source, this, nick);
+ AccessDelCallback list(source, this, mask);
list.Process();
}
else
{
- NickAlias *na = findnick(nick);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- return MOD_CONT;
- }
-
- NickCore *nc = na->nc;
-
- unsigned i, end;
- ChanAccess *access = NULL;
- for (i = 0, end = ci->GetAccessCount(); i < end; ++i)
- {
- access = ci->GetAccess(i);
-
- if (access->nc == nc)
- break;
- }
-
- if (i == end)
- source.Reply(CHAN_ACCESS_NOT_FOUND, nick.c_str(), ci->name.c_str());
- else if (nc != u->Account() && check_access(u, ci, CA_NOJOIN) && get_access(u, ci) <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
+ ChanAccess *access = ci->GetAccess(mask);
+ ChanAccess *u_access = ci->GetAccess(u);
+ int16 u_level = u_access ? u_access->level : 0;
+ if (!access)
+ source.Reply(CHAN_ACCESS_NOT_FOUND, mask.c_str(), ci->name.c_str());
+ else if (access->nc != u->Account() && check_access(u, ci, CA_NOJOIN) && u_level <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
source.Reply(ACCESS_DENIED);
else
{
- source.Reply(CHAN_ACCESS_DELETED, access->nc->display.c_str(), ci->name.c_str());
- bool override = !check_access(u, ci, CA_ACCESS_CHANGE) && nc != u->Account();
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << na->nick << " (group: " << access->nc->display << ") from level " << access->level;
+ source.Reply(CHAN_ACCESS_DELETED, access->mask.c_str(), ci->name.c_str());
+ bool override = !check_access(u, ci, CA_ACCESS_CHANGE) && access->nc != u->Account();
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << access->mask << " from level " << access->level;
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, na->nc));
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access));
- ci->EraseAccess(i);
+ ci->EraseAccess(access);
}
}
@@ -317,7 +300,7 @@ class CommandCSAccess : public Command
{
ChanAccess *access = ci->GetAccess(i);
- if (!nick.empty() && access->nc && !Anope::Match(access->nc->display, nick))
+ if (!nick.empty() && !Anope::Match(access->mask, nick))
continue;
if (!SentHeader)
@@ -359,7 +342,7 @@ class CommandCSAccess : public Command
{
ChanAccess *access = ci->GetAccess(i);
- if (!nick.empty() && access->nc && !Anope::Match(access->nc->display, nick))
+ if (!nick.empty() && !Anope::Match(access->mask, nick))
continue;
if (!SentHeader)
diff --git a/modules/core/cs_akick.cpp b/modules/core/cs_akick.cpp
index 4df83d121..20ceb7c10 100644
--- a/modules/core/cs_akick.cpp
+++ b/modules/core/cs_akick.cpp
@@ -202,7 +202,9 @@ class CommandCSAKick : public Command
* or whether the mask matches a user with higher/equal access - Viper */
if (ci->HasFlag(CI_PEACE) && nc)
{
- if (nc == ci->founder || get_access_level(ci, nc) >= get_access(u, ci))
+ ChanAccess *nc_access = ci->GetAccess(nc), *u_access = ci->GetAccess(u);
+ int16 nc_level = nc_access ? nc_access->level : 0, u_level = u_access ? u_access->level : 0;
+ if (nc == ci->founder || nc_level >= u_level)
{
source.Reply(ACCESS_DENIED);
return;
@@ -216,7 +218,9 @@ class CommandCSAKick : public Command
{
User *u2 = *it;
- if ((check_access(u2, ci, CA_FOUNDER) || get_access(u2, ci) >= get_access(u, ci)) && match_usermask(mask, u2))
+ ChanAccess *u2_access = ci->GetAccess(nc), *u_access = ci->GetAccess(u);
+ int16 u2_level = u2_access ? u2_access->level : 0, u_level = u_access ? u_access->level : 0;
+ if ((check_access(u2, ci, CA_FOUNDER) || u2_level >= u_level) && match_usermask(mask, u2))
{
source.Reply(ACCESS_DENIED);
return;
@@ -232,7 +236,9 @@ class CommandCSAKick : public Command
if (na2->HasFlag(NS_FORBIDDEN))
continue;
- if (na2->nc && (na2->nc == ci->founder || get_access_level(ci, na2->nc) >= get_access(u, ci)))
+ ChanAccess *na2_access = ci->GetAccess(na2->nc), *u_access = ci->GetAccess(u);
+ int16 na2_level = na2_access ? na2_access->level : 0, u_level = u_access ? u_access->level : 0;
+ if (na2->nc && (na2->nc == ci->founder || na2_level >= u_level))
{
Anope::string buf = na2->nick + "!" + na2->last_usermask;
if (Anope::Match(buf, mask))
diff --git a/modules/core/cs_ban.cpp b/modules/core/cs_ban.cpp
index bbcfd1325..a187b5737 100644
--- a/modules/core/cs_ban.cpp
+++ b/modules/core/cs_ban.cpp
@@ -29,17 +29,19 @@ class CommandCSBan : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
Channel *c = ci->c;
- User *u2;
-
bool is_same = target.equals_ci(u->nick);
+ User *u2 = is_same ? u : finduser(target);
+
+ ChanAccess *u_access = ci->GetAccess(u), *u2_access = ci->GetAccess(u2);
+ uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0;
if (!c)
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
- else if (is_same ? !(u2 = u) : !(u2 = finduser(target)))
+ else if (!u2)
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
else if (!is_same ? !check_access(u, ci, CA_BAN) : !check_access(u, ci, CA_BANME))
source.Reply(ACCESS_DENIED);
- else if (!is_same && (ci->HasFlag(CI_PEACE)) && (get_access(u2, ci) >= get_access(u, ci)))
+ else if (!is_same && ci->HasFlag(CI_PEACE) && u2_level >= u_level)
source.Reply(ACCESS_DENIED);
/*
* Dont ban/kick the user on channels where he is excepted
diff --git a/modules/core/cs_clone.cpp b/modules/core/cs_clone.cpp
index b36d75dc5..7eb5fd6bd 100644
--- a/modules/core/cs_clone.cpp
+++ b/modules/core/cs_clone.cpp
@@ -108,7 +108,7 @@ public:
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
ChanAccess *access = ci->GetAccess(i);
- target_ci->AddAccess(access->nc, access->level, access->creator, access->last_seen);
+ target_ci->AddAccess(access->mask, access->level, access->creator, access->last_seen);
}
source.Reply(CHAN_CLONED_ACCESS, channel.c_str(), target.c_str());
diff --git a/modules/core/cs_kick.cpp b/modules/core/cs_kick.cpp
index 8a2dd8b04..b829ce249 100644
--- a/modules/core/cs_kick.cpp
+++ b/modules/core/cs_kick.cpp
@@ -29,17 +29,19 @@ class CommandCSKick : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
Channel *c = ci->c;
- User *u2;
-
bool is_same = target.equals_ci(u->nick);
+ User *u2 = is_same ? u : finduser(target);
+
+ ChanAccess *u_access = ci->GetAccess(u), *u2_access = ci->GetAccess(u2);
+ uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0;
if (!c)
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
- else if (is_same ? !(u2 = u) : !(u2 = finduser(target)))
+ else if (!u2)
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
else if (!is_same ? !check_access(u, ci, CA_KICK) : !check_access(u, ci, CA_KICKME))
source.Reply(ACCESS_DENIED);
- else if (!is_same && (ci->HasFlag(CI_PEACE)) && get_access(u2, ci) >= get_access(u, ci))
+ else if (!is_same && (ci->HasFlag(CI_PEACE)) && u2_level >= u_level)
source.Reply(ACCESS_DENIED);
else if (u2->IsProtected())
source.Reply(ACCESS_DENIED);
diff --git a/modules/core/cs_modes.cpp b/modules/core/cs_modes.cpp
index 86e1193ef..885b4d81e 100644
--- a/modules/core/cs_modes.cpp
+++ b/modules/core/cs_modes.cpp
@@ -30,18 +30,20 @@ static CommandReturn do_util(CommandSource &source, Command *com, ChannelMode *c
User *u = source.u;
Channel *c = findchan(chan);
ChannelInfo *ci = c ? c->ci : NULL;
- User *u2;
-
Anope::string realnick = (!nick.empty() ? nick : u->nick);
bool is_same = u->nick.equals_ci(realnick);
+ User *u2 = is_same ? u : finduser(realnick);
+
+ ChanAccess *u_access = ci->GetAccess(u), *u2_access = ci->GetAccess(u2);
+ uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0;
if (!c)
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
- else if (is_same ? !(u2 = u) : !(u2 = finduser(realnick)))
+ else if (!u2)
source.Reply(NICK_X_NOT_IN_USE, realnick.c_str());
else if (is_same ? !check_access(u, ci, levelself) : !check_access(u, ci, level))
source.Reply(ACCESS_DENIED);
- else if (!set && !is_same && (ci->HasFlag(CI_PEACE)) && (get_access(u2, ci) >= get_access(u, ci)))
+ else if (!set && !is_same && ci->HasFlag(CI_PEACE) && u2_level >= u_level)
source.Reply(ACCESS_DENIED);
else if (!set && u2->IsProtected() && !is_same)
source.Reply(ACCESS_DENIED);
diff --git a/modules/core/cs_register.cpp b/modules/core/cs_register.cpp
index 39155fe84..db756afa2 100644
--- a/modules/core/cs_register.cpp
+++ b/modules/core/cs_register.cpp
@@ -28,7 +28,7 @@ class CommandCSRegister : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
- Channel *c = ci->c;
+ Channel *c = findchan(chan);
if (readonly)
{
@@ -42,7 +42,7 @@ class CommandCSRegister : public Command
source.Reply(CHAN_SYMBOL_REQUIRED);
else if (!ircdproto->IsChannelValid(chan))
source.Reply(CHAN_X_INVALID, chan.c_str());
- else if ((ci = cs_findchan(chan)))
+ else if (ci)
source.Reply(CHAN_ALREADY_REGISTERED, chan.c_str());
else if (c && !c->HasUserStatus(u, CMODE_OP))
source.Reply(CHAN_MUST_BE_CHANOP);
diff --git a/modules/core/cs_status.cpp b/modules/core/cs_status.cpp
index 899632bbf..a2a69b18e 100644
--- a/modules/core/cs_status.cpp
+++ b/modules/core/cs_status.cpp
@@ -26,8 +26,9 @@ class CommandCSStatus : public Command
const Anope::string &nick = params[1];
User *u2 = finduser(nick);
+ ChanAccess *u2_access = ci->GetAccess(u2);
if (u2)
- source.Reply(CHAN_STATUS_INFO, ci->name.c_str(), u2->nick.c_str(), get_access(u2, ci));
+ source.Reply(CHAN_STATUS_INFO, ci->name.c_str(), u2->nick.c_str(), u2_access ? u2_access->level : 0);
else /* !u2 */
source.Reply(CHAN_STATUS_NOTONLINE, nick.c_str());
return MOD_CONT;
diff --git a/modules/core/cs_xop.cpp b/modules/core/cs_xop.cpp
index 1b15d07fd..f883d1baa 100644
--- a/modules/core/cs_xop.cpp
+++ b/modules/core/cs_xop.cpp
@@ -26,7 +26,6 @@ enum
enum
{
XOP_DISABLED,
- XOP_NICKS_ONLY,
XOP_ADDED,
XOP_MOVED,
XOP_NO_SUCH_ENTRY,
@@ -43,7 +42,6 @@ enum
LanguageString xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
{CHAN_AOP_DISABLED,
- CHAN_AOP_NICKS_ONLY,
CHAN_AOP_ADDED,
CHAN_AOP_MOVED,
CHAN_AOP_NO_SUCH_ENTRY,
@@ -56,7 +54,6 @@ LanguageString xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
CHAN_AOP_LIST_HEADER,
CHAN_AOP_CLEAR},
{CHAN_SOP_DISABLED,
- CHAN_SOP_NICKS_ONLY,
CHAN_SOP_ADDED,
CHAN_SOP_MOVED,
CHAN_SOP_NO_SUCH_ENTRY,
@@ -69,7 +66,6 @@ LanguageString xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
CHAN_SOP_LIST_HEADER,
CHAN_SOP_CLEAR},
{CHAN_VOP_DISABLED,
- CHAN_VOP_NICKS_ONLY,
CHAN_VOP_ADDED,
CHAN_VOP_MOVED,
CHAN_VOP_NO_SUCH_ENTRY,
@@ -82,7 +78,6 @@ LanguageString xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
CHAN_VOP_LIST_HEADER,
CHAN_VOP_CLEAR},
{CHAN_HOP_DISABLED,
- CHAN_HOP_NICKS_ONLY,
CHAN_HOP_ADDED,
CHAN_HOP_MOVED,
CHAN_HOP_NO_SUCH_ENTRY,
@@ -95,7 +90,6 @@ LanguageString xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
CHAN_HOP_LIST_HEADER,
CHAN_HOP_CLEAR},
{CHAN_QOP_DISABLED,
- CHAN_QOP_NICKS_ONLY,
CHAN_QOP_ADDED,
CHAN_QOP_MOVED,
CHAN_QOP_NO_SUCH_ENTRY,
@@ -141,7 +135,7 @@ class XOPListCallback : public NumberList
static void DoList(CommandSource &source, ChanAccess *access, unsigned index, int level, LanguageString *messages)
{
- source.Reply(CHAN_XOP_LIST_FORMAT, index, access->nc->display.c_str());
+ source.Reply(CHAN_XOP_LIST_FORMAT, index, access->mask.c_str());
}
};
@@ -182,11 +176,11 @@ class XOPDelCallback : public NumberList
++Deleted;
if (!Nicks.empty())
- Nicks += ", " + access->nc->display;
+ Nicks += ", " + access->mask;
else
- Nicks = access->nc->display;
+ Nicks = access->mask;
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(source.ci, source.u, access->nc));
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(source.ci, source.u, access));
source.ci->EraseAccess(Number - 1);
}
@@ -200,11 +194,10 @@ class XOPBase : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
- const Anope::string &nick = params.size() > 2 ? params[2] : "";
- ChanAccess *access;
+ Anope::string mask = params.size() > 2 ? params[2] : "";
int change = 0;
- if (nick.empty())
+ if (mask.empty())
{
this->OnSyntaxError(source, "ADD");
return MOD_CONT;
@@ -216,7 +209,8 @@ class XOPBase : public Command
return MOD_CONT;
}
- short ulev = get_access(u, ci);
+ ChanAccess *access = ci->GetAccess(u);
+ uint16 ulev = access ? access->level : 0;
if ((level >= ulev || ulev < ACCESS_AOP) && !u->Account()->HasPriv("chanserv/access/modify"))
{
@@ -224,20 +218,16 @@ class XOPBase : public Command
return MOD_CONT;
}
- NickAlias *na = findnick(nick);
- if (!na)
- {
- source.Reply(messages[XOP_NICKS_ONLY]);
- return MOD_CONT;
- }
- else if (na->HasFlag(NS_FORBIDDEN))
+ NickAlias *na = findnick(mask);
+ if (!na && mask.find_first_of("!@*") == Anope::string::npos)
+ mask += "!*@*";
+ else if (na && na->HasFlag(NS_FORBIDDEN))
{
source.Reply(NICK_X_FORBIDDEN, na->nick.c_str());
return MOD_CONT;
}
- NickCore *nc = na->nc;
- access = ci->GetAccess(nc);
+ access = ci->GetAccess(mask);
if (access)
{
/**
@@ -258,7 +248,7 @@ class XOPBase : public Command
}
if (!change)
- ci->AddAccess(nc, level, u->nick);
+ access = ci->AddAccess(mask, level, u->nick);
else
{
access->level = level;
@@ -267,17 +257,17 @@ class XOPBase : public Command
}
bool override = (level >= ulev || ulev < ACCESS_AOP || (access && access->level > ulev));
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << na->nick << " (group: " << nc->display << ") as level " << level;
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " as level " << level;
if (!change)
{
- FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, nc, level));
- source.Reply(messages[XOP_ADDED], nc->display.c_str(), ci->name.c_str());
+ FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, access));
+ source.Reply(messages[XOP_ADDED], access->mask.c_str(), ci->name.c_str());
}
else
{
- FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na->nc, level));
- source.Reply(messages[XOP_MOVED], nc->display.c_str(), ci->name.c_str());
+ FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, access));
+ source.Reply(messages[XOP_MOVED], access->mask.c_str(), ci->name.c_str());
}
return MOD_CONT;
@@ -288,10 +278,9 @@ class XOPBase : public Command
User *u = source.u;
ChannelInfo *ci = source.ci;
- const Anope::string &nick = params.size() > 2 ? params[2] : "";
- ChanAccess *access;
+ const Anope::string &mask = params.size() > 2 ? params[2] : "";
- if (nick.empty())
+ if (mask.empty())
{
this->OnSyntaxError(source, "DEL");
return MOD_CONT;
@@ -309,62 +298,43 @@ class XOPBase : public Command
return MOD_CONT;
}
- NickAlias *na = NULL;
- if (!isdigit(nick[0]))
- {
- na = findnick(nick);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- return MOD_CONT;
- }
- }
-
- short ulev = get_access(u, ci);
+ ChanAccess *access = ci->GetAccess(u);
+ uint16 ulev = access ? access->level : 0;
- if ((!na || na->nc != u->Account()) && (level >= ulev || ulev < ACCESS_AOP) && !u->Account()->HasPriv("chanserv/access/modify"))
+ if ((!access || access->nc != u->Account()) && (level >= ulev || ulev < ACCESS_AOP) && !u->Account()->HasPriv("chanserv/access/modify"))
{
source.Reply(ACCESS_DENIED);
return MOD_CONT;
}
+ access = ci->GetAccess(mask);
+
/* Special case: is it a number/list? Only do search if it isn't. */
- if (isdigit(nick[0]) && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
+ if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
bool override = level >= ulev || ulev < ACCESS_AOP;
- XOPDelCallback list(source, this, messages, override, nick);
+ XOPDelCallback list(source, this, messages, override, mask);
list.Process();
}
+ else if (!access)
+ {
+ source.Reply(messages[XOP_NOT_FOUND], mask.c_str(), ci->name.c_str());
+ return MOD_CONT;
+ }
else
{
- NickCore *nc = na->nc;
- unsigned i, end;
- for (i = 0, end = ci->GetAccessCount(); i < end; ++i)
- {
- access = ci->GetAccess(nc, level);
-
- if (access->nc == nc)
- break;
- }
-
- if (i == end)
- {
- source.Reply(messages[XOP_NOT_FOUND], nick.c_str(), ci->name.c_str());
- return MOD_CONT;
- }
-
- if (nc != u->Account() && ulev <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
+ if (access->nc != u->Account() && ulev <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
source.Reply(ACCESS_DENIED);
else
{
bool override = ulev <= access->level;
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << access->nc->display;
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DEL " << access->mask;
- source.Reply(messages[XOP_DELETED], access->nc->display.c_str(), ci->name.c_str());
+ source.Reply(messages[XOP_DELETED], access->mask.c_str(), ci->name.c_str());
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, na->nc));
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access));
- ci->EraseAccess(i);
+ ci->EraseAccess(access);
}
}
@@ -378,13 +348,16 @@ class XOPBase : public Command
const Anope::string &nick = params.size() > 2 ? params[2] : "";
- if (!get_access(u, ci) && !u->Account()->HasCommand("chanserv/access/list"))
+ ChanAccess *access = ci->GetAccess(u);
+ uint16 ulev = access ? access->level : 0;
+
+ if (!ulev && !u->Account()->HasCommand("chanserv/access/list"))
{
source.Reply(ACCESS_DENIED);
return MOD_CONT;
}
- bool override = !get_access(u, ci);
+ bool override = !ulev;
Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci);
if (!ci->GetAccessCount())
@@ -404,11 +377,11 @@ class XOPBase : public Command
for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i)
{
- ChanAccess *access = ci->GetAccess(i);
+ access = ci->GetAccess(i);
if (access->level != level)
continue;
- else if (!nick.empty() && access->nc && !Anope::Match(access->nc->display, nick))
+ else if (!nick.empty() && !Anope::Match(access->mask, nick))
continue;
if (!SentHeader)
@@ -489,7 +462,7 @@ class XOPBase : public Command
return MOD_CONT;
}
public:
- XOPBase(const Anope::string &command) : Command(command, 2, 3)
+ XOPBase(const Anope::string &command) : Command(command, 2, 4)
{
}
diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp
index 2c655b7d9..44058d5e5 100644
--- a/modules/core/db_plain.cpp
+++ b/modules/core/db_plain.cpp
@@ -697,17 +697,9 @@ class DBPlain : public Module
}
else if (key.equals_ci("ACCESS"))
{
- NickCore *nc = findcore(params[0]);
- if (!nc)
- {
- std::stringstream reason;
- reason << "Access entry for nonexistant core " << params[0] << " on " << ci->name;
- throw DatabaseException(reason.str());
- }
-
int level = params[1].is_number_only() ? convertTo<int>(params[1]) : 0;
time_t last_seen = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0;
- ci->AddAccess(nc, level, params[3], last_seen);
+ ci->AddAccess(params[0], level, params[3], last_seen);
}
else if (key.equals_ci("AKICK"))
{
@@ -972,7 +964,7 @@ class DBPlain : public Module
db << "MD FORBID " << ci->forbidby << " :" << ci->forbidreason << endl;
}
for (unsigned k = 0, end = ci->GetAccessCount(); k < end; ++k)
- db << "MD ACCESS " << ci->GetAccess(k)->nc->display << " " << ci->GetAccess(k)->level << " " << ci->GetAccess(k)->last_seen << " " << ci->GetAccess(k)->creator << endl;
+ db << "MD ACCESS " << ci->GetAccess(k)->mask << " " << ci->GetAccess(k)->level << " " << ci->GetAccess(k)->last_seen << " " << ci->GetAccess(k)->creator << endl;
for (unsigned k = 0, end = ci->GetAkickCount(); k < end; ++k)
{
db << "MD AKICK 0 " << (ci->GetAkick(k)->HasFlag(AK_ISNICK) ? "NICK " : "MASK ") <<
diff --git a/modules/core/ms_staff.cpp b/modules/core/ms_staff.cpp
index 76ab0cf2e..fcbf1aee9 100644
--- a/modules/core/ms_staff.cpp
+++ b/modules/core/ms_staff.cpp
@@ -22,7 +22,6 @@ class CommandMSStaff : public Command
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
- User *u = source.u;
const Anope::string &text = params[0];
if (readonly)
diff --git a/modules/core/ns_access.cpp b/modules/core/ns_access.cpp
index 16e8690c2..51baab194 100644
--- a/modules/core/ns_access.cpp
+++ b/modules/core/ns_access.cpp
@@ -47,7 +47,6 @@ class CommandNSAccess : public Command
CommandReturn DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
- User *u = source.u;
if (mask.empty())
{
@@ -75,8 +74,6 @@ class CommandNSAccess : public Command
CommandReturn DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
- User *u = source.u;
-
if (mask.empty())
{
this->OnSyntaxError(source, "DEL");
diff --git a/modules/core/ns_alist.cpp b/modules/core/ns_alist.cpp
index f6879b6e7..fc3c9f828 100644
--- a/modules/core/ns_alist.cpp
+++ b/modules/core/ns_alist.cpp
@@ -84,7 +84,6 @@ class CommandNSAList : public Command
source.Reply(CHAN_ACCESS_LEVEL_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1);
else
{
- int level;
int chan_count = 0;
int match_count = 0;
@@ -94,23 +93,24 @@ class CommandNSAList : public Command
{
ChannelInfo *ci = it->second;
- if ((level = get_access_level(ci, na)))
+ ChanAccess *access = ci->GetAccess(na->nc);
+ if (access)
{
++chan_count;
- if (min_level > level)
+ if (min_level > access->level)
continue;
++match_count;
- if (ci->HasFlag(CI_XOP) || level == ACCESS_FOUNDER)
+ if (ci->HasFlag(CI_XOP) || access->level == ACCESS_FOUNDER)
{
- Anope::string xop = get_xop_level(level);
+ Anope::string xop = get_xop_level(access->level);
source.Reply(NICK_ALIST_XOP_FORMAT, match_count, ci->HasFlag(CI_NO_EXPIRE) ? '!' : ' ', ci->name.c_str(), xop.c_str(), !ci->desc.empty() ? ci->desc.c_str() : "");
}
else
- source.Reply(NICK_ALIST_ACCESS_FORMAT, match_count, ci->HasFlag(CI_NO_EXPIRE) ? '!' : ' ', ci->name.c_str(), level, !ci->desc.empty() ? ci->desc.c_str() : "");
+ source.Reply(NICK_ALIST_ACCESS_FORMAT, match_count, ci->HasFlag(CI_NO_EXPIRE) ? '!' : ' ', ci->name.c_str(), access->level, !ci->desc.empty() ? ci->desc.c_str() : "");
}
}
diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp
index 6c6c1c9e0..93f540be3 100644
--- a/modules/extra/db_mysql.cpp
+++ b/modules/extra/db_mysql.cpp
@@ -750,14 +750,7 @@ class DBMySQL : public Module
continue;
}
- NickCore *nc = findcore(r.Get(i, "display"));
- if (!nc)
- {
- Log() << "MySQL: Channel access entry for " << ci->name << " with nonexistant nick " << r.Get(i, "display");
- continue;
- }
-
- ci->AddAccess(nc, atoi(r.Get(i, "level").c_str()), r.Get(i, "creator"), (r.Get(i, "last_seen").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "last_seen")) : Anope::CurTime));
+ ci->AddAccess(r.Get(i, "display"), atoi(r.Get(i, "level").c_str()), r.Get(i, "creator"), (r.Get(i, "last_seen").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "last_seen")) : Anope::CurTime));
}
r = SQL->RunQuery("SELECT * FROM `anope_cs_akick`");
@@ -1216,19 +1209,19 @@ class DBMySQL : public Module
this->RunQuery("UPDATE `anope_ns_core` SET `flags` = '" + BuildFlagsList(na->nc) + "' WHERE `display` = '" + this->Escape(na->nc->display) + "'");
}
- void OnAccessAdd(ChannelInfo *ci, User *u, NickCore *nc, int level)
+ void OnAccessAdd(ChannelInfo *ci, User *u, ChanAccess *access)
{
- this->RunQuery("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES (" + stringify(level) + ", '" + this->Escape(nc->display) + "', '" + this->Escape(ci->name) + "', " + stringify(Anope::CurTime) + ", '" + this->Escape(u->nick) + "')");
+ this->RunQuery("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES (" + stringify(access->level) + ", '" + this->Escape(access->mask) + "', '" + this->Escape(ci->name) + "', " + stringify(Anope::CurTime) + ", '" + this->Escape(u->nick) + "')");
}
- void OnAccessDel(ChannelInfo *ci, User *u, NickCore *nc)
+ void OnAccessDel(ChannelInfo *ci, User *u, ChanAccess *access)
{
- this->RunQuery("DELETE FROM `anope_cs_access` WHERE `display` = '" + this->Escape(nc->display) + "' AND `channel` = '" + this->Escape(ci->name) + "'");
+ this->RunQuery("DELETE FROM `anope_cs_access` WHERE `display` = '" + this->Escape(access->mask) + "' AND `channel` = '" + this->Escape(ci->name) + "'");
}
- void OnAccessChange(ChannelInfo *ci, User *u, NickAlias *na, int level)
+ void OnAccessChange(ChannelInfo *ci, User *u, ChanAccess *access)
{
- this->RunQuery("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES (" + stringify(level) + ", '" + this->Escape(na->nc->display) + "', '" + this->Escape(ci->name) + "', " + stringify(Anope::CurTime) + ", '" + this->Escape(u->nick) + "') ON DUPLICATE KEY UPDATE level=VALUES(level), display=VALUES(display), channel=VALUES(channel), last_seen=VALUES(last_seen), creator=VALUES(creator)");
+ this->RunQuery("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES (" + stringify(access->level) + ", '" + this->Escape(access->mask) + "', '" + this->Escape(ci->name) + "', " + stringify(Anope::CurTime) + ", '" + this->Escape(u->nick) + "') ON DUPLICATE KEY UPDATE level=VALUES(level), display=VALUES(display), channel=VALUES(channel), last_seen=VALUES(last_seen), creator=VALUES(creator)");
}
void OnAccessClear(ChannelInfo *ci, User *u)
@@ -1565,7 +1558,7 @@ static void SaveDatabases()
{
ChanAccess *access = ci->GetAccess(j);
- me->RunQuery(Anope::string("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES('") + access->level + "', " + me->Escape(access->nc->display) + ", " + me->Escape(ci->name) + ", " + access->last_seen + ", " + me->Escape(access->creator) + ") ON DUPLICATE KEY UPDATE level=VALUES(level), last_seen=VALUES(last_seen), creator=VALUES(creator)");
+ me->RunQuery(Anope::string("INSERT INTO `anope_cs_access` (level, display, channel, last_seen, creator) VALUES('") + access->level + "', " + me->Escape(access->mask) + ", " + me->Escape(ci->name) + ", " + access->last_seen + ", " + me->Escape(access->creator) + ") ON DUPLICATE KEY UPDATE level=VALUES(level), last_seen=VALUES(last_seen), creator=VALUES(creator)");
}
for (unsigned j = 0, end = ci->GetAkickCount(); j < end; ++j)
diff --git a/src/botserv.cpp b/src/botserv.cpp
index 1e7eb9551..32b6a42a3 100644
--- a/src/botserv.cpp
+++ b/src/botserv.cpp
@@ -511,7 +511,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co
Anope::string mask;
User *u = finduser(nick);
- if (!u)
+ if (!u || !ci)
return;
if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u)
@@ -520,7 +520,9 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co
return;
}
- if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci))
+ ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester);
+ int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0;
+ if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level)
return;
if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(ci, u) == 1)
@@ -548,7 +550,7 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c
{
User *u = finduser(nick);
- if (!u || !ci->c->FindUser(u))
+ if (!u || !ci || !ci->c || !ci->c->FindUser(u))
return;
if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u)
@@ -557,7 +559,9 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c
return;
}
- if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci))
+ ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester);
+ int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0;
+ if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level)
return;
if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK)))
@@ -577,7 +581,7 @@ void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, c
u = finduser(nick);
- if (!u || !ci->c->FindUser(u))
+ if (!u || !ci || !ci->c || !ci->c->FindUser(u))
return;
snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(Anope::CurTime));
@@ -588,7 +592,9 @@ void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, c
return;
}
- if (mode[0] == '-' && ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci))
+ ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester);
+ int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0;
+ if (mode[0] == '-' && ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level)
return;
ci->c->SetModes(NULL, "%s %s", mode.c_str(), nick.c_str());
diff --git a/src/channels.cpp b/src/channels.cpp
index 85752a774..f146c17dd 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -459,7 +459,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string &param, bo
/* Enforce secureops, etc */
if (EnforceMLock)
- chan_set_correct_modes(u, this, 1);
+ chan_set_correct_modes(u, this, 0);
return;
}
@@ -1207,9 +1207,9 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes)
{
if ((ml.set && !c->HasUserStatus(user, ml.name)) || (!ml.set && c->HasUserStatus(user, ml.name)))
{
- if (ml.set && give_modes)
+ if (ml.set)
c->SetMode(NULL, cm, user->nick, false);
- else if (!ml.set && !give_modes)
+ else if (!ml.set)
c->RemoveMode(NULL, cm, user->nick, false);
}
}
diff --git a/src/chanserv.cpp b/src/chanserv.cpp
index a2307a082..e3a8993b0 100644
--- a/src/chanserv.cpp
+++ b/src/chanserv.cpp
@@ -401,19 +401,15 @@ void expire_chans()
/*************************************************************************/
// XXX this is slightly inefficient
-void cs_remove_nick(const NickCore *nc)
+void cs_remove_nick(NickCore *nc)
{
for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it)
{
ChannelInfo *ci = it->second;
- for (unsigned j = ci->GetAccessCount(); j > 0; --j)
- {
- ChanAccess *ca = ci->GetAccess(j - 1);
-
- if (ca->nc == nc)
- ci->EraseAccess(j - 1);
- }
+ ChanAccess *access = ci->GetAccess(nc);
+ if (access)
+ ci->EraseAccess(access);
for (unsigned j = ci->GetAkickCount(); j > 0; --j)
{
@@ -497,7 +493,8 @@ int check_access(User *user, ChannelInfo *ci, int what)
if (!user || !ci)
return 0;
- level = get_access(user, ci);
+ ChanAccess *u_access = ci->GetAccess(user);
+ level = u_access ? u_access->level : 0;
limit = ci->levels[what];
/* Resetting the last used time */
@@ -564,45 +561,6 @@ bool IsFounder(User *user, ChannelInfo *ci)
return false;
}
-/** Return the access level for the user on the channel.
- * If the channel doesn't exist, the user isn't on the access list, or the
- * channel is CI_SECURE and the user isn't identified, return 0
- * @param user The user
- * @param ci The cahnnel
- * @return The level, or 0
- */
-int get_access(User *user, ChannelInfo *ci)
-{
- ChanAccess *access = NULL;
-
- if (!ci || !user)
- return 0;
-
- /* SuperAdmin always has highest level */
- if (user->isSuperAdmin)
- return ACCESS_SUPERADMIN;
-
- if (IsFounder(user, ci))
- return ACCESS_FOUNDER;
-
- if (user->IsIdentified())
- {
- access = ci->GetAccess(user->Account());
- if (access)
- return access->level;
- }
- else
- {
- NickAlias *na = findnick(user->nick);
- if (na)
- access = ci->GetAccess(na->nc);
- if (access && user->IsRecognized() && !ci->HasFlag(CI_SECURE))
- return access->level;
- }
-
- return 0;
-}
-
/*************************************************************************/
void update_cs_lastseen(User *user, ChannelInfo *ci)
@@ -613,7 +571,7 @@ void update_cs_lastseen(User *user, ChannelInfo *ci)
return;
if (IsFounder(user, ci) || user->IsIdentified() || (user->IsRecognized() && !ci->HasFlag(CI_SECURE)))
- if ((access = ci->GetAccess(user->Account())))
+ if ((access = ci->GetAccess(user)))
access->last_seen = Anope::CurTime;
}
@@ -658,30 +616,6 @@ int get_idealban(ChannelInfo *ci, User *u, Anope::string &ret)
/*************************************************************************/
-int get_access_level(ChannelInfo *ci, NickCore *nc)
-{
- if (!ci || !nc)
- return 0;
-
- if (nc == ci->founder)
- return ACCESS_FOUNDER;
-
- ChanAccess *access = ci->GetAccess(nc);
-
- if (!access)
- return 0;
- else
- return access->level;
-}
-
-int get_access_level(ChannelInfo *ci, NickAlias *na)
-{
- if (!na)
- return 0;
-
- return get_access_level(ci, na->nc);
-}
-
Anope::string get_xop_level(int level)
{
ChannelMode *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP);
diff --git a/src/language.cpp b/src/language.cpp
index 649398cb3..3372bc9ff 100644
--- a/src/language.cpp
+++ b/src/language.cpp
@@ -958,8 +958,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("QOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"),
/* CHAN_QOP_DISABLED */
_("Sorry, channel QOP list modification is temporarily disabled."),
- /* CHAN_QOP_NICKS_ONLY */
- _("Channel QOP lists may only contain registered nicknames."),
/* CHAN_QOP_ADDED */
_("%s added to %s QOP list."),
/* CHAN_QOP_MOVED */
@@ -987,8 +985,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("AOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"),
/* CHAN_AOP_DISABLED */
_("Sorry, channel AOP list modification is temporarily disabled."),
- /* CHAN_AOP_NICKS_ONLY */
- _("Channel AOP lists may only contain registered nicknames."),
/* CHAN_AOP_ADDED */
_("%s added to %s AOP list."),
/* CHAN_AOP_MOVED */
@@ -1016,8 +1012,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("HOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"),
/* CHAN_HOP_DISABLED */
_("Sorry, channel HOP list modification is temporarily disabled."),
- /* CHAN_HOP_NICKS_ONLY */
- _("Channel HOP lists may only contain registered nicknames."),
/* CHAN_HOP_ADDED */
_("%s added to %s HOP list."),
/* CHAN_HOP_MOVED */
@@ -1045,8 +1039,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("SOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"),
/* CHAN_SOP_DISABLED */
_("Sorry, channel SOP list modification is temporarily disabled."),
- /* CHAN_SOP_NICKS_ONLY */
- _("Channel SOP lists may only contain registered nicknames."),
/* CHAN_SOP_ADDED */
_("%s added to %s SOP list."),
/* CHAN_SOP_MOVED */
@@ -1074,8 +1066,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("VOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"),
/* CHAN_VOP_DISABLED */
_("Sorry, channel VOP list modification is temporarily disabled."),
- /* CHAN_VOP_NICKS_ONLY */
- _("Channel VOP lists may only contain registered nicknames."),
/* CHAN_VOP_ADDED */
_("%s added to %s VOP list."),
/* CHAN_VOP_MOVED */
@@ -1100,7 +1090,7 @@ const char *const language_strings[LANG_STRING_COUNT] = {
/* CHAN_VOP_CLEAR */
_("Channel %s VOP list has been cleared."),
/* CHAN_ACCESS_SYNTAX */
- _("ACCESS channel {ADD|DEL|LIST|VIEW|CLEAR} [nick [level] | entry-list]"),
+ _("ACCESS channel {ADD|DEL|LIST|VIEW|CLEAR} [mask [level] | entry-list]"),
/* CHAN_ACCESS_XOP */
_("You can't use this command. \n"
"Use the AOP, SOP and VOP commands instead.\n"
@@ -1115,8 +1105,6 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("Access level must be non-zero."),
/* CHAN_ACCESS_LEVEL_RANGE */
_("Access level must be between %d and %d inclusive."),
- /* CHAN_ACCESS_NICKS_ONLY */
- _("Channel access lists may only contain registered nicknames."),
/* CHAN_ACCESS_REACHED_LIMIT */
_("Sorry, you can only have %d access entries on a channel."),
/* CHAN_ACCESS_LEVEL_UNCHANGED */
@@ -1139,7 +1127,7 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("%s access list is empty."),
/* CHAN_ACCESS_LIST_HEADER */
_("Access list for %s:\n"
- " Num Lev Nick"),
+ " Num Lev Mask"),
/* CHAN_ACCESS_LIST_FOOTER */
_("End of access list."),
/* CHAN_ACCESS_LIST_XOP_FORMAT */
@@ -3625,8 +3613,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"channel whenever the OP or DEOP commands are used for a user\n"
"in the channel."),
/* CHAN_HELP_QOP */
- _("Syntax: QOP channel ADD nick\n"
- " QOP channel DEL {nick | entry-num | list}\n"
+ _("Syntax: QOP channel ADD mask\n"
+ " QOP channel DEL {mask | entry-num | list}\n"
" QOP channel LIST [mask | list]\n"
" QOP channel CLEAR\n"
" \n"
@@ -3662,8 +3650,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"and %R%S HELP SET XOP to know how to toggle between \n"
"the access list and xOP list systems."),
/* CHAN_HELP_AOP */
- _("Syntax: AOP channel ADD nick\n"
- " AOP channel DEL {nick | entry-num | list}\n"
+ _("Syntax: AOP channel ADD mask\n"
+ " AOP channel DEL {mask | entry-num | list}\n"
" AOP channel LIST [mask | list]\n"
" AOP channel CLEAR\n"
" \n"
@@ -3701,8 +3689,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"and %R%S HELP SET XOP to know how to toggle between \n"
"the access list and xOP list systems."),
/* CHAN_HELP_HOP */
- _("Syntax: HOP channel ADD nick\n"
- " HOP channel DEL {nick | entry-num | list}\n"
+ _("Syntax: HOP channel ADD mask\n"
+ " HOP channel DEL {mask | entry-num | list}\n"
" HOP channel LIST [mask | list]\n"
" HOP channel CLEAR\n"
" \n"
@@ -3738,8 +3726,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"and %R%S HELP SET XOP to know how to toggle between \n"
"the access list and xOP list systems."),
/* CHAN_HELP_SOP */
- _("Syntax: SOP channel ADD nick\n"
- " SOP channel DEL {nick | entry-num | list}\n"
+ _("Syntax: SOP channel ADD mask\n"
+ " SOP channel DEL {mask | entry-num | list}\n"
" SOP channel LIST [mask | list]\n"
" SOP channel CLEAR\n"
" \n"
@@ -3776,8 +3764,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"and %R%S HELP SET XOP to know how to toggle between \n"
"the access list and xOP list systems."),
/* CHAN_HELP_VOP */
- _("Syntax: VOP channel ADD nick\n"
- " VOP channel DEL {nick | entry-num | list}\n"
+ _("Syntax: VOP channel ADD mask\n"
+ " VOP channel DEL {mask | entry-num | list}\n"
" VOP channel LIST [mask | list]\n"
" VOP channel CLEAR\n"
" \n"
@@ -3813,8 +3801,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"and %R%S HELP SET XOP to know how to toggle between \n"
"the access list and xOP list systems."),
/* CHAN_HELP_ACCESS */
- _("Syntax: ACCESS channel ADD nick level\n"
- " ACCESS channel DEL {nick | entry-num | list}\n"
+ _("Syntax: ACCESS channel ADD mask level\n"
+ " ACCESS channel DEL {mask | entry-num | list}\n"
" ACCESS channel LIST [mask | list]\n"
" ACCESS channel VIEW [mask | list]\n"
" ACCESS channel CLEAR\n"
@@ -3827,14 +3815,16 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"specific information. Any nick not on the access list has\n"
"a user level of 0.\n"
" \n"
- "The ACCESS ADD command adds the given nickname to the\n"
- "access list with the given user level; if the nick is\n"
+ "The ACCESS ADD command adds the given mask to the\n"
+ "access list with the given user level; if the mask is\n"
"already present on the list, its access level is changed to\n"
"the level specified in the command. The level specified\n"
"must be less than that of the user giving the command, and\n"
- "if the nick is already on the access list, the current\n"
+ "if the mask is already on the access list, the current\n"
"access level of that nick must be less than the access level\n"
- "of the user giving the command.\n"
+ "of the user giving the command. When a user joins the channel\n"
+ "the access they receive is from the highest level entry in the\n"
+ "access list.\n"
" \n"
"The ACCESS DEL command removes the given nick from the\n"
"access list. If a list of entry numbers is given, those\n"
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index 8228e4ffb..d5afbfbcf 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -12,6 +12,9 @@
#include "services.h"
#include "modules.h"
+// Awesome channel access hack for superadmin and founder
+static ChanAccess dummy_access;
+
/** Default constructor
* @param chname The channel name
*/
@@ -87,7 +90,7 @@ ChannelInfo::ChannelInfo(ChannelInfo *ci)
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
ChanAccess *access = ci->GetAccess(i);
- this->AddAccess(access->nc, access->level, access->creator, access->last_seen);
+ this->AddAccess(access->mask, access->level, access->creator, access->last_seen);
}
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
{
@@ -145,18 +148,20 @@ ChannelInfo::~ChannelInfo()
/** Add an entry to the channel access list
*
- * @param nc The NickCore of the user that the access entry should be tied to
+ * @param mask The mask of the access entry
* @param level The channel access level the user has on the channel
* @param creator The user who added the access
* @param last_seen When the user was last seen within the channel
+ * @return The new access class
*
* Creates a new access list entry and inserts it into the access list.
*/
-void ChannelInfo::AddAccess(NickCore *nc, int16 level, const Anope::string &creator, int32 last_seen)
+ChanAccess *ChannelInfo::AddAccess(const Anope::string &mask, int16 level, const Anope::string &creator, int32 last_seen)
{
ChanAccess *new_access = new ChanAccess();
- new_access->nc = nc;
+ new_access->mask = mask;
+ new_access->nc = findcore(mask);
new_access->level = level;
new_access->last_seen = last_seen;
if (!creator.empty())
@@ -165,6 +170,8 @@ void ChannelInfo::AddAccess(NickCore *nc, int16 level, const Anope::string &crea
new_access->creator = "Unknown";
this->access.push_back(new_access);
+
+ return new_access;
}
/** Get an entry from the channel access list by index
@@ -184,22 +191,102 @@ ChanAccess *ChannelInfo::GetAccess(unsigned index)
/** Get an entry from the channel access list by NickCore
*
- * @param nc The NickCore to find within the access list vector
+ * @param u The User to find within the access list vector
* @param level Optional channel access level to compare the access entries to
* @return A ChanAccess struct corresponding to the NickCore, or NULL if not found
*
* Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level.
*/
-ChanAccess *ChannelInfo::GetAccess(const NickCore *nc, int16 level)
+ChanAccess *ChannelInfo::GetAccess(User *u, int16 level)
{
+ if (!u)
+ return NULL;
+
+ if (u->isSuperAdmin || IsFounder(u, this))
+ {
+ dummy_access.level = u->isSuperAdmin ? ACCESS_SUPERADMIN : ACCESS_FOUNDER;
+ dummy_access.mask = u->nick + "!*@*";
+ dummy_access.nc = NULL;
+ dummy_access.last_seen = Anope::CurTime;
+ return &dummy_access;
+ }
+
if (this->access.empty())
return NULL;
+
+ NickAlias *na = NULL;
+ if (!u->IsIdentified())
+ na = findnick(u->nick);
+
+ ChanAccess *highest = NULL;
+ for (unsigned i = 0, end = this->access.size(); i < end; ++i)
+ {
+ ChanAccess *access = this->access[i];
+
+ if (level && level != access->level)
+ continue;
+ /* Access entry is a mask and we match it */
+ if (!access->nc && (Anope::Match(u->nick, access->mask) || Anope::Match(u->GetDisplayedMask(), access->mask)))
+ ;
+ /* Access entry is a nick core and we are identified for that account */
+ else if (access->nc && u->IsIdentified() && u->Account() == access->nc)
+ ;
+ /* User is not identified but on a registered nick, and is recognized, and is on an insecure channel */
+ else if (na && u->IsRecognized() && !this->HasFlag(CI_SECURE))
+ ;
+ else
+ continue;
+
+ /* Use the highest level access available */
+ if (!highest || access->level > highest->level)
+ highest = access;
+ }
+
+ return highest;
+}
+/** Get an entry from the channel access list by NickCore
+ *
+ * @param u The NickCore to find within the access list vector
+ * @param level Optional channel access level to compare the access entries to
+ * @return A ChanAccess struct corresponding to the NickCore, or NULL if not found
+ *
+ * Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level.
+ */
+ChanAccess *ChannelInfo::GetAccess(NickCore *nc, int16 level)
+{
+ if (nc == this->founder)
+ {
+ dummy_access.level = ACCESS_FOUNDER;
+ dummy_access.mask = nc->display;
+ dummy_access.nc = nc;
+ dummy_access.last_seen = Anope::CurTime;
+ return &dummy_access;
+ }
for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- if (this->access[i]->nc == nc && (level ? this->access[i]->level == level : true))
+ {
+ if (level && this->access[i]->level != level)
+ continue;
+ if (this->access[i]->nc && this->access[i]->nc == nc)
return this->access[i];
+ }
+ return NULL;
+}
+/** Get an entry from the channel access list by mask
+ *
+ * @param u The mask to find within the access list vector
+ * @param level Optional channel access level to compare the access entries to
+ * @return A ChanAccess struct corresponding to the mask, or NULL if not found
+ *
+ * Retrieves an entry from the access list that matches the given mask, optionally also matching a certain level.
+ */
+ChanAccess *ChannelInfo::GetAccess(const Anope::string &mask, int16 level)
+{
+ for (unsigned i = 0, end = this->access.size(); i < end; ++i)
+ if (Anope::Match(this->access[i]->mask, mask))
+ return this->access[i];
return NULL;
}
@@ -226,14 +313,33 @@ void ChannelInfo::EraseAccess(unsigned index)
this->access.erase(this->access.begin() + index);
}
+/** Erase an entry from the channel access list
+ *
+ * @param access The access to remove
+ *
+ * Clears the memory used by the given access entry and removes it from the vector.
+ */
+void ChannelInfo::EraseAccess(ChanAccess *access)
+{
+ for (unsigned i = 0, end = this->access.size(); i < end; ++i)
+ {
+ if (this->access[i] == access)
+ {
+ this->access.erase(this->access.begin() + i);
+ break;
+ }
+ }
+}
+
/** Clear the entire channel access list
*
* Clears the entire access list by deleting every item and then clearing the vector.
*/
void ChannelInfo::ClearAccess()
{
- while (!this->access.empty())
- EraseAccess(0);
+ for (unsigned i = this->access.size(); i > 0; --i)
+ delete this->access[i - 1];
+ this->access.clear();
}
/** Add an akick entry to the channel by NickCore