diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chanserv.c | 26 | ||||
-rw-r--r-- | src/core/bs_badwords.c | 170 | ||||
-rw-r--r-- | src/core/cs_access.c | 319 | ||||
-rw-r--r-- | src/core/cs_akick.c | 269 | ||||
-rw-r--r-- | src/core/cs_set.c | 8 | ||||
-rw-r--r-- | src/core/cs_xop.c | 232 | ||||
-rw-r--r-- | src/core/db_plain.cpp | 5 | ||||
-rw-r--r-- | src/core/ms_del.c | 64 | ||||
-rw-r--r-- | src/core/ms_list.c | 119 | ||||
-rw-r--r-- | src/core/ms_read.c | 111 | ||||
-rw-r--r-- | src/core/os_session.c | 269 | ||||
-rw-r--r-- | src/memoserv.c | 1 | ||||
-rw-r--r-- | src/misc.c | 132 | ||||
-rw-r--r-- | src/regchannel.cpp | 89 |
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> ¶ms) { - 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> ¶ms) { - 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> ¶ms) 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> ¶ms, 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> ¶ms) { 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> ¶ms) { - 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> ¶ms) { - 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))) |