summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/extern.h1
-rw-r--r--include/regchannel.h101
-rw-r--r--include/services.h45
-rw-r--r--src/chanserv.c112
-rw-r--r--src/core/cs_access.c228
-rw-r--r--src/core/cs_akick.c2
-rw-r--r--src/core/cs_set.c7
-rw-r--r--src/core/cs_xop.c125
8 files changed, 301 insertions, 320 deletions
diff --git a/include/extern.h b/include/extern.h
index 0539593a0..ad79cf00c 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -185,7 +185,6 @@ E ChannelInfo *cs_findchan(const char *chan);
E int check_access(User * user, ChannelInfo * ci, int what);
E int is_founder(User * user, ChannelInfo * ci);
E int get_access(User * user, ChannelInfo * ci);
-E ChanAccess *get_access_entry(NickCore * nc, ChannelInfo * ci);
E void update_cs_lastseen(User * user, ChannelInfo * ci);
E int get_idealban(ChannelInfo * ci, User * u, char *ret, int retlen);
E AutoKick *is_stuck(ChannelInfo * ci, const char *mask);
diff --git a/include/regchannel.h b/include/regchannel.h
index a295acb39..e3f9cd7fc 100644
--- a/include/regchannel.h
+++ b/include/regchannel.h
@@ -8,8 +8,8 @@
* $Id$
*
*/
-
-class ChannelInfo : public Extensible
+
+class CoreExport ChannelInfo : public Extensible
{
public:
ChannelInfo()
@@ -20,9 +20,8 @@ class ChannelInfo : public Extensible
desc = url = email = last_topic = forbidby = forbidreason = NULL;
time_registered = last_used = last_topic_time = 0;
flags = 0;
- bantype = accesscount = akickcount = 0;
+ bantype = akickcount = 0;
levels = NULL;
- access = NULL;
akick = NULL;
mlock_on = mlock_off = mlock_limit = 0;
mlock_key = mlock_flood = mlock_redirect = entry_message = NULL;
@@ -36,7 +35,7 @@ class ChannelInfo : public Extensible
floodlines = floodsecs = 0;
repeattimes = 0;
}
-
+
ChannelInfo *next, *prev;
char name[CHANMAX];
NickCore *founder;
@@ -60,8 +59,7 @@ class ChannelInfo : public Extensible
int16 bantype;
int16 *levels; /* Access levels for commands */
- uint16 accesscount;
- ChanAccess *access; /* List of authorized users */
+ std::vector<ChanAccess *> access; /* List of authorized users */
uint16 akickcount;
AutoKick *akick; /* List of users to kickban */
@@ -89,5 +87,92 @@ class ChannelInfo : public Extensible
int16 capsmin, capspercent; /* For CAPS kicker */
int16 floodlines, floodsecs; /* For FLOOD kicker */
int16 repeattimes; /* For REPEAT kicker */
-};
+ /** Add an entry to the channel access list
+ *
+ * @param nc The NickCore of the user that the access entry should be tied to
+ * @param level The channel access level the user has on the channel
+ * @param last_seen When the user was last seen within the channel
+ *
+ * Creates a new access list entry and inserts it into the access list.
+ */
+ void AddAccess(NickCore *nc, int16 level, int32 last_seen = 0)
+ {
+ ChanAccess *new_access = new ChanAccess;
+ new_access->in_use = 1;
+ new_access->nc = nc;
+ new_access->level = level;
+ new_access->last_seen = last_seen;
+ access.push_back(new_access);
+ }
+
+ /** Get an entry from the channel access list by index
+ *
+ * @param index The index in the access list vector
+ * @return A ChanAccess struct corresponding to the index given, or NULL if outside the bounds
+ *
+ * Retrieves an entry from the access list that matches the given index.
+ */
+ ChanAccess *GetAccess(unsigned index)
+ {
+ if (access.empty() || index >= access.size())
+ return NULL;
+
+ return access[index];
+ }
+
+ /** Get an entry from the channel access list by NickCore
+ *
+ * @param nc 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(NickCore *nc, int16 level = 0)
+ {
+ if (access.empty())
+ return NULL;
+
+ for (unsigned i = 0; i < access.size(); i++)
+ if (access[i]->in_use && access[i]->nc == nc && (level ? access[i]->level == level : true))
+ return access[i];
+
+ return NULL;
+ }
+
+ /** Erase an entry from the channel access list
+ *
+ * @param index The index in the access list vector
+ *
+ * Clears the memory used by the given access entry and removes it from the vector.
+ */
+ void EraseAccess(unsigned index)
+ {
+ if (access.empty() || index >= access.size())
+ return;
+ delete access[index];
+ access.erase(access.begin() + index);
+ }
+
+ /** Cleans the channel access list
+ *
+ * Cleans up the access list so it no longer contains entries no longer in use.
+ */
+ void CleanAccess()
+ {
+ for (unsigned j = access.size(); j > 0; --j)
+ if (!access[j - 1]->in_use)
+ EraseAccess(j - 1);
+ }
+
+ /** Clear the entire channel access list
+ *
+ * Clears the entire access list by deleting every item and then clearing the vector.
+ */
+ void ClearAccess()
+ {
+ while (access.begin() != access.end())
+ EraseAccess(0);
+ }
+};
diff --git a/include/services.h b/include/services.h
index cd8c18d84..82631d883 100644
--- a/include/services.h
+++ b/include/services.h
@@ -597,38 +597,39 @@ typedef struct {
/*************************************************************************/
+enum AccessLevel
+{
+ /* Note that these two levels also serve as exclusive boundaries for valid
+ * access levels. ACCESS_FOUNDER may be assumed to be strictly greater
+ * than any valid access level, and ACCESS_INVALID may be assumed to be
+ * strictly less than any valid access level. Also read below.
+ */
+ ACCESS_FOUNDER = 10000, /* Numeric level indicating founder access */
+ ACCESS_INVALID = -10000, /* Used in levels[] for disabled settings */
+ /* There is one exception to the above access levels: SuperAdmins will have
+ * access level 10001. This level is never stored, however; it is only used
+ * in comparison and to let SuperAdmins win from founders where needed
+ */
+ ACCESS_SUPERADMIN = 10001,
+ /* Levels for xOP */
+ ACCESS_VOP = 3,
+ ACCESS_HOP = 4,
+ ACCESS_AOP = 5,
+ ACCESS_SOP = 10
+};
+
/* Channel info structures. Stored similarly to the nicks, except that
* the second character of the channel name, not the first, is used to
* determine the list. (Hashing based on the first character of the name
* wouldn't get very far. ;) ) */
/* Access levels for users. */
-typedef struct {
+struct ChanAccess {
uint16 in_use; /* 1 if this entry is in use, else 0 */
int16 level;
NickCore *nc; /* Guaranteed to be non-NULL if in use, NULL if not */
time_t last_seen;
-} ChanAccess;
-
-/* Note that these two levels also serve as exclusive boundaries for valid
- * access levels. ACCESS_FOUNDER may be assumed to be strictly greater
- * than any valid access level, and ACCESS_INVALID may be assumed to be
- * strictly less than any valid access level. Also read below.
- */
-#define ACCESS_FOUNDER 10000 /* Numeric level indicating founder access */
-#define ACCESS_INVALID -10000 /* Used in levels[] for disabled settings */
-/* There is one exception to the above access levels: SuperAdmins will have
- * access level 10001. This level is never stored, however; it is only used
- * in comparison and to let SuperAdmins win from founders where needed
- */
-#define ACCESS_SUPERADMIN 10001
-
-/* Levels for xOP */
-
-#define ACCESS_VOP 3
-#define ACCESS_HOP 4
-#define ACCESS_AOP 5
-#define ACCESS_SOP 10
+};
/* AutoKick data. */
typedef struct {
diff --git a/src/chanserv.c b/src/chanserv.c
index a4079cd8b..827f82911 100644
--- a/src/chanserv.c
+++ b/src/chanserv.c
@@ -205,7 +205,8 @@ void get_chanserv_stats(long *nrec, long *memuse)
mem += strlen(ci->url) + 1;
if (ci->email)
mem += strlen(ci->email) + 1;
- mem += ci->accesscount * sizeof(ChanAccess);
+ if (!ci->access.empty())
+ mem += ci->access.size() * sizeof(ChanAccess);
mem += ci->akickcount * sizeof(AutoKick);
for (j = 0; j < ci->akickcount; j++) {
if (!(ci->akick[j].flags & AK_ISNICK)
@@ -393,27 +394,29 @@ void load_cs_dbase()
ci->levels[j] = static_cast<int16>(tmp16);
}
- SAFE(read_int16(&ci->accesscount, f));
- if (ci->accesscount) {
- ci->access = static_cast<ChanAccess *>(scalloc(ci->accesscount, sizeof(ChanAccess)));
- for (j = 0; j < ci->accesscount; j++) {
- SAFE(read_int16(&ci->access[j].in_use, f));
- if (ci->access[j].in_use) {
- SAFE(read_int16(&tmp16, f));
- ci->access[j].level = static_cast<int16>(tmp16);
+ uint16 accesscount = 0;
+ SAFE(read_int16(&accesscount, f));
+ if (accesscount) {
+ for (j = 0; j < accesscount; j++) {
+ uint16 in_use = 0;
+ SAFE(read_int16(&in_use, f));
+ if (in_use) {
+ uint16 level;
+ SAFE(read_int16(&level, f));
+ NickCore *nc;
SAFE(read_string(&s, f));
if (s) {
- ci->access[j].nc = findcore(s);
+ nc = findcore(s);
delete [] s;
}
- if (ci->access[j].nc == NULL)
- ci->access[j].in_use = 0;
- SAFE(read_int32(&tmp32, f));
- ci->access[j].last_seen = tmp32;
+ else
+ nc = NULL;
+ uint32 last_seen;
+ SAFE(read_int32(&last_seen, f));
+ if (nc)
+ ci->AddAccess(nc, level, last_seen);
}
}
- } else {
- ci->access = NULL;
}
SAFE(read_int16(&ci->akickcount, f));
@@ -610,14 +613,15 @@ void save_cs_dbase()
for (j = 0; j < CA_SIZE; j++)
SAFE(write_int16(ci->levels[j], f));
- SAFE(write_int16(ci->accesscount, f));
- for (j = 0; j < ci->accesscount; j++) {
- SAFE(write_int16(ci->access[j].in_use, f));
- if (ci->access[j].in_use) {
- SAFE(write_int16(ci->access[j].level, f));
- SAFE(write_string(ci->access[j].nc->display, f));
- SAFE(write_int32(ci->access[j].last_seen, f));
- }
+ SAFE(write_int16(ci->access.empty() ? 0 : ci->access.size(), f));
+ for (j = 0; j < ci->access.size(); j++) {
+ ChanAccess *access = ci->GetAccess(j);
+ if (!access->in_use)
+ continue;
+ SAFE(write_int16(access->in_use, f));
+ SAFE(write_int16(access->level, f));
+ SAFE(write_string(access->nc->display, f));
+ SAFE(write_int32(access->last_seen, f));
}
SAFE(write_int16(ci->akickcount, f));
@@ -1441,11 +1445,12 @@ void cs_remove_nick(const NickCore * nc)
if (ci->successor == nc)
ci->successor = NULL;
- for (ca = ci->access, j = ci->accesscount; j > 0; ca++, j--) {
- if (ca->in_use && ca->nc == nc) {
- ca->in_use = 0;
- ca->nc = NULL;
- }
+ for (j = ci->access.size(); j > 0; --j)
+ {
+ ca = ci->GetAccess(j - 1);
+
+ if (ca->in_use && ca->nc == nc)
+ ci->EraseAccess(j - 1);
}
for (akick = ci->akick, j = 0; j < ci->akickcount; akick++, j++) {
@@ -1730,8 +1735,6 @@ int delchan(ChannelInfo * ci)
delete [] ci->forbidby;
if (ci->forbidreason)
delete [] ci->forbidreason;
- if (ci->access)
- free(ci->access);
if (debug >= 2) {
alog("debug: delchan() top of the akick list");
}
@@ -1874,26 +1877,6 @@ int is_identified(User * user, ChannelInfo * ci)
/*************************************************************************/
-/* Returns the ChanAccess entry for an user */
-
-ChanAccess *get_access_entry(NickCore * nc, ChannelInfo * ci)
-{
- ChanAccess *access;
- int i;
-
- if (!ci || !nc) {
- return NULL;
- }
-
- for (access = ci->access, i = 0; i < ci->accesscount; access++, i++)
- if (access->in_use && access->nc == nc)
- return access;
-
- return NULL;
-}
-
-/*************************************************************************/
-
/* Return the access level the given user has on the channel. If the
* channel doesn't exist, the user isn't on the access list, or the channel
* is CS_SECURE and the user hasn't IDENTIFY'd with NickServ, return 0. */
@@ -1917,7 +1900,7 @@ int get_access(User * user, ChannelInfo * ci)
if (nick_identified(user)
|| (nick_recognized(user) && !(ci->flags & CI_SECURE)))
- if ((access = get_access_entry(user->nc, ci)))
+ if ((access = ci->GetAccess(user->nc)))
return access->level;
if (nick_identified(user))
@@ -1937,7 +1920,7 @@ void update_cs_lastseen(User * user, ChannelInfo * ci)
if (is_founder(user, ci) || nick_identified(user)
|| (nick_recognized(user) && !(ci->flags & CI_SECURE)))
- if ((access = get_access_entry(user->nc, ci)))
+ if ((access = ci->GetAccess(user->nc)))
access->last_seen = time(NULL);
}
@@ -2117,28 +2100,19 @@ void cs_set_redirect(ChannelInfo * ci, const char *value)
int get_access_level(ChannelInfo * ci, NickAlias * na)
{
ChanAccess *access;
- int num;
- if (!ci || !na) {
+ if (!ci || !na)
return 0;
- }
- if (na->nc == ci->founder) {
+ if (na->nc == ci->founder)
return ACCESS_FOUNDER;
- }
- for (num = 0; num < ci->accesscount; num++) {
-
- access = &ci->access[num];
-
- if (access->nc && access->nc == na->nc && access->in_use) {
- return access->level;
- }
-
- }
-
- return 0;
+ access = ci->GetAccess(na->nc);
+ if (!access)
+ return 0;
+ else
+ return access->level;
}
const char *get_xop_level(int level)
diff --git a/src/core/cs_access.c b/src/core/cs_access.c
index f144bda1b..411462e72 100644
--- a/src/core/cs_access.c
+++ b/src/core/cs_access.c
@@ -52,35 +52,34 @@ static int access_del_callback(User * u, int num, va_list args)
int *last = va_arg(args, int *);
int *perm = va_arg(args, int *);
int uacc = va_arg(args, int);
- if (num < 1 || num > ci->accesscount)
+ if (num < 1 || num > ci->access.size())
return 0;
*last = num;
- return access_del(u, ci, &ci->access[num - 1], perm, uacc);
+ return access_del(u, ci, ci->GetAccess(num - 1), perm, uacc);
}
-static int access_list(User * u, int index, ChannelInfo * ci,
- int *sent_header)
+static int access_list(User * u, int index, ChannelInfo * ci, int *sent_header)
{
- ChanAccess *access = &ci->access[index];
+ ChanAccess *access = ci->GetAccess(index);
const char *xop;
if (!access->in_use)
return 0;
- if (!*sent_header) {
+ if (!*sent_header)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name);
*sent_header = 1;
}
- if (ci->flags & CI_XOP) {
+ if (ci->flags & CI_XOP)
+ {
xop = get_xop_level(access->level);
- notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1,
- xop, access->nc->display);
- } else {
- notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1,
- access->level, access->nc->display);
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1, xop, access->nc->display);
}
+ else
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1, access->level, access->nc->display);
return 1;
}
@@ -88,7 +87,7 @@ static int access_list_callback(User * u, int num, va_list args)
{
ChannelInfo *ci = va_arg(args, ChannelInfo *);
int *sent_header = va_arg(args, int *);
- if (num < 1 || num > ci->accesscount)
+ if (num < 1 || num > ci->access.size())
return 0;
return access_list(u, num - 1, ci, sent_header);
}
@@ -116,34 +115,35 @@ class CommandCSAccess : public Command
unsigned i;
int level = 0, ulev;
- int is_list = (cmd && stricmp(cmd, "LIST") == 0);
+ int is_list = (cmd && !stricmp(cmd, "LIST"));
/* If LIST, we don't *require* any parameters, but we can take any.
* If DEL, we require a nick and no level.
* Else (ADD), we require a level (which implies a nick). */
- if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 :
- (stricmp(cmd, "DEL") == 0) ? (!nick || s) : !s)) {
+ if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : (!stricmp(cmd, "DEL")) ? (!nick || s) : !s))
this->OnSyntaxError(u);
- } else if (!(ci = cs_findchan(chan))) {
+ else if (!(ci = cs_findchan(chan)))
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
- } else if (ci->flags & CI_FORBIDDEN) {
+ else if (ci->flags & CI_FORBIDDEN)
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
- /* We still allow LIST in xOP mode, but not others */
- } else if ((ci->flags & CI_XOP) && !is_list) {
+ /* We still allow LIST in xOP mode, but not others */
+ else if ((ci->flags & CI_XOP) && !is_list)
+ {
if (ircd->halfop)
notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP_HOP, s_ChanServ);
else
notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP, s_ChanServ);
- } else if (
- (
+ }
+ else if ((
(is_list && !check_access(u, ci, CA_ACCESS_LIST) && !u->nc->HasCommand("chanserv/access/list"))
||
(!is_list && !check_access(u, ci, CA_ACCESS_CHANGE) && !u->nc->HasPriv("chanserv/access/modify"))
))
- {
notice_lang(s_ChanServ, u, ACCESS_DENIED);
- } else if (stricmp(cmd, "ADD") == 0) {
- if (readonly) {
+ else if (!stricmp(cmd, "ADD"))
+ {
+ if (readonly)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED);
return MOD_CONT;
}
@@ -157,82 +157,76 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
- if (level == 0) {
+ if (!level)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_NONZERO);
return MOD_CONT;
- } else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) {
- notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_RANGE,
- ACCESS_INVALID + 1, ACCESS_FOUNDER - 1);
+ }
+ else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER)
+ {
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1);
return MOD_CONT;
}
na = findnick(nick);
- if (!na) {
+ if (!na)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_NICKS_ONLY);
return MOD_CONT;
}
- if (na->status & NS_FORBIDDEN) {
+ if (na->status & NS_FORBIDDEN)
+ {
notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, nick);
return MOD_CONT;
}
nc = na->nc;
- for (access = ci->access, i = 0; i < ci->accesscount;
- access++, i++) {
- if (access->nc == nc) {
- /* Don't allow lowering from a level >= ulev */
- if (access->level >= ulev && !u->nc->HasPriv("chanserv/access/change"))
- {
- notice_lang(s_ChanServ, u, PERMISSION_DENIED);
- return MOD_CONT;
- }
- if (access->level == level) {
- notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_UNCHANGED,
- access->nc->display, chan, level);
- return MOD_CONT;
- }
- access->level = level;
- snprintf(event_access, BUFSIZE, "%d", access->level);
- send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick,
- na->nick, event_access);
- alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->GetIdent().c_str(), u->host, ulev, access->level, na->nick, nc->display, ci->name);
- notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED,
- access->nc->display, chan, level);
+ access = ci->GetAccess(nc);
+ if (access)
+ {
+ /* Don't allow lowering from a level >= ulev */
+ if (access->level >= ulev && !u->nc->HasPriv("chanserv/access/change"))
+ {
+ notice_lang(s_ChanServ, u, PERMISSION_DENIED);
+ return MOD_CONT;
+ }
+ if (access->level == level)
+ {
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_UNCHANGED, access->nc->display, chan, level);
return MOD_CONT;
}
+ access->level = level;
+ snprintf(event_access, BUFSIZE, "%d", access->level);
+ send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, na->nick, event_access);
+ alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->GetIdent().c_str(), u->host, ulev, access->level, na->nick, nc->display, ci->name);
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED, access->nc->display, chan, level);
+ return MOD_CONT;
}
- if (i < CSAccessMax) {
- ci->accesscount++;
- ci->access =
- static_cast<ChanAccess *>(srealloc(ci->access,
- sizeof(ChanAccess) * ci->accesscount));
- } else {
- notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT,
- CSAccessMax);
+ if (ci->access.size() >= CSAccessMax)
+ {
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT, CSAccessMax);
return MOD_CONT;
}
- access = &ci->access[i];
- access->nc = nc;
- access->in_use = 1;
- access->level = level;
- access->last_seen = 0;
+ ci->AddAccess(nc, level);
snprintf(event_access, BUFSIZE, "%d", access->level);
- send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick,
- event_access);
+ send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick, event_access);
alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->GetIdent().c_str(), u->host, ulev, access->level, na->nick, nc->display, ci->name);
- notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display,
- ci->name, access->level);
- } else if (stricmp(cmd, "DEL") == 0) {
- int deleted, a, b;
- if (readonly) {
+ notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display, ci->name, access->level);
+ }
+ else if (!stricmp(cmd, "DEL"))
+ {
+ int deleted;
+ if (readonly)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED);
return MOD_CONT;
}
- if (ci->accesscount == 0) {
+ if (ci->access.empty())
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan);
return MOD_CONT;
}
@@ -241,8 +235,7 @@ class CommandCSAccess : public Command
if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick))
{
int count, last = -1, perm = 0;
- deleted = process_numlist(nick, &count, access_del_callback, u,
- ci, &last, &perm, get_access(u, ci));
+ deleted = process_numlist(nick, &count, access_del_callback, u, ci, &last, &perm, get_access(u, ci));
if (!deleted)
{
if (perm)
@@ -273,15 +266,12 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
nc = na->nc;
- for (i = 0; i < ci->accesscount; i++)
- if (ci->access[i].nc == nc)
- break;
- if (i == ci->accesscount)
+ access = ci->GetAccess(nc);
+ if (!access)
{
notice_lang(s_ChanServ, u, CHAN_ACCESS_NOT_FOUND, nick, chan);
return MOD_CONT;
}
- access = &ci->access[i];
if (get_access(u, ci) <= access->level && !u->nc->HasPriv("chanserv/access/change"))
{
deleted = 0;
@@ -297,37 +287,10 @@ class CommandCSAccess : public Command
}
}
- if (deleted) {
- /* Reordering - DrStein */
- for (b = 0; b < ci->accesscount; b++) {
- if (ci->access[b].in_use) {
- for (a = 0; a < ci->accesscount; a++) {
- if (a > b)
- break;
- if (!ci->access[a].in_use) {
- ci->access[a].in_use = 1;
- ci->access[a].level = ci->access[b].level;
- ci->access[a].nc = ci->access[b].nc;
- ci->access[a].last_seen =
- ci->access[b].last_seen;
- ci->access[b].nc = NULL;
- ci->access[b].in_use = 0;
- break;
- }
- }
- }
- }
-
- /* After reordering only the entries at the end could still be empty.
- * We ll free the places no longer in use... */
- for (int j = ci->accesscount - 1; j >= 0; j--) {
- if (ci->access[j].in_use == 1)
- break;
-
- ci->accesscount--;
- }
- ci->access =
- static_cast<ChanAccess *>(srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount));
+ if (deleted)
+ {
+ /* We'll free the access entries no longer in use... */
+ ci->CleanAccess();
/* We don't know the nick if someone used numbers, so we trigger the event without
* nick param. We just do this once, even if someone enters a range. -Certus */
@@ -336,32 +299,37 @@ class CommandCSAccess : public Command
else
send_event(EVENT_ACCESS_DEL, 2, ci->name, u->nick);
}
- } else if (stricmp(cmd, "LIST") == 0) {
+ }
+ else if (!stricmp(cmd, "LIST"))
+ {
int sent_header = 0;
- if (ci->accesscount == 0) {
+ if (ci->access.empty())
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan);
return MOD_CONT;
}
- if (nick && strspn(nick, "1234567890,-") == strlen(nick)) {
- process_numlist(nick, NULL, access_list_callback, u, ci,
- &sent_header);
- } else {
- for (i = 0; i < ci->accesscount; i++) {
- if (nick && ci->access[i].nc
- && !Anope::Match(ci->access[i].nc->display, nick, false))
+ if (nick && strspn(nick, "1234567890,-") == strlen(nick))
+ process_numlist(nick, NULL, access_list_callback, u, ci, &sent_header);
+ else
+ {
+ for (i = 0; i < ci->access.size(); i++)
+ {
+ access = ci->GetAccess(i);
+ if (nick && access->nc && !Anope::Match(access->nc->display, nick, false))
continue;
access_list(u, i, ci, &sent_header);
}
}
- if (!sent_header) {
+ if (!sent_header)
notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan);
- } else {
+ else
notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name);
- }
- } else if (stricmp(cmd, "CLEAR") == 0) {
-
- if (readonly) {
+ }
+ else if (!stricmp(cmd, "CLEAR"))
+ {
+ if (readonly)
+ {
notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED);
return MOD_CONT;
}
@@ -372,9 +340,7 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
- free(ci->access);
- ci->access = NULL;
- ci->accesscount = 0;
+ ci->ClearAccess();
send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick);
@@ -383,9 +349,9 @@ class CommandCSAccess : public Command
s_ChanServ, u->nick, u->GetIdent().c_str(), u->host,
get_access(u, ci), chan);
- } else {
- this->OnSyntaxError(u);
}
+ else
+ this->OnSyntaxError(u);
return MOD_CONT;
}
diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c
index 753ebd64f..229678780 100644
--- a/src/core/cs_akick.c
+++ b/src/core/cs_akick.c
@@ -176,7 +176,7 @@ int get_access_nc(NickCore *nc, ChannelInfo *ci)
if (!ci || !nc)
return 0;
- if ((access = get_access_entry(nc, ci)))
+ if ((access = ci->GetAccess(nc)))
return access->level;
return 0;
}
diff --git a/src/core/cs_set.c b/src/core/cs_set.c
index f9426b510..76ec975b8 100644
--- a/src/core/cs_set.c
+++ b/src/core/cs_set.c
@@ -464,8 +464,8 @@ class CommandCSSet : public Command
int i;
ChanAccess *access;
- for (access = ci->access, i = 0; i < ci->accesscount;
- access++, i++) {
+ for (i = 0; i < ci->access.size(); i++) {
+ access = ci->GetAccess(i);
if (!access->in_use)
continue;
/* This will probably cause wrong levels to be set, but hey,
@@ -490,6 +490,9 @@ class CommandCSSet : public Command
}
}
+ /* The above may have set an access entry to not be in use, this will clean that up. */
+ ci->CleanAccess();
+
reset_levels(ci);
ci->flags |= CI_XOP;
}
diff --git a/src/core/cs_xop.c b/src/core/cs_xop.c
index 6f2c302e8..ea603c1c0 100644
--- a/src/core/cs_xop.c
+++ b/src/core/cs_xop.c
@@ -109,7 +109,7 @@ class XOPBase : public Command
{
const char *nick = params.size() > 2 ? params[2].c_str() : NULL;
ChanAccess *access;
- int change = 0, i;
+ int change = 0;
char event_access[BUFSIZE];
if (!nick)
@@ -145,43 +145,33 @@ class XOPBase : public Command
}
NickCore *nc = na->nc;
- for (access = ci->access, i = 0; i < ci->accesscount; ++access, ++i)
+ access = ci->GetAccess(nc);
+ if (access)
{
- if (access->nc == nc)
+ /**
+ * Patch provided by PopCorn to prevert AOP's reducing SOP's levels
+ **/
+ if (access->level >= ulev && !u->nc->HasPriv("chanserv/access/modify"))
{
- /**
- * Patch provided by PopCorn to prevert AOP's reducing SOP's levels
- **/
- if (access->level >= ulev && !u->nc->HasPriv("chanserv/access/modify"))
- {
- notice_lang(s_ChanServ, u, PERMISSION_DENIED);
- return MOD_CONT;
- }
- ++change;
- break;
+ notice_lang(s_ChanServ, u, PERMISSION_DENIED);
+ return MOD_CONT;
}
+ ++change;
}
- if (!change)
+ if (!change && ci->access.size() >= CSAccessMax)
{
- if (i < CSAccessMax)
- {
- ++ci->accesscount;
- ci->access = static_cast<ChanAccess *>(srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount));
- }
- else
- {
- notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, CSAccessMax);
- return MOD_CONT;
- }
-
- access = &ci->access[i];
- access->nc = nc;
+ notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, CSAccessMax);
+ return MOD_CONT;
}
- access->in_use = 1;
- access->level = level;
- access->last_seen = 0;
+ if (!change)
+ ci->AddAccess(nc, level);
+ else
+ {
+ access->level = level;
+ access->last_seen = 0;
+ }
alog("%s: %s!%s@%s (level %d) %s access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->GetIdent().c_str(), u->host, ulev, change ? "changed" : "set", access->level, na->nick, nc->display, ci->name);
@@ -205,9 +195,8 @@ class XOPBase : public Command
{
const char *nick = params.size() > 2 ? params[2].c_str() : NULL;
ChanAccess *access;
- int i;
- int deleted, a, b;
+ int deleted;
if (!nick)
{
@@ -221,7 +210,7 @@ class XOPBase : public Command
return MOD_CONT;
}
- if (!ci->accesscount)
+ if (ci->access.empty())
{
notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name);
return MOD_CONT;
@@ -266,18 +255,14 @@ class XOPBase : public Command
return MOD_CONT;
}
NickCore *nc = na->nc;
+ access = ci->GetAccess(nc, level);
- for (i = 0; i < ci->accesscount; ++i)
- if (ci->access[i].nc == nc && ci->access[i].level == level)
- break;
-
- if (i == ci->accesscount)
+ if (!access)
{
notice_lang(s_ChanServ, u, messages[XOP_NOT_FOUND], nick, ci->name);
return MOD_CONT;
}
- access = &ci->access[i];
if (ulev <= access->level && !u->nc->HasPriv("chanserv/access/change"))
{
deleted = 0;
@@ -294,41 +279,10 @@ class XOPBase : public Command
}
if (deleted)
{
- /* Reordering - DrStein */
- for (b = 0; b < ci->accesscount; ++b)
- {
- if (ci->access[b].in_use)
- {
- for (a = 0; a < ci->accesscount; ++a)
- {
- if (a > b)
- break;
- if (!ci->access[a].in_use)
- {
- ci->access[a].in_use = 1;
- ci->access[a].level = ci->access[b].level;
- ci->access[a].nc = ci->access[b].nc;
- ci->access[a].last_seen = ci->access[b].last_seen;
- ci->access[b].nc = NULL;
- ci->access[b].in_use = 0;
- break;
- }
- }
- }
- }
-
/* If the patch provided in bug #706 is applied, this should be placed
* before sending the events! */
- /* After reordering only the entries at the end could still be empty.
- * We ll free the places no longer in use... */
- for (i = ci->accesscount - 1; i >= 0; --i)
- {
- if (ci->access[i].in_use == 1)
- break;
-
- --ci->accesscount;
- }
- ci->access = static_cast<ChanAccess *>(srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount));
+ /* We'll free the access entries no longer in use... */
+ ci->CleanAccess();
}
return MOD_CONT;
@@ -345,7 +299,7 @@ class XOPBase : public Command
return MOD_CONT;
}
- if (!ci->accesscount)
+ if (ci->access.empty())
{
notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name);
return MOD_CONT;
@@ -355,9 +309,10 @@ class XOPBase : public Command
process_numlist(nick, NULL, xop_list_callback, u, ci, &sent_header, level, messages[XOP_LIST_HEADER]);
else
{
- for (int i = 0; i < ci->accesscount; ++i)
+ for (int i = 0; i < ci->access.size(); ++i)
{
- if (nick && ci->access[i].nc && !Anope::Match(ci->access[i].nc->display, nick, false))
+ ChanAccess *access = ci->GetAccess(i);
+ if (nick && access->nc && !Anope::Match(access->nc->display, nick, false))
continue;
xop_list(u, i, ci, &sent_header, level, messages[XOP_LIST_HEADER]);
}
@@ -376,7 +331,7 @@ class XOPBase : public Command
return MOD_CONT;
}
- if (!ci->accesscount)
+ if (ci->access.empty())
{
notice_lang(s_ChanServ, u, messages[XOP_LIST_EMPTY], ci->name);
return MOD_CONT;
@@ -388,13 +343,11 @@ class XOPBase : public Command
return MOD_CONT;
}
- for (int i = 0; i < ci->accesscount; ++i)
+ for (unsigned i = ci->access.size(); i > 0; --i)
{
- if (ci->access[i].in_use && ci->access[i].level == level)
- {
- ci->access[i].nc = NULL;
- ci->access[i].in_use = 0;
- }
+ ChanAccess *access = ci->GetAccess(i - 1);
+ if (access->in_use && access->level == level)
+ ci->EraseAccess(i - 1);
}
send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick);
@@ -600,17 +553,17 @@ int xop_del_callback(User *u, int num, va_list args)
int uacc = va_arg(args, int);
int xlev = va_arg(args, int);
- if (num < 1 || num > ci->accesscount)
+ if (num < 1 || num > ci->access.size())
return 0;
*last = num;
- return xop_del(u, ci, &ci->access[num - 1], perm, uacc, xlev);
+ return xop_del(u, ci, ci->GetAccess(num - 1), perm, uacc, xlev);
}
int xop_list(User *u, int index, ChannelInfo *ci, int *sent_header, int xlev, int xmsg)
{
- ChanAccess *access = &ci->access[index];
+ ChanAccess *access = ci->GetAccess(index);
if (!access->in_use || access->level != xlev)
return 0;
@@ -632,7 +585,7 @@ int xop_list_callback(User *u, int num, va_list args)
int xlev = va_arg(args, int);
int xmsg = va_arg(args, int);
- if (num < 1 || num > ci->accesscount)
+ if (num < 1 || num > ci->access.size())
return 0;
return xop_list(u, num - 1, ci, sent_header, xlev, xmsg);