diff options
author | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-11-07 18:09:09 +0000 |
---|---|---|
committer | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-11-07 18:09:09 +0000 |
commit | 029f39964b2e8f0371ef5bc776d1052d7894e695 (patch) | |
tree | b0062108291f74a2296dd2ee06cc80be87a769a7 | |
parent | 2ec83162d68c33896e2266524d9b9a29c8ee4908 (diff) |
Rewrote all of the akick code to be much cleaner
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2613 5417fbe8-f217-4b02-8779-1006273d7864
-rw-r--r-- | include/regchannel.h | 28 | ||||
-rw-r--r-- | include/services.h | 19 | ||||
-rw-r--r-- | src/chanserv.c | 248 | ||||
-rw-r--r-- | src/core/cs_akick.c | 821 | ||||
-rw-r--r-- | src/regchannel.cpp | 69 |
5 files changed, 554 insertions, 631 deletions
diff --git a/include/regchannel.h b/include/regchannel.h index 59a956710..45c8341b6 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -40,8 +40,7 @@ class CoreExport ChannelInfo : public Extensible int16 *levels; /* Access levels for commands */ std::vector<ChanAccess *> access; /* List of authorized users */ - uint16 akickcount; - AutoKick *akick; /* List of users to kickban */ + std::vector<AutoKick *> akick; /* List of users to kickban */ std::bitset<128> mlock_on; std::bitset<128> mlock_off; @@ -115,6 +114,31 @@ class CoreExport ChannelInfo : public Extensible */ void ClearAccess(); + /** Add an akick entry to the channel by NickCore + * @param user The user who added the akick + * @param akicknc The nickcore being akicked + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + */ + AutoKick *AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t = time(NULL)); + + /** Add an akick entry to the channel by reason + * @param user The user who added the akick + * @param mask The mask of the akick + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + */ + AutoKick *AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t = time(NULL)); + + /** Erase an entry from the channel akick list + * @param akick The akick + */ + void EraseAkick(AutoKick *akick); + + /** Clear the whole akick list + */ + void ClearAkick(); + /** Check if a mode is mlocked * @param Name The mode * @param status True to check mlock on, false for mlock off diff --git a/include/services.h b/include/services.h index d90146e41..738c4b283 100644 --- a/include/services.h +++ b/include/services.h @@ -645,19 +645,18 @@ struct ChanAccess { }; /* AutoKick data. */ -typedef struct { - int16 in_use; /* Always 0 if not in use */ - int16 is_nick; /* 1 if a regged nickname, 0 if a nick!user@host mask */ +struct AutoKick +{ uint16 flags; - union { - char *mask; /* Guaranteed to be non-NULL if in use, NULL if not */ - NickCore *nc; /* Same */ - } u; - char *reason; - char *creator; + /* Only one of these can be in use */ + std::string mask; + NickCore *nc; + + std::string reason; + std::string creator; time_t addtime; -} AutoKick; +}; #define AK_USED 0x0001 #define AK_ISNICK 0x0002 diff --git a/src/chanserv.c b/src/chanserv.c index 53a11eb36..c87177f66 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -235,16 +235,8 @@ void get_chanserv_stats(long *nrec, long *memuse) mem += strlen(ci->email) + 1; if (!ci->access.empty()) mem += ci->access.size() * sizeof(ChanAccess); - mem += ci->akickcount * sizeof(AutoKick); - for (j = 0; j < ci->akickcount; j++) { - if (!(ci->akick[j].flags & AK_ISNICK) - && ci->akick[j].u.mask) - mem += strlen(ci->akick[j].u.mask) + 1; - if (ci->akick[j].reason) - mem += strlen(ci->akick[j].reason) + 1; - if (ci->akick[j].creator) - mem += strlen(ci->akick[j].creator) + 1; - } + if (!ci->akick.empty()) + mem += ci->akick.size() * sizeof(AutoKick); if (ci->GetParam(CMODE_KEY, ¶m)) mem += param.length() + 1; @@ -456,39 +448,31 @@ void load_cs_dbase() } } - SAFE(read_int16(&ci->akickcount, f)); - if (ci->akickcount) { - ci->akick = static_cast<AutoKick *>(scalloc(ci->akickcount, sizeof(AutoKick))); - for (j = 0; j < ci->akickcount; j++) { - SAFE(read_int16(&ci->akick[j].flags, f)); - if (ci->akick[j].flags & AK_USED) { - SAFE(read_string(&s, f)); - if (ci->akick[j].flags & AK_ISNICK) { - ci->akick[j].u.nc = findcore(s); - if (!ci->akick[j].u.nc) - ci->akick[j].flags &= ~AK_USED; - delete [] s; - } else { - ci->akick[j].u.mask = s; - } - SAFE(read_string(&s, f)); - if (ci->akick[j].flags & AK_USED) - ci->akick[j].reason = s; - else if (s) - delete [] s; - SAFE(read_string(&s, f)); - if (ci->akick[j].flags & AK_USED) { - ci->akick[j].creator = s; - } else if (s) { - delete [] s; - } - SAFE(read_int32(&tmp32, f)); - if (ci->akick[j].flags & AK_USED) - ci->akick[j].addtime = tmp32; + uint16 akickcount = 0; + NickCore *nc; + SAFE(read_int16(&akickcount, f)); + if (akickcount) { + for (j = 0; j < akickcount; ++j) + { + uint16 flags; + SAFE(read_int16(&flags, f)); + SAFE(read_string(&s, f)); + char *akickreason; + SAFE(read_string(&akickreason, f)); + char *akickcreator; + SAFE(read_string(&akickcreator, f)); + SAFE(read_int32(&tmp32, f)); + + if (flags & AK_ISNICK) + { + nc = findcore(s); + if (!nc) + continue; + ci->AddAkick(akickcreator, nc, akickreason ? akickreason : "", tmp32); } + else + ci->AddAkick(akickcreator, s, akickreason ? akickreason : "", tmp32); } - } else { - ci->akick = NULL; } //SAFE(read_int32(&ci->mlock_on, f)); @@ -695,18 +679,17 @@ void save_cs_dbase() //SAFE(write_string(access->creator.c_str(), f)); } - SAFE(write_int16(ci->akickcount, f)); - for (j = 0; j < ci->akickcount; j++) { - SAFE(write_int16(ci->akick[j].flags, f)); - if (ci->akick[j].flags & AK_USED) { - if (ci->akick[j].flags & AK_ISNICK) - SAFE(write_string(ci->akick[j].u.nc->display, f)); - else - SAFE(write_string(ci->akick[j].u.mask, f)); - SAFE(write_string(ci->akick[j].reason, f)); - SAFE(write_string(ci->akick[j].creator, f)); - SAFE(write_int32(ci->akick[j].addtime, f)); - } + SAFE(write_int16(ci->akick.size(), f)); + for (j = 0; j < ci->akick.size(); ++j) + { + SAFE(write_int16(ci->akick[j]->flags, f)); + if (ci->akick[j]->flags & AK_ISNICK) + SAFE(write_string(ci->akick[j]->nc->display, f)); + else + SAFE(write_string(ci->akick[j]->mask.c_str(), f)); + SAFE(write_string(ci->akick[j]->reason.c_str(), f)); + SAFE(write_string(ci->akick[j]->creator.c_str(), f)); + SAFE(write_int32(ci->akick[j]->addtime, f)); } //SAFE(write_int32(ci->mlock_on, f)); @@ -1154,7 +1137,6 @@ int check_kick(User * user, const char *chan, time_t chants) ChannelInfo *ci = cs_findchan(chan); Channel *c; AutoKick *akick; - int i; bool set_modes = false; NickCore *nc; const char *av[4]; @@ -1187,7 +1169,7 @@ int check_kick(User * user, const char *chan, time_t chants) goto kick; } - if (user->IsRecognized()) + if (user->nc || user->IsRecognized()) nc = user->nc; else nc = NULL; @@ -1203,25 +1185,29 @@ int check_kick(User * user, const char *chan, time_t chants) return 0; } - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + for (unsigned j = 0; j < ci->akick.size(); ++j) + { + akick = ci->akick[j]; + if (!(akick->flags & AK_USED)) continue; - if ((akick->flags & AK_ISNICK && akick->u.nc == nc) + + if ((akick->flags & AK_ISNICK && akick->nc == nc) || (!(akick->flags & AK_ISNICK) - && match_usermask(akick->u.mask, user))) { + && match_usermask(akick->mask.c_str(), user))) + { if (debug >= 2) - alog("debug: %s matched akick %s", user->nick, - (akick->flags & AK_ISNICK) ? akick->u.nc-> - display : akick->u.mask); + alog("debug: %s matched akick %s", user->nick, (akick->flags & AK_ISNICK) ? akick->nc->display : akick->mask.c_str()); if (akick->flags & AK_ISNICK) get_idealban(ci, user, mask, sizeof(mask)); else - strlcpy(mask, akick->u.mask, sizeof(mask)); - reason = akick->reason ? akick->reason : CSAutokickReason; + strlcpy(mask, akick->mask.c_str(), sizeof(mask)); + reason = !akick->reason.empty() ? akick->reason.c_str() : CSAutokickReason; goto kick; - } + } } + if (check_access(user, ci, CA_NOJOIN)) { get_idealban(ci, user, mask, sizeof(mask)); reason = getstring(user, CHAN_NOT_ALLOWED_TO_JOIN); @@ -1462,7 +1448,7 @@ void expire_chans() void cs_remove_nick(const NickCore * nc) { - int i, j, k; + int i, j; ChannelInfo *ci, *next; ChanAccess *ca; AutoKick *akick; @@ -1512,65 +1498,12 @@ void cs_remove_nick(const NickCore * nc) ci->EraseAccess(j - 1); } - for (akick = ci->akick, j = 0; j < ci->akickcount; akick++, j++) { - if ((akick->flags & AK_USED) && (akick->flags & AK_ISNICK) - && akick->u.nc == nc) { - if (akick->creator) { - delete [] akick->creator; - akick->creator = NULL; - } - if (akick->reason) { - delete [] akick->reason; - akick->reason = NULL; - } - akick->flags = 0; - akick->addtime = 0; - akick->u.nc = NULL; - - /* Only one occurance can exist in every akick list.. ~ Viper */ - break; - } - } - - /* Are there any akicks behind us? - * If so, move all following akicks.. ~ Viper */ - if (j < ci->akickcount - 1) { - for (k = j + 1; k < ci->akickcount; j++, k++) { - if (ci->akick[k].flags & AK_USED) { - /* Move the akick one place ahead and clear the original */ - if (ci->akick[k].flags & AK_ISNICK) { - ci->akick[j].u.nc = ci->akick[k].u.nc; - ci->akick[k].u.nc = NULL; - } else { - ci->akick[j].u.mask = sstrdup(ci->akick[k].u.mask); - delete [] ci->akick[k].u.mask; - ci->akick[k].u.mask = NULL; - } - - if (ci->akick[k].reason) { - ci->akick[j].reason = sstrdup(ci->akick[k].reason); - delete [] ci->akick[k].reason; - ci->akick[k].reason = NULL; - } else - ci->akick[j].reason = NULL; - - ci->akick[j].creator = sstrdup(ci->akick[k].creator); - delete [] ci->akick[k].creator; - ci->akick[k].creator = NULL; - - ci->akick[j].flags = ci->akick[k].flags; - ci->akick[k].flags = 0; - - ci->akick[j].addtime = ci->akick[k].addtime; - ci->akick[k].addtime = 0; - } - } + for (j = ci->akick.size(); j > 0; --j) + { + akick = ci->akick[j - 1]; + if ((akick->flags & AK_USED) && (akick->flags & AK_ISNICK) && akick->nc == nc) + ci->EraseAkick(akick); } - - /* After moving only the last entry should still be empty. - * Free the place no longer in use... ~ Viper */ - ci->akickcount = j; - ci->akick = static_cast<AutoKick *>(srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount)); } } } @@ -1756,22 +1689,7 @@ int delchan(ChannelInfo * ci) delete [] ci->forbidby; if (ci->forbidreason) delete [] ci->forbidreason; - if (debug >= 2) { - alog("debug: delchan() top of the akick list"); - } - for (i = 0; i < ci->akickcount; i++) { - if (!(ci->akick[i].flags & AK_ISNICK) && ci->akick[i].u.mask) - delete [] ci->akick[i].u.mask; - if (ci->akick[i].reason) - delete [] ci->akick[i].reason; - if (ci->akick[i].creator) - delete [] ci->akick[i].creator; - } - if (debug >= 2) { - alog("debug: delchan() done with the akick list"); - } - if (ci->akick) - free(ci->akick); + ci->ClearAkick(); if (ci->levels) delete [] ci->levels; if (debug >= 2) { @@ -2053,25 +1971,22 @@ const char *get_xop_level(int level) AutoKick *is_stuck(ChannelInfo * ci, const char *mask) { - int i; - AutoKick *akick; - - if (!ci) { + if (!ci) return NULL; - } + + for (unsigned i = 0; i < ci->akick.size(); ++i) + { + AutoKick *akick = ci->akick[i]; - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { - if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK) - || !(akick->flags & AK_STUCK)) + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK) || !(akick->flags & AK_STUCK)) continue; - /* Example: mask = *!*@*.org and akick->u.mask = *!*@*.anope.org */ - if (Anope::Match(akick->u.mask, mask, false)) + + if (Anope::Match(akick->mask, mask, false)) return akick; - if (ircd->reversekickcheck) { - /* Example: mask = *!*@irc.anope.org and akick->u.mask = *!*@*.anope.org */ - if (Anope::Match(mask, akick->u.mask, false)) + + if (ircd->reversekickcheck) + if (Anope::Match(mask, akick->mask, false)) return akick; - } } return NULL; @@ -2092,18 +2007,13 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick) for (ban = ci->c->bans->entries; ban; ban = ban->next) { /* If akick is already covered by a wider ban. Example: c->bans[i] = *!*@*.org and akick->u.mask = *!*@*.epona.org */ - char *mask = sstrdup(akick->u.mask); - if (entry_match_mask(ban, mask, 0)) - { - delete [] mask; + if (entry_match_mask(ban, akick->mask.c_str(), 0)) return; - } - delete [] mask; if (ircd->reversekickcheck) { /* If akick is wider than a ban already in place. Example: c->bans[i] = *!*@irc.epona.org and akick->u.mask = *!*@*.epona.org */ - if (Anope::Match(ban->mask, akick->u.mask, false)) + if (Anope::Match(ban->mask, akick->mask.c_str(), false)) return; } } @@ -2111,8 +2021,8 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick) /* Falling there means set the ban */ av[0] = "+b"; - av[1] = akick->u.mask; - ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->u.mask); + av[1] = akick->mask.c_str(); + ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->mask.c_str()); chan_set_modes(s_ChanServ, ci->c, 2, av, 1); } @@ -2120,22 +2030,22 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick) void stick_all(ChannelInfo * ci) { - int i; const char *av[2]; - AutoKick *akick; - if (!ci) { + if (!ci) return; - } - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + for (unsigned i = 0; i < ci->akick.size(); ++i) + { + AutoKick *akick = ci->akick[i]; + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK) || !(akick->flags & AK_STUCK)) continue; av[0] = "+b"; - av[1] = akick->u.mask; - ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->u.mask); + av[1] = akick->mask.c_str(); + ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->mask.c_str()); chan_set_modes(s_ChanServ, ci->c, 2, av, 1); } } diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c index c700dc21e..b68dbeec5 100644 --- a/src/core/cs_akick.c +++ b/src/core/cs_akick.c @@ -46,29 +46,6 @@ static void split_usermask(const char *mask, const char **nick, const char **use delete [] mask2; } -int akick_del(User * u, AutoKick * akick) -{ - if (!(akick->flags & AK_USED)) - return 0; - if (akick->flags & AK_ISNICK) { - akick->u.nc = NULL; - } else { - delete [] akick->u.mask; - akick->u.mask = NULL; - } - if (akick->reason) { - delete [] akick->reason; - akick->reason = NULL; - } - if (akick->creator) { - delete [] akick->creator; - akick->creator = NULL; - } - akick->addtime = 0; - akick->flags = 0; - return 1; -} - int akick_del_callback(User * u, int num, va_list args) { ChannelInfo *ci = va_arg(args, ChannelInfo *); @@ -76,16 +53,17 @@ int akick_del_callback(User * u, int num, va_list args) *last = num; - if (num < 1 || num > ci->akickcount) + if (num < 1 || num > ci->akick.size()) return 0; - return akick_del(u, &ci->akick[num - 1]); + ci->EraseAkick(ci->akick[num - 1]); + return 1; } int akick_list(User * u, int index, ChannelInfo * ci, int *sent_header) { - AutoKick *akick = &ci->akick[index]; + AutoKick *akick = ci->akick[index]; if (!(akick->flags & AK_USED)) return 0; @@ -95,10 +73,10 @@ int akick_list(User * u, int index, ChannelInfo * ci, int *sent_header) } notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_FORMAT, index + 1, - ((akick->flags & AK_ISNICK) ? akick->u.nc-> - display : akick->u.mask), - (akick->reason ? akick-> - reason : getstring(u, NO_REASON))); + ((akick->flags & AK_ISNICK) ? akick->nc-> + display : akick->mask.c_str()), + (!akick->reason.empty() ? akick-> + reason.c_str() : getstring(u, NO_REASON))); return 1; } @@ -106,14 +84,14 @@ 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->akickcount) + if (num < 1 || num > ci->akick.size()) return 0; return akick_list(u, num - 1, ci, sent_header); } int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header) { - AutoKick *akick = &ci->akick[index]; + AutoKick *akick = ci->akick[index]; char timebuf[64]; struct tm tm; @@ -136,13 +114,13 @@ int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header) ((akick-> flags & AK_STUCK) ? CHAN_AKICK_VIEW_FORMAT_STUCK : CHAN_AKICK_VIEW_FORMAT), index + 1, - ((akick->flags & AK_ISNICK) ? akick->u.nc-> - display : akick->u.mask), - akick->creator ? akick->creator : getstring(u, + ((akick->flags & AK_ISNICK) ? akick->nc-> + display : akick->mask.c_str()), + !akick->creator.empty() ? akick->creator.c_str() : getstring(u, UNKNOWN), timebuf, - (akick->reason ? akick-> - reason : getstring(u, NO_REASON))); + (!akick->reason.empty() ? akick-> + reason.c_str() : getstring(u, NO_REASON))); return 1; } @@ -150,7 +128,7 @@ 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->akickcount) + if (num < 1 || num > ci->akick.size()) return 0; return akick_view(u, num - 1, ci, sent_header); } @@ -168,477 +146,424 @@ int get_access_nc(NickCore *nc, ChannelInfo *ci) class CommandCSAKick : public Command { - public: - CommandCSAKick() : Command("AKICK", 2, 4) + void DoAdd(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) { - } - - CommandReturn Execute(User *u, std::vector<ci::string> ¶ms) - { - const char *chan = params[0].c_str(); - ci::string cmd = params[1]; - const char *mask = params.size() > 2 ? params[2].c_str() : NULL; - const char *reason = NULL; - - if (params.size() > 3) - { - params[3].resize(200); // XXX: is this right? - reason = params[3].c_str(); - } - - ChannelInfo *ci = cs_findchan(chan); + ci::string mask = params[2]; + ci::string reason = params.size() > 3 ? params[3] : ""; + NickAlias *na = findnick(mask.c_str()); + NickCore *nc = NULL; AutoKick *akick; int i; - Channel *c; - struct c_userlist *cu = NULL; - struct c_userlist *unext; - User *u2; - const char *argv[3]; - int count = 0; - if (!mask && (cmd == "ADD" || cmd == "STICK" || cmd == "UNSTICK" || cmd == "DEL")) - syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX); - else if (!check_access(u, ci, CA_AKICK) && !u->nc->HasPriv("chanserv/access/modify")) - notice_lang(s_ChanServ, u, ACCESS_DENIED); - else if (cmd == "ADD") { - NickAlias *na = findnick(mask), *na2; - NickCore *nc = NULL; + if (!na) + { const char *nick, *user, *host; - int freemask = 0; - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); - return MOD_CONT; - } + split_usermask(mask.c_str(), &nick, &user, &host); + mask = ci::string(nick) + "!" + user + "@" + host; + delete [] nick; + delete [] user; + delete [] host; + } + else + { + if (na->status & NS_FORBIDDEN) + { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, mask.c_str()); + return; + } - if (!na) { - split_usermask(mask, &nick, &user, &host); - std::string smask = std::string(nick) + "!" + user + "@" + host; - freemask = 1; - mask = sstrdup(smask.c_str()); - delete [] nick; - delete [] user; - delete [] host; - } else { - if (na->status & NS_FORBIDDEN) { - notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, mask); - return MOD_CONT; - } - nc = na->nc; - } + nc = na->nc; + } - /* Check excepts BEFORE we get this far */ - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) - { - if (is_excepted_mask(ci, mask) == 1) { - notice_lang(s_ChanServ, u, CHAN_EXCEPTED, mask, chan); - if (freemask) - delete [] mask; - return MOD_CONT; - } - } + /* Check excepts BEFORE we get this far */ + if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) + { + if (is_excepted_mask(ci, mask.c_str())) + { + notice_lang(s_ChanServ, u, CHAN_EXCEPTED, mask.c_str(), ci->name); + return; + } + } - /* Check whether target nick has equal/higher access - * or whether the mask matches a user with higher/equal access - Viper */ - if ((ci->flags & CI_PEACE) && nc) { - if ((nc == ci->founder) || (get_access_nc(nc, ci) >= get_access(u, ci))) { - notice_lang(s_ChanServ, u, ACCESS_DENIED); - if (freemask) - delete [] mask; - return MOD_CONT; - } - } else if ((ci->flags & CI_PEACE)) { - char buf[BUFSIZE]; - /* Match against all currently online users with equal or - * higher access. - Viper */ - for (i = 0; i < 1024; i++) { - for (u2 = userlist[i]; u2; u2 = u2->next) { - if (IsFounder(u2, ci) || (get_access(u2, ci) >= get_access(u, ci))) { - if (match_usermask(mask, u2)) { - notice_lang(s_ChanServ, u, ACCESS_DENIED); - delete [] mask; - return MOD_CONT; - } + /* Check whether target nick has equal/higher access + * or whether the mask matches a user with higher/equal access - Viper */ + if ((ci->flags & CI_PEACE) && nc) + { + if ((nc == ci->founder) || (get_access_nc(nc, ci) >= get_access(u, ci))) + { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + return; + } + } + else if ((ci->flags & CI_PEACE)) + { + char buf[BUFSIZE]; + /* Match against all currently online users with equal or + * higher access. - Viper */ + for (i = 0; i < 1024; i++) + { + for (User *u2 = userlist[i]; u2; u2 = u2->next) + { + if (IsFounder(u2, ci) || (get_access(u2, ci) >= get_access(u, ci))) + { + if (match_usermask(mask.c_str(), u2)) + { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + return; } } } + } + + + /* Match against the lastusermask of all nickalias's with equal + * or higher access. - Viper */ + for (i = 0; i < 1024; i++) + { + for (NickAlias *na2 = nalists[i]; na2; na2 = na2->next) + { + if (na2->status & NS_FORBIDDEN) + continue; - /* Match against the lastusermask of all nickalias's with equal - * or higher access. - Viper */ - for (i = 0; i < 1024; i++) { - for (na2 = nalists[i]; na2; na2 = na2->next) { - if (na2->status & NS_FORBIDDEN) - continue; - - if (na2->nc && ((na2->nc == ci->founder) || (get_access_nc(na2->nc, ci) - >= get_access(u, ci)))) { - snprintf(buf, BUFSIZE, "%s!%s", na2->nick, na2->last_usermask); - if (Anope::Match(buf, mask, false)) { - notice_lang(s_ChanServ, u, ACCESS_DENIED); - delete [] mask; - return MOD_CONT; - } + if (na2->nc && ((na2->nc == ci->founder) || (get_access_nc(na2->nc, ci) >= get_access(u, ci)))) + { + snprintf(buf, BUFSIZE, "%s!%s", na2->nick, na2->last_usermask); + if (Anope::Match(buf, mask.c_str(), false)) + { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + return; } } } - } + } + } - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { - if (!(akick->flags & AK_USED)) - continue; - if ((akick->flags & AK_ISNICK) ? akick->u.nc == nc - : stricmp(akick->u.mask, mask) == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_ALREADY_EXISTS, - (akick->flags & AK_ISNICK) ? akick->u.nc-> - display : akick->u.mask, chan); - if (freemask) - delete [] mask; - return MOD_CONT; - } + for (unsigned j = 0; j < ci->akick.size(); ++j) + { + akick = ci->akick[j]; + if (!(akick->flags & AK_USED)) + continue; + if ((akick->flags & AK_ISNICK) ? akick->nc == nc : akick->mask == mask) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_ALREADY_EXISTS, (akick->flags & AK_ISNICK) ? akick->nc->display : akick->mask.c_str(), ci->name); + return; } + } - /* All entries should be in use so we don't have to go over - * the entire list. We simply add new entries at the end. */ - if (ci->akickcount >= CSAutokickMax) { - notice_lang(s_ChanServ, u, CHAN_AKICK_REACHED_LIMIT, CSAutokickMax); - if (freemask) - delete [] mask; - return MOD_CONT; - } - ci->akickcount++; - ci->akick = - static_cast<AutoKick *>(srealloc(ci->akick, sizeof(AutoKick) * ci->akickcount)); - akick = &ci->akick[i]; - akick->flags = AK_USED; - if (nc) { - akick->flags |= AK_ISNICK; - akick->u.nc = nc; - } else { - akick->u.mask = sstrdup(mask); - } - akick->creator = sstrdup(u->nick); - akick->addtime = time(NULL); - if (reason) { - akick->reason = sstrdup(reason); - } else { - akick->reason = NULL; - } + /* All entries should be in use so we don't have to go over + * the entire list. We simply add new entries at the end. */ + if (ci->akick.size() >= CSAutokickMax) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_REACHED_LIMIT, CSAutokickMax); + return; + } - /* Auto ENFORCE #63 */ - c = findchan(ci->name); - if (c) { - cu = c->users; - while (cu) { - unext = cu->next; - if (check_kick(cu->user, c->name, c->creation_time)) { - argv[0] = sstrdup(c->name); - argv[1] = sstrdup(cu->user->nick); - if (akick->reason) - argv[2] = sstrdup(akick->reason); - else - argv[2] = sstrdup("none"); - - do_kick(s_ChanServ, 3, argv); - - delete [] argv[2]; - delete [] argv[1]; - delete [] argv[0]; - count++; + if (nc) + akick = ci->AddAkick(u->nick, nc, !reason.empty() ? reason.c_str() : ""); + else + akick = ci->AddAkick(u->nick, mask.c_str(), !reason.empty() ? reason.c_str() : ""); - } - cu = unext; - } - } - notice_lang(s_ChanServ, u, CHAN_AKICK_ADDED, mask, chan); + notice_lang(s_ChanServ, u, CHAN_AKICK_ADDED, mask.c_str(), ci->name); - if (count) - notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan, - count); + this->DoEnforce(u, ci, params); + } - if (freemask) - delete [] mask; + void DoStick(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + NickAlias *na; + NickCore *nc; + ci::string mask = params[2]; + unsigned i; + AutoKick *akick; - } else if (cmd == "STICK") { - NickAlias *na; - NickCore *nc; + if (ci->akick.empty()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return; + } - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); - return MOD_CONT; - } + na = findnick(mask.c_str()); + nc = (na ? na->nc : NULL); - if (ci->akickcount == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); - return MOD_CONT; - } + for (i = 0; i < ci->akick.size(); ++i) + { + akick = ci->akick[i]; - na = findnick(mask); - nc = (na ? na->nc : NULL); + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) + continue; + if (akick->mask == mask) + break; + } - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { - if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) - continue; - if (!stricmp(akick->u.mask, mask)) - break; - } + if (i == ci->akick.size()) { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask.c_str(), ci->name); + return; + } - if (i == ci->akickcount) { - notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, - ci->name); - return MOD_CONT; - } + akick->flags |= AK_STUCK; + notice_lang(s_ChanServ, u, CHAN_AKICK_STUCK, akick->mask.c_str(), ci->name); - akick->flags |= AK_STUCK; - notice_lang(s_ChanServ, u, CHAN_AKICK_STUCK, akick->u.mask, - ci->name); + if (ci->c) + stick_mask(ci, akick); + } - if (ci->c) - stick_mask(ci, akick); - } else if (cmd == "UNSTICK") { - NickAlias *na; - NickCore *nc; + void DoUnStick(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + NickAlias *na; + NickCore *nc; + AutoKick *akick; + unsigned i; + ci::string mask = params[2]; - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); - return MOD_CONT; - } + if (ci->akick.empty()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return; + } - if (ci->akickcount == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); - return MOD_CONT; - } + na = findnick(mask.c_str()); + nc = (na ? na->nc : NULL); - na = findnick(mask); - nc = (na ? na->nc : NULL); + for (i = 0; i < ci->akick.size(); ++i) + { + akick = ci->akick[i]; - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { - if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) - continue; - if (!stricmp(akick->u.mask, mask)) - break; - } + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) + continue; + if (akick->mask == mask) + break; + } - if (i == ci->akickcount) { - notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, - ci->name); - return MOD_CONT; - } + if (i == ci->akick.size()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask.c_str(), ci->name); + return; + } - akick->flags &= ~AK_STUCK; - notice_lang(s_ChanServ, u, CHAN_AKICK_UNSTUCK, akick->u.mask, - ci->name); + akick->flags &= ~AK_STUCK; + notice_lang(s_ChanServ, u, CHAN_AKICK_UNSTUCK, akick->mask.c_str(), ci->name); + } - } else if (cmd == "DEL") { - int deleted, a, b; + void DoDel(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + ci::string mask = params[2]; + AutoKick *akick; + unsigned i; - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); - return MOD_CONT; - } + if (ci->akick.empty()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return; + } - if (ci->akickcount == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); - return MOD_CONT; - } + /* 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; - /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { - int last = -1; - deleted = process_numlist(mask, &count, akick_del_callback, u, - ci, &last); - if (!deleted) { - if (count == 1) { - notice_lang(s_ChanServ, u, CHAN_AKICK_NO_SUCH_ENTRY, - last, ci->name); - } else { - notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, - ci->name); - } - } else if (deleted == 1) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_ONE, - ci->name); - } else { - notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL, - deleted, ci->name); - } - } else { - NickAlias *na = findnick(mask); - NickCore *nc = (na ? na->nc : NULL); + deleted = process_numlist(mask.c_str(), &count, akick_del_callback, u, ci, &last); - for (akick = ci->akick, i = 0; i < ci->akickcount; - akick++, i++) { - if (!(akick->flags & AK_USED)) - continue; - if (((akick->flags & AK_ISNICK) && akick->u.nc == nc) - || (!(akick->flags & AK_ISNICK) - && stricmp(akick->u.mask, mask) == 0)) - break; - } - if (i == ci->akickcount) { - notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, - chan); - return MOD_CONT; - } - notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED, mask, chan); - akick_del(u, akick); - deleted = 1; - } - if (deleted) { - /* Reordering - DrStein */ - for (b = 0; b < ci->akickcount; b++) { - if (ci->akick[b].flags & AK_USED) { - for (a = 0; a < ci->akickcount; a++) { - if (a > b) - break; - if (!(ci->akick[a].flags & AK_USED)) { - ci->akick[a].flags = ci->akick[b].flags; - if (ci->akick[b].flags & AK_ISNICK) { - ci->akick[a].u.nc = ci->akick[b].u.nc; - } else { - ci->akick[a].u.mask = - sstrdup(ci->akick[b].u.mask); - } - /* maybe we should first check whether there - is a reason before we sstdrup it -Certus */ - if (ci->akick[b].reason) - ci->akick[a].reason = - sstrdup(ci->akick[b].reason); - else - ci->akick[a].reason = NULL; - ci->akick[a].creator = - sstrdup(ci->akick[b].creator); - ci->akick[a].addtime = ci->akick[b].addtime; - - akick_del(u, &ci->akick[b]); - break; - } - } - } - } - /* After reordering only the entries at the end could still be empty. - * We ll free the places no longer in use... - Viper */ - for (i = ci->akickcount - 1; i >= 0; i--) { - if (ci->akick[i].flags & AK_USED) - break; + if (!deleted) + { + if (count == 1) + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_SUCH_ENTRY, last, ci->name); + else + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name); + } + else if (deleted == 1) + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_ONE, ci->name); + else + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL, deleted, ci->name); + } + else + { + NickAlias *na = findnick(mask.c_str()); + NickCore *nc = (na ? na->nc : NULL); - ci->akickcount--; - } - ci->akick = - static_cast<AutoKick *>(srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount)); - } - } else if (cmd == "LIST") { - int sent_header = 0; + for (i = 0; i < ci->akick.size(); ++i) + { + akick = ci->akick[i]; - if (ci->akickcount == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); - return MOD_CONT; - } - if (mask && isdigit(*mask) && - strspn(mask, "1234567890,-") == strlen(mask)) { - process_numlist(mask, NULL, akick_list_callback, u, ci, - &sent_header); - } else { - for (akick = ci->akick, i = 0; i < ci->akickcount; - akick++, i++) { - if (!(akick->flags & AK_USED)) - continue; - if (mask) { - if (!(akick->flags & AK_ISNICK) - && !Anope::Match(akick->u.mask, mask, false)) - continue; - if ((akick->flags & AK_ISNICK) - && !Anope::Match(akick->u.nc->display, mask, false)) - continue; - } - akick_list(u, i, ci, &sent_header); - } - } - if (!sent_header) - notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan); - - } else if (cmd == "VIEW") { - int sent_header = 0; - if (ci->akickcount == 0) { - notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); - return MOD_CONT; - } - if (mask && isdigit(*mask) && - strspn(mask, "1234567890,-") == strlen(mask)) { - process_numlist(mask, NULL, akick_view_callback, u, ci, - &sent_header); - } else { - for (akick = ci->akick, i = 0; i < ci->akickcount; - akick++, i++) { - if (!(akick->flags & AK_USED)) - continue; - if (mask) { - if (!(akick->flags & AK_ISNICK) - && !Anope::Match(akick->u.mask, mask, false)) - continue; - if ((akick->flags & AK_ISNICK) - && !Anope::Match(akick->u.nc->display, mask, false)) - continue; - } - akick_view(u, i, ci, &sent_header); - } + if (!(akick->flags & AK_USED)) + continue; + if (((akick->flags & AK_ISNICK) && akick->nc == nc) + || (!(akick->flags & AK_ISNICK) + && akick->mask == mask)) + break; } - if (!sent_header) - notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan); + + if (i == ci->akick.size()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask.c_str(), ci->name); + return; + } + + ci->EraseAkick(akick); + + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED, mask.c_str(), ci->name); + } + } - } else if (cmd == "ENFORCE") { - c = findchan(ci->name); - cu = NULL; - count = 0; + void DoList(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + int sent_header = 0; + ci::string mask = params.size() > 2 ? params[2] : ""; + unsigned i; + AutoKick *akick; - if (!c) { - notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, ci->name); - return MOD_CONT; - } + if (ci->akick.empty()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return; + } - cu = c->users; + 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); + else + { + for (i = 0; i < ci->akick.size(); ++i) + { + akick = ci->akick[i]; - while (cu) { - unext = cu->next; - if (check_kick(cu->user, c->name, c->creation_time)) { - argv[0] = sstrdup(c->name); - argv[1] = sstrdup(cu->user->nick); - argv[2] = sstrdup(CSAutokickReason); + if (!(akick->flags & AK_USED)) + continue; + if (!mask.empty()) + { + if (!(akick->flags & AK_ISNICK) && !Anope::Match(akick->mask.c_str(), mask.c_str(), false)) + continue; + if ((akick->flags & AK_ISNICK) && !Anope::Match(akick->nc->display, mask.c_str(), false)) + continue; + } + akick_list(u, i, ci, &sent_header); + } + } - do_kick(s_ChanServ, 3, argv); + if (!sent_header) + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name); - delete [] argv[2]; - delete [] argv[1]; - delete [] argv[0]; + } - count++; - } - cu = unext; - } + void DoView(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + int sent_header = 0; + ci::string mask = params.size() > 2 ? params[2] : ""; + AutoKick *akick; + unsigned i; - notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan, count); + if (ci->akick.empty()) + { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return; + } - } else if (cmd == "CLEAR") { - if (readonly) { - notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); - return MOD_CONT; - } + 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); + else + { + for (i = 0; i < ci->akick.size(); ++i) + { + akick = ci->akick[i]; - for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { - if (!(akick->flags & AK_USED)) + if (!(akick->flags & AK_USED)) continue; - akick_del(u, akick); - } + if (!mask.empty()) + { + if (!(akick->flags & AK_ISNICK) && !Anope::Match(akick->mask.c_str(), mask.c_str(), false)) + continue; + if ((akick->flags & AK_ISNICK) && !Anope::Match(akick->nc->display, mask.c_str(), false)) + continue; + } + akick_view(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, ci->name); - free(ci->akick); - ci->akick = NULL; - ci->akickcount = 0; + } - notice_lang(s_ChanServ, u, CHAN_AKICK_CLEAR, ci->name); + void DoEnforce(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + Channel *c = ci->c; + c_userlist *cu, *unext; + int count = 0; + const char *argv[3]; - } else { - syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX); + if (!c) + { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, ci->name); + return; } + + cu = c->users; + + while (cu) + { + unext = cu->next; + if (check_kick(cu->user, c->name, c->creation_time)) + { + argv[0] = sstrdup(c->name); + argv[1] = sstrdup(cu->user->nick); + argv[2] = sstrdup(CSAutokickReason); + + do_kick(s_ChanServ, 3, argv); + + delete [] argv[2]; + delete [] argv[1]; + delete [] argv[0]; + count++; + } + cu = unext; + } + + notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, ci->name, count); + } + + void DoClear(User *u, ChannelInfo *ci, std::vector<ci::string> ¶ms) + { + ci->ClearAkick(); + notice_lang(s_ChanServ, u, CHAN_AKICK_CLEAR, ci->name); + } + + public: + CommandCSAKick() : Command("AKICK", 2, 4) + { + } + + CommandReturn Execute(User *u, std::vector<ci::string> ¶ms) + { + ci::string chan = params[0]; + ci::string cmd = params[1]; + ci::string mask = params.size() > 2 ? params[2] : ""; + + ChannelInfo *ci = cs_findchan(chan.c_str()); + + if (mask.empty() && (cmd == "ADD" || cmd == "STICK" || cmd == "UNSTICK" || cmd == "DEL")) + this->OnSyntaxError(u); + else if (!check_access(u, ci, CA_AKICK) && !u->nc->HasPriv("chanserv/access/modify")) + notice_lang(s_ChanServ, u, ACCESS_DENIED); + else if (cmd != "LIST" && cmd != "VIEW" && cmd != "ENFORCE" && readonly) + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + else if (cmd == "ADD") + this->DoAdd(u, ci, params); + else if (cmd == "STICK") + this->DoStick(u, ci, params); + else if (cmd == "UNSTICK") + this->DoUnStick(u, ci, params); + else if (cmd == "DEL") + this->DoDel(u, ci, params); + else if (cmd == "LIST") + this->DoList(u, ci, params); + else if (cmd == "VIEW") + this->DoView(u, ci, params); + else if (cmd == "ENFORCE") + this->DoEnforce(u, ci, params); + else if (cmd == "CLEAR") + this->DoClear(u, ci, params); + else + this->OnSyntaxError(u); + return MOD_CONT; } diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 896e74942..8727fa176 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -22,9 +22,8 @@ ChannelInfo::ChannelInfo() desc = url = email = last_topic = forbidby = forbidreason = NULL; time_registered = last_used = last_topic_time = 0; flags = 0; - bantype = akickcount = 0; + bantype = 0; levels = NULL; - akick = NULL; entry_message = NULL; c = NULL; bi = NULL; @@ -135,6 +134,72 @@ void ChannelInfo::ClearAccess() EraseAccess(0); } +/** Add an akick entry to the channel by NickCore + * @param user The user who added the akick + * @param akicknc The nickcore being akicked + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + * @return The AutoKick structure + */ +AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t) +{ + if (!akicknc) + return NULL; + + AutoKick *autokick = new AutoKick(); + autokick->flags = AK_USED | AK_ISNICK; + autokick->nc = akicknc; + autokick->reason = reason; + autokick->creator = user; + autokick->addtime = t; + + akick.push_back(autokick); + return autokick; +} + +/** Add an akick entry to the channel by reason + * @param user The user who added the akick + * @param mask The mask of the akick + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + * @return The AutoKick structure + */ +AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t) +{ + AutoKick *autokick = new AutoKick(); + autokick->mask = mask; + autokick->flags = AK_USED; + autokick->reason = reason; + autokick->creator = user; + autokick->addtime = t; + + akick.push_back(autokick); + return autokick; +} + +/** Erase an entry from the channel akick list + * @param akick The akick + */ +void ChannelInfo::EraseAkick(AutoKick *autokick) +{ + std::vector<AutoKick *>::iterator it = std::find(akick.begin(), akick.end(), autokick); + + if (it != akick.end()) + { + delete *it; + akick.erase(it); + } +} + +/** Clear the whole akick list + */ +void ChannelInfo::ClearAkick() +{ + for (unsigned i = akick.size(); i > 0; --i) + { + EraseAkick(akick[i - 1]); + } +} /** Check if a mode is mlocked * @param Name The mode |