summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-09-15 16:40:55 -0400
committerAdam <Adam@anope.org>2010-09-15 16:40:55 -0400
commit813185105823daa6a1b574d86053950382343589 (patch)
tree793d4f54cddc88275b4372839f93bba01301b427 /src
parent6239b5a053fc8fd94b798495f8e189a2e2bda285 (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.cpp104
-rw-r--r--src/chanserv.cpp127
-rw-r--r--src/regchannel.cpp38
-rw-r--r--src/servers.cpp4
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();
}
}