diff options
author | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2010-03-31 04:41:44 +0000 |
---|---|---|
committer | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2010-03-31 04:41:44 +0000 |
commit | 94822c99c0bc84756ee0870b7d39c6410ed9184a (patch) | |
tree | ceef914590a40c3d03973f938b791b01d7dd8fed | |
parent | a3347b59a1f103d265c68c5880f9dabee1bbfd6a (diff) |
Added last used time to akick view
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2846 5417fbe8-f217-4b02-8779-1006273d7864
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | include/regchannel.h | 6 | ||||
-rw-r--r-- | include/services.h | 21 | ||||
-rw-r--r-- | lang/en_us.l | 2 | ||||
-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 |
9 files changed, 185 insertions, 170 deletions
@@ -12,8 +12,8 @@ Legend: [x] SANE password encryption - prefix password with the method it was encrypted with, allowing for *seamless* upgrading to different methods [x] Salted SHA256 (contact Special for this) [+] New database format (text, not binary - works very well for merging and so on) -[ ] generic database routines modules can use to create their own database -[ ] IRCd capability support: don't rely on CAPAB, provide an interface to turn capabilities on specifically +[x] generic database routines modules can use to create their own database +[?] IRCd capability support: don't rely on CAPAB, provide an interface to turn capabilities on specifically [ ] Socket subsystem needs some serious loving [ ] Multiple sockets [ ] Asynchronous, using select() (multiple engines? not really needed..) @@ -22,7 +22,7 @@ Legend: [x] generic way to check which modes a user has set (u->HasUmode(UMODE_OPER)) [?] way for one module to depend on another... not like 2 MOD_HEADs and it being unpredictable which is loaded first.. the MOD_HEAD MOD_TAIL allows for too few combinations (interface code of insp, hooks code of insp?) -[ ] Last used time on AKICK/access entries +[x] Last used time on AKICK/access entries [x] Channel passwords seem to be of limited use, think of a more appropriate way to handle this [+] General options block, ability to turn LOGCHAN on from the config file.. [x] Docs directory cleanup diff --git a/include/regchannel.h b/include/regchannel.h index 6b0e9c264..18b2eead8 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -177,16 +177,18 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag> * @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 */ - AutoKick *AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t = time(NULL)); + AutoKick *AddAkick(const std::string &user, NickCore *akicknc, const std::string &reason, time_t t = time(NULL), time_t lu = 0); /** 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 + * @param lu The time the akick was last used, defaults to never */ - AutoKick *AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t = time(NULL)); + AutoKick *AddAkick(const std::string &user, const std::string &mask, const std::string &reason, time_t t = time(NULL), time_t lu = 0); /** Get an entry from the channel akick list * @param index The index in the akick vector diff --git a/include/services.h b/include/services.h index e13866e81..7e6783404 100644 --- a/include/services.h +++ b/include/services.h @@ -564,6 +564,7 @@ class AutoKick : public Flags<AutoKickFlag> std::string reason; std::string creator; time_t addtime; + time_t last_used; }; /** Flags for badwords @@ -1226,4 +1227,24 @@ class NickServRelease : public Timer static void ClearTimers(NickAlias *na, bool dorelease = false); }; +/** 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: + /** Default constructor + * @param chan The channel + */ + ChanServTimer(Channel *chan); + + /** Called when th edelay is up + * @param The current time + */ + void Tick(time_t); +}; + #endif /* SERVICES_H */ diff --git a/lang/en_us.l b/lang/en_us.l index b62e2d0d7..66cee5294 100644 --- a/lang/en_us.l +++ b/lang/en_us.l @@ -1506,6 +1506,8 @@ CHAN_AKICK_VIEW_FORMAT CHAN_AKICK_VIEW_FORMAT_STUCK %3d %s (stuck) (by %s on %s) %s +CHAN_AKICK_LAST_USED + Last used %s CHAN_AKICK_ENFORCE_DONE AKICK ENFORCE for %s complete; %d users were affected. CHAN_AKICK_CLEAR 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; |