summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-08-21 01:40:36 -0400
committerAdam <Adam@anope.org>2010-08-21 01:40:36 -0400
commitfb551f0d5d412246a5221e8e9e310c191033b317 (patch)
treee737cdf9db93d53313701695c338ab9c96e83e9f
parent931b0777fbd961a4ca961ddfa763af92dcce946c (diff)
Made Anope keep track of channels its clients are in if it splits from its uplink, then burst them back to its uplink once connection is reestablished.
Also made Anope use TS enforcement to change persistant channels creation time to the time they were registered.
-rw-r--r--include/bots.h18
-rw-r--r--include/channels.h26
-rw-r--r--include/extern.h2
-rw-r--r--include/modes.h8
-rw-r--r--include/services.h10
-rw-r--r--include/users.h9
-rw-r--r--modules/core/cs_set_persist.cpp4
-rw-r--r--modules/core/db_plain.cpp38
-rw-r--r--modules/core/os_chanlist.cpp4
-rw-r--r--modules/extra/db_mysql.cpp25
-rw-r--r--modules/protocol/bahamut.cpp65
-rw-r--r--modules/protocol/inspircd11.cpp63
-rw-r--r--modules/protocol/inspircd12.cpp55
-rw-r--r--modules/protocol/inspircd20.cpp57
-rw-r--r--modules/protocol/ratbox.cpp50
-rw-r--r--modules/protocol/unreal32.cpp50
-rw-r--r--src/bots.cpp34
-rw-r--r--src/channels.cpp144
-rw-r--r--src/chanserv.cpp4
-rw-r--r--src/init.cpp36
-rw-r--r--src/main.cpp9
-rw-r--r--src/modes.cpp51
-rw-r--r--src/protocol.cpp5
-rw-r--r--src/regchannel.cpp71
-rw-r--r--src/servers.cpp8
25 files changed, 435 insertions, 411 deletions
diff --git a/include/bots.h b/include/bots.h
index 7d2fa74f3..f6b8d2e14 100644
--- a/include/bots.h
+++ b/include/bots.h
@@ -71,8 +71,22 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>
*/
void UnAssign(User *u, ChannelInfo *ci);
- void Join(Channel *c);
- void Join(const Anope::string &chname);
+ /** Join this bot to a channel
+ * @param c The channel
+ * @param update_ts Assume we're updating the TS for this channel
+ */
+ void Join(Channel *c, bool update_ts = false);
+
+ /** Join this bot to a channel
+ * @param chname The channel name
+ * @param update_ts Assume we're updating the TS for this channel
+ */
+ void Join(const Anope::string &chname, bool update_ts = false);
+
+ /** Part this bot from a channel
+ * @param c The channel
+ * @param reason The reason we're parting
+ */
void Part(Channel *c, const Anope::string &reason = "");
};
diff --git a/include/channels.h b/include/channels.h
index 845f8fc36..8c5d83c5d 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -44,7 +44,7 @@ struct UserContainer
{
User *user;
UserData ud;
- Flags<ChannelModeName> *Status;
+ ChannelStatus *Status;
UserContainer(User *u) : user(u) { }
virtual ~UserContainer() { }
@@ -104,6 +104,11 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlags>
int16 bouncy_modes; /* Did we fail to set modes here? */
int16 topic_sync; /* Is the topic in sync? */
+ /** Call if we need to unset all modes and clear all user status (internally).
+ * Only useful if we get a SJOIN with a TS older than what we have here
+ */
+ void Reset();
+
/** Restore the channel topic, set mlock (key), set stickied bans, etc
*/
void Sync();
@@ -217,23 +222,27 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlags>
/** Clear all the modes from the channel
* @param bi The client unsetting the modes
+ * @param internal Only remove the modes internally
*/
- void ClearModes(BotInfo *bi = NULL);
+ void ClearModes(BotInfo *bi = NULL, bool internal = false);
/** Clear all the bans from the channel
* @param bi The client unsetting the modes
+ * @param internal Only remove the modes internally
*/
- void ClearBans(BotInfo *bi = NULL);
+ void ClearBans(BotInfo *bi = NULL, bool internal = false);
/** Clear all the excepts from the channel
* @param bi The client unsetting the modes
+ * @param internal Only remove the modes internally
*/
- void ClearExcepts(BotInfo *bi = NULL);
+ void ClearExcepts(BotInfo *bi = NULL, bool internal = false);
/** Clear all the invites from the channel
* @param bi The client unsetting the modes
+ * @param internal Only remove the modes internally
*/
- void ClearInvites(BotInfo *bi = NULL);
+ void ClearInvites(BotInfo *bi = NULL, bool internal = false);
/** Get a param from the channel
* @param Name The mode
@@ -268,6 +277,13 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlags>
* @return true if the kick was scucessful, false if a module blocked the kick
*/
bool Kick(BotInfo *bi, User *u, const char *reason = NULL, ...);
+
+ /** Get a string of the modes set on this channel
+ * @param complete Include mode parameters
+ * @param plus If set to false (with complete), mode parameters will not be given for modes requring no parameters to be unset
+ * @return A mode string
+ */
+ Anope::string GetModes(bool complete, bool plus);
};
#endif // CHANNELS_H
diff --git a/include/extern.h b/include/extern.h
index b2dd30b79..4dc6cb4ba 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -66,8 +66,6 @@ E void ChanSetInternalModes(Channel *c, int ac, const char **av);
E User *nc_on_chan(Channel *c, const NickCore *nc);
-E Anope::string chan_get_modes(Channel *chan, int complete, int plus);
-
E int get_access_level(ChannelInfo *ci, NickAlias *na);
E int get_access_level(ChannelInfo *ci, NickCore *nc);
E Anope::string get_xop_level(int level);
diff --git a/include/modes.h b/include/modes.h
index 6447550ad..4d0706a9a 100644
--- a/include/modes.h
+++ b/include/modes.h
@@ -420,7 +420,7 @@ class CoreExport ModeManager
public:
/* List of all modes Anope knows about */
- static std::list<Mode *> Modes;
+ static std::map<Anope::string, Mode *> Modes;
/* User modes */
static std::map<char, UserMode *> UserModesByChar;
@@ -468,6 +468,12 @@ class CoreExport ModeManager
*/
static UserMode *FindUserModeByName(UserModeName Name);
+ /** Find a mode by name
+ * @param name The mode name
+ * @return The mode
+ */
+ static Mode *FindModeByName(const Anope::string &name);
+
/** Gets the channel mode char for a symbol (eg + returns v)
* @param Value The symbol
* @return The char
diff --git a/include/services.h b/include/services.h
index 15670c8ac..ca02d087e 100644
--- a/include/services.h
+++ b/include/services.h
@@ -730,13 +730,13 @@ struct LevelInfo
/*************************************************************************/
-#include "users.h"
-#include "bots.h"
-
/* This structure stocks ban data since it must not be removed when
* user is kicked.
*/
+#include "users.h"
+#include "bots.h"
+
struct BanData
{
BanData *next, *prev;
@@ -973,7 +973,8 @@ class CoreExport IRCDProto
virtual void SendQuit(const BotInfo *bi, const char *fmt, ...);
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
virtual void SendPong(const Anope::string &servname, const Anope::string &who);
- virtual void SendJoin(const BotInfo *bi, const Anope::string &, time_t) = 0;
+ virtual void SendJoin(const BotInfo *, const Anope::string &, time_t) = 0;
+ virtual void SendJoin(BotInfo *, const ChannelContainer *);
virtual void SendSQLineDel(const XLine *x) = 0;
virtual void SendInvite(const BotInfo *bi, const Anope::string &chan, const Anope::string &nick);
virtual void SendPart(const BotInfo *bi, const Channel *chan, const char *fmt, ...);
@@ -998,6 +999,7 @@ class CoreExport IRCDProto
virtual void SendSVSJoin(const Anope::string &, const Anope::string &, const Anope::string &, const Anope::string &) { }
virtual void SendSVSPart(const Anope::string &, const Anope::string &, const Anope::string &) { }
virtual void SendSWhois(const Anope::string &, const Anope::string &, const Anope::string &) { }
+ virtual void SendBOB() { }
virtual void SendEOB() { }
virtual void SendServer(const Server *) = 0;
virtual bool IsNickValid(const Anope::string &) { return true; }
diff --git a/include/users.h b/include/users.h
index 78d83c062..40e98b114 100644
--- a/include/users.h
+++ b/include/users.h
@@ -17,10 +17,17 @@ typedef unordered_map_namespace::unordered_map<Anope::string, User *, Anope::has
extern CoreExport user_map UserListByNick;
extern CoreExport user_uid_map UserListByUID;
+class ChannelStatus : public Flags<ChannelModeName>
+{
+ public:
+ Anope::string BuildCharPrefixList() const;
+ Anope::string BuildModePrefixList() const;
+};
+
struct ChannelContainer
{
Channel *chan;
- Flags<ChannelModeName> *Status;
+ ChannelStatus *Status;
ChannelContainer(Channel *c) : chan(c) { }
virtual ~ChannelContainer() { }
diff --git a/modules/core/cs_set_persist.cpp b/modules/core/cs_set_persist.cpp
index fe3c84242..955e2082f 100644
--- a/modules/core/cs_set_persist.cpp
+++ b/modules/core/cs_set_persist.cpp
@@ -33,6 +33,8 @@ class CommandCSSetPersist : public Command
if (!ci->HasFlag(CI_PERSIST))
{
ci->SetFlag(CI_PERSIST);
+ if (ci->c)
+ ci->c->SetFlag(CH_PERSIST);
/* Channel doesn't exist, create it */
if (!ci->c)
@@ -65,6 +67,8 @@ class CommandCSSetPersist : public Command
if (ci->HasFlag(CI_PERSIST))
{
ci->UnsetFlag(CI_PERSIST);
+ if (ci->c)
+ ci->c->UnsetFlag(CH_PERSIST);
/* Unset perm mode */
if (cm && ci->c && ci->c->HasMode(CMODE_PERM))
diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp
index 7f90ad6f9..9c47306ca 100644
--- a/modules/core/db_plain.cpp
+++ b/modules/core/db_plain.cpp
@@ -1011,43 +1011,33 @@ class DBPlain : public Module
if (ci->GetMLockCount(true))
{
db << "MD MLOCK_ON";
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
{
- if ((*it)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
-
- if (ci->HasMLock(cm->Name, true))
- db << " " << cm->NameAsString;
- }
+ ChannelMode *cm = it->second;
+ if (ci->HasMLock(cm->Name, true))
+ db << " " << cm->NameAsString;
}
db << endl;
}
if (ci->GetMLockCount(false))
{
db << "MD MLOCK_OFF";
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- if ((*it)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
- if (ci->HasMLock(cm->Name, false))
- db << " " << cm->NameAsString;
- }
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ {
+ ChannelMode *cm = it->second;
+ if (ci->HasMLock(cm->Name, false))
+ db << " " << cm->NameAsString;
}
db << endl;
}
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
{
- if ((*it)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
+ ChannelMode *cm = it->second;
+ Anope::string Param;
- Anope::string Param;
- if (ci->GetParam(cm->Name, Param))
- db << "MD MLP " << cm->NameAsString << " " << Param << endl;
- }
+ if (ci->GetParam(cm->Name, Param))
+ db << "MD MLP " << cm->NameAsString << " " << Param << endl;
}
if (!ci->memos.memos.empty())
{
diff --git a/modules/core/os_chanlist.cpp b/modules/core/os_chanlist.cpp
index 8fcb1c397..87b3d736d 100644
--- a/modules/core/os_chanlist.cpp
+++ b/modules/core/os_chanlist.cpp
@@ -46,7 +46,7 @@ class CommandOSChanList : public Command
if (!cc->chan->HasMode(*it))
continue;
- notice_lang(Config->s_OperServ, u, OPER_CHANLIST_RECORD, cc->chan->name.c_str(), cc->chan->users.size(), chan_get_modes(cc->chan, 1, 1).c_str(), !cc->chan->topic.empty() ? cc->chan->topic.c_str() : "");
+ notice_lang(Config->s_OperServ, u, OPER_CHANLIST_RECORD, cc->chan->name.c_str(), cc->chan->users.size(), cc->chan->GetModes(true, true).c_str(), !cc->chan->topic.empty() ? cc->chan->topic.c_str() : "");
}
}
else
@@ -64,7 +64,7 @@ class CommandOSChanList : public Command
if (!c->HasMode(*it))
continue;
- notice_lang(Config->s_OperServ, u, OPER_CHANLIST_RECORD, c->name.c_str(), c->users.size(), chan_get_modes(c, 1, 1).c_str(), !c->topic.empty() ? c->topic.c_str() : "");
+ notice_lang(Config->s_OperServ, u, OPER_CHANLIST_RECORD, c->name.c_str(), c->users.size(), c->GetModes(true, true).c_str(), !c->topic.empty() ? c->topic.c_str() : "");
}
}
diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp
index 27a1226d1..4aeac0322 100644
--- a/modules/extra/db_mysql.cpp
+++ b/modules/extra/db_mysql.cpp
@@ -199,15 +199,11 @@ static Anope::string MakeMLock(ChannelInfo *ci, bool status)
{
Anope::string ret;
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
{
- if ((*it)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
-
- if (ci->HasMLock(cm->Name, status))
- ret += " " + cm->NameAsString;
- }
+ ChannelMode *cm = it->second;
+ if (ci->HasMLock(cm->Name, status))
+ ret += " " + cm->NameAsString;
}
if (!ret.empty())
@@ -230,16 +226,13 @@ static Anope::string GetMLockParams(ChannelInfo *ci)
{
Anope::string ret;
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
{
- if ((*it)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
+ ChannelMode *cm = it->second;
- Anope::string param;
- if (ci->GetParam(cm->Name, param))
- ret += " " + cm->NameAsString + " " + param;
- }
+ Anope::string param;
+ if (ci->GetParam(cm->Name, param))
+ ret += " " + cm->NameAsString + " " + param;
}
if (!ret.empty())
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp
index 572b91367..9c3e107a4 100644
--- a/modules/protocol/bahamut.cpp
+++ b/modules/protocol/bahamut.cpp
@@ -197,6 +197,19 @@ class BahamutIRCdProto : public IRCDProto
send_cmd(user->nick, "SJOIN %ld %s", static_cast<long>(chantime), channel.c_str());
}
+ void SendJoin(BotInfo *user, const ChannelContainer *cc)
+ {
+ SendJoin(user, cc->chan->name, cc->chan->creation_time);
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ {
+ if (cc->Status->HasFlag(it->second->Name))
+ {
+ cc->chan->SetMode(user, it->second, user->nick);
+ }
+ }
+ cc->chan->SetModes(user, false, "%s", cc->chan->GetModes(true, true).c_str());
+ }
+
void SendAkill(const XLine *x)
{
// Calculate the time left before this would expire, capping it at 2 days
@@ -226,6 +239,11 @@ class BahamutIRCdProto : public IRCDProto
this->SendModeInternal(NULL, u, merge_args(ac, av));
}
+ void SendBOB()
+ {
+ send_cmd("", "BURST");
+ }
+
void SendEOB()
{
send_cmd("", "BURST 0");
@@ -290,56 +308,26 @@ int anope_event_sjoin(const Anope::string &source, int ac, const char **av)
{
Channel *c = findchan(av[1]);
time_t ts = Anope::string(av[0]).is_number_only() ? convertTo<time_t>(av[0]) : 0;
- bool was_created = false;
bool keep_their_modes = false;
if (!c)
{
c = new Channel(av[1], ts);
- was_created = true;
+ c->SetFlag(CH_SYNCING);
}
/* Our creation time is newer than what the server gave us */
else if (c->creation_time > ts)
{
c->creation_time = ts;
+ c->Reset();
- /* Remove status from all of our users */
- for (std::list<Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- Mode *m = *it;
-
- if (m->Type != MODE_STATUS)
- continue;
-
- ChannelMode *cm = debug_cast<ChannelMode *>(m);
-
- for (CUserList::const_iterator uit = c->users.begin(), uit_end = c->users.end(); uit != uit_end; ++uit)
- {
- UserContainer *uc = *uit;
-
- c->RemoveMode(NULL, cm, uc->user->nick);
- }
- }
- if (c->ci)
- {
- /* Rejoin the bot to fix the TS */
- if (c->ci->bi)
- {
- c->ci->bi->Part(c, "TS reop");
- c->ci->bi->Join(c);
- }
- /* Reset mlock */
- check_modes(c);
- }
+ /* Reset mlock */
+ check_modes(c);
}
/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
- else
+ else if (ts > c->creation_time)
keep_their_modes = false;
- /* Mark the channel as syncing */
- if (was_created)
- c->SetFlag(CH_SYNCING);
-
/* If we need to keep their modes, and this SJOIN string contains modes */
if (keep_their_modes && ac >= 4)
{
@@ -350,7 +338,7 @@ int anope_event_sjoin(const Anope::string &source, int ac, const char **av)
/* For a reason unknown to me, bahamut will send a SJOIN from the user joining a channel
* if the channel already existed
*/
- if (!was_created && ac == 2)
+ if (!c->HasFlag(CH_SYNCING) && ac == 2)
{
User *u = finduser(source);
if (!u)
@@ -396,7 +384,8 @@ int anope_event_sjoin(const Anope::string &source, int ac, const char **av)
continue;
}
- Status.push_back(cm);
+ if (keep_their_modes)
+ Status.push_back(cm);
}
User *u = finduser(buf);
@@ -433,7 +422,7 @@ int anope_event_sjoin(const Anope::string &source, int ac, const char **av)
}
/* Channel is done syncing */
- if (was_created)
+ if (c->HasFlag(CH_SYNCING))
{
/* Unset the syncing flag */
c->UnsetFlag(CH_SYNCING);
diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp
index c06b74501..cc2c99fa6 100644
--- a/modules/protocol/inspircd11.cpp
+++ b/modules/protocol/inspircd11.cpp
@@ -185,6 +185,19 @@ class InspIRCdProto : public IRCDProto
send_cmd(user->nick, "JOIN %s %ld", channel.c_str(), static_cast<long>(chantime));
}
+ void SendJoin(BotInfo *user, const ChannelContainer *cc)
+ {
+ SendJoin(user, cc->chan->name, cc->chan->creation_time);
+ for (std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ {
+ if (cc->Status->HasFlag(it->second->Name))
+ {
+ cc->chan->SetMode(user, it->second, user->nick);
+ }
+ }
+ cc->chan->SetModes(user, false, "%s", cc->chan->GetModes(true, true).c_str());
+ }
+
/* UNSQLINE */
void SendSQLineDel(const XLine *x)
{
@@ -270,6 +283,11 @@ class InspIRCdProto : public IRCDProto
send_cmd(source, "SVSPART %s %s", nick.c_str(), chan.c_str());
}
+ void SendBOB()
+ {
+ send_cmd("", "BURST %ld", time(NULL));
+ }
+
void SendEOB()
{
send_cmd("", "ENDBURST");
@@ -386,56 +404,26 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
{
Channel *c = findchan(av[0]);
time_t ts = Anope::string(av[1]).is_number_only() ? convertTo<time_t>(av[1]) : 0;
- bool was_created = false;
bool keep_their_modes = true;
if (!c)
{
c = new Channel(av[0], ts);
- was_created = true;
+ c->SetFlag(CH_SYNCING);
}
/* Our creation time is newer than what the server gave us */
else if (c->creation_time > ts)
{
c->creation_time = ts;
+ c->Reset();
- /* Remove status from all of our users */
- for (std::list<Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- Mode *m = *it;
-
- if (m->Type != MODE_STATUS)
- continue;
-
- ChannelMode *cm = debug_cast<ChannelMode *>(m);
-
- for (CUserList::const_iterator uit = c->users.begin(), uit_end = c->users.end(); uit != uit_end; ++uit)
- {
- UserContainer *uc = *uit;
-
- c->RemoveMode(NULL, cm, uc->user->nick);
- }
- }
- if (c->ci)
- {
- /* Rejoin the bot to fix the TS */
- if (c->ci->bi)
- {
- c->ci->bi->Part(c, "TS reop");
- c->ci->bi->Join(c);
- }
- /* Reset mlock */
- check_modes(c);
- }
+ /* Reset mlock */
+ check_modes(c);
}
/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
- else
+ else if (ts > c->creation_time)
keep_their_modes = false;
- /* Mark the channel as syncing */
- if (was_created)
- c->SetFlag(CH_SYNCING);
-
spacesepstream sep(av[ac - 1]);
Anope::string buf;
while (sep.GetToken(buf))
@@ -456,7 +444,8 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
buf.erase(buf.begin());
- Status.push_back(cm);
+ if (keep_their_modes)
+ Status.push_back(cm);
}
User *u = finduser(buf);
@@ -492,7 +481,7 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
/* Channel is done syncing */
- if (was_created)
+ if (c->HasFlag(CH_SYNCING))
{
/* Unset the syncing flag */
c->UnsetFlag(CH_SYNCING);
diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp
index a78ead0a8..55a371700 100644
--- a/modules/protocol/inspircd12.cpp
+++ b/modules/protocol/inspircd12.cpp
@@ -185,6 +185,11 @@ class InspIRCdProto : public IRCDProto
send_cmd(TS6SID, "FJOIN %s %ld + :,%s", channel.c_str(), static_cast<long>(chantime), user->GetUID().c_str());
}
+ void SendJoin(BotInfo *user, const ChannelContainer *cc)
+ {
+ send_cmd(TS6SID, "FJOIN %s %ld +%s :%s,%s", cc->chan->name.c_str(), static_cast<long>(cc->chan->creation_time), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildCharPrefixList().c_str(), user->GetUID().c_str());
+ }
+
/* UNSQLINE */
void SendSQLineDel(const XLine *x)
{
@@ -275,6 +280,11 @@ class InspIRCdProto : public IRCDProto
send_cmd(TS6SID, "METADATA %s swhois :%s", u->GetUID().c_str(), mask.c_str());
}
+ void SendBOB()
+ {
+ send_cmd(TS6SID, "BURST %ld", time(NULL));
+ }
+
void SendEOB()
{
send_cmd(TS6SID, "ENDBURST");
@@ -427,56 +437,26 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
{
Channel *c = findchan(av[0]);
time_t ts = Anope::string(av[1]).is_number_only() ? convertTo<time_t>(av[1]) : 0;
- bool was_created = false;
bool keep_their_modes = true;
if (!c)
{
c = new Channel(av[0], ts);
- was_created = true;
+ c->SetFlag(CH_SYNCING);
}
/* Our creation time is newer than what the server gave us */
else if (c->creation_time > ts)
{
c->creation_time = ts;
+ c->Reset();
- /* Remove status from all of our users */
- for (std::list<Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- Mode *m = *it;
-
- if (m->Type != MODE_STATUS)
- continue;
-
- ChannelMode *cm = debug_cast<ChannelMode *>(m);
-
- for (CUserList::const_iterator uit = c->users.begin(), uit_end = c->users.end(); uit != uit_end; ++uit)
- {
- UserContainer *uc = *uit;
-
- c->RemoveMode(NULL, cm, uc->user->nick);
- }
- }
- if (c->ci)
- {
- /* Rejoin the bot to fix the TS */
- if (c->ci->bi)
- {
- c->ci->bi->Part(c, "TS reop");
- c->ci->bi->Join(c);
- }
- /* Reset mlock */
- check_modes(c);
- }
+ /* Reset mlock */
+ check_modes(c);
}
/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
- else
+ else if (ts > c->creation_time)
keep_their_modes = false;
- /* Mark the channel as syncing */
- if (was_created)
- c->SetFlag(CH_SYNCING);
-
/* If we need to keep their modes, and this FJOIN string contains modes */
if (keep_their_modes && ac >= 4)
{
@@ -502,7 +482,8 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
buf.erase(buf.begin());
- Status.push_back(cm);
+ if (keep_their_modes)
+ Status.push_back(cm);
}
buf.erase(buf.begin());
@@ -539,7 +520,7 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
/* Channel is done syncing */
- if (was_created)
+ if (c->HasFlag(CH_SYNCING))
{
/* Unset the syncing flag */
c->UnsetFlag(CH_SYNCING);
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
index c55bc7020..8a8748d49 100644
--- a/modules/protocol/inspircd20.cpp
+++ b/modules/protocol/inspircd20.cpp
@@ -183,6 +183,11 @@ class InspIRCdProto : public IRCDProto
send_cmd(TS6SID, "FJOIN %s %ld + :,%s", channel.c_str(), static_cast<long>(chantime), user->GetUID().c_str());
}
+ void SendJoin(BotInfo *user, const ChannelContainer *cc)
+ {
+ send_cmd(TS6SID, "FJOIN %s %ld +%s :%s,%s", cc->chan->name.c_str(), static_cast<long>(cc->chan->creation_time), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildCharPrefixList().c_str(), user->GetUID().c_str());
+ }
+
/* UNSQLINE */
void SendSQLineDel(const XLine *x)
{
@@ -276,6 +281,11 @@ class InspIRCdProto : public IRCDProto
send_cmd(TS6SID, "METADATA %s swhois :%s", u->GetUID().c_str(), mask.c_str());
}
+ void SendBOB()
+ {
+ send_cmd(TS6SID, "BURST %ld", time(NULL));
+ }
+
void SendEOB()
{
send_cmd(TS6SID, "ENDBURST");
@@ -425,56 +435,26 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
{
Channel *c = findchan(av[0]);
time_t ts = Anope::string(av[1]).is_number_only() ? convertTo<time_t>(av[1]) : 0;
- bool was_created = false;
bool keep_their_modes = true;
if (!c)
{
c = new Channel(av[0], ts);
- was_created = true;
+ c->SetFlag(CH_SYNCING);
}
/* Our creation time is newer than what the server gave us */
else if (c->creation_time > ts)
{
c->creation_time = ts;
+ c->Reset();
- /* Remove status from all of our users */
- for (std::list<Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- Mode *m = *it;
-
- if (m->Type != MODE_STATUS)
- continue;
-
- ChannelMode *cm = debug_cast<ChannelMode *>(m);
-
- for (CUserList::const_iterator uit = c->users.begin(), uit_end = c->users.end(); uit != uit_end; ++uit)
- {
- UserContainer *uc = *uit;
-
- c->RemoveMode(NULL, cm, uc->user->nick);
- }
- }
- if (c->ci)
- {
- /* Rejoin the bot to fix the TS */
- if (c->ci->bi)
- {
- c->ci->bi->Part(c, "TS reop");
- c->ci->bi->Join(c);
- }
- /* Reset mlock */
- check_modes(c);
- }
+ /* Reset mlock */
+ check_modes(c);
}
- /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
- else
+ /* Their TS is newer than ours, our modes > theirs, unset their modes */
+ else if (ts > c->creation_time)
keep_their_modes = false;
- /* Mark the channel as syncing */
- if (was_created)
- c->SetFlag(CH_SYNCING);
-
/* If we need to keep their modes, and this FJOIN string contains modes */
if (keep_their_modes && ac >= 4)
{
@@ -500,7 +480,8 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
buf.erase(buf.begin());
- Status.push_back(cm);
+ if (keep_their_modes)
+ Status.push_back(cm);
}
buf.erase(buf.begin());
@@ -537,7 +518,7 @@ int anope_event_fjoin(const Anope::string &source, int ac, const char **av)
}
/* Channel is done syncing */
- if (was_created)
+ if (c->HasFlag(CH_SYNCING))
{
/* Unset the syncing flag */
c->UnsetFlag(CH_SYNCING);
diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp
index 8db46a3d5..a26ee9598 100644
--- a/modules/protocol/ratbox.cpp
+++ b/modules/protocol/ratbox.cpp
@@ -145,6 +145,11 @@ class RatboxProto : public IRCDTS6Proto
send_cmd("", "SJOIN %ld %s + :%s", static_cast<long>(chantime), cha