mirror of
https://github.com/anope/anope.git
synced 2026-07-03 16:13:12 +02:00
Replace manual array for ChannelInfo's access list to use an std::vector instead, cleans up the code by a huge portion and fixes bug #1024 in the process.
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2184 5417fbe8-f217-4b02-8779-1006273d7864
This commit is contained in:
@@ -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);
|
||||
|
||||
+93
-8
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
+23
-22
@@ -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 {
|
||||
|
||||
+43
-69
@@ -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)
|
||||
|
||||
+99
-133
@@ -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 (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 (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;
|
||||
}
|
||||
|
||||
access = &ci->access[i];
|
||||
access->nc = nc;
|
||||
access->in_use = 1;
|
||||
access->level = level;
|
||||
access->last_seen = 0;
|
||||
if (ci->access.size() >= CSAccessMax)
|
||||
{
|
||||
notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT, CSAccessMax);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+5
-2
@@ -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;
|
||||
}
|
||||
|
||||
+39
-86
@@ -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,44 +145,34 @@ 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 && ci->access.size() >= CSAccessMax)
|
||||
{
|
||||
notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, CSAccessMax);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (!change)
|
||||
ci->AddAccess(nc, level);
|
||||
else
|
||||
{
|
||||
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;
|
||||
access->level = level;
|
||||
access->last_seen = 0;
|
||||
}
|
||||
|
||||
access->in_use = 1;
|
||||
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);
|
||||
|
||||
snprintf(event_access, BUFSIZE, "%d", access->level);
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user