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), channel.c_str(), user->GetUID().c_str());
}
+ void SendJoin(const BotInfo *user, const ChannelContainer *cc)
+ {
+ send_cmd("", "SJOIN %ld %s +%s :%s%s", static_cast<long>(cc->chan->creation_time), cc->chan->name.c_str(), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildModePrefixList().c_str(), user->GetUID().c_str());
+ }
+
void SendAkill(const XLine *x)
{
BotInfo *bi = OperServ;
@@ -281,56 +286,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 = true;
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)
{
@@ -356,7 +331,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);
@@ -392,7 +368,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/unreal32.cpp b/modules/protocol/unreal32.cpp
index 1e18e92f9..ff04e87eb 100644
--- a/modules/protocol/unreal32.cpp
+++ b/modules/protocol/unreal32.cpp
@@ -214,6 +214,12 @@ class UnrealIRCdProto : public IRCDProto
send_cmd(Config->ServerName, "~ %ld %s :%s", static_cast<long>(chantime), channel.c_str(), user->nick.c_str());
}
+ void SendJoin(BotInfo *user, const ChannelContainer *cc)
+ {
+ send_cmd(Config->ServerName, "~ %ld %s :%s%s", static_cast<long>(cc->chan->creation_time), cc->chan->name.c_str(), cc->Status->BuildModePrefixList().c_str(), user->nick.c_str());
+ cc->chan->SetModes(user, false, "%s", cc->chan->GetModes(true, true).c_str());
+ }
+
/* unsqline
*/
void SendSQLineDel(const XLine *x)
@@ -988,54 +994,25 @@ 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 keep_their_modes = true;
- bool was_created = 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();
- 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)
{
@@ -1090,7 +1067,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);
@@ -1127,7 +1105,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/src/bots.cpp b/src/bots.cpp
index cb7a370c1..d63f6787f 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -49,7 +49,7 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
if (!this->uid.empty())
BotListByUID[this->uid] = this;
- // If we're synchronised with the uplink already, call introduce_user() for this bot.
+ // If we're synchronised with the uplink already, send the bot.
if (Me && !Me->GetLinks().empty() && Me->GetLinks().front()->IsSynced())
{
ircdproto->SendClientIntroduction(this->nick, this->GetIdent(), this->host, this->realname, ircd->pseudoclient_mode, this->uid);
@@ -136,7 +136,7 @@ void BotInfo::UnAssign(User *u, ChannelInfo *ci)
ci->bi = NULL;
}
-void BotInfo::Join(Channel *c)
+void BotInfo::Join(Channel *c, bool update_ts)
{
if (Config->BSSmartJoin)
{
@@ -162,19 +162,39 @@ void BotInfo::Join(Channel *c)
if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit))
ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str());
}
+
+ ModeManager::ProcessModes();
}
- ircdproto->SendJoin(this, c->name, c->creation_time);
- for (std::list<ChannelModeStatus *>::iterator it = BotModes.begin(), it_end = BotModes.end(); it != it_end; ++it)
- c->SetMode(this, *it, this->nick, false);
c->JoinUser(this);
+ ChannelContainer *cc = this->FindChannel(c);
+ for (std::list<ChannelModeStatus *>::iterator it = BotModes.begin(), it_end = BotModes.end(); it != it_end; ++it)
+ {
+ if (!update_ts)
+ {
+ c->SetMode(this, *it, this->nick, false);
+ }
+ else
+ {
+ cc->Status->SetFlag((*it)->Name);
+ c->SetModeInternal(*it, this->nick, false);
+ }
+ }
+ if (!update_ts)
+ ircdproto->SendJoin(this, c->name, c->creation_time);
+ else
+ {
+ ircdproto->SendJoin(this, cc);
+
+ c->Reset();
+ }
FOREACH_MOD(I_OnBotJoin, OnBotJoin(c->ci, this));
}
-void BotInfo::Join(const Anope::string &chname)
+void BotInfo::Join(const Anope::string &chname, bool update_ts)
{
Channel *c = findchan(chname);
- return this->Join(c ? c : new Channel(chname));
+ return this->Join(c ? c : new Channel(chname), update_ts);
}
void BotInfo::Part(Channel *c, const Anope::string &reason)
diff --git a/src/channels.cpp b/src/channels.cpp
index a10a4e675..709d9cf01 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -75,6 +75,28 @@ Channel::~Channel()
ChannelList.erase(this->name);
}
+void Channel::Reset()
+{
+ this->ClearModes(NULL, false);
+ this->ClearBans(NULL, false);
+ this->ClearExcepts(NULL, false);
+ this->ClearInvites(NULL, false);
+
+ for (CUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
+ {
+ UserContainer *uc = *it;
+
+ if (findbot(uc->user->nick))
+ continue;
+
+ uc->Status->ClearFlags();
+ }
+
+ check_modes(this);
+ for (CUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
+ chan_set_correct_modes((*it)->user, this, 1);
+}
+
void Channel::Sync()
{
if (this->users.empty() || (this->users.size() == 1 && this->ci && this->ci->bi == this->users.front()->user))
@@ -84,7 +106,6 @@ void Channel::Sync()
if (this->ci)
{
check_modes(this);
- stick_all(this->ci);
}
if (Me && Me->IsSynced() && !this->topic_sync)
@@ -95,7 +116,7 @@ void Channel::JoinUser(User *user)
{
Alog(LOG_DEBUG) << user->nick << " joins " << this->name;
- Flags<ChannelModeName> *Status = new Flags<ChannelModeName>;
+ ChannelStatus *Status = new ChannelStatus();
ChannelContainer *cc = new ChannelContainer(this);
cc->Status = Status;
user->chans.push_back(cc);
@@ -104,6 +125,14 @@ void Channel::JoinUser(User *user)
uc->Status = Status;
this->users.push_back(uc);
+ bool update_ts = false;
+ if (this->ci && this->ci->HasFlag(CI_PERSIST) && this->creation_time > this->ci->time_registered)
+ {
+ Alog(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << this->ci->time_registered;
+ this->creation_time = this->ci->time_registered;
+ update_ts = true;
+ }
+
if (!get_ignore(user->nick))
{
if (this->ci && check_access(user, this->ci, CA_MEMO) && this->ci->memos.memos.size() > 0)
@@ -126,11 +155,9 @@ void Channel::JoinUser(User *user)
* and the ignored user doesnt just leave, the bot will never
* make it into the channel, leaving the channel botless even for
* legit users - Rob
- * But don't join the bot if the channel is persistant - Adam
- * But join persistant channels when syncing with our uplink- DP
**/
- if ((!Me->IsSynced() || !this->ci->HasFlag(CI_PERSIST)) && this->users.size() >= Config->BSMinUsers && !this->FindUser(this->ci->bi))
- this->ci->bi->Join(this);
+ if (this->users.size() >= Config->BSMinUsers && !this->FindUser(this->ci->bi))
+ this->ci->bi->Join(this, update_ts);
/* Only display the greet if the main uplink we're connected
* to has synced, or we'll get greet-floods when the net
* recovers from a netsplit. -GD
@@ -141,6 +168,16 @@ void Channel::JoinUser(User *user)
this->ci->bi->lastmsg = time(NULL);
}
}
+
+ if (update_ts)
+ {
+ /* Send the updated TS */
+ if (!this->ci->bi || !this->FindUser(this->ci->bi))
+ {
+ whosends(this->ci)->Join(this, update_ts);
+ whosends(this->ci)->Part(this);
+ }
+ }
}
/** Remove a user internally from the channel
@@ -296,7 +333,8 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string &param, bool
cc->Status->SetFlag(cm->Name);
/* Enforce secureops, etc */
- chan_set_correct_modes(u, this, 0);
+ if (EnforceMLock)
+ chan_set_correct_modes(u, this, 0);
return;
}
/* Setting b/e/I etc */
@@ -654,24 +692,31 @@ bool Channel::HasParam(ChannelModeName Name) const
/** Clear all the modes from the channel
* @param bi The client setting the modes
+ * @param internal Only remove the modes internally
*/
-void Channel::ClearModes(BotInfo *bi)
+void Channel::ClearModes(BotInfo *bi, bool internal)
{
- ChannelMode *cm;
-
for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n)
{
- cm = ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(n));
+ ChannelMode *cm = ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(n));
if (cm && this->HasMode(cm->Name))
{
if (cm->Type == MODE_REGULAR)
- this->RemoveMode(NULL, cm);
+ {
+ if (!internal)
+ this->RemoveMode(NULL, cm);
+ else
+ this->RemoveModeInternal(cm);
+ }
else if (cm->Type == MODE_PARAM)
{
Anope::string param;
this->GetParam(cm->Name, param);
- this->RemoveMode(NULL, cm, param);
+ if (!internal)
+ this->RemoveMode(NULL, cm, param);
+ else
+ this->RemoveModeInternal(cm, param);
}
}
}
@@ -681,58 +726,67 @@ void Channel::ClearModes(BotInfo *bi)
/** Clear all the bans from the channel
* @param bi The client setting the modes
+ * @param internal Only remove the modes internally
*/
-void Channel::ClearBans(BotInfo *bi)
+void Channel::ClearBans(BotInfo *bi, bool internal)
{
Entry *entry, *nexte;
- ChannelModeList *cml;
- cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN));
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN));
if (cml && this->bans && this->bans->count)
for (entry = this->bans->entries; entry; entry = nexte)
{
nexte = entry->next;
- this->RemoveMode(bi, CMODE_BAN, entry->mask);
+ if (!internal)
+ this->RemoveMode(bi, cml, entry->mask);
+ else
+ this->RemoveModeInternal(cml, entry->mask);
}
}
/** Clear all the excepts from the channel
* @param bi The client setting the modes
+ * @param internal Only remove the modes internally
*/
-void Channel::ClearExcepts(BotInfo *bi)
+void Channel::ClearExcepts(BotInfo *bi, bool internal)
{
Entry *entry, *nexte;
- ChannelModeList *cml;
- cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT));
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT));
if (cml && this->excepts && this->excepts->count)
for (entry = this->excepts->entries; entry; entry = nexte)
{
nexte = entry->next;
- this->RemoveMode(bi, CMODE_EXCEPT, entry->mask);
+ if (!internal)
+ this->RemoveMode(bi, cml, entry->mask);
+ else
+ this->RemoveModeInternal(cml, entry->mask);
}
}
/** Clear all the invites from the channel
* @param bi The client setting the modes
+ * @param internal Only remove the modes internally
*/
-void Channel::ClearInvites(BotInfo *bi)
+void Channel::ClearInvites(BotInfo *bi, bool internal)
{
Entry *entry, *nexte;
- ChannelModeList *cml;
- cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE));
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE));
if (cml && this->invites && this->invites->count)
for (entry = this->invites->entries; entry; entry = nexte)
{
nexte = entry->next;
- this->RemoveMode(bi, CMODE_INVITEOVERRIDE, entry->mask);
+ if (!internal)
+ this->RemoveMode(bi, cml, entry->mask);
+ else
+ this->RemoveModeInternal(cml, entry->mask);
}
}
@@ -922,24 +976,21 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
return true;
}
-/* Returns a fully featured binary modes string. If complete is 0, the
- * eventual parameters won't be added to the string.
- */
-
-Anope::string chan_get_modes(Channel *chan, int complete, int plus)
+Anope::string Channel::GetModes(bool complete, bool plus)
{
- Anope::string res, params, param;
+ Anope::string res;
- if (chan->HasModes())
+ if (this->HasModes())
{
- for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
+ Anope::string params;
+ for (std::map<Anope::string, Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
{
- if ((*it)->Class != MC_CHANNEL)
+ if (it->second->Class != MC_CHANNEL)
continue;
- ChannelMode *cm = debug_cast<ChannelMode *>(*it);
+ ChannelMode *cm = debug_cast<ChannelMode *>(it->second);
- if (chan->HasMode(cm->Name))
+ if (this->HasMode(cm->Name))
{
res += cm->ModeChar;
@@ -951,7 +1002,8 @@ Anope::string chan_get_modes(Channel *chan, int complete, int plus)
if (plus || !cmp->MinusNoArg)
{
- chan->GetParam(cmp->Name, param);
+ Anope::string param;
+ this->GetParam(cmp->Name, param);
if (!param.empty())
params += " " + param;
@@ -1056,7 +1108,6 @@ User *nc_on_chan(Channel *c, const NickCore *nc)
void do_join(const Anope::string &source, int ac, const char **av)
{
User *user;
- Channel *chan;
time_t ctime = time(NULL);
user = finduser(source);
@@ -1085,7 +1136,7 @@ void do_join(const Anope::string &source, int ac, const char **av)
continue;
}
- chan = findchan(buf);
+ Channel *chan = findchan(buf);
/* Channel doesn't exist, create it */
if (!chan)
@@ -1099,19 +1150,10 @@ void do_join(const Anope::string &source, int ac, const char **av)
/* Their time is older, we lose */
if (chan->creation_time > ts)
{
- Alog(LOG_DEBUG) << "recieved a new TS for JOIN: " << ts;
+ Alog(LOG_DEBUG) << "Recieved an older TS " << chan->name << " in JOIN, changing from " << chan->creation_time << " to " << ts;
+ chan->creation_time = ts;
- if (chan->ci)
- {
- /* Cycle the bot to fix ts */
- if (chan->ci->bi)
- {
- chan->ci->bi->Part(chan, "TS reop");
- chan->ci->bi->Join(chan);
- }
- /* Be sure to set mlock again, else we could be -r etc.. */
- check_modes(chan);
- }
+ chan->Reset();
}
}
diff --git a/src/chanserv.cpp b/src/chanserv.cpp
index 03760b9b6..c80de4c75 100644
--- a/src/chanserv.cpp
+++ b/src/chanserv.cpp
@@ -290,8 +290,6 @@ void check_modes(Channel *c)
/* If this channel does not have the mode and the mode is mlocked */
if (cm->Type == MODE_REGULAR && !c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true))
{
- c->SetMode(NULL, cm);
-
/* Add the eventual parameter and modify the Channel structure */
if (cm->Type == MODE_PARAM)
{
@@ -335,6 +333,8 @@ void check_modes(Channel *c)
c->RemoveMode(NULL, cm);
}
}
+
+ stick_all(ci);
}
/*************************************************************************/
diff --git a/src/init.cpp b/src/init.cpp
index 35407ec81..d3476a490 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -22,16 +22,16 @@ extern void moduleAddIRCDMsgs();
void introduce_user(const Anope::string &user)
{
/* Watch out for infinite loops... */
-#define LTSIZE 20
- static int lasttimes[LTSIZE];
- if (lasttimes[0] >= time(NULL) - 3)
- fatal("introduce_user() loop detected");
- memmove(lasttimes, lasttimes + 1, sizeof(lasttimes) - sizeof(int));
- lasttimes[LTSIZE - 1] = time(NULL);
-#undef LTSIZE
- /* We make the bots go online */
+ time_t now = time(NULL);
+ static time_t lasttime = now - 4;
+ if (lasttime >= now - 3)
+ fatal("introduce_user loop detected");
+ lasttime = now;
+
+ if (user.empty())
+ ircdproto->SendBOB();
- /* XXX: it might be nice to have this inside BotInfo's constructor, or something? */
+ /* We make the bots go online */
for (botinfo_map::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it)
{
BotInfo *bi = it->second;
@@ -41,8 +41,20 @@ void introduce_user(const Anope::string &user)
ircdproto->SendClientIntroduction(bi->nick, bi->GetIdent(), bi->host, bi->realname, ircd->pseudoclient_mode, bi->GetUID());
XLine x(bi->nick, "Reserved for services");
ircdproto->SendSQLine(&x);
+
+ for (UChannelList::const_iterator cit = bi->chans.begin(), cit_end = bi->chans.end(); cit != cit_end; ++cit)
+ {
+ ircdproto->SendJoin(bi, *cit);
+ }
}
}
+
+ if (user.empty())
+ {
+ /* Load MLock from the database now that we know what modes exist */
+ for (registered_channel_map::iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it)
+ it->second->LoadMLock();
+ }
}
/*************************************************************************/
@@ -66,16 +78,14 @@ static int set_group()
if (gr)
{
setgid(gr->gr_gid);
- return 0;
}
else
{
- Alog() << "Unknown group `" << RUNGROUP << "'";
+ Alog() << "Unknown run group '" << RUNGROUP << "'";
return -1;
}
-#else
- return 0;
#endif
+ return 0;
}
/*************************************************************************/
diff --git a/src/main.cpp b/src/main.cpp
index df7c61c63..bcb67b6fa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -553,15 +553,6 @@ int main(int ac, char **av, char **envp)
delete u;
}
- /* Nuke all channels */
- for (channel_map::const_iterator it = ChannelList.begin(); it != ChannelList.end();)
- {
- Channel *c = it->second;
- ++it;
-
- delete c;
- }
-
Me->SetFlag(SERVER_SYNCING);
Me->ClearLinks();
diff --git a/src/modes.cpp b/src/modes.cpp
index 624023e66..ce34e461c 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -13,7 +13,7 @@
std::list<std::pair<void *, StackerInfo *> > ModeManager::StackerObjects;
/* List of all modes Anope knows about */
-std::list<Mode *> ModeManager::Modes;
+std::map<Anope::string, Mode *> ModeManager::Modes;
/* User modes */
std::map<char, UserMode *> ModeManager::UserModesByChar;
@@ -91,6 +91,37 @@ void SetDefaultMLock(ServerConfig *config)
}
}
+Anope::string ChannelStatus::BuildCharPrefixList() const
+{
+ Anope::string ret;
+
+ for (std::map<char, ChannelMode *>::const_iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ {
+ if (this->HasFlag(it->second->Name))
+ {
+ ret += it->second->ModeChar;
+ }
+ }
+
+ return ret;
+}
+
+Anope::string ChannelStatus::BuildModePrefixList() const
+{
+ Anope::string ret;
+
+ for (std::map<char, ChannelMode *>::const_iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ {
+ if (this->HasFlag(it->second->Name))
+ {
+ ChannelModeStatus *cm = debug_cast<ChannelModeStatus *>(it->second);
+ ret += cm->Symbol;
+ }
+ }
+
+ return ret;
+}
+
/** Default constructor
* @param mClass The type of mode this is
* @param mNameAsString The mode name as a string
@@ -607,7 +638,7 @@ bool ModeManager::AddUserMode(UserMode *um)
Alog() << "ModeManager: Added generic support for user mode " << um->ModeChar;
}
ModeManager::UserModesByName.insert(std::make_pair(um->Name, um));
- ModeManager::Modes.push_back(um);
+ ModeManager::Modes.insert(std::make_pair(um->NameAsString, um));
FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um));
@@ -631,7 +662,7 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
Alog() << "ModeManager: Added generic support for channel mode " << cm->ModeChar;
}
ModeManager::ChannelModesByName.insert(std::make_pair(cm->Name, cm));
- ModeManager::Modes.push_back(cm);
+ ModeManager::Modes.insert(std::make_pair(cm->NameAsString, cm));
/* Apply this mode to the new default mlock if its used */
SetDefaultMLock(Config);
@@ -671,6 +702,20 @@ UserMode *ModeManager::FindUserModeByChar(char Mode)
return NULL;
}
+/** Find a mode by name
+ * @param name The mode name
+ * @return The mode
+ */
+Mode *ModeManager::FindModeByName(const Anope::string &name)
+{
+ std::map<Anope::string, Mode *>::const_iterator it = ModeManager::Modes.find(name);
+
+ if (it != ModeManager::Modes.end())
+ return it->second;
+
+ return NULL;
+}
+
/** Find a channel mode
* @param Mode The modename
* @return The mode class
diff --git a/src/protocol.cpp b/src/protocol.cpp
index d0cfef071..dfa7d2b3d 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -197,6 +197,11 @@ void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who
send_cmd(ircd->ts6 ? TS6SID : Config->ServerName, "PONG %s %s", servname.c_str(), who.c_str());
}
+void IRCDProto::SendJoin(BotInfo *bi, const ChannelContainer *cc)
+{
+ SendJoin(bi, cc->chan->name, cc->chan->creation_time);
+}
+
void IRCDProto::SendInvite(const BotInfo *bi, const Anope::string &chan, const Anope::string &nick)
{
send_cmd(ircd->ts6 ? bi->GetUID() : bi->nick, "INVITE %s %s", nick.c_str(), chan.c_str());
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index d055a632b..393054acf 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -343,65 +343,60 @@ void ChannelInfo::ClearBadWords()
*/
void ChannelInfo::LoadMLock()
{
- std::vector<Anope::string> modenames;
+ std::vector<Anope::string> modenames_on, modenames_off;
- if (this->GetExtRegular("db_mlock_modes_on", modenames))
+ // Force +r
+ this->SetMLock(CMODE_REGISTERED, true);
+ this->GetExtRegular("db_mlock_modes_on", modenames_on);
+ this->GetExtRegular("db_mlock_modes_off", modenames_off);
+
+ if (!modenames_on.empty() || !modenames_off.empty())
{
- for (std::vector<Anope::string>::iterator it = modenames.begin(), it_end = modenames.end(); it != it_end; ++it)
+ for (std::vector<Anope::string>::iterator it = modenames_on.begin(), it_end = modenames_on.end(); it != it_end; ++it)
{
- for (std::list<Mode *>::iterator mit = ModeManager::Modes.begin(), mit_end = ModeManager::Modes.end(); mit != mit_end; ++mit)
- {
- if ((*mit)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*mit);
+ Mode *m = ModeManager::FindModeByName(*it);
- if (cm->NameAsString.equals_ci(*it))
- this->SetMLock(cm->Name, true);
- }
+ if (m && m->NameAsString.equals_cs(*it))
+ {
+ ChannelMode *cm = debug_cast<ChannelMode *>(m);
+ this->SetMLock(cm->Name, true);
}
}
-
- this->Shrink("db_mlock_modes_on");
- }
-
- if (this->GetExtRegular("db_mlock_modes_off", modenames))
- {
- for (std::vector<Anope::string>::iterator it = modenames.begin(), it_end = modenames.end(); it != it_end; ++it)
+ for (std::vector<Anope::string>::iterator it = modenames_off.begin(), it_end = modenames_off.end(); it != it_end; ++it)
{
- for (std::list<Mode *>::iterator mit = ModeManager::Modes.begin(), mit_end = ModeManager::Modes.end(); mit != mit_end; ++mit)
- {
- if ((*mit)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*mit);
+ Mode *m = ModeManager::FindModeByName(*it);
- if (cm->NameAsString.equals_ci(*it))
- this->SetMLock(cm->Name, false);
- }
+ if (m && m->NameAsString.equals_cs(*it))
+ {
+ ChannelMode *cm = debug_cast<ChannelMode *>(m);
+ this->SetMLock(cm->Name, false);
}
}
-
- this->Shrink("db_mlock_modes_off");
}
std::vector<std::pair<Anope::string, Anope::string> > params;
-
if (this->GetExtRegular("db_mlp", params))
{
for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = params.begin(), it_end = params.end(); it != it_end; ++it)
{
- for (std::list<Mode *>::iterator mit = ModeManager::Modes.begin(), mit_end = ModeManager::Modes.end(); mit != mit_end; ++mit)
+ Mode *m = ModeManager::FindModeByName(it->first);
+ if (m && m->Class == MC_CHANNEL)
{
- if ((*mit)->Class == MC_CHANNEL)
- {
- ChannelMode *cm = debug_cast<ChannelMode *>(*mit);
-
- if (cm->NameAsString.equals_ci(it->first))
- this->SetMLock(cm->Name, true, it->second);
- }
+ ChannelMode *cm = debug_cast<ChannelMode *>(m);
+ this->SetMLock(cm->Name, true, it->second);
}
}
+ }
- this->Shrink("db_mlp");
+ /* Create perm channel */
+ if (this->HasFlag(CI_PERSIST) && !this->c)
+ {
+ this->c = new Channel(this->name, this->time_registered);
+ if (!this->bi)
+ ChanServ->Assign(NULL, this);
+ this->bi->Join(c);
+ check_modes(this->c);
+ restore_topic(this->name);
}
}
diff --git a/src/servers.cpp b/src/servers.cpp
index 7668cebbf..520cf5f36 100644
--- a/src/servers.cpp
+++ b/src/servers.cpp
@@ -413,14 +413,6 @@ void CapabParse(int ac, const char **av)
}
}
}
-
- /* Apply MLock now that we know what modes exist (capab is parsed after modes are added to Anope) */
- for (registered_channel_map::iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it)
- {
- ChannelInfo *ci = it->second;
-
- ci->LoadMLock();
- }
}
/*************************************************************************/