summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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();
- }
}
/*************************************************************************/