diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chanserv.c | 187 | ||||
-rw-r--r-- | src/core/cs_akick.c | 7 | ||||
-rw-r--r-- | src/core/db_plain.cpp | 7 | ||||
-rw-r--r-- | src/regchannel.cpp | 117 | ||||
-rw-r--r-- | src/tools/db-convert.c | 2 |
5 files changed, 155 insertions, 165 deletions
diff --git a/src/chanserv.c b/src/chanserv.c index b144df6f3..622f823d7 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -119,45 +119,6 @@ void moduleAddChanServCmds() { /* *INDENT-ON* */ /*************************************************************************/ -/** A timer used to keep the BotServ bot/ChanServ in the channel - * after kicking the last user in a channel - */ -class ChanServTimer : public Timer -{ - private: - Channel *c; - - public: - ChanServTimer(Channel *chan) : Timer(Config.CSInhabit), c(chan) - { - if (c->ci) - c->ci->SetFlag(CI_INHABIT); - } - - void Tick(time_t) - { - if (!c->ci) - return; - - c->ci->UnsetFlag(CI_INHABIT); - - /* If the channel has users again, don't part it and halt */ - if (!c->users.empty()) - return; - - if (c->ci->bi) - ircdproto->SendPart(c->ci->bi, c, NULL); - else - ircdproto->SendPart(findbot(Config.s_ChanServ), c, NULL); - - /* Now delete the channel as it is empty */ - if (!c->HasFlag(CH_PERSIST) && !c->ci->HasFlag(CI_PERSIST)) - delete c; - } -}; - -/*************************************************************************/ - /* Returns modes for mlock in a nice way. */ char *get_mlock_modes(ChannelInfo * ci, int complete) @@ -614,114 +575,6 @@ int check_should_protect(User * user, char *chan) /*************************************************************************/ -/** Check whether a user is permitted to be on this channel - * @param u The user - * @return true if they were banned, false if they are allowed - */ -bool ChannelInfo::CheckKick(User *user) -{ - AutoKick *akick; - bool set_modes = false, do_kick = false; - NickCore *nc; - char mask[BUFSIZE]; - const char *reason; - - if (!user || !this->c) - return false; - - if (user->isSuperAdmin == 1) - return true; - - /* We don't enforce services restrictions on clients on ulined services - * as this will likely lead to kick/rejoin floods. ~ Viper */ - if (is_ulined(user->server->name)) - return true; - - if (this->HasFlag(CI_SUSPENDED) || this->HasFlag(CI_FORBIDDEN)) - { - if (is_oper(user)) - return 0; - - get_idealban(this, user, mask, sizeof(mask)); - reason = this->forbidreason ? this->forbidreason : getstring(user, CHAN_MAY_NOT_BE_USED); - set_modes = true; - do_kick = true; - } - - if (user->Account() || user->IsRecognized()) - nc = user->Account(); - else - nc = NULL; - - if (!do_kick && ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(this, user) == 1) - return true; - - for (unsigned j = 0; j < this->GetAkickCount(); ++j) - { - akick = this->GetAkick(j); - - if (!akick->InUse || do_kick) - continue; - - if ((akick->HasFlag(AK_ISNICK) && akick->nc == nc) - || (!akick->HasFlag(AK_ISNICK) - && match_usermask(akick->mask.c_str(), user))) - { - Alog(LOG_DEBUG_2) << user->nick << " matched akick " << (akick->HasFlag(AK_ISNICK) ? akick->nc->display : akick->mask); - if (akick->HasFlag(AK_ISNICK)) - get_idealban(this, user, mask, sizeof(mask)); - else - strlcpy(mask, akick->mask.c_str(), sizeof(mask)); - reason = !akick->reason.empty() ? akick->reason.c_str() : Config.CSAutokickReason; - do_kick = true; - } - } - - - if (!do_kick && check_access(user, this, CA_NOJOIN)) - { - get_idealban(this, user, mask, sizeof(mask)); - reason = getstring(user, CHAN_NOT_ALLOWED_TO_JOIN); - do_kick = true; - } - - if (!do_kick) - return false; - - Alog(LOG_DEBUG) << "channel: Autokicking "<< user->GetMask() << " from " << this->name; - - /* If the channel doesnt have any users and if a bot isn't already in the channel, join it - * NOTE: we use usercount == 1 here as there is one user, but they are about to be destroyed - */ - if (this->c->users.size() == 1 && !this->HasFlag(CI_INHABIT)) - { - /* If channel was forbidden, etc, set it +si to prevent rejoin */ - if (set_modes) - { - c->SetMode(NULL, CMODE_NOEXTERNAL); - c->SetMode(NULL, CMODE_TOPIC); - c->SetMode(NULL, CMODE_SECRET); - c->SetMode(NULL, CMODE_INVITE); - } - - /* This channel has no bot assigned to it, join ChanServ */ - if (!this->bi) - { - ircdproto->SendJoin(findbot(Config.s_ChanServ), this->name.c_str(), this->c->creation_time); - } - - /* Set a timer for this channel to part the bots later */ - new ChanServTimer(this->c); - } - - this->c->SetMode(NULL, CMODE_BAN, mask); - this->c->Kick(NULL, user, "%s", reason); - - return true; -} - -/*************************************************************************/ - /* Record the current channel topic in the ChannelInfo structure. */ void record_topic(const char *chan) @@ -1263,18 +1116,6 @@ const char *get_xop_level(int level) /*********************** ChanServ command routines ***********************/ /*************************************************************************/ -/*************************************************************************/ - - -/*************************************************************************/ - -/* `last' is set to the last index this routine was called with - * `perm' is incremented whenever a permission-denied error occurs - */ - - -/*************************************************************************/ - /* Is the mask stuck? */ AutoKick *is_stuck(ChannelInfo * ci, const char *mask) @@ -1347,3 +1188,31 @@ void stick_all(ChannelInfo * ci) ci->c->SetMode(NULL, CMODE_BAN, akick->mask.c_str()); } } + +ChanServTimer::ChanServTimer(Channel *chan) : Timer(Config.CSInhabit), c(chan) +{ + if (c->ci) + c->ci->SetFlag(CI_INHABIT); +} + +void ChanServTimer::Tick(time_t) +{ + if (!c->ci) + return; + + c->ci->UnsetFlag(CI_INHABIT); + + /* If the channel has users again, don't part it and halt */ + if (!c->users.empty()) + return; + + if (c->ci->bi) + ircdproto->SendPart(c->ci->bi, c, NULL); + else + ircdproto->SendPart(findbot(Config.s_ChanServ), c, NULL); + + /* Now delete the channel as it is empty */ + if (!c->HasFlag(CH_PERSIST) && !c->ci->HasFlag(CI_PERSIST)) + delete c; +} + diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c index 355dd09ee..f73360769 100644 --- a/src/core/cs_akick.c +++ b/src/core/cs_akick.c @@ -114,6 +114,13 @@ int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header) ((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); + } return 1; } diff --git a/src/core/db_plain.cpp b/src/core/db_plain.cpp index 10e21359c..02dc71b3b 100644 --- a/src/core/db_plain.cpp +++ b/src/core/db_plain.cpp @@ -733,9 +733,9 @@ class DBPlain : public Module } AutoKick *ak; if (Nick) - ak = ci->AddAkick(params[3], nc, params.size() > 5 ? params[5] : "", strtol(params[4].c_str(), NULL, 10)); + ak = ci->AddAkick(params[3], nc, params.size() > 6 ? params[6] : "", atol(params[4].c_str()), atol(params[5].c_str())); else - ak = ci->AddAkick(params[3], params[2], params.size() > 5 ? params[5] : "", strtol(params[4].c_str(), NULL, 10)); + ak = ci->AddAkick(params[3], params[2], params.size() > 6 ? params[6] : "", atol(params[4].c_str()), atol(params[5].c_str())); if (Stuck) ak->SetFlag(AK_STUCK); if (Nick) @@ -1016,7 +1016,8 @@ class DBPlain : public Module << (ci->GetAkick(k)->HasFlag(AK_STUCK) ? "STUCK " : "UNSTUCK ") << (ci->GetAkick(k)->HasFlag(AK_ISNICK) ? "NICK " : "MASK ") << (ci->GetAkick(k)->HasFlag(AK_ISNICK) ? ci->GetAkick(k)->nc->display : ci->GetAkick(k)->mask) - << " " << ci->GetAkick(k)->creator << " " << ci->GetAkick(k)->addtime << " :"; + << " " << ci->GetAkick(k)->creator << " " << ci->GetAkick(k)->addtime + << " " << ci->last_used << " :"; if (!ci->GetAkick(k)->reason.empty()) db << ci->GetAkick(k)->reason; db << endl; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 1f4542948..1dcf9f515 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -14,6 +14,7 @@ #include "services.h" #include "modules.h" +#include "language.h" /** Default constructor * @param chname The channel name @@ -245,9 +246,10 @@ void ChannelInfo::ClearAccess() * @param akicknc The nickcore being akicked * @param reason The reason for the akick * @param t The time the akick was added, defaults to now + * @param lu The time the akick was last used, defaults to never * @return The AutoKick structure */ -AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t) +AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t, time_t lu) { if (!akicknc) return NULL; @@ -259,6 +261,7 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, cons autokick->reason = reason; autokick->creator = user; autokick->addtime = t; + autokick->last_used = lu; akick.push_back(autokick); return autokick; @@ -269,9 +272,10 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, NickCore *akicknc, cons * @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 + * @param lu The time the akick was last used, defaults to never * @return The AutoKick structure */ -AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t) +AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t, time_t lu) { AutoKick *autokick = new AutoKick(); autokick->mask = mask; @@ -279,6 +283,7 @@ AutoKick *ChannelInfo::AddAkick(const std::string &user, const std::string &mask autokick->reason = reason; autokick->creator = user; autokick->addtime = t; + autokick->last_used = lu; akick.push_back(autokick); return autokick; @@ -551,3 +556,111 @@ void ChannelInfo::ClearParams() Params.clear(); } +/** Check whether a user is permitted to be on this channel + * @param u The user + * @return true if they were banned, false if they are allowed + */ +bool ChannelInfo::CheckKick(User *user) +{ + AutoKick *akick; + bool set_modes = false, do_kick = false; + NickCore *nc; + char mask[BUFSIZE]; + const char *reason; + + if (!user || !this->c) + return false; + + if (user->isSuperAdmin == 1) + return true; + + /* We don't enforce services restrictions on clients on ulined services + * as this will likely lead to kick/rejoin floods. ~ Viper */ + if (is_ulined(user->server->name)) + return true; + + if (this->HasFlag(CI_SUSPENDED) || this->HasFlag(CI_FORBIDDEN)) + { + if (is_oper(user)) + return 0; + + get_idealban(this, user, mask, sizeof(mask)); + reason = this->forbidreason ? this->forbidreason : getstring(user, CHAN_MAY_NOT_BE_USED); + set_modes = true; + do_kick = true; + } + + if (user->Account() || user->IsRecognized()) + nc = user->Account(); + else + nc = NULL; + + if (!do_kick && ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(this, user) == 1) + return true; + + for (unsigned j = 0; j < this->GetAkickCount(); ++j) + { + akick = this->GetAkick(j); + + if (!akick->InUse || do_kick) + continue; + + if ((akick->HasFlag(AK_ISNICK) && akick->nc == nc) + || (!akick->HasFlag(AK_ISNICK) + && match_usermask(akick->mask.c_str(), user))) + { + Alog(LOG_DEBUG_2) << user->nick << " matched akick " << (akick->HasFlag(AK_ISNICK) ? +akick->nc->display : akick->mask); + akick->last_used = time(NULL); + if (akick->HasFlag(AK_ISNICK)) + get_idealban(this, user, mask, sizeof(mask)); + else + strlcpy(mask, akick->mask.c_str(), sizeof(mask)); + reason = !akick->reason.empty() ? akick->reason.c_str() : Config.CSAutokickReason; + do_kick = true; + } + } + + + if (!do_kick && check_access(user, this, CA_NOJOIN)) + { + get_idealban(this, user, mask, sizeof(mask)); + reason = getstring(user, CHAN_NOT_ALLOWED_TO_JOIN); + do_kick = true; + } + + if (!do_kick) + return false; + + Alog(LOG_DEBUG) << "channel: Autokicking "<< user->GetMask() << " from " << this->name; + + /* If the channel doesnt have any users and if a bot isn't already in the channel, join it + * NOTE: we use usercount == 1 here as there is one user, but they are about to be destroyed + */ + if (this->c->users.size() == 1 && !this->HasFlag(CI_INHABIT)) + { + /* If channel was forbidden, etc, set it +si to prevent rejoin */ + if (set_modes) + { + c->SetMode(NULL, CMODE_NOEXTERNAL); + c->SetMode(NULL, CMODE_TOPIC); + c->SetMode(NULL, CMODE_SECRET); + c->SetMode(NULL, CMODE_INVITE); + } + + /* This channel has no bot assigned to it, join ChanServ */ + if (!this->bi) + { + ircdproto->SendJoin(findbot(Config.s_ChanServ), this->name.c_str(), this->c->creation_time); + } + + /* Set a timer for this channel to part the bots later */ + new ChanServTimer(this->c); + } + + this->c->SetMode(NULL, CMODE_BAN, mask); + this->c->Kick(NULL, user, "%s", reason); + + return true; +} + diff --git a/src/tools/db-convert.c b/src/tools/db-convert.c index 53760771a..8f3c326a2 100644 --- a/src/tools/db-convert.c +++ b/src/tools/db-convert.c @@ -827,7 +827,7 @@ int main(int argc, char *argv[]) << ((ci->akick[j].flags & AK_STUCK) ? "STUCK " : "UNSTUCK " ) << ((ci->akick[j].flags & AK_ISNICK) ? "NICK " : "MASK ") << ((ci->akick[j].flags & AK_ISNICK) ? ci->akick[j].u.nc->display : ci->akick[j].u.mask ) - << " " << ci->akick[j].creator << " " << ci->akick[j].addtime << " :"; + << " " << ci->akick[j].creator << " " << ci->akick[j].addtime << " 0 :"; // 0 is for last used, added in 1.9.2 if (ci->akick[j].reason) fs << ci->akick[j].reason; fs << std::endl; |