diff options
| author | Adam <Adam@anope.org> | 2010-09-15 16:40:55 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2010-09-15 16:40:55 -0400 |
| commit | 813185105823daa6a1b574d86053950382343589 (patch) | |
| tree | 793d4f54cddc88275b4372839f93bba01301b427 /src | |
| parent | 6239b5a053fc8fd94b798495f8e189a2e2bda285 (diff) | |
Rewrote all of the topic code, fixes a few topic related problems on some older IRCds
Diffstat (limited to 'src')
| -rw-r--r-- | src/channels.cpp | 104 | ||||
| -rw-r--r-- | src/chanserv.cpp | 127 | ||||
| -rw-r--r-- | src/regchannel.cpp | 38 | ||||
| -rw-r--r-- | src/servers.cpp | 4 |
4 files changed, 75 insertions, 198 deletions
diff --git a/src/channels.cpp b/src/channels.cpp index 76db386e4..24d18b102 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -31,7 +31,7 @@ Channel::Channel(const Anope::string &nname, time_t ts) this->creation_time = ts; this->bans = this->excepts = this->invites = NULL; this->server_modetime = this->chanserv_modetime = 0; - this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_sync = this->topic_time = 0; + this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_time = 0; this->ci = cs_findchan(this->name); if (this->ci) @@ -113,10 +113,10 @@ void Channel::Sync() if (this->ci) { check_modes(this); - } - if (Me && Me->IsSynced() && !this->topic_sync) - restore_topic(name); + if (Me && Me->IsSynced()) + this->ci->RestoreTopic(); + } } void Channel::JoinUser(User *user) @@ -1026,6 +1026,38 @@ Anope::string Channel::GetModes(bool complete, bool plus) return res; } +void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts) +{ + this->topic = newtopic; + this->topic_setter = user; + this->topic_time = ts; + + Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << user << " to " << newtopic; + + FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic)); + + if (this->ci) + { + this->ci->CheckTopic(); + } +} + +void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts) +{ + this->topic = newtopic; + this->topic_setter = user; + this->topic_time = ts; + + ircdproto->SendTopic(whosends(this->ci), this); + + FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic)); + + if (this->ci) + { + this->ci->CheckTopic(); + } +} + /*************************************************************************/ Channel *findchan(const Anope::string &chan) @@ -1312,57 +1344,6 @@ void do_cmode(const Anope::string &source, int ac, const char **av) /*************************************************************************/ -/* Handle a TOPIC command. */ - -void do_topic(const Anope::string &source, int ac, const char **av) -{ - Channel *c = findchan(av[0]); - ChannelInfo *ci; - time_t topic_time = Anope::string(av[2]).is_pos_number_only() ? convertTo<time_t>(av[2]) : 0; - - if (!c) - { - Log() << "TOPIC " << merge_args(ac - 1, av + 1) << " for nonexistent channel " << av[0]; - return; - } - - /* We can be sure that the topic will be in sync here -GD */ - c->topic_sync = 1; - - ci = c->ci; - - /* For Unreal, cut off the ! and any futher part of the topic setter. - * This way, nick!ident@host setters will only show the nick. -GD - */ - Anope::string topicsetter = myStrGetToken(av[1], '!', 0); - - /* If the current topic we have matches the last known topic for this - * channel exactly, there's no need to update anything and we can as - * well just return silently without updating anything. -GD - */ - if (ac > 3 && *av[3] && ci && !ci->last_topic.empty() && ci->last_topic.equals_cs(av[3]) && ci->last_topic_setter.equals_cs(topicsetter)) - return; - - if (check_topiclock(c, topic_time)) - return; - - if (!c->topic.empty()) - c->topic.clear(); - if (ac > 3 && *av[3]) - c->topic = av[3]; - - c->topic_setter = topicsetter; - c->topic_time = topic_time; - - record_topic(av[0]); - - FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(c, av[0])); -} - -/*************************************************************************/ -/**************************** Internal Calls *****************************/ -/*************************************************************************/ - /** * Set the correct modes, or remove the ones granted without permission, * for the specified user on ths specified channel. This doesn't give @@ -1443,19 +1424,6 @@ void MassChannelModes(BotInfo *bi, const Anope::string &modes) /*************************************************************************/ -void restore_unsynced_topics() -{ - for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - { - Channel *c = it->second; - - if (!c->topic_sync) - restore_topic(c->name); - } -} - -/*************************************************************************/ - /** * This handles creating a new Entry. * This function destroys and free's the given mask as a side effect. diff --git a/src/chanserv.cpp b/src/chanserv.cpp index c0ae4efd9..9d8fb411a 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -422,133 +422,6 @@ int check_valid_op(User *user, Channel *chan, int servermode) /*************************************************************************/ -/* Record the current channel topic in the ChannelInfo structure. */ - -void record_topic(const Anope::string &chan) -{ - Channel *c; - ChannelInfo *ci; - - if (readonly) - return; - - c = findchan(chan); - if (!c || !(ci = c->ci)) - return; - - ci->last_topic = c->topic; - ci->last_topic_setter = c->topic_setter; - ci->last_topic_time = c->topic_time; -} - -/*************************************************************************/ - -/* Restore the topic in a channel when it's created, if we should. */ - -void restore_topic(const Anope::string &chan) -{ - Channel *c = findchan(chan); - ChannelInfo *ci; - - if (!c || !(ci = c->ci)) - return; - /* We can be sure that the topic will be in sync when we return -GD */ - c->topic_sync = 1; - if (!ci->HasFlag(CI_KEEPTOPIC)) - { - /* We need to reset the topic here, since it's currently empty and - * should be updated with a TOPIC from the IRCd soon. -GD - */ - ci->last_topic.clear(); - ci->last_topic_setter = whosends(ci)->nick; - ci->last_topic_time = Anope::CurTime; - return; - } - if (!ci->last_topic.empty()) - { - c->topic = ci->last_topic; - c->topic_setter = ci->last_topic_setter; - c->topic_time = ci->last_topic_time; - } - else - { - c->topic.clear(); - c->topic_setter = whosends(ci)->nick; - } - if (ircd->join2set && whosends(ci) == ChanServ) - { - ChanServ->Join(chan); - c->SetMode(NULL, CMODE_OP, Config->s_ChanServ); - } - ircdproto->SendTopic(whosends(ci), c, c->topic_setter, c->topic); - if (ircd->join2set && whosends(ci) == ChanServ) - ChanServ->Part(c); -} - -/*************************************************************************/ - -/* See if the topic is locked on the given channel, and return 1 (and fix - * the topic) if so. */ - -int check_topiclock(Channel *c, time_t topic_time) -{ - ChannelInfo *ci; - - if (!c) - { - Log() << "check_topiclock called with NULL values"; - return 0; - } - - if (!(ci = c->ci) || !ci->HasFlag(CI_TOPICLOCK)) - return 0; - - if (!ci->last_topic.empty()) - { - c->topic = ci->last_topic; - c->topic_setter = ci->last_topic_setter; - } - else - { - c->topic.clear(); - /* Bot assigned & Symbiosis ON?, the bot will set the topic - doc */ - /* Altough whosends() also checks for Config->BSMinUsers -GD */ - c->topic_setter = whosends(ci)->nick; - } - - if (ircd->topictsforward) - { - /* Because older timestamps are rejected */ - /* Some how the topic_time from do_topic is 0 set it to current + 1 */ - if (!topic_time) - c->topic_time = Anope::CurTime + 1; - else - c->topic_time = topic_time + 1; - } - else - { - /* If no last topic, we can't use last topic time! - doc */ - if (!ci->last_topic.empty()) - c->topic_time = ci->last_topic_time; - else - c->topic_time = Anope::CurTime + 1; - } - - if (ircd->join2set && whosends(ci) == ChanServ) - { - ChanServ->Join(c); - c->SetMode(NULL, CMODE_OP, Config->s_ChanServ); - } - - ircdproto->SendTopic(whosends(ci), c, c->topic_setter, c->topic); - - if (ircd->join2set && whosends(ci) == ChanServ) - ChanServ->Part(c); - return 1; -} - -/*************************************************************************/ - /* Remove all channels which have expired. */ void expire_chans() diff --git a/src/regchannel.cpp b/src/regchannel.cpp index e88065eb5..fb8036677 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -398,7 +398,7 @@ void ChannelInfo::LoadMLock() ChanServ->Assign(NULL, this); this->bi->Join(c); check_modes(this->c); - restore_topic(this->name); + this->CheckTopic(); } } @@ -607,7 +607,7 @@ bool ChannelInfo::CheckKick(User *user) * ChanServ always enforces channels like this to keep people from deleting bots etc * that are holding channels. */ - if (this->c->users.size() == (this->bi ? 2 : 1) && !this->HasFlag(CI_INHABIT) && !this->c->HasFlag(CH_SYNCING)) + if (this->c->users.size() == (this->bi && this->c->FindUser(this->bi) ? 2 : 1) && !this->HasFlag(CI_INHABIT) && !this->c->HasFlag(CH_SYNCING)) { /* If channel was forbidden, etc, set it +si to prevent rejoin */ if (set_modes) @@ -627,3 +627,37 @@ bool ChannelInfo::CheckKick(User *user) return true; } + +void ChannelInfo::CheckTopic() +{ + if (!this->c) + return; + + /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not + * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us. + * This desyncs what is really set with what we have stored, and we end up resetting the topic often when + * it is not required + */ + if (this->HasFlag(CI_TOPICLOCK) && this->last_topic != this->c->topic) + { + this->c->ChangeTopic(this->last_topic_setter, this->last_topic, this->last_topic_time); + } + else + { + this->last_topic = this->c->topic; + this->last_topic_setter = this->c->topic_setter; + this->last_topic_time = this->c->topic_time; + } +} + +void ChannelInfo::RestoreTopic() +{ + if (!this->c) + return; + + if ((this->HasFlag(CI_KEEPTOPIC) || this->HasFlag(CI_TOPICLOCK)) && this->last_topic != this->c->topic) + { + this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : whosends(this)->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime); + } +} + diff --git a/src/servers.cpp b/src/servers.cpp index 37518e01e..d8752d90b 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -248,7 +248,9 @@ void Server::Sync(bool SyncLinks) if (this->GetUplink() && this->GetUplink() == Me) { FOREACH_MOD(I_OnUplinkSync, OnUplinkSync(this)); - restore_unsynced_topics(); + for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) + if (it->second->ci) + it->second->ci->RestoreTopic(); } } |
