summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/channels.h6
-rw-r--r--src/channels.cpp39
-rw-r--r--src/commands/cmd_topic.cpp88
3 files changed, 64 insertions, 69 deletions
diff --git a/include/channels.h b/include/channels.h
index c27329310..605ac8216 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -232,6 +232,12 @@ class CoreExport Channel : public Extensible
*/
std::string GetModeParameter(char mode);
+ /** Sets the channel topic.
+ * @param u The user setting the topic
+ * @param t The topic to set it to. Non-const, as it may be modified by a hook.
+ */
+ int SetTopic(User *u, std::string &t);
+
/** Obtain the channel "user counter"
* This returns the channel reference counter, which is initialized
* to 0 when the channel is created and incremented/decremented
diff --git a/src/channels.cpp b/src/channels.cpp
index 9da94b4bf..19cfccc79 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -73,6 +73,45 @@ std::string Channel::GetModeParameter(char mode)
return "";
}
+int Channel::SetTopic(User *u, std::string &ntopic)
+{
+ if (IS_LOCAL(u))
+ {
+ int MOD_RESULT = 0;
+ /* 0: check status, 1: don't, -1: disallow change silently */
+
+ FOREACH_RESULT(I_OnLocalTopicChange,OnLocalTopicChange(u,this,ntopic));
+ if (MOD_RESULT == -1)
+ return CMD_FAILURE;
+ else if (MOD_RESULT == 0)
+ {
+ if (!this->HasUser(u))
+ {
+ u->WriteNumeric(442, "%s %s :You're not on that channel!",u->nick.c_str(), this->name.c_str());
+ return CMD_FAILURE;
+ }
+ if ((this->IsModeSet('t')) && (this->GetStatus(u) < STATUS_HOP))
+ {
+ u->WriteNumeric(482, "%s %s :You must be at least a half-operator to change the topic on this channel", u->nick.c_str(), this->name.c_str());
+ return CMD_FAILURE;
+ }
+ }
+
+ this->topic.assign(ntopic, 0, ServerInstance->Config->Limits.MaxTopic);
+ }
+
+ this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
+ this->topicset = ServerInstance->Time();
+ this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
+
+ if (IS_LOCAL(u))
+ {
+ FOREACH_MOD(I_OnPostLocalTopicChange,OnPostLocalTopicChange(u, this, this->topic));
+ }
+
+ return CMD_SUCCESS;
+}
+
long Channel::GetUserCounter()
{
return (this->internal_userlist.size());
diff --git a/src/commands/cmd_topic.cpp b/src/commands/cmd_topic.cpp
index 0e1a115da..3f2bc1f06 100644
--- a/src/commands/cmd_topic.cpp
+++ b/src/commands/cmd_topic.cpp
@@ -22,93 +22,43 @@ extern "C" DllExport Command* init_command(InspIRCd* Instance)
CmdResult CommandTopic::Handle (const std::vector<std::string>& parameters, User *user)
{
- Channel* Ptr;
+ Channel* c;
+
+ c = ServerInstance->FindChan(parameters[0]);
+ if (!c)
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
if (parameters.size() == 1)
{
- Ptr = ServerInstance->FindChan(parameters[0]);
- if (Ptr)
+ if (c)
{
- if ((Ptr->IsModeSet('s')) && (!Ptr->HasUser(user)))
+ if ((c->IsModeSet('s')) && (!c->HasUser(user)))
{
- user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), c->name.c_str());
return CMD_FAILURE;
}
- if (Ptr->topicset)
+
+ if (c->topic.length())
{
- user->WriteNumeric(332, "%s %s :%s", user->nick.c_str(), Ptr->name.c_str(), Ptr->topic.c_str());
- user->WriteNumeric(333, "%s %s %s %lu", user->nick.c_str(), Ptr->name.c_str(), Ptr->setby.c_str(), (unsigned long)Ptr->topicset);
+ user->WriteNumeric(332, "%s %s :%s", user->nick.c_str(), c->name.c_str(), c->topic.c_str());
+ user->WriteNumeric(333, "%s %s %s %lu", user->nick.c_str(), c->name.c_str(), c->setby.c_str(), (unsigned long)c->topicset);
}
else
{
- user->WriteNumeric(331, "%s %s :No topic is set.", user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(331, "%s %s :No topic is set.", user->nick.c_str(), c->name.c_str());
}
}
- else
- {
- user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
- }
return CMD_SUCCESS;
}
else if (parameters.size()>1)
{
- Ptr = ServerInstance->FindChan(parameters[0]);
- if (Ptr)
- {
- if (IS_LOCAL(user))
- {
- if (!Ptr->HasUser(user))
- {
- user->WriteNumeric(442, "%s %s :You're not on that channel!",user->nick.c_str(), Ptr->name.c_str());
- return CMD_FAILURE;
- }
- if ((Ptr->IsModeSet('t')) && (Ptr->GetStatus(user) < STATUS_HOP))
- {
- user->WriteNumeric(482, "%s %s :You must be at least a half-operator to change the topic on this channel", user->nick.c_str(), Ptr->name.c_str());
- return CMD_FAILURE;
- }
- }
-
- std::string topic;
-
- if (IS_LOCAL(user))
- {
- /* XXX: we need two string copies for a local topic, because we cant
- * let a module see the topic as longer than it actually is
- */
- int MOD_RESULT = 0;
-
- topic.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxTopic);
- FOREACH_RESULT(I_OnLocalTopicChange,OnLocalTopicChange(user,Ptr,topic));
- if (MOD_RESULT)
- return CMD_FAILURE;
-
- Ptr->topic.assign(topic, 0, ServerInstance->Config->Limits.MaxTopic);
- }
- else
- {
- /* Sneaky shortcut, one string copy for a remote topic */
- Ptr->topic.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxTopic);
- }
-
- Ptr->setby.assign(ServerInstance->Config->FullHostInTopic ?
- user->GetFullHost() : user->nick,
- 0, 128);
-
- Ptr->topicset = ServerInstance->Time();
- Ptr->WriteChannel(user, "TOPIC %s :%s", Ptr->name.c_str(), Ptr->topic.c_str());
-
- if (IS_LOCAL(user))
- /* We know 'topic' will contain valid data here */
- FOREACH_MOD(I_OnPostLocalTopicChange,OnPostLocalTopicChange(user, Ptr, topic));
- }
- else
- {
- user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
- }
+ std::string t = parameters[1]; // needed, in case a module wants to change it
+ c->SetTopic(user, t);
}
+
return CMD_SUCCESS;
}