summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chanserv.c26
-rw-r--r--src/core/bs_badwords.c170
-rw-r--r--src/core/cs_access.c319
-rw-r--r--src/core/cs_akick.c269
-rw-r--r--src/core/cs_set.c8
-rw-r--r--src/core/cs_xop.c232
-rw-r--r--src/core/db_plain.cpp5
-rw-r--r--src/core/ms_del.c64
-rw-r--r--src/core/ms_list.c119
-rw-r--r--src/core/ms_read.c111
-rw-r--r--src/core/os_session.c269
-rw-r--r--src/memoserv.c1
-rw-r--r--src/misc.c132
-rw-r--r--src/regchannel.cpp89
14 files changed, 898 insertions, 916 deletions
diff --git a/src/chanserv.c b/src/chanserv.c
index 7f5602ed1..17dd65a7b 100644
--- a/src/chanserv.c
+++ b/src/chanserv.c
@@ -788,15 +788,15 @@ void cs_remove_nick(const NickCore * nc)
{
ca = ci->GetAccess(j - 1);
- if (ca->in_use && ca->nc == nc)
+ if (ca->nc == nc)
ci->EraseAccess(j - 1);
}
for (j = ci->GetAkickCount(); j > 0; --j)
{
akick = ci->GetAkick(j - 1);
- if (akick->InUse && akick->HasFlag(AK_ISNICK) && akick->nc == nc)
- ci->EraseAkick(akick);
+ if (akick->HasFlag(AK_ISNICK) && akick->nc == nc)
+ ci->EraseAkick(j - 1);
}
}
}
@@ -1054,6 +1054,22 @@ int get_access_level(ChannelInfo * ci, NickAlias * na)
return access->level;
}
+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;
+}
+
const char *get_xop_level(int level)
{
ChannelMode *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP);
@@ -1091,7 +1107,7 @@ AutoKick *is_stuck(ChannelInfo * ci, const char *mask)
{
AutoKick *akick = ci->GetAkick(i);
- if (!akick->InUse || akick->HasFlag(AK_ISNICK) || !akick->HasFlag(AK_STUCK))
+ if (akick->HasFlag(AK_ISNICK) || !akick->HasFlag(AK_STUCK))
continue;
if (Anope::Match(akick->mask, mask, false))
@@ -1146,7 +1162,7 @@ void stick_all(ChannelInfo * ci)
{
AutoKick *akick = ci->GetAkick(i);
- if (!akick->InUse || (akick->HasFlag(AK_ISNICK) || !akick->HasFlag(AK_STUCK)))
+ if (akick->HasFlag(AK_ISNICK) || !akick->HasFlag(AK_STUCK))
continue;
ci->c->SetMode(NULL, CMODE_BAN, akick->mask.c_str());
diff --git a/src/core/bs_badwords.c b/src/core/bs_badwords.c
index 3db6f1e42..ce026e9c4 100644
--- a/src/core/bs_badwords.c
+++ b/src/core/bs_badwords.c
@@ -14,40 +14,106 @@
#include "module.h"
-int badwords_del_callback(User * u, int num, va_list args);
-int badwords_list(User * u, int index, ChannelInfo * ci, int *sent_header);
-int badwords_list_callback(User * u, int num, va_list args);
+class BadwordsListCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ bool SentHeader;
+ public:
+ BadwordsListCallback(User *_u, ChannelInfo *_ci, const std::string &list) : NumberList(list), u(_u), ci(_ci), SentHeader(false)
+ {
+ }
+
+ ~BadwordsListCallback()
+ {
+ if (!SentHeader)
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name.c_str());
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetBadWordCount())
+ return;
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name.c_str());
+ }
+
+ DoList(u, ci, Number - 1, ci->GetBadWord(Number - 1));
+ }
+
+ static void DoList(User *u, ChannelInfo *ci, unsigned Number, BadWord *bw)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_FORMAT, Number + 1, bw->word.c_str(), ((bw->type == BW_SINGLE) ? "(SINGLE)" : ((bw->type == BW_START) ? "(START)" : ((bw->type == BW_END) ? "(END)" : ""))));
+ }
+};
+
+class BadwordsDelCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ unsigned Deleted;
+ public:
+ BadwordsDelCallback(User *_u, ChannelInfo *_ci, const std::string &list) : NumberList(list), u(_u), ci(_ci), Deleted(0)
+ {
+ }
+
+ ~BadwordsDelCallback()
+ {
+ if (!Deleted)
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name.c_str());
+ else if (Deleted == 1)
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_DELETED_ONE, ci->name.c_str());
+ else
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, Deleted, ci->name.c_str());
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetBadWordCount())
+ return;
+
+ ++Deleted;
+ ci->EraseBadWord(Number - 1);
+ }
+};
class CommandBSBadwords : public Command
{
private:
CommandReturn DoList(User *u, ChannelInfo *ci, const ci::string &word)
{
- int sent_header = 0;
-
if (!ci->GetBadWordCount())
{
notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, ci->name.c_str());
- return MOD_CONT;
- }
- if (!word.empty() && strspn(word.c_str(), "1234567890,-") == word.length())
- {
- process_numlist(word.c_str(), NULL, badwords_list_callback, u, ci, &sent_header);
}
+ else if (!word.empty() && strspn(word.c_str(), "1234567890,-") == word.length())
+ (new BadwordsListCallback(u, ci, word.c_str()))->Process();
else
{
+ bool SentHeader = false;
+
for (unsigned i = 0; i < ci->GetBadWordCount(); i++)
{
- BadWord *badword = ci->GetBadWord(i);
+ BadWord *bw = ci->GetBadWord(i);
- if (!word.empty() && !Anope::Match(badword->word, word.c_str(), false))
+ if (!word.empty() && !Anope::Match(bw->word, word.c_str(), false))
continue;
- badwords_list(u, i, ci, &sent_header);
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name.c_str());
+ }
+
+ BadwordsListCallback::DoList(u, ci, i, bw);
}
+
+ if (!SentHeader)
+ notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name.c_str());
}
- if (!sent_header)
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name.c_str());
return MOD_CONT;
}
@@ -102,33 +168,7 @@ class CommandBSBadwords : public Command
{
/* Special case: is it a number/list? Only do search if it isn't. */
if (!word.empty() && isdigit(word[0]) && strspn(word.c_str(), "1234567890,-") == word.length())
- {
- int count, deleted, last = -1;
- deleted = process_numlist(word.c_str(), &count, badwords_del_callback, u, ci, &last);
-
- if (!deleted)
- {
- if (count == 1)
- {
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, last, ci->name.c_str());
- }
- else
- {
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name.c_str());
- }
- }
- else if (deleted == 1)
- {
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_DELETED_ONE, ci->name.c_str());
- }
- else
- {
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, deleted, ci->name.c_str());
- }
-
- if (deleted)
- ci->CleanBadWords();
- }
+ (new BadwordsDelCallback(u, ci, word.c_str()))->Process();
else
{
unsigned i;
@@ -148,7 +188,7 @@ class CommandBSBadwords : public Command
return MOD_CONT;
}
- ci->EraseBadWord(badword);
+ ci->EraseBadWord(i);
notice_lang(Config.s_BotServ, u, BOT_BADWORDS_DELETED, badword->word.c_str(), ci->name.c_str());
}
@@ -239,48 +279,4 @@ class BSBadwords : public Module
}
};
-int badwords_del_callback(User * u, int num, va_list args)
-{
- ChannelInfo *ci = va_arg(args, ChannelInfo *);
- int *last = va_arg(args, int *);
-
- *last = num;
-
- if (num < 1 || num > ci->GetBadWordCount())
- return 0;
-
- ci->GetBadWord(num - 1)->InUse = false;
-
- return 1;
-}
-
-int badwords_list(User * u, int index, ChannelInfo * ci, int *sent_header)
-{
- BadWord *bw = ci->GetBadWord(index);
-
- if (!*sent_header)
- {
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name.c_str());
- *sent_header = 1;
- }
-
- notice_lang(Config.s_BotServ, u, BOT_BADWORDS_LIST_FORMAT, index + 1, bw->word.c_str(),
- ((bw->type == BW_SINGLE) ? "(SINGLE)" : ((bw->type == BW_START) ? "(START)"
- : ((bw->type == BW_END) ? "(END)" : "")))
- );
-
- return 1;
-}
-
-int badwords_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->GetBadWordCount())
- return 0;
-
- return badwords_list(u, num - 1, ci, sent_header);
-}
-
MODULE_INIT(BSBadwords)
diff --git a/src/core/cs_access.c b/src/core/cs_access.c
index 718a7dc0f..f49fca990 100644
--- a/src/core/cs_access.c
+++ b/src/core/cs_access.c
@@ -14,116 +14,151 @@
#include "module.h"
-static int access_del(User * u, ChannelInfo *ci, ChanAccess * access, int *perm, int uacc)
+class AccessListCallback : public NumberList
{
- if (!access->in_use)
- return 0;
- if (uacc <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
+ protected:
+ User *u;
+ ChannelInfo *ci;
+ bool SentHeader;
+ public:
+ AccessListCallback(User *_u, ChannelInfo *_ci, const std::string &numlist) : NumberList(numlist), u(_u), ci(_ci), SentHeader(false)
{
- (*perm)++;
- return 0;
}
- NickCore *nc = access->nc;
- access->nc = NULL;
- access->in_use = 0;
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, nc));
+ ~AccessListCallback()
+ {
+ if (SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, ci->name.c_str());
+ }
- return 1;
-}
+ virtual void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAccessCount())
+ return;
-static int access_del_callback(User * u, int num, va_list args)
-{
- ChannelInfo *ci = va_arg(args, ChannelInfo *);
- int *last = va_arg(args, int *);
- int *perm = va_arg(args, int *);
- int uacc = va_arg(args, int);
- if (num < 1 || num > ci->GetAccessCount())
- return 0;
- *last = num;
- return access_del(u, ci, ci->GetAccess(num - 1), perm, uacc);
-}
-
-
-static int access_list(User * u, int index, ChannelInfo * ci, int *sent_header)
-{
- ChanAccess *access = ci->GetAccess(index);
- const char *xop;
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
+ }
- if (!access->in_use)
- return 0;
+ DoList(u, ci, Number - 1, ci->GetAccess(Number - 1));
+ }
- if (!*sent_header)
+ static void DoList(User *u, ChannelInfo *ci, unsigned Number, ChanAccess *access)
{
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
- *sent_header = 1;
+ if (ci->HasFlag(CI_XOP))
+ {
+ const char *xop = get_xop_level(access->level);
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, Number + 1, xop, access->nc->display);
+ }
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, Number + 1, access->level, access->nc->display);
}
+};
- if (ci->HasFlag(CI_XOP))
+class AccessViewCallback : public AccessListCallback
+{
+ public:
+ AccessViewCallback(User *_u, ChannelInfo *_ci, const std::string &numlist) : AccessListCallback(_u, _ci, numlist)
{
- xop = get_xop_level(access->level);
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1, xop, access->nc->display);
}
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1, access->level, access->nc->display);
- return 1;
-}
-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->GetAccessCount())
- return 0;
- return access_list(u, num - 1, ci, sent_header);
-}
-
-static int access_view(User *u, int index, ChannelInfo *ci, int *sent_header)
-{
- ChanAccess *access = ci->GetAccess(index);
- const char *xop;
- char timebuf[64];
- tm tm;
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAccessCount())
+ return;
- if (!access || !access->in_use)
- return 0;
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
+ }
+
+ DoList(u, ci, Number - 1, ci->GetAccess(Number - 1));
+ }
- if (!*sent_header)
+ static void DoList(User *u, ChannelInfo *ci, unsigned Number, ChanAccess *access)
{
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
- *sent_header = 1;
+ char timebuf[64];
+ struct tm tm;
+
+ memset(&timebuf, 0, sizeof(timebuf));
+ if (ci->c && u->Account() && nc_on_chan(ci->c, u->Account()))
+ snprintf(timebuf, sizeof(timebuf), "Now");
+ else if (access->last_seen == 0)
+ snprintf(timebuf, sizeof(timebuf), "Never");
+ else
+ {
+ tm = *localtime(&access->last_seen);
+ strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
+ }
+
+ if (ci->HasFlag(CI_XOP))
+ {
+ const char *xop = get_xop_level(access->level);
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_VIEW_XOP_FORMAT, Number + 1, xop, access->nc->display, access->creator.c_str(), timebuf);
+ }
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, access->level, access->nc->display, access->creator.c_str(), timebuf);
}
+};
- memset(&timebuf, 0, sizeof(timebuf));
- if (ci->c && u->Account() && nc_on_chan(ci->c, u->Account()))
- sprintf(timebuf, "Now");
- else if (access->last_seen == 0)
- sprintf(timebuf, "Never");
- else
+class AccessDelCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ unsigned Deleted;
+ std::string Nicks;
+ bool Denied;
+ public:
+ AccessDelCallback(User *_u, ChannelInfo *_ci, const std::string &numlist) : NumberList(numlist), u(_u), ci(_ci), Deleted(0), Denied(false)
{
- tm = *localtime(&access->last_seen);
- strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
}
- if (ci->HasFlag(CI_XOP))
+ ~AccessDelCallback()
{
- xop = get_xop_level(access->level);
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_VIEW_XOP_FORMAT, index + 1, xop, access->nc->display, access->creator.c_str(), timebuf);
+ if (Denied && !Deleted)
+ notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
+ else if (!Deleted)
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, ci->name.c_str());
+ else
+ {
+ Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << get_access(u, ci) << ") deleted access of user" << (Deleted == 1 ? " " : "s ") << Nicks << " on " << ci->name;
+
+ if (Deleted == 1)
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DELETED_ONE, ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DELETED_SEVERAL, Deleted, ci->name.c_str());
+ }
}
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_VIEW_AXS_FORMAT, index + 1, access->level, access->nc->display, access->creator.c_str(), timebuf);
- return 1;
-}
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAccessCount())
+ return;
+
+ ChanAccess *access = ci->GetAccess(Number - 1);
-static int access_view_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->GetAccessCount())
- return 0;
- return access_view(u, num - 1, ci, sent_header);
-}
+ if (get_access(u, ci) <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
+ {
+ Denied = true;
+ return;
+ }
+
+ ++Deleted;
+ if (!Nicks.empty())
+ Nicks += ", " + std::string(access->nc->display);
+ else
+ Nicks = access->nc->display;
+
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access->nc));
+
+ ci->EraseAccess(Number - 1);
+ }
+};
class CommandCSAccess : public Command
{
@@ -224,7 +259,7 @@ class CommandCSAccess : public Command
}
access->level = level;
- FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na, level));
+ FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na->nc, level));
Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << ulev << ") set access level "
<< access->level << " to " << na->nick << " (group " << nc->display << ") on channel " << ci->name;
@@ -238,10 +273,9 @@ class CommandCSAccess : public Command
return MOD_CONT;
}
- std::string usernick = u->nick;
- ci->AddAccess(nc, level, usernick);
+ ci->AddAccess(nc, level, u->nick);
- FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, na, level));
+ FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, nc, level));
Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << ulev << ") set access level "
<< level << " to " << na->nick << " (group " << nc->display << ") on channel " << ci->name;
@@ -249,7 +283,6 @@ class CommandCSAccess : public Command
}
else if (cmd == "DEL")
{
- int deleted;
if (readonly)
{
notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DISABLED);
@@ -264,31 +297,7 @@ class CommandCSAccess : public Command
/* Special case: is it a number/list? Only do search if it isn't. */
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));
- if (!deleted)
- {
- if (perm)
- notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
- else if (count == 1)
- {
- last = atoi(nick);
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_SUCH_ENTRY, last, ci->name.c_str());
- }
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, ci->name.c_str());
- }
- else
- {
- Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << get_access(u, ci)
- << ") deleted access of user" << (deleted == 1 ? " " : "s ") << nick << " on " << chan;
- if (deleted == 1)
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DELETED_ONE, ci->name.c_str());
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DELETED_SEVERAL, deleted, ci->name.c_str());
- }
- }
+ (new AccessDelCallback(u, ci, nick))->Process();
else
{
na = findnick(nick);
@@ -297,16 +306,25 @@ class CommandCSAccess : public Command
notice_lang(Config.s_ChanServ, u, NICK_X_NOT_REGISTERED, nick);
return MOD_CONT;
}
+
nc = na->nc;
- access = ci->GetAccess(nc);
- if (!access)
+
+ for (i = 0; i < ci->GetAccessCount(); ++i)
+ {
+ access = ci->GetAccess(i);
+
+ if (access->nc == nc)
+ break;
+ }
+
+ if (i == ci->GetAccessCount())
{
notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NOT_FOUND, nick, chan);
return MOD_CONT;
}
+
if (get_access(u, ci) <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
{
- deleted = 0;
notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
}
else
@@ -314,76 +332,81 @@ class CommandCSAccess : public Command
notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_DELETED, access->nc->display, ci->name.c_str());
Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << get_access(u, ci)
<< ") deleted access of " << na->nick << " (group " << access->nc->display << ") on " << chan;
- access->nc = NULL;
- access->in_use = 0;
- deleted = 1;
- }
- }
-
- if (deleted)
- {
- /* We'll free the access entries no longer in use... */
- ci->CleanAccess();
-
- /* Only call this event if na exists (if they deleted by user, not numlist).
- * The callback for deleting by numlist will call this event otherwise - Adam */
- if (na)
- {
FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, na->nc));
+
+ ci->EraseAccess(i);
}
}
}
else if (cmd == "LIST")
{
- int sent_header = 0;
-
if (!ci->GetAccessCount())
{
notice_lang(Config.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);
+ (new AccessListCallback(u, ci, nick))->Process();
else
{
+ bool SentHeader = false;
+
for (i = 0; i < ci->GetAccessCount(); 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 (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
+ }
+
+ AccessListCallback::DoList(u, ci, i, access);
}
+
+ if (SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan);
}
- if (!sent_header)
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan);
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name.c_str());
}
else if (cmd == "VIEW")
{
- int sent_header = 0;
-
if (!ci->GetAccessCount())
{
notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan);
return MOD_CONT;
}
if (nick && strspn(nick, "1234567890,-") == strlen(nick))
- process_numlist(nick, NULL, access_view_callback, u, ci, &sent_header);
+ (new AccessViewCallback(u, ci, nick))->Process();
else
{
+ bool SentHeader = false;
+
for (i = 0; i < ci->GetAccessCount(); ++i)
{
access = ci->GetAccess(i);
+
if (nick && access->nc && !Anope::Match(access->nc->display, nick, false))
continue;
- access_view(u, i, ci, &sent_header);
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name.c_str());
+ }
+
+ AccessViewCallback::DoList(u, ci, i, access);
}
+
+ if (SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan);
}
- if (!sent_header)
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan);
- else
- notice_lang(Config.s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name.c_str());
}
else if (cmd == "CLEAR")
{
diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c
index abd00be6a..42b79c362 100644
--- a/src/core/cs_akick.c
+++ b/src/core/cs_akick.c
@@ -45,103 +45,125 @@ static void split_usermask(const char *mask, const char **nick, const char **use
delete [] mask2;
}
-int akick_del_callback(User * u, int num, va_list args)
+class AkickListCallback : public NumberList
{
- ChannelInfo *ci = va_arg(args, ChannelInfo *);
- int *last = va_arg(args, int *);
+ protected:
+ User *u;
+ ChannelInfo *ci;
+ bool SentHeader;
+ public:
+ AkickListCallback(User *_u, ChannelInfo *_ci, const std::string &numlist) : NumberList(numlist), u(_u), ci(_ci), SentHeader(false)
+ {
+ }
+
+ ~AkickListCallback()
+ {
+ if (!SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
+ }
- *last = num;
+ virtual void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAkickCount())
+ return;
- if (num < 1 || num > ci->GetAkickCount())
- return 0;
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
+ }
- ci->GetAkick(num - 1)->InUse = false;
- return 1;
-}
+ DoList(u, ci, Number - 1, ci->GetAkick(Number - 1));
+ }
+ static void DoList(User *u, ChannelInfo *ci, unsigned index, AutoKick *akick)
+ {
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_FORMAT, index + 1,
+ ((akick->HasFlag(AK_ISNICK)) ? akick->nc->display : akick->mask.c_str()),
+ (!akick->reason.empty() ? akick->reason.c_str() : getstring(u, NO_REASON)));
+ }
+};
-int akick_list(User * u, int index, ChannelInfo * ci, int *sent_header)
+class AkickViewCallback : public AkickListCallback
{
- AutoKick *akick = ci->GetAkick(index);
-
- if (!akick->InUse)
- return 0;
- if (!*sent_header) {
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
- *sent_header = 1;
+ public:
+ AkickViewCallback(User *_u, ChannelInfo *_ci, const std::string &numlist) : AkickListCallback(u, ci, numlist)
+ {
}
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_FORMAT, index + 1,
- ((akick->HasFlag(AK_ISNICK)) ? akick->nc->
- display : akick->mask.c_str()),
- (!akick->reason.empty() ? akick->
- reason.c_str() : getstring(u, NO_REASON)));
- return 1;
-}
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAkickCount())
+ return;
-int akick_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->GetAkickCount())
- return 0;
- return akick_list(u, num - 1, ci, sent_header);
-}
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
+ }
-int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header)
-{
- AutoKick *akick = ci->GetAkick(index);
- char timebuf[64];
- struct tm tm;
-
- if (!akick->InUse)
- return 0;
- if (!*sent_header) {
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
- *sent_header = 1;
+ DoList(u, ci, Number - 1, ci->GetAkick(Number - 1));
}
- if (akick->addtime) {
- tm = *localtime(&akick->addtime);
- strftime_lang(timebuf, sizeof(timebuf), u,
- STRFTIME_SHORT_DATE_FORMAT, &tm);
- } else {
- snprintf(timebuf, sizeof(timebuf), "%s", getstring(u, UNKNOWN));
+ static void DoList(User *u, ChannelInfo *ci, unsigned index, AutoKick *akick)
+ {
+ char timebuf[64];
+ struct tm tm;
+
+ memset(&timebuf, 0, sizeof(timebuf));
+
+ if (akick->addtime)
+ {
+ tm = *localtime(&akick->addtime);
+ strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, &tm);
+ }
+ else
+ snprintf(timebuf, sizeof(timebuf), "%s", getstring(u, UNKNOWN));
+
+ notice_lang(Config.s_ChanServ, u, (akick->HasFlag(AK_STUCK) ? CHAN_AKICK_VIEW_FORMAT_STUCK : CHAN_AKICK_VIEW_FORMAT), index + 1,
+ ((akick->HasFlag(AK_ISNICK)) ? akick->nc->display : akick->mask.c_str()),
+ !akick->creator.empty() ? akick->creator.c_str() : getstring(u, UNKNOWN), timebuf,
+ (!akick->reason.empty() ? akick->reason.c_str() : getstring(u, NO_REASON)));
+
+ if (akick->last_used)
+ {
+ char last_used[64];
+ tm = *localtime(&akick->last_used);
+ strftime_lang(last_used, sizeof(last_used), u, STRFTIME_SHORT_DATE_FORMAT, &tm);
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LAST_USED, last_used);
+ }
}
+};
- notice_lang(Config.s_ChanServ, u, (akick->HasFlag(AK_STUCK) ? CHAN_AKICK_VIEW_FORMAT_STUCK : CHAN_AKICK_VIEW_FORMAT), index + 1,
- ((akick->HasFlag(AK_ISNICK)) ? akick->nc->display : akick->mask.c_str()),
- !akick->creator.empty() ? akick->creator.c_str() : getstring(u, UNKNOWN), timebuf,
- (!akick->reason.empty() ? akick->reason.c_str() : getstring(u, NO_REASON)));
- if (akick->last_used)
+class AkickDelCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ unsigned Deleted;
+ public:
+ AkickDelCallback(User *_u, ChannelInfo *_ci, const std::string &list) : NumberList(list), u(_u), ci(_ci), Deleted(0)
{
- char last_used[64];
- tm = *localtime(&akick->last_used);
- strftime_lang(last_used, sizeof(last_used), u, STRFTIME_SHORT_DATE_FORMAT, &tm);
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LAST_USED, last_used);
}
- return 1;
-}
-int akick_view_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->GetAkickCount())
- return 0;
- return akick_view(u, num - 1, ci, sent_header);
-}
+ ~AkickDelCallback()
+ {
+ if (!Deleted)
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
+ else if (Deleted == 1)
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_DELETED_ONE, ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL, Deleted, ci->name.c_str());
+ }
-int get_access_nc(NickCore *nc, ChannelInfo *ci)
-{
- ChanAccess *access;
- if (!ci || !nc)
- return 0;
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAkickCount())
+ return;
- if ((access = ci->GetAccess(nc)))
- return access->level;
- return 0;
-}
+ ++Deleted;
+ ci->EraseAkick(Number - 1);
+ }
+};
class CommandCSAKick : public Command
{
@@ -188,7 +210,7 @@ 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_nc(nc, ci) >= get_access(u, ci)))
+ if ((nc == ci->founder) || (get_access_level(ci, nc) >= get_access(u, ci)))
{
notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
return;
@@ -221,7 +243,7 @@ class CommandCSAKick : public Command
if (na2->HasFlag(NS_FORBIDDEN))
continue;
- if (na2->nc && ((na2->nc == ci->founder) || (get_access_nc(na2->nc, ci) >= get_access(u, ci))))
+ if (na2->nc && ((na2->nc == ci->founder) || (get_access_level(ci, na2->nc) >= get_access(u, ci))))
{
char buf[BUFSIZE];
@@ -238,8 +260,6 @@ class CommandCSAKick : public Command
for (unsigned j = 0; j < ci->GetAkickCount(); ++j)
{
akick = ci->GetAkick(j);
- if (!akick->InUse)
- continue;
if ((akick->HasFlag(AK_ISNICK)) ? akick->nc == nc : akick->mask == mask)
{
notice_lang(Config.s_ChanServ, u, CHAN_AKICK_ALREADY_EXISTS, (akick->HasFlag(AK_ISNICK)) ? akick->nc->display : akick->mask.c_str(), ci->name.c_str());
@@ -259,6 +279,8 @@ class CommandCSAKick : public Command
else
akick = ci->AddAkick(u->nick, mask.c_str(), !reason.empty() ? reason.c_str() : "");
+ FOREACH_MOD(I_OnAkickAdd, OnAkickAdd(u, ci, akick));
+
notice_lang(Config.s_ChanServ, u, CHAN_AKICK_ADDED, mask.c_str(), ci->name.c_str());
this->DoEnforce(u, ci, params);
@@ -285,7 +307,7 @@ class CommandCSAKick : public Command
{
akick = ci->GetAkick(i);
- if (!akick->InUse || akick->HasFlag(AK_ISNICK))
+ if (akick->HasFlag(AK_ISNICK))
continue;
if (akick->mask == mask)
break;
@@ -325,7 +347,7 @@ class CommandCSAKick : public Command
{
akick = ci->GetAkick(i);
- if (!akick->InUse || akick->HasFlag(AK_ISNICK))
+ if (akick->HasFlag(AK_ISNICK))
continue;
if (akick->mask == mask)
break;
@@ -355,25 +377,7 @@ class CommandCSAKick : public Command
/* Special case: is it a number/list? Only do search if it isn't. */
if (isdigit(*mask.c_str()) && strspn(mask.c_str(), "1234567890,-") == strlen(mask.c_str()))
- {
- int last = -1, deleted, count;
-
- deleted = process_numlist(mask.c_str(), &count, akick_del_callback, u, ci, &last);
-
- if (!deleted)
- {
- if (count == 1)
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_SUCH_ENTRY, last, ci->name.c_str());
- else
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
- }
- else if (deleted == 1)
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_DELETED_ONE, ci->name.c_str());
- else
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL, deleted, ci->name.c_str());
- if (deleted)
- ci->CleanAkick();
- }
+ (new AkickDelCallback(u, ci, mask.c_str()))->Process();
else
{
NickAlias *na = findnick(mask.c_str());
@@ -383,8 +387,6 @@ class CommandCSAKick : public Command
{
akick = ci->GetAkick(i);
- if (!akick->InUse)
- continue;
if (((akick->HasFlag(AK_ISNICK)) && akick->nc == nc)
|| (!(akick->HasFlag(AK_ISNICK))
&& akick->mask == mask))
@@ -397,7 +399,7 @@ class CommandCSAKick : public Command
return;
}
- ci->EraseAkick(akick);
+ ci->EraseAkick(i);
notice_lang(Config.s_ChanServ, u, CHAN_AKICK_DELETED, mask.c_str(), ci->name.c_str());
}
@@ -405,10 +407,7 @@ class CommandCSAKick : public Command
void DoList(User *u, ChannelInfo *ci, const std::vector<ci::string> &params)
{
- int sent_header = 0;
ci::string mask = params.size() > 2 ? params[2] : "";
- unsigned i;
- AutoKick *akick;
if (!ci->GetAkickCount())
{
@@ -417,15 +416,15 @@ class CommandCSAKick : public Command
}
if (!mask.empty() && isdigit(*mask.c_str()) && strspn(mask.c_str(), "1234567890,-") == strlen(mask.c_str()))
- process_numlist(mask.c_str(), NULL, akick_list_callback, u, ci, &sent_header);
+ (new AkickListCallback(u, ci, mask.c_str()))->Process();
else
{
- for (i = 0; i < ci->GetAkickCount(); ++i)
+ bool SentHeader = false;
+
+ for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
{
- akick = ci->GetAkick(i);
+ AutoKick *akick = ci->GetAkick(i);
- if (!akick->InUse)
- continue;
if (!mask.empty())
{
if (!(akick->HasFlag(AK_ISNICK)) && !Anope::Match(akick->mask.c_str(), mask.c_str(), false))
@@ -433,21 +432,24 @@ class CommandCSAKick : public Command
if ((akick->HasFlag(AK_ISNICK)) && !Anope::Match(akick->nc->display, mask.c_str(), false))
continue;
}
- akick_list(u, i, ci, &sent_header);
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
+ }
+
+ AkickListCallback::DoList(u, ci, i, akick);
}
+
+ if (!SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
}
-
- if (!sent_header)
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
-
}
void DoView(User *u, ChannelInfo *ci, const std::vector<ci::string> &params)
{
- int sent_header = 0;
ci::string mask = params.size() > 2 ? params[2] : "";
- AutoKick *akick;
- unsigned i;
if (!ci->GetAkickCount())
{
@@ -456,15 +458,15 @@ class CommandCSAKick : public Command
}
if (!mask.empty() && isdigit(*mask.c_str()) && strspn(mask.c_str(), "1234567890,-") == strlen(mask.c_str()))
- process_numlist(mask.c_str(), NULL, akick_view_callback, u, ci, &sent_header);
+ (new AkickViewCallback(u, ci, mask.c_str()))->Process();
else
{
- for (i = 0; i < ci->GetAkickCount(); ++i)
+ bool SentHeader = false;
+
+ for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
{
- akick = ci->GetAkick(i);
+ AutoKick *akick = ci->GetAkick(i);
- if (!akick->InUse)
- continue;
if (!mask.empty())
{
if (!(akick->HasFlag(AK_ISNICK)) && !Anope::Match(akick->mask.c_str(), mask.c_str(), false))
@@ -472,12 +474,19 @@ class CommandCSAKick : public Command
if ((akick->HasFlag(AK_ISNICK)) && !Anope::Match(akick->nc->display, mask.c_str(), false))
continue;
}
- akick_view(u, i, ci, &sent_header);
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name.c_str());
+ }
+
+ AkickViewCallback::DoList(u, ci, i, akick);
}
- }
- if (!sent_header)
- notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
+ if (!SentHeader)
+ notice_lang(Config.s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name.c_str());
+ }
}
void DoEnforce(User *u, ChannelInfo *ci, const std::vector<ci::string> &params)
diff --git a/src/core/cs_set.c b/src/core/cs_set.c
index 0a8d6ac5b..75850f453 100644
--- a/src/core/cs_set.c
+++ b/src/core/cs_set.c
@@ -466,11 +466,10 @@ class CommandCSSet : public Command
{
ChanAccess *access;
- for (unsigned i = 0; i < ci->GetAccessCount(); i++)
+ for (unsigned i = ci->GetAccessCount() - 1; 0 <= i; --i)
{
access = ci->GetAccess(i);
- if (!access->in_use)
- continue;
+
/* This will probably cause wrong levels to be set, but hey,
* it's better than losing it altogether.
*/
@@ -490,9 +489,6 @@ 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->SetFlag(CI_XOP);
}
diff --git a/src/core/cs_xop.c b/src/core/cs_xop.c
index 522c28001..eb4a76c47 100644
--- a/src/core/cs_xop.c
+++ b/src/core/cs_xop.c
@@ -14,10 +14,6 @@
#include "module.h"
-int xop_del_callback(User *u, int num, va_list args);
-int xop_list_callback(User *u, int num, va_list args);
-int xop_list(User *u, int index, ChannelInfo *ci, int *sent_header, int xlev, int xmsg);
-
enum
{
XOP_AOP,
@@ -114,6 +110,89 @@ int xop_msgs[XOP_TYPES][XOP_MESSAGES] = {
CHAN_QOP_CLEAR}
};
+class XOPListCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ int level;
+ int *messages;
+ bool SentHeader;
+ public:
+ XOPListCallback(User *_u, ChannelInfo *_ci, const std::string &numlist, int _level, int *_messages) : NumberList(numlist), u(_u), ci(_ci), level(_level), messages(_messages), SentHeader(false)
+ {
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAccessCount())
+ return;
+
+ ChanAccess *access = ci->GetAccess(Number - 1);
+
+ if (level != access->level)
+ return;
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, messages[XOP_LIST_HEADER], ci->name.c_str());
+ }
+
+ DoList(u, ci, access, Number - 1, level, messages);
+ }
+
+ static void DoList(User *u, ChannelInfo *ci, ChanAccess *access, unsigned index, int level, int *messages)
+ {
+ notice_lang(Config.s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index, access->nc->display);
+ }
+};
+
+class XOPDelCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ int *messages;
+ unsigned Deleted;
+ std::string Nicks;
+ public:
+ XOPDelCallback(User *_u, ChannelInfo *_ci, int *_messages, const std::string &numlist) : NumberList(numlist), u(_u), ci(_ci), messages(_messages), Deleted(0)
+ {
+ }
+
+ ~XOPDelCallback()
+ {
+ if (!Deleted)
+ notice_lang(Config.s_ChanServ, u, messages[XOP_NO_MATCH], ci->name.c_str());
+ else
+ {
+ Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << get_access(u, ci) << ") deleted access of users " << Nicks << " on " << ci->name;
+
+ if (Deleted == 1)
+ notice_lang(Config.s_ChanServ, u, messages[XOP_DELETED_ONE], ci->name.c_str());
+ else
+ notice_lang(Config.s_ChanServ, u, messages[XOP_DELETED_SEVERAL], Deleted, ci->name.c_str());
+ }
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > ci->GetAccessCount())
+ return;
+
+ ChanAccess *access = ci->GetAccess(Number - 1);
+
+ ++Deleted;
+ if (!Nicks.empty())
+ Nicks += ", " + std::string(access->nc->display);
+ else
+ Nicks = access->nc->display;
+
+ FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, access->nc));
+
+ ci->EraseAccess(Number - 1);
+ }
+};
+
class XOPBase : public Command
{
private:
@@ -178,8 +257,7 @@ class XOPBase : public Command
if (!change)
{
- std::string usernick = u->nick;
- ci->AddAccess(nc, level, usernick);
+ ci->AddAccess(nc, level, u->nick);
}
else
{
@@ -194,12 +272,12 @@ class XOPBase : public Command
if (!change)
{
- FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, na, level));
+ FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, nc, level));
notice_lang(Config.s_ChanServ, u, messages[XOP_ADDED], nc->display, ci->name.c_str());
}
else
{
- FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na, level));
+ FOREACH_MOD(I_OnAccessChange, OnAccessChange(ci, u, na->nc, level));
notice_lang(Config.s_ChanServ, u, messages[XOP_MOVED], nc->display, ci->name.c_str());
}
@@ -211,8 +289,6 @@ class XOPBase : public Command
const char *nick = params.size() > 2 ? params[2].c_str() : NULL;
ChanAccess *access;
- int deleted;
-
if (!nick)
{
this->OnSyntaxError(u, "DEL");
@@ -241,26 +317,7 @@ class XOPBase : public Command
/* Special case: is it a number/list? Only do search if it isn't. */
if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick))
- {
- int count, last = -1, perm = 0;
- deleted = process_numlist(nick, &count, xop_del_callback, u, ci, &last, &perm, ulev, level);
- if (!deleted)
- {
- if (perm)
- notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
- else if (count == 1)
- {
- last = atoi(nick);
- notice_lang(Config.s_ChanServ, u, messages[XOP_NO_SUCH_ENTRY], last, ci->name.c_str());
- }
- else
- notice_lang(Config.s_ChanServ, u, messages[XOP_NO_MATCH], ci->name.c_str());
- }
- else if (deleted == 1)
- notice_lang(Config.s_ChanServ, u, messages[XOP_DELETED_ONE], ci->name.c_str());
- else
- notice_lang(Config.s_ChanServ, u, messages[XOP_DELETED_SEVERAL], deleted, ci->name.c_str());
- }
+ (new XOPDelCallback(u, ci, messages, nick))->Process();
else
{
NickAlias *na = findnick(nick);
@@ -270,9 +327,17 @@ class XOPBase : public Command
return MOD_CONT;
}
NickCore *nc = na->nc;
- access = ci->GetAccess(nc, level);
- if (!access)
+ unsigned i;
+ for (i = 0; i < ci->GetAccessCount(); ++i)
+ {
+ access = ci->GetAccess(nc, level);
+
+ if (access->nc == nc)
+ break;
+ }
+
+ if (i == ci->GetAccessCount())
{
notice_lang(Config.s_ChanServ, u, messages[XOP_NOT_FOUND], nick, ci->name.c_str());
return MOD_CONT;
@@ -280,34 +345,25 @@ class XOPBase : public Command
if (ulev <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
{
- deleted = 0;
notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
}
else
{
+ Alog() << Config.s_ChanServ << ": " << u->GetMask() << " (level " << get_access(u, ci) << ") deleted access of user " << access->nc->display << " on " << ci->name;
+
notice_lang(Config.s_ChanServ, u, messages[XOP_DELETED], access->nc->display, ci->name.c_str());
- access->nc = NULL;
- access->in_use = 0;
FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, na->nc));
- deleted = 1;
+ ci->EraseAccess(i);
}
}
- if (deleted)
- {
- /* If the patch provided in bug #706 is applied, this should be placed
- * before sending the events! */
- /* We'll free the access entries no longer in use... */
- ci->CleanAccess();
- }
return MOD_CONT;
}
CommandReturn DoList(User *u, const std::vector<ci::string> &params, ChannelInfo *ci, int level, int *messages)
{
- int sent_header = 0;
const char *nick = params.size() > 2 ? params[2].c_str() : NULL;
if (!get_access(u, ci) && !u->Account()->HasCommand("chanserv/access/list"))
@@ -323,19 +379,30 @@ class XOPBase : public Command
}
if (nick && strspn(nick, "1234567890,-") == strlen(nick))
- process_numlist(nick, NULL, xop_list_callback, u, ci, &sent_header, level, messages[XOP_LIST_HEADER]);
+ (new XOPListCallback(u, ci, nick, level, messages))->Process();
else
{
+ bool SentHeader = false;
+
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
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]);
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_ChanServ, u, messages[XOP_LIST_HEADER], ci->name.c_str());
+ }
+
+ XOPListCallback::DoList(u, ci, access, i, level, messages);
}
+
+ if (!SentHeader)
+ notice_lang(Config.s_ChanServ, u, messages[XOP_NO_MATCH], ci->name.c_str());
}
- if (!sent_header)
- notice_lang(Config.s_ChanServ, u, messages[XOP_NO_MATCH], ci->name.c_str());
return MOD_CONT;
}
@@ -363,7 +430,7 @@ class XOPBase : public Command
for (unsigned i = ci->GetAccessCount(); i > 0; --i)
{
ChanAccess *access = ci->GetAccess(i - 1);
- if (access->in_use && access->level == level)
+ if (access->level == level)
ci->EraseAccess(i - 1);
}
@@ -580,71 +647,4 @@ class CSXOP : public Module
}
};
-/* `last' is set to the last index this routine was called with
- * `perm' is incremented whenever a permission-denied error occurs
- */
-int xop_del(User *u, ChannelInfo *ci, ChanAccess *access, int *perm, int uacc, int xlev)
-{
- if (!access->in_use || access->level != xlev)
- return 0;
- if (uacc <= access->level && !u->Account()->HasPriv("chanserv/access/modify"))
- {
- ++(*perm);
- return 0;
- }
- NickCore *nc = access->nc;
- access->nc = NULL;
- access->in_use = 0;
-
- FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, u, nc));
-
- return 1;
-}
-
-int xop_del_callback(User *u, int num, va_list args)
-{
- ChannelInfo *ci = va_arg(args, ChannelInfo *);
- int *last = va_arg(args, int *);
- int *perm = va_arg(args, int *);
- int uacc = va_arg(args, int);
- int xlev = va_arg(args, int);
-
- if (num < 1 || num > ci->GetAccessCount())
- return 0;
- *last = num;
-
- 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->GetAccess(index);
-
- if (!access->in_use || access->level != xlev)
- return 0;
-
- if (!*sent_header)
- {
- notice_lang(Config.s_ChanServ, u, xmsg, ci->name.c_str());
- *sent_header = 1;
- }
-
- notice_lang(Config.s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index + 1, access->nc->display);
- return 1;
-}
-
-int xop_list_callback(User *u, int num, va_list args)
-{
- ChannelInfo *ci = va_arg(args, ChannelInfo *);
- int *sent_header = va_arg(args, int *);
- int xlev = va_arg(args, int);
- int xmsg = va_arg(args, int);
-
- if (num < 1 || num > ci->GetAccessCount())
- return 0;
-
- return xop_list(u, num - 1, ci, sent_header, xlev, xmsg);
-}
-
MODULE_INIT(CSXOP)
diff --git a/src/core/db_plain.cpp b/src/core/db_plain.cpp
index 095082009..868374813 100644
--- a/src/core/db_plain.cpp
+++ b/src/core/db_plain.cpp
@@ -1061,9 +1061,8 @@ class DBPlain : public Module
db << "MD FORBID " << ci->forbidby << " :" << ci->forbidreason << endl;
}
for (unsigned k = 0; k < ci->GetAccessCount(); ++k)
- if (ci->GetAccess(k)->in_use)
- 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)->nc->display << " " << ci->GetAccess(k)->level << " "
+ << ci->GetAccess(k)->last_seen << " " << ci->GetAccess(k)->creator << endl;
for (unsigned k = 0; k < ci->GetAkickCount(); ++k)
{
db << "MD AKICK "
diff --git a/src/core/ms_del.c b/src/core/ms_del.c
index b2fd08fa1..68c093f86 100644
--- a/src/core/ms_del.c
+++ b/src/core/ms_del.c
@@ -14,7 +14,33 @@
#include "module.h"
-int del_memo_callback(User *u, int num, va_list args);
+class MemoDelCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ MemoInfo *mi;
+ public:
+ MemoDelCallback(User *_u, ChannelInfo *_ci, MemoInfo *_mi, const std::string &list) : NumberList(list), u(_u), ci(_ci), mi(_mi)
+ {
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > mi->memos.size())
+ return;
+
+ if (ci)
+ {
+ FOREACH_MOD(I_OnMemoDel, OnMemoDel(ci, mi, Number - 1));
+ }
+ else
+ {
+ FOREACH_MOD(I_OnMemoDel, OnMemoDel(u->Account(), mi, Number - 1));
+ }
+
+ delmemo(mi, Number - 1);
+ }
+};
class CommandMSDel : public Command
{
@@ -28,10 +54,8 @@ class CommandMSDel : public Command
MemoInfo *mi;
ChannelInfo *ci = NULL;
ci::string numstr = params.size() ? params[0] : "", chan;
- int last, last0;
unsigned i;
- char buf[BUFSIZE], *end;
- int delcount, count, left;
+ int last;
if (!numstr.empty() && numstr[0] == '#')
{
@@ -71,37 +95,7 @@ class CommandMSDel : public Command
else
{
if (isdigit(numstr[0]))
- {
- /* Delete a specific memo or memos. */
- last = -1; /* Last memo deleted */
- last0 = -1; /* Beginning of range of last memos deleted */
- end = buf;
- left = sizeof(buf);
- delcount = process_numlist(numstr.c_str(), &count, del_memo_callback, u, mi, &last, &last0, &end, &left, ci);
- if (last != -1)
- {
- /* Some memos got deleted; tell them which ones. */
- if (delcount > 1)
- {
- if (last0 != last)
- end += snprintf(end, sizeof(buf) - (end - buf), ",%d-%d", last0, last);
- else
- end += snprintf(end, sizeof(buf) - (end - buf), ",%d", last);
- /* "buf+1" here because *buf == ',' */
- notice_lang(Config.s_MemoServ, u, MEMO_DELETED_SEVERAL, buf + 1);
- }
- else
- notice_lang(Config.s_MemoServ, u, MEMO_DELETED_ONE, last);
- }
- else
- {
- /* No memos were deleted. Tell them so. */
- if (count == 1)
- notice_lang(Config.s_MemoServ, u, MEMO_DOES_NOT_EXIST, atoi(numstr.c_str()));
- else
- notice_lang(Config.s_MemoServ, u, MEMO_DELETED_NONE);
- }
- }
+ (new MemoDelCallback(u, ci, mi, numstr.c_str()))->Process();
else if (numstr == "LAST")
{
/* Delete last memo. */
diff --git a/src/core/ms_list.c b/src/core/ms_list.c
index a2e63c2da..c653f7708 100644
--- a/src/core/ms_list.c
+++ b/src/core/ms_list.c
@@ -14,8 +14,46 @@
#include "module.h"
-int list_memo_callback(User *u, int num, va_list args);
-int list_memo(User *u, int index, MemoInfo *mi, int *sent_header, int newi, const char *chan);
+class MemoListCallback : public NumberList
+{
+ User *u;
+ ChannelInfo *ci;
+ MemoInfo *mi;
+ bool SentHeader;
+ public:
+ MemoListCallback(User *_u, ChannelInfo *_ci, MemoInfo *_mi, const std::string &list) : NumberList(list), u(_u), ci(_ci), mi(_mi), SentHeader(false)
+ {
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > mi->memos.size())
+ return;
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ if (ci)
+ notice_lang(Config.s_MemoServ, u, MEMO_LIST_CHAN_MEMOS, ci->name.c_str(), Config.s_MemoServ, ci->name.c_str());
+ else
+ notice_lang(Config.s_MemoServ, u, MEMO_LIST_MEMOS, u->nick.c_str(), Config.s_MemoServ);
+
+ notice_lang(Config.s_MemoServ, u, MEMO_LIST_HEADER);
+ }
+
+ DoList(u, ci, mi, Number - 1);
+ }
+
+ static void DoList(User *u, ChannelInfo *ci, MemoInfo *mi, unsigned index)
+ {
+ Memo *m = mi->memos[index];
+ struct tm tm = *localtime(&m->time);
+ char timebuf[64];
+ strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
+ timebuf[sizeof(timebuf) - 1] = 0; /* just in case */
+ notice_lang(Config.s_MemoServ, u, MEMO_LIST_FORMAT, (m->HasFlag(MF_UNREAD)) ? '*' : ' ', m->number, m->sender.c_str(), timebuf);
+ }
+};
class CommandMSList : public Command
{
@@ -63,9 +101,8 @@ class CommandMSList : public Command
}
else
{
- int sent_header = 0;
if (!param.empty() && isdigit(param[0]))
- process_numlist(param.c_str(), NULL, list_memo_callback, u, mi, &sent_header, chan.empty() ? NULL : chan.c_str());
+ (new MemoListCallback(u, ci, mi, param.c_str()))->Process();
else
{
if (!param.empty())
@@ -84,11 +121,25 @@ class CommandMSList : public Command
return MOD_CONT;
}
}
+
+ bool SentHeader = false;
+
for (i = 0; i < mi->memos.size(); ++i)
{
if (!param.empty() && !(mi->memos[i]->HasFlag(MF_UNREAD)))
continue;
- list_memo(u, i, mi, &sent_header, !param.empty(), chan.empty() ? NULL : chan.c_str());
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ if (ci)
+ notice_lang(Config.s_MemoServ, u, !param.empty() ? MEMO_LIST_CHAN_NEW_MEMOS : MEMO_LIST_CHAN_MEMOS, ci->name.c_str(), Config.s_MemoServ, ci->name.c_str());
+ else
+ notice_lang(Config.s_MemoServ, u, !param.empty() ? MEMO_LIST_NEW_MEMOS : MEMO_LIST_MEMOS, u->nick.c_str(), Config.s_MemoServ);
+ notice_lang(Config.s_MemoServ, u, MEMO_LIST_HEADER);
+ }
+
+ MemoListCallback::DoList(u, ci, mi, i);
}
}
}
@@ -125,62 +176,4 @@ class MSList : public Module
}
};
-/**
- * list memno callback function
- * @param u User Struct
- * @param int Memo number
- * @param va_list List of arguements
- * @return result form list_memo()
- */
-int list_memo_callback(User *u, int num, va_list args)
-{
- MemoInfo *mi = va_arg(args, MemoInfo *);
- int *sent_header = va_arg(args, int *);
- const char *chan = va_arg(args, const char *);
- int i;
-
- for (i = 0; i < mi->memos.size(); ++i)
- {
- if (mi->memos[i]->number == num)
- break;
- }
- /* Range checking done by list_memo() */
- return list_memo(u, i, mi, sent_header, 0, chan);
-}
-
-/**
- * Display a single memo entry, possibly printing the header first.
- * @param u User Struct
- * @param int Memo index
- * @param mi MemoInfo Struct
- * @param send_header If we are to send the headers
- * @param newi If we are listing new memos
- * @param chan Channel name
- * @return MOD_CONT
- */
-int list_memo(User *u, int index, MemoInfo *mi, int *sent_header, int newi, const char *chan)
-{
- Memo *m;
- char timebuf[64];
- struct tm tm;
-
- if (index < 0 || index >= mi->memos.size())
- return 0;
- if (!*sent_header)
- {
- if (chan)
- notice_lang(Config.s_MemoServ, u, newi ? MEMO_LIST_CHAN_NEW_MEMOS : MEMO_LIST_CHAN_MEMOS, chan, Config.s_MemoServ, chan);
- else
- notice_lang(Config.s_MemoServ, u, newi ? MEMO_LIST_NEW_MEMOS : MEMO_LIST_MEMOS, u->nick.c_str(), Config.s_MemoServ);
- notice_lang(Config.s_MemoServ, u, MEMO_LIST_HEADER);
- *sent_header = 1;
- }
- m = mi->memos[index];
- tm = *localtime(&m->time);
- strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
- timebuf[sizeof(timebuf) - 1] = 0; /* just in case */
- notice_lang(Config.s_MemoServ, u, MEMO_LIST_FORMAT, (m->HasFlag(MF_UNREAD)) ? '*' : ' ', m->number, m->sender.c_str(), timebuf);
- return 1;
-}
-
MODULE_INIT(MSList)
diff --git a/src/core/ms_read.c b/src/core/ms_read.c
index 65b5c3a4b..600e92cae 100644
--- a/src/core/ms_read.c
+++ b/src/core/ms_read.c
@@ -14,9 +14,42 @@
#include "module.h"
-int read_memo_callback(User *u, int num, va_list args);
-int read_memo(User *u, int index, MemoInfo *mi, const char *chan);
-extern void rsend_notify(User *u, Memo *m, const char *chan);
+class MemoListCallback : public NumberList
+{
+ User *u;
+ MemoInfo *mi;
+ public:
+ MemoListCallback(User *_u, MemoInfo *_mi, const std::string &numlist) : NumberList(numlist), u(_u), mi(_mi)
+ {
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > mi->memos.size())
+ return;
+
+ MemoListCallback::DoRead(u, mi, NULL, Number - 1);
+ }
+
+ static void DoRead(User *u, MemoInfo *mi, ChannelInfo *ci, unsigned index)
+ {
+ Memo *m = mi->memos[index];
+ struct tm tm = *localtime(&m->time);
+ char timebuf[64];
+ strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
+ timebuf[sizeof(timebuf) - 1] = 0;
+ if (ci)
+ notice_lang(Config.s_MemoServ, u, MEMO_CHAN_HEADER, m->number, m->sender.c_str(), timebuf, Config.s_MemoServ, ci->name.c_str(), m->number);
+ else
+ notice_lang(Config.s_MemoServ, u, MEMO_HEADER, m->number, m->sender.c_str(), timebuf, Config.s_MemoServ, m->number);
+ notice_lang(Config.s_MemoServ, u, MEMO_TEXT, m->text);
+ m->UnsetFlag(MF_UNREAD);
+
+ /* Check if a receipt notification was requested */
+ if (m->HasFlag(MF_RECEIPT))
+ rsend_notify(u, m, ci ? ci->name.c_str() : NULL);
+ }
+};
class CommandMSRead : public Command
{
@@ -28,9 +61,9 @@ class CommandMSRead : public Command
CommandReturn Execute(User *u, const std::vector<ci::string> &params)
{
MemoInfo *mi;
- ChannelInfo *ci;
+ ChannelInfo *ci = NULL;
ci::string numstr = params.size() ? params[0] : "", chan;
- int num, count;
+ int num;
if (!numstr.empty() && numstr[0] == '#')
{
@@ -73,7 +106,7 @@ class CommandMSRead : public Command
{
if (mi->memos[i]->HasFlag(MF_UNREAD))
{
- read_memo(u, i, mi, !chan.empty() ? chan.c_str() : NULL);
+ MemoListCallback::DoRead(u, mi, ci, i);
++readcount;
}
}
@@ -88,17 +121,11 @@ class CommandMSRead : public Command
else if (numstr == "LAST")
{
for (i = 0; i < mi->memos.size() - 1; ++i);
- read_memo(u, i, mi, !chan.empty() ? chan.c_str() : NULL);
+ MemoListCallback::DoRead(u, mi, ci, i);
}
else /* number[s] */
{
- if (!process_numlist(numstr.c_str(), &count, read_memo_callback, u, mi, !chan.empty() ? chan.c_str() : NULL))
- {
- if (count == 1)
- notice_lang(Config.s_MemoServ, u, MEMO_DOES_NOT_EXIST, num);
- else
- notice_lang(Config.s_MemoServ, u, MEMO_LIST_NOT_FOUND, numstr.c_str());
- }
+ (new MemoListCallback(u, mi, numstr.c_str()))->Process();
}
}
return MOD_CONT;
@@ -134,60 +161,4 @@ class MSRead : public Module
}
};
-/**
- * Read a memo callback function
- * @param u User Struct
- * @param int Index number
- * @param va_list variable arguements
- * @return result of read_memo()
- */
-int read_memo_callback(User *u, int num, va_list args)
-{
- MemoInfo *mi = va_arg(args, MemoInfo *);
- const char *chan = va_arg(args, const char *);
- int i;
-
- for (i = 0; i < mi->memos.size(); ++i)
- {
- if (mi->memos[i]->number == num)
- break;
- }
- /* Range check done in read_memo */
- return read_memo(u, i, mi, chan);
-}
-
-/**
- * Read a memo
- * @param u User Struct
- * @param int Index number
- * @param mi MemoInfo struct
- * @param chan Channel Name
- * @return 1 on success, 0 if failed
- */
-int read_memo(User *u, int index, MemoInfo *mi, const char *chan)
-{
- Memo *m;
- char timebuf[64];
- struct tm tm;
-
- if (index < 0 || index >= mi->memos.size())
- return 0;
- m = mi->memos[index];
- tm = *localtime(&m->time);
- strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, &tm);
- timebuf[sizeof(timebuf) - 1] = 0;
- if (chan)
- notice_lang(Config.s_MemoServ, u, MEMO_CHAN_HEADER, m->number, m->sender.c_str(), timebuf, Config.s_MemoServ, chan, m->number);
- else
- notice_lang(Config.s_MemoServ, u, MEMO_HEADER, m->number, m->sender.c_str(), timebuf, Config.s_MemoServ, m->number);
- notice_lang(Config.s_MemoServ, u, MEMO_TEXT, m->text);
- m->UnsetFlag(MF_UNREAD);
-
- /* Check if a receipt notification was requested */
- if (m->HasFlag(MF_RECEIPT))
- rsend_notify(u, m, chan);
-
- return 1;
-}
-
MODULE_INIT(MSRead)
diff --git a/src/core/os_session.c b/src/core/os_session.c
index 2f272ab1a..06331eb79 100644
--- a/src/core/os_session.c
+++ b/src/core/os_session.c
@@ -14,6 +14,121 @@
#include "module.h"
+class ExceptionDelCallback : public NumberList
+{
+ protected:
+ User *u;
+ unsigned Deleted;
+ public:
+ ExceptionDelCallback(User *_u, const std::string &numlist) : NumberList(numlist), u(_u), Deleted(0)
+ {
+ }
+
+ ~ExceptionDelCallback()
+ {
+ if (!Deleted)
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
+ else if (Deleted == 1)
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED_ONE);
+ else
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED_SEVERAL, Deleted);
+ }
+
+ virtual void HandleNumber(unsigned Number)
+ {
+ if (Number > nexceptions)
+ return;
+
+ ++Deleted;
+
+ DoDel(u, Number - 1);
+ }
+
+ static void DoDel(User *u, unsigned index)
+ {
+ FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(u, &exceptions[index]));
+
+ delete [] exceptions[index].mask;
+ delete [] exceptions[index].reason;
+ --nexceptions;
+ memmove(exceptions + index, exceptions + index + 1, sizeof(Exception) * (nexceptions - index));
+ exceptions = static_cast<Exception *>(srealloc(exceptions, sizeof(Exception) * nexceptions));
+ }
+};
+
+class ExceptionListCallback : public NumberList
+{
+ protected:
+ User *u;
+ bool SentHeader;
+ public:
+ ExceptionListCallback(User *_u, const std::string &numlist) : NumberList(numlist), u(_u), SentHeader(false)
+ {
+ }
+
+ virtual void HandleNumber(unsigned Number)
+ {
+ if (Number > nexceptions)
+ return;
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD);
+ }
+
+ DoList(u, Number - 1);
+ }
+
+ static void DoList(User *u, unsigned index)
+ {
+ if (index >= nexceptions)
+ return;
+
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_FORMAT, index + 1, exceptions[index].limit, exceptions[index].mask);
+ }
+};
+
+class ExceptionViewCallback : public ExceptionListCallback
+{
+ public:
+ ExceptionViewCallback(User *_u, const std::string &numlist) : ExceptionListCallback(_u, numlist)
+ {
+ }
+
+ void HandleNumber(unsigned Number)
+ {
+ if (Number > nexceptions)
+ return;
+
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
+ }
+
+ DoList(u, Number - 1);
+ }
+
+ static void DoList(User *u, unsigned index)
+ {
+ if (index >= nexceptions)
+ return;
+
+ char timebuf[32], expirebuf[256];
+ struct tm tm;
+ time_t t = time(NULL);
+
+ tm = *localtime(exceptions[index].time ? &exceptions[index].time : &t);
+ strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, &tm);
+
+ expire_left(u->Account(), expirebuf, sizeof(expirebuf), exceptions[index].expires);
+
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_VIEW_FORMAT, index + 1, exceptions[index].mask, exceptions[index].who ? exceptions[index].who : "<unknown>", timebuf, expirebuf, exceptions[index].limit, exceptions[index].reason);
+ }
+};
+
class CommandOSSession : public Command
{
private:
@@ -91,93 +206,6 @@ class CommandOSSession : public Command
}
};
-static int exception_del(User *u, const int index)
-{
- if (index < 0 || index >= nexceptions)
- return 0;
-
- FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(u, &exceptions[index]));
-
- delete [] exceptions[index].mask;
- delete [] exceptions[index].reason;
- --nexceptions;
- memmove(exceptions + index, exceptions + index + 1, sizeof(Exception) * (nexceptions - index));
- exceptions = static_cast<Exception *>(srealloc(exceptions, sizeof(Exception) * nexceptions));
-
- return 1;
-}
-
-/* We use the "num" property to keep track of the position of each exception
- * when deleting using ranges. This is because an exception's position changes
- * as others are deleted. The positions will be recalculated once the process
- * is complete. -TheShadow
- */
-
-static int exception_del_callback(User *u, int num, va_list args)
-{
- int i;
- int *last = va_arg(args, int *);
-
- *last = num;
- for (i = 0; i < nexceptions; ++i)
- if (num - 1 == exceptions[i].num)
- break;
-
- if (i < nexceptions)
- return exception_del(u, i);
- else
- return 0;
-}
-
-static int exception_list(User *u, const int index, int *sent_header)
-{
- if (index < 0 || index >= nexceptions)
- return 0;
- if (!*sent_header) {
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD);
- *sent_header = 1;
- }
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_FORMAT, index + 1, exceptions[index].limit, exceptions[index].mask);
- return 1;
-}
-
-static int exception_list_callback(User *u, int num, va_list args)
-{
- int *sent_header = va_arg(args, int *);
-
- return exception_list(u, num - 1, sent_header);
-}
-
-static int exception_view(User *u, const int index, int *sent_header)
-{
- char timebuf[32], expirebuf[256];
- struct tm tm;
- time_t t = time(NULL);
-
- if (index < 0 || index >= nexceptions)
- return 0;
- if (!*sent_header) {
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
- *sent_header = 1;
- }
-
- tm = *localtime(exceptions[index].time ? &exceptions[index].time : &t);
- strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, &tm);
-
- expire_left(u->Account(), expirebuf, sizeof(expirebuf), exceptions[index].expires);
-
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_VIEW_FORMAT, index + 1, exceptions[index].mask, exceptions[index].who ? exceptions[index].who : "<unknown>", timebuf, expirebuf, exceptions[index].limit, exceptions[index].reason);
- return 1;
-}
-
-static int exception_view_callback(User *u, int num, va_list args)
-{
- int *sent_header = va_arg(args, int *);
-
- return exception_view(u, num - 1, sent_header);
-}
-
class CommandOSException : public Command
{
private:
@@ -188,12 +216,6 @@ class CommandOSException : public Command
unsigned last_param = 3;
int x;
- if (nexceptions >= 32767)
- {
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_TOO_MANY);
- return MOD_CONT;
- }
-
mask = params.size() > 1 ? params[1].c_str() : NULL;
if (mask && *mask == '+')
{
@@ -267,21 +289,7 @@ class CommandOSException : public Command
}
if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask))
- {
- int count, deleted, last = -1;
- deleted = process_numlist(mask, &count, exception_del_callback, u, &last);
- if (!deleted)
- {
- if (count == 1)
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_SUCH_ENTRY, last);
- else
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
- }
- else if (deleted == 1)
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED_ONE);
- else
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED_SEVERAL, deleted);
- }
+ (new ExceptionDelCallback(u, mask))->Process();
else
{
int deleted = 0;
@@ -290,7 +298,7 @@ class CommandOSException : public Command
{
if (!stricmp(mask, exceptions[i].mask))
{
- exception_del(u, i);
+ ExceptionDelCallback::DoDel(u, i);
notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED, mask);
deleted = 1;
break;
@@ -367,44 +375,67 @@ class CommandOSException : public Command
CommandReturn DoList(User *u, const std::vector<ci::string> &params)
{
- int sent_header = 0, i;
+ int i;
expire_exceptions();
const char *mask = params.size() > 1 ? params[1].c_str() : NULL;
if (mask && strspn(mask, "1234567890,-") == strlen(mask))
- process_numlist(mask, NULL, exception_list_callback, u, &sent_header);
+ (new ExceptionListCallback(u, mask))->Process();
else
{
+ bool SentHeader = false;
+
for (i = 0; i < nexceptions; ++i)
{
if (!mask || Anope::Match(exceptions[i].mask, mask, false))
- exception_list(u, i, &sent_header);
+ {
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD);
+ }
+
+ ExceptionListCallback::DoList(u, i);
+ }
}
+
+ if (!SentHeader)
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
}
- if (!sent_header)
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
return MOD_CONT;
}
CommandReturn DoView(User *u, const std::vector<ci::string> &params)
{
- int sent_header = 0, i;
+ int i;
expire_exceptions();
const char *mask = params.size() > 1 ? params[1].c_str() : NULL;
if (mask && strspn(mask, "1234567890,-") == strlen(mask))
- process_numlist(mask, NULL, exception_view_callback, u, &sent_header);
+ (new ExceptionViewCallback(u, mask))->Process();
else
{
+ bool SentHeader = false;
+
for (i = 0; i < nexceptions; ++i)
{
if (!mask || Anope::Match(exceptions[i].mask, mask, false))
- exception_view(u, i, &sent_header);
+ {
+ if (!SentHeader)
+ {
+ SentHeader = true;
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
+ }
+
+ ExceptionViewCallback::DoList(u, i);
+ }
}
+
+ if (!SentHeader)
+ notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
}
- if (!sent_header)
- notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
return MOD_CONT;
}
diff --git a/src/memoserv.c b/src/memoserv.c
index 405813332..11121cee3 100644
--- a/src/memoserv.c
+++ b/src/memoserv.c
@@ -20,7 +20,6 @@
E void moduleAddMemoServCmds();
static bool SendMemoMail(NickCore *nc, Memo *m);
-E void rsend_notify(User *u, Memo *m, const char *chan);
/*************************************************************************/
diff --git a/src/misc.c b/src/misc.c
index 443dec298..d7060660e 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -223,83 +223,83 @@ const char *merge_args(int argc, char **argv)
}
/*************************************************************************/
-/**
- * Process a string containing a number/range list in the form
- * "n1[-n2][,n3[-n4]]...", calling a caller-specified routine for each
- * number in the list. If the callback returns -1, stop immediately.
- * Returns the sum of all nonnegative return values from the callback.
- * If `count' is non-NULL, it will be set to the total number of times the
- * callback was called.
- *
- * The callback should be of type range_callback_t, which is defined as:
- * int (*range_callback_t)(User *u, int num, va_list args)
- * @param numstr
- * @param count_ret
- * @param callback Call back function
- * @param u User Struct
- * @param ... various args
- * @return int
- */
-int process_numlist(const char *numstr, int *count_ret,
- range_callback_t callback, User * u, ...)
+
+NumberList::NumberList(const std::string &list)
{
- int n1, n2, i;
- int res = 0, retval = 0, count = 0;
- va_list args, preserve;
+ commasepstream sep(list);
+ std::string token;
- if (!numstr || !*numstr) {
- return -1;
- }
+ sep.GetToken(token);
+ if (token.empty())
+ token = list;
+ do
+ {
+ char *h = strchr(token.c_str(), '-');
- va_start(args, u);
-
- /*
- * This algorithm ignores invalid characters, ignores a dash
- * when it precedes a comma, and ignores everything from the
- * end of a valid number or range to the next comma or null.
- */
- for (;;) {
- n1 = n2 = strtol(numstr, const_cast<char **>(&numstr), 10);
- numstr += strcspn(numstr, "0123456789,-");
- if (*numstr == '-') {
- numstr++;
- numstr += strcspn(numstr, "0123456789,");
- if (isdigit(*numstr)) {
- n2 = strtol(numstr, const_cast<char **>(&numstr), 10);
- numstr += strcspn(numstr, "0123456789,-");
+ if (!h)
+ {
+ errno = 0;
+ unsigned num = strtol(token.c_str(), NULL, 10);
+ if (!errno)
+ {
+ numbers.insert(num);
}
- }
- for (i = n1; i <= n2 && i >= 0; i++) {
- VA_COPY(preserve, args);
- res = callback(u, i, preserve);
- va_end(preserve);
- count++;
- if (res < 0)
- break;
- retval += res;
- if (count >= 32767) {
- if (count_ret)
- *count_ret = count;
- return retval;
+ else
+ {
+ if (!this->InvalidRange(list))
+ {
+ delete this;
+ return;
+ }
}
}
- if (res < -1)
- break;
- numstr += strcspn(numstr, ",");
- if (*numstr)
- numstr++;
else
- break;
- }
- if (count_ret)
- *count_ret = count;
+ {
+ *h++ = '\0';
+ errno = 0;
+ unsigned num1 = strtol(token.c_str(), NULL, 10);
+ unsigned num2 = strtol(h, NULL, 10);
+ if (!errno)
+ {
+ for (unsigned i = num1; i <= num2; ++i)
+ {
+ numbers.insert(i);
+ }
+ }
+ else
+ {
+ if (!this->InvalidRange(list))
+ {
+ delete this;
+ return;
+ }
+ }
+ }
+ } while (sep.GetToken(token));
+}
- va_end(args);
+NumberList::~NumberList()
+{
+}
- return retval;
+void NumberList::Process()
+{
+ for (std::set<unsigned>::reverse_iterator it = numbers.rbegin(); it != numbers.rend(); ++it)
+ {
+ this->HandleNumber(*it);
+ }
+
+ delete this;
}
-/*************************************************************************/
+void NumberList::HandleNumber(unsigned)
+{
+}
+
+bool NumberList::InvalidRange(const std::string &)
+{
+ return true;
+}
/**
* dotime: Return the number of seconds corresponding to the given time
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index 8bc5078aa..15a72ca87 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -138,7 +138,6 @@ ChannelInfo::~ChannelInfo()
void ChannelInfo::AddAccess(NickCore *nc, int16 level, const std::string &creator, int32 last_seen)
{
ChanAccess *new_access = new ChanAccess();
- new_access->in_use = 1;
new_access->nc = nc;
new_access->level = level;
new_access->last_seen = last_seen;
@@ -181,7 +180,7 @@ ChanAccess *ChannelInfo::GetAccess(NickCore *nc, int16 level)
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))
+ if (access[i]->nc == nc && (level ? access[i]->level == level : true))
return access[i];
return NULL;
@@ -210,25 +209,16 @@ void ChannelInfo::EraseAccess(unsigned 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 ChannelInfo::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 ChannelInfo::ClearAccess()
{
- while (access.begin() != access.end())
+ while (!access.empty())
+ {
EraseAccess(0);
+ }
}
/** Add an akick entry to the channel by NickCore
@@ -245,7 +235,6 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, cons
return NULL;
AutoKick *autokick = new AutoKick();
- autokick->InUse = true;
autokick->SetFlag(AK_ISNICK);
autokick->nc = akicknc;
autokick->reason = reason;
@@ -255,8 +244,6 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, cons
akick.push_back(autokick);
- FOREACH_MOD(I_OnAkickAdd, OnAkickAdd(this, autokick));
-
return autokick;
}
@@ -272,7 +259,6 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask
{
AutoKick *autokick = new AutoKick();
autokick->mask = mask;
- autokick->InUse = true;
autokick->reason = reason;
autokick->creator = user;
autokick->addtime = t;
@@ -280,8 +266,6 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask
akick.push_back(autokick);
- FOREACH_MOD(I_OnAkickAdd, OnAkickAdd(this, autokick));
-
return autokick;
}
@@ -306,40 +290,27 @@ const unsigned ChannelInfo::GetAkickCount() const
}
/** Erase an entry from the channel akick list
- * @param akick The akick
+ * @param index The index of the akick
*/
-void ChannelInfo::EraseAkick(AutoKick *autokick)
+void ChannelInfo::EraseAkick(unsigned index)
{
- std::vector<AutoKick *>::iterator it = std::find(akick.begin(), akick.end(), autokick);
-
- if (it != akick.end())
- {
- FOREACH_MOD(I_OnAkickDel, OnAkickDel(this, *it));
-
- delete *it;
- akick.erase(it);
- }
+ if (akick.empty() || index > akick.size())
+ return;
+
+ delete akick[index];
+ akick.erase(akick.begin() + index);
}
/** Clear the whole akick list
*/
void ChannelInfo::ClearAkick()
{
- for (unsigned i = akick.size(); i > 0; --i)
+ while (!akick.empty())
{
- EraseAkick(akick[i - 1]);
+ EraseAkick(0);
}
}
-/** Clean all of the nonused entries from the akick list
- */
-void ChannelInfo::CleanAkick()
-{
- for (unsigned i = akick.size(); i > 0; --i)
- if (!akick[i - 1]->InUse)
- EraseAkick(akick[i - 1]);
-}
-
/** Add a badword to the badword list
* @param word The badword
* @param type The type (SINGLE START END)
@@ -348,7 +319,6 @@ void ChannelInfo::CleanAkick()
BadWord *ChannelInfo::AddBadWord(const std::string &word, BadWordType type)
{
BadWord *bw = new BadWord;
- bw->InUse = true;
bw->word = word;
bw->type = type;
@@ -380,39 +350,27 @@ const unsigned ChannelInfo::GetBadWordCount() const
}
/** Remove a badword
- * @param badword The badword
+ * @param index The index of the badword
*/
-void ChannelInfo::EraseBadWord(BadWord *badword)
+void ChannelInfo::EraseBadWord(unsigned index)
{
- std::vector<BadWord *>::iterator it = std::find(badwords.begin(), badwords.end(), badword);
-
- if (it != badwords.end())
- {
- FOREACH_MOD(I_OnBadWordDel, OnBadWordDel(this, *it));
- delete *it;
- badwords.erase(it);
- }
+ if (badwords.empty() || index >= badwords.size())
+ return;
+
+ delete badwords[index];
+ badwords.erase(badwords.begin() + index);
}
/** Clear all badwords from the channel
*/
void ChannelInfo::ClearBadWords()
{
- for (unsigned i = badwords.size(); i > 0; --i)
+ while (!badwords.empty())
{
- EraseBadWord(badwords[i - 1]);
+ EraseBadWord(0);
}
}
-/** Clean all of the nonused entries from the badwords list
- */
-void ChannelInfo::CleanBadWords()
-{
- for (unsigned i = badwords.size(); i > 0; --i)
- if (!badwords[i - 1]->InUse)
- EraseBadWord(badwords[i - 1]);
-}
-
/** Check if a mode is mlocked
* @param Name The mode
* @param status True to check mlock on, false for mlock off
@@ -598,9 +556,6 @@ bool ChannelInfo::CheckKick(User *user)
{
autokick = this->GetAkick(j);
- if (!autokick->InUse)
- continue;
-
if ((autokick->HasFlag(AK_ISNICK) && autokick->nc == nc)
|| (!autokick->HasFlag(AK_ISNICK)
&& match_usermask(autokick->mask.c_str(), user)))