summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actions.c61
-rw-r--r--src/botserv.c99
-rw-r--r--src/channels.c882
-rw-r--r--src/chanserv.c240
-rw-r--r--src/core/cs_ban.c6
-rw-r--r--src/core/cs_clear.c151
-rw-r--r--src/core/cs_drop.c3
-rw-r--r--src/core/cs_modes.c14
-rw-r--r--src/core/cs_register.c6
-rw-r--r--src/core/cs_set.c6
-rw-r--r--src/core/ns_logout.c4
-rw-r--r--src/core/os_clearmodes.c100
-rw-r--r--src/core/os_defcon.c30
-rw-r--r--src/core/os_mode.c8
-rw-r--r--src/core/os_oline.c2
-rw-r--r--src/core/os_umode.c4
-rw-r--r--src/main.c3
-rw-r--r--src/modes.cpp610
-rw-r--r--src/modules/cs_enforce.c10
-rw-r--r--src/modules/cs_tban.c19
-rw-r--r--src/nickalias.cpp6
-rw-r--r--src/nickcore.cpp1
-rw-r--r--src/protocol.cpp10
-rw-r--r--src/protocol/bahamut.c66
-rw-r--r--src/protocol/inspircd11.c74
-rw-r--r--src/protocol/inspircd12.cpp85
-rw-r--r--src/protocol/ratbox.c46
-rw-r--r--src/protocol/unreal32.c118
-rw-r--r--src/regchannel.cpp2
-rw-r--r--src/users.c217
30 files changed, 1457 insertions, 1426 deletions
diff --git a/src/actions.c b/src/actions.c
index 9ed6b3b72..37bf95798 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -130,10 +130,7 @@ void sqline(char *mask, char *reason)
*/
void common_unban(ChannelInfo * ci, char *nick)
{
- const char *av[4];
char *host = NULL;
- char buf[BUFSIZE];
- int ac;
uint32 ip = 0;
User *u;
Entry *ban, *next;
@@ -163,63 +160,21 @@ void common_unban(ChannelInfo * ci, char *nick)
if (host)
ip = str_is_ip(host);
- if (ircd->svsmode_unban) {
+ if (ircd->svsmode_unban)
ircdproto->SendBanDel(ci->name, nick);
- } else {
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = ci->name;
- av[1] = buf;
- av[2] = "-b";
- ac = 4;
- } else {
- av[0] = ci->name;
- av[1] = "-b";
- ac = 3;
- }
-
- for (ban = ci->c->bans->entries; ban; ban = next) {
+ else
+ {
+ for (ban = ci->c->bans->entries; ban; ban = next)
+ {
next = ban->next;
if (entry_match(ban, u->nick, u->GetIdent().c_str(), u->host, ip) ||
- entry_match(ban, u->nick, u->GetIdent().c_str(), u->GetDisplayedHost().c_str(), ip)) {
- ircdproto->SendMode(whosends(ci), ci->name, "-b %s", ban->mask);
- if (ircdcap->tsmode)
- av[3] = ban->mask;
- else
- av[2] = ban->mask;
-
- do_cmode(whosends(ci)->nick, ac, av);
- }
+ entry_match(ban, u->nick, u->GetIdent().c_str(), u->GetDisplayedHost().c_str(), ip))
+ ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask);
}
}
/* host_resolve() sstrdup us this info so we gotta free it */
- if (host) {
+ if (host)
delete [] host;
- }
-}
-
-/*************************************************************************/
-
-/**
- * Prepare to set SVSMODE and update internal user modes
- * @param u user to apply modes to
- * @param modes the modes to set on the user
- * @param arg the arguments for the user modes
- * @return void
- */
-void common_svsmode(User * u, const char *modes, const char *arg)
-{
- int ac = 1;
- const char *av[2];
-
- av[0] = modes;
- if (arg) {
- av[1] = arg;
- ac++;
- }
-
- ircdproto->SendSVSMode(u, ac, av);
- ircdproto->ProcessUsermodes(u, ac, av);
}
/*************************************************************************/
diff --git a/src/botserv.c b/src/botserv.c
index cbd3ccfc2..ab20b0852 100644
--- a/src/botserv.c
+++ b/src/botserv.c
@@ -736,38 +736,20 @@ void bot_join(ChannelInfo * ci)
if (!ci || !ci->c || !ci->bi)
return;
- if (Config.BSSmartJoin) {
+ if (Config.BSSmartJoin)
+ {
/* We check for bans */
- if (ci->c->bans && ci->c->bans->count) {
- char buf[BUFSIZE];
- const char *av[4];
+ if (ci->c->bans && ci->c->bans->count)
+ {
Entry *ban, *next;
- int ac;
-
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = ci->c->name;
- av[1] = buf;
- av[2] = "-b";
- ac = 4;
- } else {
- av[0] = ci->c->name;
- av[1] = "-b";
- ac = 3;
- }
- for (ban = ci->c->bans->entries; ban; ban = next) {
+ for (ban = ci->c->bans->entries; ban; ban = next)
+ {
next = ban->next;
- if (entry_match
- (ban, ci->bi->nick, ci->bi->user, ci->bi->host, 0)) {
- ircdproto->SendMode(whosends(ci), ci->name, "-b %s",
- ban->mask);
- if (ircdcap->tsmode)
- av[3] = ban->mask;
- else
- av[2] = ban->mask;
- do_cmode(whosends(ci)->nick, ac, av);
+ if (entry_match(ban, ci->bi->nick, ci->bi->user, ci->bi->host, 0))
+ {
+ ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask);
}
}
}
@@ -787,7 +769,8 @@ void bot_join(ChannelInfo * ci)
ci->bi->nick, ci->bi->nick);
}
ircdproto->SendJoin(ci->bi, ci->c->name, ci->c->creation_time);
- ircdproto->SendBotOp(ci->bi->nick, ci->c->name);
+ ci->c->SetMode(NULL, CMODE_PROTECT, ci->bi->nick);
+ ci->c->SetMode(NULL, CMODE_OP, ci->bi->nick);
FOREACH_MOD(I_OnBotJoin, OnBotJoin(ci, ci->bi));
}
@@ -809,31 +792,14 @@ static void check_ban(ChannelInfo * ci, User * u, int ttbtype)
/* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype]
* if the TTB was changed after it was not set (0) before and the user had already been
* kicked a few times. Bug #1056 - Adam */
- const char *av[4];
- int ac;
char mask[BUFSIZE];
- char buf[BUFSIZE];
bd->ttb[ttbtype] = 0;
get_idealban(ci, u, mask, sizeof(mask));
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = ci->name;
- av[1] = buf;
- av[2] = "+b";
- av[3] = mask;
- ac = 4;
- } else {
- av[0] = ci->name;
- av[1] = "+b";
- av[2] = mask;
- ac = 3;
- }
-
- ircdproto->SendMode(ci->bi, ci->name, "+b %s", mask);
- do_cmode(ci->bi->nick, ac, av);
+ if (ci->c)
+ ci->c->SetMode(NULL, CMODE_BAN, mask);
FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask));
}
}
@@ -874,11 +840,8 @@ static void bot_kick(ChannelInfo * ci, User * u, int message, ...)
void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick,
const char *reason)
{
- int ac;
- const char *av[4];
const char *kav[4]; // seperate as not everything is constified XXX -- w00t
char mask[BUFSIZE];
- char buf[BUFSIZE];
User *u = finduser(nick);
if (!u)
@@ -907,22 +870,7 @@ void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick,
get_idealban(ci, u, mask, sizeof(mask));
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = ci->name;
- av[1] = buf;
- av[2] = "+b";
- av[3] = mask;
- ac = 4;
- } else {
- av[0] = ci->name;
- av[1] = "+b";
- av[2] = mask;
- ac = 3;
- }
-
- ircdproto->SendMode(ci->bi, ci->name, "+b %s", mask);
- do_cmode(ci->bi->nick, ac, av);
+ ci->c->SetMode(NULL, CMODE_BAN, mask);
kav[0] = ci->name;
kav[1] = nick;
@@ -998,8 +946,6 @@ void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick,
void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode,
char *nick)
{
- const char *av[4];
- int ac;
char buf[BUFSIZE];
User *u;
@@ -1024,22 +970,7 @@ void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode,
&& (get_access(u, ci) >= get_access(requester, ci)))
return;
- if (ircdcap->tsmode) {
- av[0] = ci->name;
- av[1] = buf;
- av[2] = mode;
- av[3] = nick;
- ac = 4;
- ircdproto->SendMode(ci->bi, av[0], "%s %s", av[2], av[3]);
- } else {
- av[0] = ci->name;
- av[1] = mode;
- av[2] = nick;
- ac = 3;
- ircdproto->SendMode(ci->bi, av[0], "%s %s", av[1], av[2]);
- }
-
- do_cmode(ci->bi->nick, ac, av);
+ ci->c->SetModes(NULL, "%s %s", mode, nick);
}
/*************************************************************************/
diff --git a/src/channels.c b/src/channels.c
index b9d276a49..2115d2658 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -133,58 +133,189 @@ bool Channel::HasMode(ChannelModeName Name)
return modes[Name];
}
-/**
- * Set a mode on a channel
- * @param Name The mode name
+/** Set a mode internally on a channel, this is not sent out to the IRCd
+ * @param cm The mode
+ * @param param The param
+ * @param EnforeMLock true if mlocks should be enforced, false to override mlock
*/
-void Channel::SetMode(ChannelModeName Name, const std::string param)
+void Channel::SetModeInternal(ChannelMode *cm, const std::string &param, bool EnforceMLock)
{
- modes[Name] = true;
+ if (!cm)
+ return;
+
+ /* Setting v/h/o/a/q etc */
+ if (cm->Type == MODE_STATUS)
+ {
+ if (param.empty())
+ {
+ alog("Channel::SetModeInternal() mode %c with no parameter for channel %s", cm->ModeChar, this->name);
+ return;
+ }
+
+ /* We don't track bots */
+ if (findbot(param.c_str()))
+ return;
+
+ User *u = finduser(param.c_str());
+ if (!u)
+ {
+ if (debug)
+ alog("debug: MODE %s +%c for nonexistant user %s", this->name, cm->ModeChar, param.c_str());
+ return;
+ }
+
+ if (debug)
+ alog("debug: Setting +%c on %s for %s", cm->ModeChar, this->name, u->nick);
+
+ ChannelModeStatus *cms = static_cast<ChannelModeStatus *>(cm);
+ /* Set the new status on the user */
+ chan_set_user_status(this, u, cms->Status);
+ /* Enforce secureops, etc */
+ chan_set_correct_modes(u, this, 0);
+ return;
+ }
+ /* Setting b/e/I etc */
+ else if (cm->Type == MODE_LIST)
+ {
+ if (param.empty())
+ {
+ alog("Channel::SetModeInternal() mode %c with no parameter for channel %s", cm->ModeChar, this->name);
+ return;
+ }
+
+ ChannelModeList *cml = static_cast<ChannelModeList *>(cm);
+ cml->AddMask(this, param.c_str());
+ return;
+ }
+
+ modes[cm->Name] = true;
/* Channel mode +P or so was set, mark this channel as persistant */
- if (Name == CMODE_PERM && ci)
+ if (cm->Name == CMODE_PERM && ci)
{
ci->SetFlag(CI_PERSIST);
}
if (!param.empty())
{
+ if (cm->Type != MODE_PARAM)
+ {
+ alog("Channel::SetModeInternal() mode %c for %s with a paramater, but its not a param mode", cm->ModeChar, this->name);
+ return;
+ }
+
/* They could be resetting the mode to change its params */
- std::map<ChannelModeName, std::string>::iterator it = Params.find(Name);
+ std::map<ChannelModeName, std::string>::iterator it = Params.find(cm->Name);
if (it != Params.end())
{
Params.erase(it);
}
- Params.insert(std::make_pair(Name, param));
+ Params.insert(std::make_pair(cm->Name, param));
}
- FOREACH_MOD(I_OnChannelModeSet, OnChannelModeSet(this, Name));
-}
+ FOREACH_MOD(I_OnChannelModeSet, OnChannelModeSet(this, cm->Name));
-/**
- * Set a mode on a channel
- * @param Mode The mode
- */
-void Channel::SetMode(char Mode, const std::string param)
-{
- ChannelMode *cm;
+ /* Check for mlock */
+
+ /* Non registered channel, no mlock */
+ if (!ci || !EnforceMLock)
+ return;
- if ((cm = ModeManager::FindChannelModeByChar(Mode)))
+ /* If this channel has this mode locked negative */
+ if (ci->HasMLock(cm->Name, false))
{
- SetMode(cm->Name, param);
+ /* Remove the mode */
+ if (cm->Type == MODE_PARAM)
+ {
+ ChannelModeParam *cmp = static_cast<ChannelModeParam *>(cmp);
+
+ if (!cmp->MinusNoArg)
+ {
+ /* Get the current param set on the channel and send it with the mode */
+ std::string cparam;
+ if (GetParam(cmp->Name, &cparam))
+ RemoveMode(NULL, cm, cparam);
+ }
+ else
+ RemoveMode(NULL, cm);
+ }
+ else if (cm->Type == MODE_REGULAR)
+ RemoveMode(NULL, cm);
+ }
+ /* If this is a param mode and its mlocked +, check to ensure someone didn't reset it with the wrong param */
+ else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true))
+ {
+ ChannelModeParam *cmp = static_cast<ChannelModeParam *>(cm);
+ std::string cparam, ciparam;
+ /* Get the param currently set on this channel */
+ GetParam(cmp->Name, &cparam);
+ /* Get the param set in mlock */
+ ci->GetParam(cmp->Name, &ciparam);
+
+ /* We have the wrong param set */
+ if (cparam.empty() || ciparam.empty() || cparam != ciparam)
+ {
+ /* Reset the mode with the correct param */
+ SetMode(NULL, cm, ciparam);
+ }
}
}
-/**
- * Remove a mode from a channel
- * @param Name The mode name
+/** Remove a mode internally on a channel, this is not sent out to the IRCd
+ * @param cm The mode
+ * @param param The param
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
*/
-void Channel::RemoveMode(ChannelModeName Name)
+void Channel::RemoveModeInternal(ChannelMode *cm, const std::string &param, bool EnforceMLock)
{
- modes[Name] = false;
+ if (!cm)
+ return;
- if (Name == CMODE_PERM && ci)
+ /* Setting v/h/o/a/q etc */
+ if (cm->Type == MODE_STATUS)
+ {
+ if (param.empty())
+ {
+ alog("Channel::RemoveModeInternal() mode %c with no parameter for channel %s", cm->ModeChar, this->name);
+ return;
+ }
+
+ /* We don't track bots */
+ if (findbot(param.c_str()))
+ return;
+
+ User *u = finduser(param.c_str());
+ if (!u)
+ {
+ alog("Channel::RemoveModeInternal() MODE %s +%c for nonexistant user %s", this->name, cm->ModeChar, param.c_str());
+ return;
+ }
+
+ if (debug)
+ alog("debug: Setting +%c on %s for %s", cm->ModeChar, this->name, u->nick);
+
+ ChannelModeStatus *cms = static_cast<ChannelModeStatus *>(cm);
+ chan_remove_user_status(this, u, cms->Status);
+ return;
+ }
+ /* Setting b/e/I etc */
+ else if (cm->Type == MODE_LIST)
+ {
+ if (param.empty())
+ {
+ alog("Channel::SetModeInternal() mode %c with no parameter for channel %s", cm->ModeChar, this->name);
+ return;
+ }
+
+ ChannelModeList *cml = static_cast<ChannelModeList *>(cm);
+ cml->DelMask(this, param.c_str());
+ return;
+ }
+
+ modes[cm->Name] = false;
+
+ if (cm->Name == CMODE_PERM && ci)
{
ci->UnsetFlag(CI_PERSIST);
if (Config.s_BotServ && ci->bi && usercount == Config.BSMinUsers - 1)
@@ -193,27 +324,118 @@ void Channel::RemoveMode(ChannelModeName Name)
delete this;
}
- std::map<ChannelModeName, std::string>::iterator it = Params.find(Name);
- if (it != Params.end())
+ if (cm->Type == MODE_PARAM)
{
- Params.erase(it);
+ std::map<ChannelModeName, std::string>::iterator it = Params.find(cm->Name);
+ if (it != Params.end())
+ {
+ Params.erase(it);
+ }
}
- FOREACH_MOD(I_OnChannelModeUnset, OnChannelModeUnset(this, Name));
+ FOREACH_MOD(I_OnChannelModeUnset, OnChannelModeUnset(this, cm->Name));
+
+ /* Check for mlock */
+
+ /* Non registered channel, no mlock */
+ if (!ci || !EnforceMLock)
+ return;
+
+ /* This channel has this the mode locked on */
+ if (ci->HasMLock(cm->Name, true))
+ {
+ if (cm->Type == MODE_REGULAR)
+ {
+ /* Set the mode */
+ SetMode(NULL, cm);
+ }
+ /* This is a param mode */
+ else if (cm->Type == MODE_PARAM)
+ {
+ std::string cparam;
+ /* Get the param stored in mlock for this mode */
+ if (ci->GetParam(cm->Name, &cparam))
+ SetMode(NULL, cm, cparam);
+ }
+ }
+}
+
+/** Set a mode on a channel
+ * @param bi The client setting the modes
+ * @param cm The mode
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
+ */
+void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const std::string &param, bool EnforceMLock)
+{
+ if (!cm)
+ return;
+
+ ModeManager::StackerAdd(bi, this, cm, true, param);
+ SetModeInternal(cm, param, EnforceMLock);
}
/**
- * Remove a mode from a channel
+ * Set a mode on a channel
+ * @param bi The client setting the modes
+ * @param Name The mode name
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
+ */
+void Channel::SetMode(BotInfo *bi, ChannelModeName Name, const std::string &param, bool EnforceMLock)
+{
+ SetMode(bi, ModeManager::FindChannelModeByName(Name), param, EnforceMLock);
+}
+
+/**
+ * Set a mode on a channel
+ * @param bi The client setting the modes
* @param Mode The mode
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
*/
-void Channel::RemoveMode(char Mode)
+void Channel::SetMode(BotInfo *bi, char Mode, const std::string &param, bool EnforceMLock)
{
- ChannelMode *cm;
+ SetMode(bi, ModeManager::FindChannelModeByChar(Mode), param, EnforceMLock);
+}
- if ((cm = ModeManager::FindChannelModeByChar(Mode)))
- {
- RemoveMode(cm->Name);
- }
+/** Remove a mode from a channel
+ * @param bi The client setting the modes
+ * @param cm The mode
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
+ */
+void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const std::string &param, bool EnforceMLock)
+{
+ if (!cm)
+ return;
+
+ ModeManager::StackerAdd(bi, this, cm, false, param);
+ RemoveModeInternal(cm, param, EnforceMLock);
+}
+
+/**
+ * Remove a mode from a channel
+ * @param bi The client setting the modes
+ * @param Name The mode name
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
+ */
+void Channel::RemoveMode(BotInfo *bi, ChannelModeName Name, const std::string &param, bool EnforceMLock)
+{
+ RemoveMode(bi, ModeManager::FindChannelModeByName(Name), param, EnforceMLock);
+}
+
+/**
+ * Remove a mode from a channel
+ * @param bi The client setting the modes
+ * @param Mode The mode
+ * @param param Optional param arg for the mode
+ * @param EnforceMLock true if mlocks should be enforced, false to override mlock
+ */
+void Channel::RemoveMode(BotInfo *bi, char Mode, const std::string &param, bool EnforceMLock)
+{
+ RemoveMode(bi, ModeManager::FindChannelModeByChar(Mode), param, EnforceMLock);
}
/** Get a param from the channel
@@ -254,15 +476,12 @@ const bool Channel::HasParam(ChannelModeName Name)
/*************************************************************************/
/** Clear all the modes from the channel
- * @param client The client unsetting the modes
+ * @param bi The client setting the modes
*/
-void Channel::ClearModes(char *client)
+void Channel::ClearModes(BotInfo *bi)
{
ChannelMode *cm;
ChannelModeParam *cmp;
- std::string buf, buf2;
- const char *argv[2];
- BotInfo *sender = (client ? findbot(client) : whosends(ci));
for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n)
{
@@ -272,41 +491,21 @@ void Channel::ClearModes(char *client)
{
if (cm->Type == MODE_REGULAR)
{
- buf = '-';
- buf += cm->ModeChar;
-
- argv[0] = buf.c_str();
-
- ircdproto->SendMode(sender, this->name, "-%c", cm->ModeChar);
- chan_set_modes(sender->nick, this, 1, argv, 0);
+ this->RemoveMode(NULL, cm);
}
else if (cm->Type == MODE_PARAM)
{
cmp = static_cast<ChannelModeParam *>(cm);
- buf = '-';
- buf += cmp->ModeChar;
- buf2.clear();
-
if (!cmp->MinusNoArg)
{
- buf2 = this->GetParam(cmp->Name, &buf2);
- }
-
- argv[0] = buf.c_str();
- if (!buf2.empty())
- {
- argv[1] = buf2.c_str();
-
- ircdproto->SendMode(sender, this->name, "-%c %s", cm->ModeChar, buf2.c_str());
- chan_set_modes(sender->nick, this, 2, argv, 0);
+ std::string buf;
+ if (this->GetParam(cmp->Name, &buf))
+ this->RemoveMode(NULL, cm, buf);
}
else
{
- argv[1] = NULL;
-
- ircdproto->SendMode(sender, this->name, "-%c", cm->ModeChar);
- chan_set_modes(sender->nick, this, 1, argv, 0);
+ this->RemoveMode(NULL, cm);
}
}
}
@@ -316,100 +515,195 @@ void Channel::ClearModes(char *client)
}
/** Clear all the bans from the channel
- * @param client The client unsetting the modes
+ * @param bi The client setting the modes
*/
-void Channel::ClearBans(char *client)
+void Channel::ClearBans(BotInfo *bi)
{
Entry *entry, *nexte;
- BotInfo *sender = (client ? findbot(client) : whosends(ci));
ChannelModeList *cml;
- std::string buf;
- const char *argv[2];
cml = static_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN));
if (cml && this->bans && this->bans->count)
{
- buf = '-';
- buf += cml->ModeChar;
-
for (entry = this->bans->entries; entry; entry = nexte)
{
nexte = entry->next;
- argv[0] = buf.c_str();
- argv[1] = sstrdup(entry->mask);
- ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask);
- chan_set_modes(sender->nick, this, 2, argv, 0);
- delete [] argv[1];
+ this->RemoveMode(bi, CMODE_BAN, entry->mask);
}
}
}
/** Clear all the excepts from the channel
- * @param client The client unsetting the modes
+ * @param bi The client setting the modes
*/
-void Channel::ClearExcepts(char *client)
+void Channel::ClearExcepts(BotInfo *bi)
{
Entry *entry, *nexte;
- BotInfo *sender = (client ? findbot(client) : whosends(ci));
ChannelModeList *cml;
- std::string buf;
- const char *argv[2];
cml = static_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT));
if (cml && this->excepts && this->excepts->count)
{
- buf = '+';
- buf += cml->ModeChar;
-
for (entry = this->excepts->entries; entry; entry = nexte)
{
nexte = entry->next;
- argv[0] = buf.c_str();
- argv[1] = sstrdup(entry->mask);
- ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask);
- chan_set_modes(sender->nick, this, 2, argv, 0);
- delete [] argv[1];
+ this->RemoveMode(bi, CMODE_EXCEPT, entry->mask);
}
}
}
/** Clear all the invites from the channel
- * @param client The client unsetting the modes
+ * @param bi The client setting the modes
*/
-void Channel::ClearInvites(char *client)
+void Channel::ClearInvites(BotInfo *bi)
{
Entry *entry, *nexte;
- BotInfo *sender = (client ? findbot(client) : whosends(ci));
ChannelModeList *cml;
- std::string buf;
- const char *argv[2];
cml = static_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE));
if (cml && this->invites && this->invites->count)
{
- buf = '-';
- buf += cml->ModeChar;
-
for (entry = this->invites->entries; entry; entry = nexte)
{
nexte = entry->next;
- argv[0] = buf.c_str();
- argv[1] = sstrdup(entry->mask);
- ircdproto->SendMode(sender, this->name, "%s %s", buf.c_str(), entry->mask);
- chan_set_modes(sender->nick, this, 2, argv, 0);
- delete [] argv[1];
+ this->RemoveMode(bi, CMODE_INVITEOVERRIDE, entry->mask);
+ }
+ }
+}
+
+/** Set a string of modes on the channel
+ * @param bi The client setting the modes
+ * @param EnforceMLock Should mlock be enforced on this mode change
+ * @param cmodes The modes to set
+ */
+void Channel::SetModes(BotInfo *bi, bool EnforceMLock, const std::string &cmodes, ...)
+{
+ char buf[BUFSIZE] = "";
+ va_list args;
+ std::string modebuf, sbuf;
+ int add = -1;
+ va_start(args, cmodes.c_str());
+ vsnprintf(buf, BUFSIZE - 1, cmodes.c_str(), args);
+ va_end(args);
+
+ spacesepstream sep(buf);
+ sep.GetToken(modebuf);
+ for (unsigned i = 0; i < modebuf.size(); ++i)
+ {
+ ChannelMode *cm;
+
+ switch (modebuf[i])
+ {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add == -1)
+ continue;
+ cm = ModeManager::FindChannelModeByChar(modebuf[i]);
+ if (!cm)
+ continue;
+ }
+
+ if (add)
+ {
+ if (cm->Type == MODE_PARAM && sep.GetToken(sbuf))
+ this->SetMode(bi, cm, sbuf, EnforceMLock);
+ else
+ this->SetMode(bi, cm, "", EnforceMLock);
+ }
+ else if (add == 0)
+ {
+ if (cm->Type == MODE_PARAM && sep.GetToken(sbuf))
+ this->RemoveMode(bi, cm, sbuf, EnforceMLock);
+ else
+ this->RemoveMode(bi, cm, "", EnforceMLock);
}
}
}
/*************************************************************************/
+/** Set modes internally on the channel
+ * @param c The channel
+ * @param ac Number of args
+ * @param av args
+ */
+void ChanSetInternalModes(Channel *c, int ac, const char **av)
+{
+ if (!ac)
+ return;
+
+ int k = 0, j = 0, add = -1;
+ for (unsigned int i = 0; i < strlen(av[0]); ++i)
+ {
+ ChannelMode *cm;
+
+ switch (av[0][i])
+ {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add == -1)
+ continue;
+ cm = ModeManager::FindChannelModeByChar(av[0][i]);
+ if (!cm)
+ continue;
+ }
+
+ if (cm->Type == MODE_REGULAR)
+ {
+ if (add)
+ c->SetModeInternal(cm);
+ else
+ c->RemoveModeInternal(cm);
+ continue;
+ }
+ else if (cm->Type == MODE_PARAM)
+ {
+ ChannelModeParam *cmp = static_cast<ChannelModeParam *>(cm);
+
+ if (!add && cmp->MinusNoArg)
+ {
+ c->RemoveModeInternal(cm);
+ ++k;
+ continue;
+ }
+ }
+ if (++j < ac)
+ {
+ if (add)
+ c->SetModeInternal(cm, av[j]);
+ else
+ c->RemoveModeInternal(cm, av[j]);
+ }
+ else
+ {
+ alog("warning: ChanSetInternalModes() recieved more modes requiring params than params, modes: %s, ac: %d, j: %d", merge_args(ac, av), ac, j);
+ }
+ }
+
+ if (j + k + 1 < ac)
+ {
+ alog("warning: ChanSetInternalModes() recieved more params than modes requiring them, modes: %s, ac: %d, j: %d k: %d", merge_args(ac, av), ac, j, k);
+ }
+}
+
+/*************************************************************************/
+
void chan_deluser(User * user, Channel * c)
{
struct c_userlist *u;
@@ -563,204 +857,12 @@ void chan_remove_user_status(Channel * chan, User * user, int16 status)
/*************************************************************************/
-void chan_set_modes(const char *source, Channel *chan, int ac, const char **av, int check)
-{
- int add = 1, i, real_ac = ac;
- ChannelMode *cm;
- ChannelModeStatus *cms;
- ChannelModeList *cml;
- ChannelModeParam *cmp;
- const char *modes, **real_av = av;
- char mode;
- BotInfo *bi;
- unsigned char botmode = 0;
- User *user;
-
- modes = av[0];
-
- if (debug)
- alog("debug: Changing modes for %s to %s", chan->name, merge_args(ac, av));
-
- ac--;
-
- while ((mode = *modes++))
- {
- switch (mode)
- {
- case '+':
- add = 1;
- continue;
- case '-':
- add = 0;
- continue;
- }
-
- if ((cm = ModeManager::FindChannelModeByChar(mode)))
- {
- /* v/h/o/a/q etc */
- if (cm->Type == MODE_STATUS)
- {
- cms = static_cast<ChannelModeStatus *>(cm);
-
- if (ac == 0)
- {
- alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
- continue;
- }
-
- ac--;
- av++;
-
- if (cms->ProtectBotServ && !add)
- {
- if ((bi = findbot(*av)))
- {
- if (!botmode || botmode != mode)
- {
- ircdproto->SendMode(bi, chan->name, "+%c %s", mode, bi->nick);
- botmode = mode;
- continue;
- }
- else
- {
- botmode = mode;
- continue;
- }
- }
- }
- else if ((bi = findbot(*av)))
- continue;
-
- if (!(user = finduser(*av)) && !(ircd->ts6 && (user = find_byuid(*av))))
- {
- if (debug)
- {
- alog("debug: MODE %s %c%c for nonexistent user %s",
- chan->name, (add ? '+' : '-'), mode, *av);
- }
- continue;
- }
-
- if (debug)
- alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'),
- mode, chan->name, user->nick);
-
- if (add)
- chan_set_user_status(chan, user, cms->Status);
- /* If this does +o, remove any DEOPPED flag */
- else
- chan_remove_user_status(chan, user, cms->Status);
- }
- /* b/e/I etc */
- else if (cm->Type == MODE_LIST)
- {
- cml = static_cast<ChannelModeList *>(cm);
-
- if (ac == 0)
- {
- alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
- continue;
- }
-
- ac--;
- av++;
-
- if (add)
- cml->AddMask(chan, *av);
- else
- cml->DelMask(chan, *av);
- }
- else
- {
- if (cm->Type == MODE_PARAM)
- {
- cmp = static_cast<ChannelModeParam *>(cm);
-
- if (add || !cmp->MinusNoArg)
- {
- if (ac == 0)
- {
- alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
- continue;
- }
-
- ac--;
- av++;
- }
-
- if (!cmp->IsValid(*av))
- continue;
- if (add)
- {
- std::string Param = *av;
- chan->SetMode(mode, Param);
- }
- else
- {
- chan->RemoveMode(mode);
- }
- }
- else
- {
- if (add)
- chan->SetMode(mode);
- else
- chan->RemoveMode(mode);
- }
- }
- }
- }
-
- // Don't bounce modes from u:lined clients or servers, bug #1004
- user = finduser(source);
- if ((user && is_ulined(user->server->name)) || is_ulined(source))
- return;
-
- if (check > 0)
- {
- check_modes(chan);
-
- if ((check < 2) || (check == 3))
- {
- /* Walk through all users we've set modes for and see if they are
- * valid. Invalid modes (like +o with SECUREOPS on) will be removed
- */
- real_ac--;
- real_av++;
-
- for (i = 0; i < real_ac; i++)
- {
- if ((user = finduser(*real_av)) && is_on_chan(chan, user))
- {
- if (check < 2)
- chan_set_correct_modes(user, chan, 0);
- else if (chan->ci->HasFlag(CI_SECUREOPS))
- {
- /* Fixing bug #1006 oringinally caused by fixing #922
- * we must check for secureops here, not in chan_set_correct_modes
- * because chan_set_corret_modes will also check for usercount == 1
- * where it will deop the user, this way we know the channel was not
- * just created. (check == 3 from /cs (half)op) - Adam
- */
- chan_set_correct_modes(user, chan, 0);
- }
- }
-
- real_av++;
- }
- }
- }
-}
-
-/*************************************************************************/
-
/* Set the status of an user on a channel */
void chan_set_user_status(Channel * chan, User * user, int16 status)
{
struct u_chanlist *uc;
UserMode *um;
- char av[3];
if (debug >= 2)
alog("debug: setting user status (%d) on %s for %s", status,
@@ -774,9 +876,7 @@ void chan_set_user_status(Channel * chan, User * user, int16 status)
user->nick, status, chan->name);
}
- snprintf(av, sizeof(av), "+%c", um->ModeChar);
-
- common_svsmode(user, av, NULL);
+ user->SetMode(um);
}
for (uc = user->chans; uc; uc = uc->next) {
@@ -1210,11 +1310,8 @@ void do_sjoin(const char *source, int ac, const char **av)
else if (c->creation_time > ts) {
c->creation_time = ts;
for (cu = c->users; cu; cu = cu->next) {
- /* XXX */
- modes[0] = "-ov";
- modes[1] = cu->user->nick;
- modes[2] = cu->user->nick;
- chan_set_modes(source, c, 3, modes, 2);
+ c->RemoveMode(NULL, CMODE_OP, cu->user->nick);
+ c->RemoveMode(NULL, CMODE_VOICE, cu->user->nick);
}
if (c->ci)
{
@@ -1227,8 +1324,7 @@ void do_sjoin(const char *source, int ac, const char **av)
/* Make sure +r is set */
if (ModeManager::FindChannelModeByName(CMODE_REGISTERED))
{
- c->SetMode(CMODE_REGISTERED);
- ircdproto->SendMode(whosends(c->ci), c->name, "+r");
+ c->SetMode(NULL, CMODE_REGISTERED);
}
}
/* XXX simple modes and bans */
@@ -1348,8 +1444,8 @@ void do_sjoin(const char *source, int ac, const char **av)
for (i = 1; i < end2 - cubuf; i++)
modes[i] = user->nick;
- chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
- modes, 2);
+
+ ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes);
}
if (c->ci && (!serv || is_sync(serv))
@@ -1368,7 +1464,7 @@ void do_sjoin(const char *source, int ac, const char **av)
if (c && keep_their_modes) {
/* We now update the channel mode. */
- chan_set_modes(source, c, ac - 3, &av[2], 2);
+ ChanSetInternalModes(c, ac - 3, &av[2]);
}
/* Unreal just had to be different */
@@ -1434,8 +1530,7 @@ void do_sjoin(const char *source, int ac, const char **av)
for (i = 1; i < end2 - cubuf; i++)
modes[i] = user->nick;
- chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
- modes, 2);
+ ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes);
}
chan_set_correct_modes(user, c, 1);
@@ -1510,8 +1605,7 @@ void do_sjoin(const char *source, int ac, const char **av)
for (i = 1; i < end2 - cubuf; i++)
modes[i] = user->nick;
- chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
- modes, 2);
+ ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes);
}
chan_set_correct_modes(user, c, 1);
@@ -1564,79 +1658,76 @@ void do_sjoin(const char *source, int ac, const char **av)
}
}
-
/*************************************************************************/
-/* Handle a channel MODE command. */
-
-/*
- * av[0]: channel
- * av[1]: (tsmode) channel TS (this should be moved to a protocol module)
- * av[2-]: (tsmode) modes and parameters
- *
- * av[1-]: modes and parameters.
- *
+/** Process a MODE command from the server, and set the modes on the user/channel
+ * it was sent for
+ * @param source The source of the command
+ * @param ac Number of args in array..
+ * @param av Array of args
*/
void do_cmode(const char *source, int ac, const char **av)
{
- Channel *chan;
- ChannelInfo *ci = NULL;
+ Channel *c;
+ ChannelInfo *ci;
unsigned int i;
const char *t;
- if (ircdcap->tsmode) {
- /* TSMODE for bahamut - leave this code out to break MODEs. -GD */
- /* if they don't send it in CAPAB check if we just want to enable it */
- if (uplink_capab & ircdcap->tsmode || UseTSMODE) {
- for (i = 0; i < strlen(av[1]); i++) {
+ if (ircdcap->tsmode)
+ {
+ if (uplink_capab & ircdcap->tsmode || UseTSMODE)
+ {
+ for (i = 0; i < strlen(av[1]); i++)
if (!isdigit(av[1][i]))
break;
- }
- if (av[1][i] == '\0') {
- /* We have a valid TS field in av[1] now, so we can strip it off */
- /* After we swap av[0] and av[1] ofcourse to not break stuff! :) */
+ if (av[1][i] == '\0')
+ {
t = av[0];
av[0] = av[1];
av[1] = t;
ac--;
av++;
- } else {
- alog("TSMODE enabled but MODE has no valid TS");
}
+ else
+ alog("TSMODE enabled but MODE has no valid TS");
}
}
/* :42XAAAAAO TMODE 1106409026 #ircops +b *!*@*.aol.com */
- if (ircd->ts6) {
- if (isdigit(av[0][0])) {
+ if (ircd->ts6)
+ {
+ if (isdigit(av[0][0]))
+ {
ac--;
av++;
}
}
- chan = findchan(av[0]);
- if (!chan) {
- if (debug) {
+ c = findchan(av[0]);
+ if (!c)
+ {
+ if (debug)
+ {
ci = cs_findchan(av[0]);
- if (!(ci && (ci->HasFlag(CI_FORBIDDEN))))
- alog("debug: MODE %s for nonexistent channel %s",
- merge_args(ac - 1, av + 1), av[0]);
+ if (!ci || ci->HasFlag(CI_FORBIDDEN))
+ alog("debug: MODE %s for nonexistant channel %s", merge_args(ac - 1, av + 1), av[0]);
}
return;
}
- /* This shouldn't trigger on +o, etc. */
- if (strchr(source, '.') && !av[1][strcspn(av[1], "bovahq")]) {
- if (time(NULL) != chan->server_modetime) {
- chan->server_modecount = 0;
- chan->server_modetime = time(NULL);
+ if (strchr(source, '.') && !av[1][strcspn(av[1], "bovahq")])
+ {
+ if (time(NULL) != c->server_modetime)
+ {
+ c->server_modecount = 0;
+ c->server_modetime = time(NULL);
}
- chan->server_modecount++;
+ c->server_modecount++;
}
ac--;
av++;
- chan_set_modes(source, chan, ac, av, 1);
+ ChanSetInternalModes(c, ac, av);
}
/*************************************************************************/
@@ -1728,7 +1819,6 @@ void do_topic(const char *source, int ac, const char **av)
**/
void chan_set_correct_modes(User * user, Channel * c, int give_modes)
{
- std::string modebuf, userbuf;
int status;
int add_modes = 0;
int rem_modes = 0;
@@ -1801,74 +1891,51 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes)
if (add_modes > 0)
{
- modebuf += "+";
-
if (owner && (add_modes & CUS_OWNER) && !(status & CUS_OWNER))
- {
- modebuf += owner->ModeChar;
- userbuf += " " + std::string(user->nick);
- }
+ c->SetMode(NULL, CMODE_OWNER, user->nick);
else
add_modes &= ~CUS_OWNER;
if (admin && (add_modes & CUS_PROTECT) && !(status & CUS_PROTECT))
- {
- modebuf += admin->ModeChar;
- userbuf += " " + std::string(user->nick);
- }
+ c->SetMode(NULL, CMODE_PROTECT, user->nick);
else
add_modes &= ~CUS_PROTECT;
if (op && (add_modes & CUS_OP) && !(status & CUS_OP))
- {
- modebuf += op->ModeChar;
- userbuf += " " + std::string(user->nick);
- }
+ c->SetMode(NULL, CMODE_OP, user->nick);
else
add_modes &= ~CUS_OP;
if (halfop && (add_modes & CUS_HALFOP) && !(status & CUS_HALFOP))
- {
- modebuf += halfop->ModeChar;
- userbuf += " " + std::string(user->nick);
- }
+ c->SetMode(NULL, CMODE_HALFOP, user->nick);
else
add_modes &= ~CUS_HALFOP;
if (voice && (add_modes & CUS_VOICE) && !(status & CUS_VOICE))
- {
- modebuf += voice->ModeChar;
- userbuf += " " + std::string(user->nick);
- }
+ c->SetMode(NULL, CMODE_VOICE, user->nick);
else
add_modes &= ~CUS_VOICE;
}
if (rem_modes > 0)
{
- modebuf += "-";
-
if (owner && rem_modes & CUS_OWNER)
{
- modebuf += owner->ModeChar;
- userbuf += " " + std::string(user->nick);
+ c->RemoveMode(NULL, CMODE_OWNER, user->nick);
}
if (admin && rem_modes & CUS_PROTECT)
{
- modebuf += admin->ModeChar;
- userbuf += " " + std::string(user->nick);
+ c->RemoveMode(NULL, CMODE_PROTECT, user->nick);
}
if (op && rem_modes & CUS_OP)
{
- modebuf += op->ModeChar;
- userbuf += " " + std::string(user->nick);
+ c->RemoveMode(NULL, CMODE_OP, user->nick);
}
if (halfop && rem_modes & CUS_HALFOP)
{
- modebuf += halfop->ModeChar;
- userbuf += " " + std::string(user->nick);
+ c->RemoveMode(NULL, CMODE_HALFOP, user->nick);
}
}
@@ -1878,7 +1945,6 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes)
if (!add_modes && !rem_modes)
return;
- ircdproto->SendMode(whosends(ci), c->name, "%s%s", modebuf.c_str(), userbuf.c_str());
if (add_modes > 0)
chan_set_user_status(c, user, add_modes);
if (rem_modes > 0)
@@ -1969,16 +2035,12 @@ Channel *join_user_update(User * user, Channel * chan, const char *name,
if (chan->creation_time > chants && chants != 0)
{
struct c_userlist *cu;
- const char *modes[6];
chan->creation_time = chants;
for (cu = chan->users; cu; cu = cu->next)
{
- /* XXX */
- modes[0] = "-ov";
- modes[1] = cu->user->nick;
- modes[2] = cu->user->nick;
- chan_set_modes(Config.s_OperServ, chan, 3, modes, 2);
+ chan->RemoveMode(NULL, CMODE_OP, cu->user->nick);
+ chan->RemoveMode(NULL, CMODE_VOICE, cu->user->nick);
}
if (chan->ci)
{
@@ -1991,8 +2053,7 @@ Channel *join_user_update(User * user, Channel * chan, const char *name,
/* Make sure +r is set */
if (ModeManager::FindChannelModeByName(CMODE_REGISTERED))
{
- chan->SetMode(CMODE_REGISTERED);
- ircdproto->SendMode(whosends(chan->ci), chan->name, "+r");
+ chan->SetMode(NULL, CMODE_REGISTERED);
}
}
/* XXX simple modes and bans */
@@ -2018,34 +2079,21 @@ Channel *join_user_update(User * user, Channel * chan, const char *name,
/*************************************************************************/
-
-void do_mass_mode(char *modes)
+/** Set modes on every channel
+ * This overrides mlock on channels
+ * @param bi The bot to send the modes from
+ * @param modes The modes
+ */
+void MassChannelModes(BotInfo *bi, const std::string &modes)
{
- int ac;
- const char **av;
Channel *c;
- char *myModes;
-
- if (!modes) {
- return;
- }
- /* Prevent modes being altered by split_buf */
- myModes = sstrdup(modes);
- ac = split_buf(myModes, &av, 1);
-
- for (c = firstchan(); c; c = nextchan()) {
- if (c->bouncy_modes) {
- free(av);
- delete [] myModes;
+ for (c = firstchan(); c; c = nextchan())
+ {
+ if (c->bouncy_modes)
return;
- } else {
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "%s", modes);
- chan_set_modes(Config.s_OperServ, c, ac, av, 1);
- }
+ c->SetModes(bi, false, modes);
}
- free(av);
- delete [] myModes;
}
/*************************************************************************/
diff --git a/src/chanserv.c b/src/chanserv.c
index e54ce75fd..b09f9e808 100644
--- a/src/chanserv.c
+++ b/src/chanserv.c
@@ -776,19 +776,14 @@ void save_cs_dbase()
/* Check the current modes on a channel; if they conflict with a mode lock,
* fix them.
- *
- * Also check to make sure that every mode set or unset is allowed by the
- * defcon mlock settings. This is more important than any normal channel
- * mlock'd mode. --gdex (21-04-07)
*/
-void check_modes(Channel * c)
+void check_modes(Channel *c)
{
time_t t = time(NULL);
ChannelInfo *ci;
ChannelMode *cm;
ChannelModeParam *cmp;
- std::string modebuf, argbuf;
std::map<char, ChannelMode *>::iterator it;
std::string param, ciparam;
@@ -811,7 +806,7 @@ void check_modes(Channel * c)
return;
}
- if (c->chanserv_modetime != time(NULL))
+ if (c->chanserv_modetime != t)
{
c->chanserv_modecount = 0;
c->chanserv_modetime = t;
@@ -823,14 +818,11 @@ void check_modes(Channel * c)
{
if (c->HasMode(CMODE_REGISTERED))
{
- c->RemoveMode(CMODE_REGISTERED);
- ircdproto->SendMode(whosends(ci), c->name, "-r");
+ c->RemoveMode(NULL, CMODE_REGISTERED);
}
return;
}
- modebuf = "+";
-
for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it)
{
cm = it->second;
@@ -838,45 +830,31 @@ 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))
{
- modebuf += it->first;
- c->SetMode(cm->Name);
+ c->SetMode(NULL, cm);
/* Add the eventual parameter and modify the Channel structure */
if (cm->Type == MODE_PARAM)
{
- cmp = static_cast<ChannelModeParam *>(cm);
- ci->GetParam(cmp->Name, &param);
-
- if (!param.empty())
- {
- argbuf += " " + param;
- }
+ if (ci->GetParam(cmp->Name, &param))
+ c->SetMode(NULL, cm, param);
}
+ else
+ c->SetMode(NULL, cm);
}
/* If this is a param mode and its mlocked, check to ensure it is set and set to the correct value */
else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true))
{
- cmp = static_cast<ChannelModeParam *>(cm);
- c->GetParam(cmp->Name, &param);
- ci->GetParam(cmp->Name, &ciparam);
+ c->GetParam(cm->Name, &param);
+ ci->GetParam(cm->Name, &ciparam);
/* If the channel doesnt have the mode, or it does and it isn't set correctly */
if (!c->HasMode(cm->Name) || (!param.empty() && !ciparam.empty() && param != ciparam))
{
- modebuf += it->first;
-
- c->SetMode(cmp->Name, ciparam);
-
- argbuf += " " + ciparam;
+ c->SetMode(NULL, cm, ciparam);
}
}
}
- if (modebuf == "+")
- modebuf.clear();
-
- modebuf += "-";
-
for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it)
{
cm = it->second;
@@ -884,9 +862,6 @@ void check_modes(Channel * c)
/* If the channel has the mode */
if (c->HasMode(cm->Name) && ci->HasMLock(cm->Name, false))
{
- modebuf += it->first;
- c->RemoveMode(cm->Name);
-
/* Add the eventual parameter */
if (cm->Type == MODE_PARAM)
{
@@ -894,24 +869,14 @@ void check_modes(Channel * c)
if (!cmp->MinusNoArg)
{
- c->GetParam(cmp->Name, &param);
-
- if (!param.empty())
- {
- argbuf += " " + param;
- }
+ if (c->GetParam(cmp->Name, &param))
+ c->RemoveMode(NULL, cm, param);
}
}
+ else
+ c->RemoveMode(NULL, cm);
}
}
-
- if (modebuf[modebuf.length() - 1] == '-')
- modebuf.erase(modebuf.length() - 1);
-
- if (modebuf.empty())
- return;
-
- ircdproto->SendMode((ci ? whosends(ci) : findbot(Config.s_OperServ)), c->name, "%s%s", modebuf.c_str(), argbuf.empty() ? "" : argbuf.c_str());
}
/*************************************************************************/
@@ -930,16 +895,16 @@ int check_valid_admin(User * user, Channel * chan, int servermode)
if (chan->ci->HasFlag(CI_FORBIDDEN))
return 0;
- if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) {
+ if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT))
+ {
notice_lang(Config.s_ChanServ, user, CHAN_IS_REGISTERED, Config.s_ChanServ);
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-%s %s",
- cm->ModeChar, user->nick);
+ chan->RemoveMode(NULL, CMODE_PROTECT, user->nick);
return 0;
}
- if (check_access(user, chan->ci, CA_AUTODEOP)) {
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-%s %s",
- cm->ModeChar, user->nick);
+ if (check_access(user, chan->ci, CA_AUTODEOP))
+ {
+ chan->RemoveMode(NULL, CMODE_PROTECT, user->nick);
return 0;
}
@@ -966,66 +931,32 @@ int check_valid_op(User * user, Channel * chan, int servermode)
protect = ModeManager::FindChannelModeByName(CMODE_PROTECT);
halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP);
- if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) {
+ if (servermode && !check_access(user, chan->ci, CA_AUTOOP))
+ {
notice_lang(Config.s_ChanServ, user, CHAN_IS_REGISTERED, Config.s_ChanServ);
- if (halfop)
- {
- if (owner && protect)
- {
- if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-%so%s %s %s %s", protect->ModeChar,
- owner->ModeChar, user->nick,
- user->nick, user->nick);
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-%sho%s %s %s %s %s",
- protect->ModeChar,
- owner->ModeChar,
- user->nick, user->nick, user->nick,
- user->nick);
- }
- } else if (!owner && protect) {
- if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-%so %s %s", protect->ModeChar,
- user->nick, user->nick);
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-%soh %s %s %s", protect->ModeChar,
- user->nick, user->nick, user->nick);
- }
- } else {
- if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-o %s",
- user->nick);
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-ho %s %s", user->nick, user->nick);
- }
- }
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-o %s",
- user->nick);
- }
+
+ if (owner)
+ chan->RemoveMode(NULL, CMODE_OWNER, user->nick);
+ if (protect)
+ chan->RemoveMode(NULL, CMODE_PROTECT, user->nick);
+ chan->RemoveMode(NULL, CMODE_OP, user->nick);
+ if (halfop && !check_access(user, chan->ci, CA_AUTOHALFOP))
+ chan->RemoveMode(NULL, CMODE_HALFOP, user->nick);
+
return 0;
}
- if (check_access(user, chan->ci, CA_AUTODEOP)) {
- if (halfop) {
- if (owner && protect) {
- ircdproto->SendMode(whosends(chan->ci), chan->name,
- "-%sho%s %s %s %s %s", protect->ModeChar,
- owner->ModeChar, user->nick, user->nick,
- user->nick, user->nick);
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-ho %s %s",
- user->nick, user->nick);
- }
- } else {
- ircdproto->SendMode(whosends(chan->ci), chan->name, "-o %s",
- user->nick);
- }
+ if (check_access(user, chan->ci, CA_AUTODEOP))
+ {
+ chan->RemoveMode(NULL, CMODE_OP, user->nick);
+
+ if (owner)
+ chan->RemoveMode(NULL, CMODE_OWNER, user->nick);
+ if (protect)
+ chan->RemoveMode(NULL, CMODE_PROTECT, user->nick);
+ if (halfop)
+ chan->RemoveMode(NULL, CMODE_HALFOP, user->nick);
+
return 0;
}
@@ -1048,8 +979,9 @@ int check_should_op(User * user, char *chan)
if ((ci->HasFlag(CI_SECURE)) && !nick_identified(user))
return 0;
- if (check_access(user, ci, CA_AUTOOP)) {
- ircdproto->SendMode(whosends(ci), chan, "+o %s", user->nick);
+ if (check_access(user, ci, CA_AUTOOP))
+ {
+ ci->c->SetMode(NULL, CMODE_OP, user->nick);
return 1;
}
@@ -1071,8 +1003,9 @@ int check_should_voice(User * user, char *chan)
if ((ci->HasFlag(CI_SECURE)) && !nick_identified(user))
return 0;
- if (check_access(user, ci, CA_AUTOVOICE)) {
- ircdproto->SendMode(whosends(ci), chan, "+v %s", user->nick);
+ if (check_access(user, ci, CA_AUTOVOICE))
+ {
+ ci->c->SetMode(NULL, CMODE_VOICE, user->nick);
return 1;
}
@@ -1088,8 +1021,9 @@ int check_should_halfop(User * user, char *chan)
if (!ci || (ci->HasFlag(CI_FORBIDDEN)) || *chan == '+')
return 0;
- if (check_access(user, ci, CA_AUTOHALFOP)) {
- ircdproto->SendMode(whosends(ci), chan, "+h %s", user->nick);
+ if (check_access(user, ci, CA_AUTOHALFOP))
+ {
+ ci->c->SetMode(NULL, CMODE_HALFOP, user->nick);
return 1;
}
@@ -1101,15 +1035,14 @@ int check_should_halfop(User * user, char *chan)
int check_should_owner(User * user, char *chan)
{
ChannelInfo *ci = cs_findchan(chan);
- ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OWNER);
- if (!ci || (ci->HasFlag(CI_FORBIDDEN)) || *chan == '+')
+ if (!ci || !ci->c || ci->HasFlag(CI_FORBIDDEN) || *chan == '+')
return 0;
- if (((ci->HasFlag(CI_SECUREFOUNDER)) && IsRealFounder(user, ci))
- || (!(ci->HasFlag(CI_SECUREFOUNDER)) && IsFounder(user, ci))) {
- ircdproto->SendMode(whosends(ci), chan, "+o%s %s %s", cm->ModeChar, user->nick,
- user->nick);
+ if ((ci->HasFlag(CI_SECUREFOUNDER) && IsRealFounder(user, ci))
+ || (!ci->HasFlag(CI_SECUREFOUNDER) && IsFounder(user, ci))) {
+ ci->c->SetMode(NULL, CMODE_OP, user->nick);
+ ci->c->SetMode(NULL, CMODE_OWNER, user->nick);
return 1;
}
@@ -1121,14 +1054,14 @@ int check_should_owner(User * user, char *chan)
int check_should_protect(User * user, char *chan)
{
ChannelInfo *ci = cs_findchan(chan);
- ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PROTECT);
- if (!ci || (ci->HasFlag(CI_FORBIDDEN)) || *chan == '+')
+ if (!ci || !ci->c || ci->HasFlag(CI_FORBIDDEN) || *chan == '+')
return 0;
- if (check_access(user, ci, CA_AUTOPROTECT)) {
- ircdproto->SendMode(whosends(ci), chan, "+o%s %s %s", cm->ModeChar, user->nick,
- user->nick);
+ if (check_access(user, ci, CA_AUTOPROTECT))
+ {
+ ci->c->SetMode(NULL, CMODE_OWNER, user->nick);
+ ci->c->SetMode(NULL, CMODE_PROTECT, user->nick);
return 1;
}
@@ -1151,9 +1084,6 @@ int check_kick(User * user, const char *chan, time_t chants)
AutoKick *akick;
bool set_modes = false;
NickCore *nc;
- const char *av[4];
- int ac;
- char buf[BUFSIZE];
char mask[BUFSIZE];
const char *reason;
ChanServTimer *t;
@@ -1247,32 +1177,22 @@ int check_kick(User * user, const char *chan, time_t chants)
*/
if (set_modes)
{
- ircdproto->SendMode(findbot(Config.s_ChanServ), chan, "+ntsi");
+ c->SetMode(NULL, CMODE_NOEXTERNAL);
+ c->SetMode(NULL, CMODE_TOPIC);
+ c->SetMode(NULL, CMODE_SECRET);
+ c->SetMode(NULL, CMODE_INVITE);
}
t = new ChanServTimer(Config.CSInhabit, chan);
ci->SetFlag(CI_INHABIT);
}
- if (c) {
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = chan;
- av[1] = buf;
- av[2] = "+b";
- av[3] = mask;
- ac = 4;
- } else {
- av[0] = chan;
- av[1] = "+b";
- av[2] = mask;
- ac = 3;
- }
-
- do_cmode(whosends(ci)->nick, ac, av);
+ if (c)
+ {
+ c->RemoveMode(NULL, CMODE_BAN, mask);
}
- ircdproto->SendMode(whosends(ci), chan, "+b %s", mask);
+ c->SetMode(NULL, CMODE_BAN, mask);
ircdproto->SendKick(whosends(ci), chan, user->nick, "%s", reason);
return 1;
@@ -1341,7 +1261,7 @@ void restore_topic(const char *chan)
if (ircd->join2set) {
if (whosends(ci) == findbot(Config.s_ChanServ)) {
ircdproto->SendJoin(findbot(Config.s_ChanServ), chan, c->creation_time);
- ircdproto->SendMode(NULL, chan, "+o %s", Config.s_ChanServ);
+ c->SetMode(NULL, CMODE_OP, Config.s_ChanServ);
}
}
ircdproto->SendTopic(whosends(ci), c->name, c->topic_setter,
@@ -1403,7 +1323,7 @@ int check_topiclock(Channel * c, time_t topic_time)
if (ircd->join2set) {
if (whosends(ci) == findbot(Config.s_ChanServ)) {
ircdproto->SendJoin(findbot(Config.s_ChanServ), c->name, c->creation_time);
- ircdproto->SendMode(NULL, c->name, "+o %s", Config.s_ChanServ);
+ c->SetMode(NULL, CMODE_OP, Config.s_ChanServ);
}
}
@@ -1487,8 +1407,7 @@ void cs_remove_nick(const NickCore * nc)
/* Maybe move this to delchan() ? */
if (ci->c && ci->c->HasMode(CMODE_REGISTERED))
{
- ci->c->RemoveMode(CMODE_REGISTERED);
- ircdproto->SendMode(whosends(ci), ci->name, "-r");
+ ci->c->RemoveMode(NULL, CMODE_REGISTERED);
}
}
@@ -1871,7 +1790,6 @@ AutoKick *is_stuck(ChannelInfo * ci, const char *mask)
void stick_mask(ChannelInfo * ci, AutoKick * akick)
{
- const char *av[2];
Entry *ban;
if (!ci) {
@@ -1895,18 +1813,13 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick)
}
/* Falling there means set the ban */
- av[0] = "+b";
- av[1] = akick->mask.c_str();
- ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->mask.c_str());
- chan_set_modes(Config.s_ChanServ, ci->c, 2, av, 1);
+ ci->c->SetMode(NULL, CMODE_BAN, akick->mask.c_str());
}
/* Ban the stuck mask in a safe manner. */
void stick_all(ChannelInfo * ci)
{
- const char *av[2];
-
if (!ci)
return;
@@ -1917,9 +1830,6 @@ void stick_all(ChannelInfo * ci)
if (!akick->InUse || (akick->HasFlag(AK_ISNICK) || !akick->HasFlag(AK_STUCK)))
continue;
- av[0] = "+b";
- av[1] = akick->mask.c_str();
- ircdproto->SendMode(whosends(ci), ci->c->name, "+b %s", akick->mask.c_str());
- chan_set_modes(Config.s_ChanServ, ci->c, 2, av, 1);
+ ci->c->SetMode(NULL, CMODE_BAN, akick->mask.c_str());
}
}
diff --git a/src/core/cs_ban.c b/src/core/cs_ban.c
index 86ed13332..c154064ca 100644
--- a/src/core/cs_ban.c
+++ b/src/core/cs_ban.c
@@ -66,14 +66,10 @@ class CommandCSBan : public Command
} else if (is_protected(u2)) {
notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
} else {
- const char *av[3];
char mask[BUFSIZE];
- av[0] = "+b";
get_idealban(ci, u2, mask, sizeof(mask));
- av[1] = mask;
- ircdproto->SendMode(whosends(ci), c->name, "+b %s", av[1]);
- chan_set_modes(Config.s_ChanServ, c, 2, av, 1);
+ c->SetMode(NULL, CMODE_BAN, mask);
/* We still allow host banning while not allowing to kick */
if (!is_on_chan(c, u2))
diff --git a/src/core/cs_clear.c b/src/core/cs_clear.c
index ea01eb90e..fa82c9f11 100644
--- a/src/core/cs_clear.c
+++ b/src/core/cs_clear.c
@@ -63,8 +63,7 @@ class CommandCSClear : public Command
notice_lang(Config.s_ChanServ, u, CHAN_CLEARED_MODES, chan);
} else if (what == "ops") {
const char *av[6]; /* The max we have to hold: chan, ts, modes(max3), nick, nick, nick */
- int ac, isop, isadmin, isown, count, i;
- char buf[BUFSIZE], tmp[BUFSIZE], tmp2[BUFSIZE];
+ int isop, isadmin, isown;
struct c_userlist *cu, *bnext;
if (ircd->svsmode_ucmode) {
@@ -82,167 +81,71 @@ class CommandCSClear : public Command
ircdproto->SendSVSModeChan(av[0], modebuf.c_str(), NULL);
}
- for (cu = c->users; cu; cu = bnext) {
+ for (cu = c->users; cu; cu = bnext)
+ {
bnext = cu->next;
isop = chan_has_user_status(c, cu->user, CUS_OP);
isadmin = chan_has_user_status(c, cu->user, CUS_PROTECT);
isown = chan_has_user_status(c, cu->user, CUS_OWNER);
- count = (isop ? 1 : 0) + (isadmin ? 1 : 0) + (isown ? 1 : 0);
if (!isop && !isadmin && !isown)
continue;
- snprintf(tmp, BUFSIZE, "-%s%s%s", (isop ? "o" : ""), (isadmin ?
- &admin->ModeChar : ""), (isown ? &owner->ModeChar : ""));
-
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[1] = buf;
- av[2] = tmp;
- /* We have to give as much nicks as modes.. - Viper */
- for (i = 0; i < count; i++)
- av[i+3] = cu->user->nick;
- ac = 3 + i;
- } else {
- av[1] = tmp;
- /* We have to give as much nicks as modes.. - Viper */
- for (i = 0; i < count; i++)
- av[i+2] = cu->user->nick;
- ac = 2 + i;
- }
-
- do_cmode(Config.s_ChanServ, ac, av);
+ if (isown)
+ c->RemoveMode(NULL, CMODE_OWNER, cu->user->nick);
+ if (admin)
+ c->RemoveMode(NULL, CMODE_PROTECT, cu->user->nick);
+ if (isop)
+ c->RemoveMode(NULL, CMODE_OP, cu->user->nick);
}
} else {
av[0] = chan;
- for (cu = c->users; cu; cu = bnext) {
+ for (cu = c->users; cu; cu = bnext)
+ {
bnext = cu->next;
isop = chan_has_user_status(c, cu->user, CUS_OP);
isadmin = chan_has_user_status(c, cu->user, CUS_PROTECT);
isown = chan_has_user_status(c, cu->user, CUS_OWNER);
- count = (isop ? 1 : 0) + (isadmin ? 1 : 0) + (isown ? 1 : 0);
if (!isop && !isadmin && !isown)
continue;
- snprintf(tmp, BUFSIZE, "-%s%s%s", (isop ? "o" : ""), (isadmin ?
- &admin->ModeChar : ""), (isown ? &owner->ModeChar : ""));
- /* We need to send the IRCd a nick for every mode.. - Viper */
- snprintf(tmp2, BUFSIZE, "%s %s %s", (isop ? cu->user->nick : ""),
- (isadmin ? cu->user->nick : ""), (isown ? cu->user->nick : ""));
-
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[1] = buf;
- av[2] = tmp;
- /* We have to give as much nicks as modes.. - Viper */
- for (i = 0; i < count; i++)
- av[i+3] = cu->user->nick;
- ac = 3 + i;
-
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[2], tmp2);
- } else {
- av[1] = tmp;
- /* We have to give as much nicks as modes.. - Viper */
- for (i = 0; i < count; i++)
- av[i+2] = cu->user->nick;
- ac = 2 + i;
-
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[1], tmp2);
- }
-
- do_cmode(Config.s_ChanServ, ac, av);
+ if (isown)
+ c->RemoveMode(NULL, CMODE_OWNER, cu->user->nick);
+ if (isadmin)
+ c->RemoveMode(NULL, CMODE_PROTECT, cu->user->nick);
+ if (isop)
+ c->RemoveMode(NULL, CMODE_OP, cu->user->nick);
}
}
notice_lang(Config.s_ChanServ, u, CHAN_CLEARED_OPS, chan);
} else if (ModeManager::FindChannelModeByName(CMODE_HALFOP) && what == "hops") {
- const char *av[4];
- int ac;
- char buf[BUFSIZE];
struct c_userlist *cu, *bnext;
- for (cu = c->users; cu; cu = bnext) {
+ for (cu = c->users; cu; cu = bnext)
+ {
bnext = cu->next;
+
if (!chan_has_user_status(c, cu->user, CUS_HALFOP))
continue;
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
- av[0] = chan;
- av[1] = buf;
- av[2] = "-h";
- av[3] = cu->user->nick;
- ac = 4;
- } else {
- av[0] = chan;
- av[1] = "-h";
- av[2] = cu->user->nick;
- ac = 3;
- }
-
- if (ircd->svsmode_ucmode) {
- if (ircdcap->tsmode)
- ircdproto->SendSVSModeChan(av[0], av[2], NULL);
- else
- ircdproto->SendSVSModeChan(av[0], av[1], NULL);
-
- do_cmode(Config.s_ChanServ, ac, av);
- break;
- } else {
- if (ircdcap->tsmode)
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[2],
- av[3]);
- else
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[1],
- av[2]);
- }
- do_cmode(Config.s_ChanServ, ac, av);
+ c->RemoveMode(NULL, CMODE_HALFOP, cu->user->nick);
}
+
notice_lang(Config.s_ChanServ, u, CHAN_CLEARED_HOPS, chan);
} else if (what == "voices") {
- const char *av[4];
- int ac;
- char buf[BUFSIZE];
struct c_userlist *cu, *bnext;
- for (cu = c->users; cu; cu = bnext) {
+ for (cu = c->users; cu; cu = bnext)
+ {
bnext = cu->next;
+
if (!chan_has_user_status(c, cu->user, CUS_VOICE))
continue;
- if (ircdcap->tsmode) {
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long int>(time(NULL)));
- av[0] = chan;
- av[1] = buf;
- av[2] = "-v";
- av[3] = cu->user->nick;
- ac = 4;
- } else {
- av[0] = chan;
- av[1] = "-v";
- av[2] = cu->user->nick;
- ac = 3;
- }
-
- if (ircd->svsmode_ucmode) {
- if (ircdcap->tsmode)
- ircdproto->SendSVSModeChan(av[0], av[2], NULL);
- else
- ircdproto->SendSVSModeChan(av[0], av[1], NULL);
-
- do_cmode(Config.s_ChanServ, ac, av);
- break;
- } else {
- if (ircdcap->tsmode) {
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[2],
- av[3]);
- } else {
- ircdproto->SendMode(whosends(ci), av[0], "%s %s", av[1],
- av[2]);
- }
- }
- do_cmode(Config.s_ChanServ, ac, av);
+ c->RemoveMode(NULL, CMODE_VOICE, cu->user->nick);
}
+
notice_lang(Config.s_ChanServ, u, CHAN_CLEARED_VOICES, chan);
} else if (what == "users") {
const char *av[3];
diff --git a/src/core/cs_drop.c b/src/core/cs_drop.c
index 1999ef02e..561f79e6f 100644
--- a/src/core/cs_drop.c
+++ b/src/core/cs_drop.c
@@ -61,8 +61,7 @@ class CommandCSDrop : public Command
{
if (ModeManager::FindChannelModeByName(CMODE_REGISTERED))
{
- ci->c->RemoveMode(CMODE_REGISTERED);
- ircdproto->SendMode(whosends(ci), ci->name, "-r");
+ ci->c->RemoveMode(NULL, CMODE_REGISTERED);
}
}
diff --git a/src/core/cs_modes.c b/src/core/cs_modes.c
index f1ad758d0..9dc76e10f 100644
--- a/src/core/cs_modes.c
+++ b/src/core/cs_modes.c
@@ -28,11 +28,9 @@
*/
static CommandReturn do_util(User *u, ChannelMode *cm, const char *chan, const char *nick, bool set, int level, int levelself, const std::string &name, ChannelInfoFlag notice)
{
- const char *av[2];
Channel *c = findchan(chan);
ChannelInfo *ci;
User *u2;
- char modebuf[3];
int is_same;
@@ -58,14 +56,10 @@ static CommandReturn do_util(User *u, ChannelMode *cm, const char *chan, const c
notice_lang(Config.s_ChanServ, u, ACCESS_DENIED);
else
{
- snprintf(modebuf, sizeof(modebuf), "%c%c", (set ? '+' : '-'), cm->ModeChar);
-
- ircdproto->SendMode(whosends(ci), c->name, "%s %s", modebuf, u2->nick);
-
- av[0] = modebuf;
- av[1] = u2->nick;
-
- chan_set_modes(Config.s_ChanServ, c, 2, av, 3);
+ if (set)
+ c->SetMode(NULL, cm, u2->nick);
+ else
+ c->RemoveMode(NULL, cm, u2->nick);
if (notice && ci->HasFlag(notice))
ircdproto->SendMessage(whosends(ci), c->name, "%s command used for %s by %s",
diff --git a/src/core/cs_register.c b/src/core/cs_register.c
index 6a258a684..364fed989 100644
--- a/src/core/cs_register.c
+++ b/src/core/cs_register.c
@@ -82,9 +82,9 @@ class CommandCSRegister : public Command
check_modes(c);
/* On most ircds you do not receive the admin/owner mode till its registered */
if ((cm = ModeManager::FindChannelModeByName(CMODE_OWNER)))
- ircdproto->SendMode(findbot(Config.s_ChanServ), chan, "+%c %s", cm->ModeChar, u->nick);
+ c->SetMode(NULL, cm, u->nick);
else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT)))
- ircdproto->SendMode(findbot(Config.s_ChanServ), chan, "+%c %s", cm->ModeChar, u->nick);
+ c->RemoveMode(NULL, cm, u->nick);
/* Mark the channel as persistant */
if (c->HasMode(CMODE_PERM))
@@ -92,7 +92,7 @@ class CommandCSRegister : public Command
/* Persist may be in def cflags, set it here */
else if (ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM)))
{
- ircdproto->SendMode(whosends(ci), chan, "+%c", cm->ModeChar);
+ c->SetMode(NULL, CMODE_PERM);
ci->SetFlag(CI_PERSIST);
}
diff --git a/src/core/cs_set.c b/src/core/cs_set.c
index c7cb6bc2b..fa0a21d68 100644
--- a/src/core/cs_set.c
+++ b/src/core/cs_set.c
@@ -568,8 +568,7 @@ class CommandCSSet : public Command
/* Set the perm mode */
if (cm && ci->c && !ci->c->HasMode(CMODE_PERM))
{
- ci->c->SetMode(CMODE_PERM);
- ircdproto->SendMode(whosends(ci), ci->c->name, "+%c", cm->ModeChar);
+ ci->c->SetMode(NULL, CMODE_PERM);
}
}
@@ -584,8 +583,7 @@ class CommandCSSet : public Command
/* Unset perm mode */
if (ci->c && ci->c->HasMode(CMODE_PERM))
{
- ircdproto->SendMode(whosends(ci), ci->c->name, "-%c", cm->ModeChar);
- ci->c->RemoveMode(CMODE_PERM);
+ ci->c->RemoveMode(NULL, CMODE_PERM);
}
/* Persist is set off... remove the bot and delete the channel if its empty */
else if (ci->c)
diff --git a/src/core/ns_logout.c b/src/core/ns_logout.c
index 4304d7b18..ed85370a5 100644
--- a/src/core/ns_logout.c
+++ b/src/core/ns_logout.c
@@ -48,9 +48,6 @@ class CommandNSLogout : public Command
validate_user(u2);
}
- if (ircd->modeonunreg)
- common_svsmode(u2, ircd->modeonunreg, "1");
-
u2->isSuperAdmin = 0; /* Dont let people logout and remain a SuperAdmin */
alog("%s: %s!%s@%s logged out nickname %s", Config.s_NickServ, u->nick, u->GetIdent().c_str(), u->host, u2->nick);
@@ -65,6 +62,7 @@ class CommandNSLogout : public Command
del_ns_timeout(na, TO_COLLIDE);
ircdproto->SendAccountLogout(u2, u2->nc);
+ ircdproto->SendUnregisteredNick(u2);
u2->nc = NULL;
diff --git a/src/core/os_clearmodes.c b/src/core/os_clearmodes.c
index 2c3658570..d2e136983 100644
--- a/src/core/os_clearmodes.c
+++ b/src/core/os_clearmodes.c
@@ -24,7 +24,6 @@ class CommandOSClearModes : public Command
CommandReturn Execute(User *u, const std::vector<ci::string> &params)
{
- const char *argv[2];
const char *chan = params[0].c_str();
Channel *c;
int all = 0;
@@ -61,31 +60,31 @@ class CommandOSClearModes : public Command
/* Clear mode +o */
if (ircd->svsmode_ucmode)
ircdproto->SendSVSModeChan(c->name, "-o", NULL);
- for (cu = c->users; cu; cu = next)
+ else
{
- next = cu->next;
- if (!chan_has_user_status(c, cu->user, CUS_OP))
- continue;
- argv[0] = "-o";
- argv[1] = cu->user->nick;
- if (!ircd->svsmode_ucmode)
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "-o %s", cu->user->nick);
- chan_set_modes(Config.s_OperServ, c, 2, argv, 0);
+ for (cu = c->users; cu; cu = next)
+ {
+ next = cu->next;
+ if (!chan_has_user_status(c, cu->user, CUS_OP))
+ continue;
+
+ c->RemoveMode(NULL, CMODE_OP, cu->user->nick);
+ }
}
/* Clear mode +v */
if (ircd->svsmode_ucmode)
ircdproto->SendSVSModeChan(c->name, "-v", NULL);
- for (cu = c->users; cu; cu = next)
+ else
{
- next = cu->next;
- if (!chan_has_user_status(c, cu->user, CUS_VOICE))
- continue;
- argv[0] = "-v";
- argv[1] = cu->user->nick;
- if (!ircd->svsmode_ucmode)
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "-v %s", cu->user->nick);
- chan_set_modes(Config.s_OperServ, c, 2, argv, 0);
+ for (cu = c->users; cu; cu = next)
+ {
+ next = cu->next;
+ if (!chan_has_user_status(c, cu->user, CUS_VOICE))
+ continue;
+
+ c->RemoveMode(NULL, CMODE_VOICE, cu->user->nick);
+ }
}
/* Clear mode +h */
@@ -93,16 +92,16 @@ class CommandOSClearModes : public Command
{
if (ircd->svsmode_ucmode)
ircdproto->SendSVSModeChan(c->name, "-h", NULL);
- for (cu = c->users; cu; cu = next)
+ else
{
- next = cu->next;
- if (!chan_has_user_status(c, cu->user, CUS_HALFOP))
- continue;
- argv[0] = "-h";
- argv[1] = cu->user->nick;
- if (!ircd->svsmode_ucmode)
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "-h %s", cu->user->nick);
- chan_set_modes(Config.s_OperServ, c, 2, argv, 0);
+ for (cu = c->users; cu; cu = next)
+ {
+ next = cu->next;
+ if (!chan_has_user_status(c, cu->user, CUS_HALFOP))
+ continue;
+
+ c->RemoveMode(NULL, CMODE_HALFOP, cu->user->nick);
+ }
}
}
@@ -114,16 +113,16 @@ class CommandOSClearModes : public Command
if (ircd->svsmode_ucmode)
ircdproto->SendSVSModeChan(c->name, buf.c_str(), NULL);
- for (cu = c->users; cu; cu = next)
+ else
{
- next = cu->next;
- if (!chan_has_user_status(c, cu->user, CUS_OWNER))
- continue;
- argv[0] = buf.c_str();
- argv[1] = cu->user->nick;
- if (!ircd->svsmode_ucmode)
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "%s %s", buf.c_str(), cu->user->nick);
- chan_set_modes(Config.s_OperServ, c, 2, argv, 0);
+ for (cu = c->users; cu; cu = next)
+ {
+ next = cu->next;
+ if (!chan_has_user_status(c, cu->user, CUS_OWNER))
+ continue;
+
+ c->RemoveMode(NULL, CMODE_OWNER, cu->user->nick);
+ }
}
}
@@ -135,26 +134,25 @@ class CommandOSClearModes : public Command
if (ircd->svsmode_ucmode)
ircdproto->SendSVSModeChan(c->name, buf.c_str(), NULL);
- for (cu = c->users; cu; cu = next)
+ else
{
- next = cu->next;
- if (!chan_has_user_status(c, cu->user, CUS_PROTECT))
- continue;
- argv[0] = buf.c_str();
- argv[1] = cu->user->nick;
- if (!ircd->svsmode_ucmode)
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "%s %s", buf.c_str(), cu->user->nick);
- chan_set_modes(Config.s_OperServ, c, 2, argv, 0);
+ for (cu = c->users; cu; cu = next)
+ {
+ next = cu->next;
+ if (!chan_has_user_status(c, cu->user, CUS_PROTECT))
+ continue;
+
+ c->RemoveMode(NULL, CMODE_PROTECT, cu->user->nick);
+ }
}
}
}
- c->ClearModes(Config.s_OperServ);
-
- c->ClearBans(Config.s_OperServ);
- c->ClearExcepts(Config.s_OperServ);
- c->ClearInvites(Config.s_OperServ);
+ c->ClearModes();
+ c->ClearBans();
+ c->ClearExcepts();
+ c->ClearInvites();
}
if (all)
diff --git a/src/core/os_defcon.c b/src/core/os_defcon.c
index 2ab97058a..5cdb38b9b 100644
--- a/src/core/os_defcon.c
+++ b/src/core/os_defcon.c
@@ -186,8 +186,7 @@ class OSDEFCON : public Module
if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesOff.HasFlag(Name))
{
- c->RemoveMode(Name);
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "-%c", cm->ModeChar);
+ c->RemoveMode(NULL, Name);
}
}
@@ -198,18 +197,14 @@ class OSDEFCON : public Module
if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesOn.HasFlag(Name))
{
std::string param;
- GetDefConParam(Name, &param);
- std::string buf = "+" + std::string(&cm->ModeChar);
- if (!param.empty())
+ if (GetDefConParam(Name, &param))
{
- buf += " " + param;
- c->SetMode(Name, param);
+ c->SetMode(NULL, Name, param);
}
else
- c->SetMode(Name);
+ c->SetMode(NULL, Name);
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, buf.c_str());
}
}
@@ -328,20 +323,9 @@ class OSDEFCON : public Module
void OnChannelCreate(Channel *c)
{
- char *myModes;
- int ac;
- const char **av;
-
if (CheckDefCon(DEFCON_FORCE_CHAN_MODES))
{
- myModes = sstrdup(Config.DefConChanModes);
- ac = split_buf(myModes, &av, 1);
-
- ircdproto->SendMode(findbot(Config.s_OperServ), c->name, "%s", Config.DefConChanModes);
- chan_set_modes(Config.s_OperServ, c, ac, av, 1);
-
- free(av);
- delete [] myModes;
+ c->SetModes(findbot(Config.s_OperServ), false, Config.DefConChanModes);
}
}
};
@@ -385,7 +369,7 @@ void runDefCon()
{
alog("DEFCON: setting %s on all chan's", Config.DefConChanModes);
DefConModesSet = 1;
- do_mass_mode(Config.DefConChanModes);
+ MassChannelModes(findbot(Config.s_OperServ), Config.DefConChanModes);
}
}
}
@@ -399,7 +383,7 @@ void runDefCon()
if ((newmodes = defconReverseModes(Config.DefConChanModes)))
{
alog("DEFCON: setting %s on all chan's", newmodes);
- do_mass_mode(newmodes);
+ MassChannelModes(findbot(Config.s_OperServ), newmodes);
delete [] newmodes;
}
}
diff --git a/src/core/os_mode.c b/src/core/os_mode.c
index 6984c73f7..af19bb6d5 100644
--- a/src/core/os_mode.c
+++ b/src/core/os_mode.c
@@ -24,8 +24,6 @@ class CommandOSMode : public Command
CommandReturn Execute(User *u, const std::vector<ci::string> &params)
{
- int ac;
- const char **av;
const char *chan = params[0].c_str(), *modes = params[1].c_str();
Channel *c;
@@ -35,11 +33,7 @@ class CommandOSMode : public Command
notice_lang(Config.s_OperServ, u, OPER_BOUNCY_MODES_U_LINE);
else
{
- ircdproto->SendMode(findbot(Config.s_OperServ), chan, "%s", modes);
-
- ac = split_buf(const_cast<char *>(modes), /* XXX */ &av, 1);
- chan_set_modes(Config.s_OperServ, c, ac, av, -1);
- free(av);
+ c->SetModes(findbot(Config.s_OperServ), false, modes);
if (Config.WallOSMode)
ircdproto->SendGlobops(Config.s_OperServ, "%s used MODE %s on %s", u->nick, modes, chan);
diff --git a/src/core/os_oline.c b/src/core/os_oline.c
index b96f1451f..883f9344e 100644
--- a/src/core/os_oline.c
+++ b/src/core/os_oline.c
@@ -34,7 +34,7 @@ class CommandOSOLine : public Command
else if (u2 && flag[0] == '+')
{
ircdproto->SendSVSO(Config.s_OperServ, nick, flag);
- common_svsmode(u2, "+o", NULL);
+ u2->SetMode(UMODE_OPER);
notice_lang(Config.s_OperServ, u2, OPER_OLINE_IRCOP);
notice_lang(Config.s_OperServ, u, OPER_OLINE_SUCCESS, flag, nick);
ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 used OLINE for %s", u->nick, nick);
diff --git a/src/core/os_umode.c b/src/core/os_umode.c
index 34e3502e2..6f86dbd44 100644
--- a/src/core/os_umode.c
+++ b/src/core/os_umode.c
@@ -42,9 +42,7 @@ class CommandOSUMode : public Command
notice_lang(Config.s_OperServ, u, NICK_X_NOT_IN_USE, nick);
else
{
- ircdproto->SendMode(findbot(Config.s_OperServ), nick, "%s", modes);
-
- common_svsmode(u2, modes, NULL);
+ u2->SetModes(modes);
notice_lang(Config.s_OperServ, u, OPER_UMODE_SUCCESS, nick);
notice_lang(Config.s_OperServ, u2, OPER_UMODE_CHANGED, u->nick);
diff --git a/src/main.c b/src/main.c
index 570583880..dc0c5ab9d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -487,6 +487,9 @@ int main(int ac, char **av, char **envp)
last_check = t;
}
+ /* Process any modes that need to be (un)set */
+ ModeManager::ProcessModes();
+
/* this is a nasty nasty typecast. we need to rewrite the
socket stuff -Certus */
i = static_cast<int>(reinterpret_cast<long>(sgets2(inbuf, sizeof(inbuf), servsock)));
diff --git a/src/modes.cpp b/src/modes.cpp
index e43596620..57780985c 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -1,7 +1,7 @@
/* Mode support
*
- * (C) 2009 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2009 Adam <Adam@anope.org>
+ * Copyright (C) 2008-2009 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -12,6 +12,9 @@
#include "services.h"
#include "modules.h"
+/* List of pairs of user/channels and their stacker info */
+std::list<std::pair<void *, StackerInfo *> > ModeManager::StackerObjects;
+
std::map<char, UserMode *> ModeManager::UserModesByChar;
std::map<UserModeName, UserMode *> ModeManager::UserModesByName;
/* Channel modes */
@@ -76,139 +79,89 @@ void SetDefaultMLock()
}
}
-/** Add a user mode to Anope
- * @param Mode The mode
- * @param um A UserMode or UserMode derived class
- * @return true on success, false on error
+/** Default constructor
+ * @param mName The mode name
*/
-bool ModeManager::AddUserMode(char Mode, UserMode *um)
+UserMode::UserMode(UserModeName mName)
{
- um->ModeChar = Mode;
- bool ret = ModeManager::UserModesByChar.insert(std::make_pair(Mode, um)).second;
- if (ret)
- ret = ModeManager::UserModesByName.insert(std::make_pair(um->Name, um)).second;
-
- if (ret)
- {
- FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um));
- }
-
- return ret;
+ this->Name = mName;
+ this->Type = MODE_REGULAR;
}
-/** Add a channel mode to Anope
- * @param Mode The mode
- * @param cm A ChannelMode or ChannelMode derived class
- * @return true on success, false on error
+/** Default destructor
*/
-bool ModeManager::AddChannelMode(char Mode, ChannelMode *cm)
+UserMode::~UserMode()
{
- cm->ModeChar = Mode;
- bool ret = ModeManager::ChannelModesByChar.insert(std::make_pair(Mode, cm)).second;
- if (ret)
- ret = ModeManager::ChannelModesByName.insert(std::make_pair(cm->Name, cm)).second;
-
- if (ret)
- {
- /* Apply this mode to the new default mlock if its used */
- SetDefaultMLock();
-
- FOREACH_MOD(I_OnChannelModeAdd, OnChannelModeAdd(cm));
- }
+}
- return ret;
+UserModeParam::UserModeParam(UserModeName mName) : UserMode(mName)
+{
+ this->Type = MODE_PARAM;
}
-/** Find a channel mode
- * @param Mode The mode
- * @return The mode class
+/** Default constrcutor
+ * @param mName The mode name
*/
-ChannelMode *ModeManager::FindChannelModeByChar(char Mode)
+ChannelMode::ChannelMode(ChannelModeName mName)
{
- std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.find(Mode);
-
- if (it != ModeManager::ChannelModesByChar.end())
- {
- return it->second;
- }
-
- return NULL;
+ this->Name = mName;
+ this->Type = MODE_REGULAR;
}
-/** Find a user mode
- * @param Mode The mode
- * @return The mode class
+/** Default destructor
*/
-UserMode *ModeManager::FindUserModeByChar(char Mode)
+ChannelMode::~ChannelMode()
{
- std::map<char, UserMode *>::iterator it = ModeManager::UserModesByChar.find(Mode);
-
- if (it != ModeManager::UserModesByChar.end())
- {
- return it->second;
- }
-
- return NULL;
}
-/** Find a channel mode
- * @param Mode The modename
- * @return The mode class
+/** Default constructor
+ * @param mName The mode name
*/
-ChannelMode *ModeManager::FindChannelModeByName(ChannelModeName Name)
+ChannelModeList::ChannelModeList(ChannelModeName mName) : ChannelMode(mName)
{
- std::map<ChannelModeName, ChannelMode *>::iterator it = ModeManager::ChannelModesByName.find(Name);
-
- if (it != ModeManager::ChannelModesByName.end())
- {
- return it->second;
- }
-
- return NULL;
+ this->Type = MODE_LIST;
}
-/** Find a user mode
- * @param Mode The modename
- * @return The mode class
+/** Default destructor
*/
-UserMode *ModeManager::FindUserModeByName(UserModeName Name)
+ChannelModeList::~ChannelModeList()
{
- std::map<UserModeName, UserMode *>::iterator it = ModeManager::UserModesByName.find(Name);
-
- if (it != ModeManager::UserModesByName.end())
- {
- return it->second;
- }
-
- return NULL;
}
-/** Gets the channel mode char for a symbol (eg + returns v)
- * @param Value The symbol
- * @return The char
+/** Default constructor
+ * @param mName The mode name
+ * @param MinusArg true if the mode sends no arg when unsetting
*/
-char ModeManager::GetStatusChar(char Value)
+ChannelModeParam::ChannelModeParam(ChannelModeName mName, bool MinusArg) : ChannelMode(mName)
{
- std::map<char, ChannelMode *>::iterator it;
- ChannelMode *cm;
- ChannelModeStatus *cms;
-
- for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it)
- {
- cm = it->second;
+ this->Type = MODE_PARAM;
+ this->MinusNoArg = MinusArg;
+}
- if (cm->Type == MODE_STATUS)
- {
- cms = static_cast<ChannelModeStatus *>(cm);
+/** Default destructor
+ */
+ChannelModeParam::~ChannelModeParam()
+{
+}
- if (Value == cms->Symbol)
- {
- return it->first;
- }
- }
- }
+/** Default constructor
+ * @param mName The mode name
+ * @param mStatus A CUS_ value
+ * @param mSymbol The symbol for the mode, eg @ % +
+ * @param mProtectBotServ Should botserv clients reset this on themself if it gets unset?
+ */
+ChannelModeStatus::ChannelModeStatus(ChannelModeName mName, int16 mStatus, char mSymbol, bool mProtectBotServ) : ChannelMode(mName)
+{
+ this->Type = MODE_STATUS;
+ this->Status = mStatus;
+ this->Symbol = mSymbol;
+ this->ProtectBotServ = mProtectBotServ;
+}
- return 0;
+/** Default destructor
+ */
+ChannelModeStatus::~ChannelModeStatus()
+{
}
/** Is the key valid
@@ -326,7 +279,6 @@ void ChannelModeBan::DelMask(Channel *chan, const char *mask)
if (chan->ci && (akick = is_stuck(chan->ci, mask)))
stick_mask(chan->ci, akick);
-
}
/** Add an except to the channel
@@ -432,3 +384,449 @@ void ChannelModeInvite::DelMask(Channel *chan, const char *mask)
chan->name);
}
}
+
+void StackerInfo::AddMode(void *Mode, bool Set, const std::string &Param)
+{
+ ChannelMode *cm = NULL;
+ UserMode *um = NULL;
+ std::list<std::pair<void *, std::string> > *list, *otherlist;
+ std::list<std::pair<void *, std::string > >::iterator it;
+
+ if (Type == ST_CHANNEL)
+ cm = static_cast<ChannelMode *>(Mode);
+ else if (Type == ST_USER)
+ um = static_cast<UserMode *>(Mode);
+ if (Set)
+ {
+ list = &AddModes;
+ otherlist = &DelModes;
+ }
+ else
+ {
+ list = &DelModes;
+ otherlist = &AddModes;
+ }
+
+ /* Don't allow modes to be on the list twice, but only if they are
+ * not a list or status mode
+ */
+ if (cm && (cm->Type != MODE_LIST && cm->Type != MODE_STATUS))
+ {
+ /* Remove this mode from our list if it already exists */
+ for (it = list->begin(); it != list->end(); ++it)
+ {
+ if (it->first == Mode)
+ {
+ list->erase(it);
+ /* It can't be on the list twice */
+ break;
+ }
+ }
+
+ /* Remove the mode from the other list */
+ for (it = otherlist->begin(); it != otherlist->end(); ++it)
+ {
+ if (it->first == Mode)
+ {
+ otherlist->erase(it);
+ /* It can't be on the list twice */
+ break;
+ }
+ }
+ }
+ /* This is a list mode or a status mode, or a usermode */
+ else
+ {
+ /* If exactly the same thing is being set on the other list, remove it from the other list */
+ it = std::find(otherlist->begin(), otherlist->end(), std::make_pair(Mode, Param));
+ if (it != otherlist->end())
+ {
+ otherlist->erase(it);
+ /* If it is on the other list then just return, it would alreayd be set proprely */
+ return;
+ }
+ }
+
+ /* Add this mode and its param to our list */
+ list->push_back(std::make_pair(Mode, Param));
+}
+
+/** Get the stacker info for an item, if one doesnt exist it is created
+ * @param Item The user/channel etc
+ * @return The stacker info
+ */
+StackerInfo *ModeManager::GetInfo(void *Item)
+{
+ for (std::list<std::pair<void *, StackerInfo *> >::const_iterator it = StackerObjects.begin(); it !=
+StackerObjects.end(); ++it)
+ {
+ const std::pair<void *, StackerInfo *> &PItem = *it;
+ if (PItem.first == Item)
+ return PItem.second;
+ }
+
+ StackerInfo *s = new StackerInfo;
+ StackerObjects.push_back(std::make_pair(Item, s));
+ return s;
+}
+
+/** Build a list of mode strings to send to the IRCd from the mode stacker
+ * @param info The stacker info for a channel or user
+ * @return a list of strings
+ */
+std::list<std::string> ModeManager::BuildModeStrings(StackerInfo *info)
+{
+ std::list<std::string> ret;
+ std::list<std::pair<void *, std::string> >::iterator it;
+ std::string buf, parambuf;
+ ChannelMode *cm = NULL;
+ UserMode *um = NULL;
+ unsigned Modes = 0;
+
+ buf = "+";
+ for (it = info->AddModes.begin(); it != info->AddModes.end(); ++it)
+ {
+ if (++Modes > 12) //XXX this number needs to be recieved from the ircd
+ {
+ ret.push_back(buf + parambuf);
+ buf = "+";
+ parambuf.clear();
+ Modes = 1;
+ }
+
+ if (info->Type == ST_CHANNEL)
+ {
+ cm = static_cast<ChannelMode *>(it->first);
+ buf += cm->ModeChar;
+ }
+ else if (info->Type == ST_USER)
+ {
+ um = static_cast<UserMode *>(it->first);
+ buf += um->ModeChar;
+ }
+
+ if (!it->second.empty())
+ parambuf += " " + it->second;
+ }
+
+ if (buf[buf.length() - 1] == '+')
+ buf.erase(buf.length() - 1);
+
+ buf += "-";
+ for (it = info->DelModes.begin(); it != info->DelModes.end(); ++it)
+ {
+ if (++Modes > 12) //XXX this number needs to be recieved from the ircd
+ {
+ ret.push_back(buf + parambuf);
+ buf = "-";
+ parambuf.clear();
+ Modes = 1;
+ }
+
+ if (info->Type == ST_CHANNEL)
+ {
+ cm = static_cast<ChannelMode *>(it->first);
+ buf += cm->ModeChar;
+ }
+ else if (info->Type == ST_USER)
+ {
+ um = static_cast<UserMode *>(it->first);
+ buf += um->ModeChar;
+ }
+
+ if (!it->second.empty())
+ parambuf += " " + it->second;
+ }
+
+ if (buf[buf.length() - 1] == '-')
+ buf.erase(buf.length() - 1);
+
+ if (!buf.empty())
+ ret.push_back(buf + parambuf);
+
+ return ret;
+}
+
+/** Add a mode to the stacker, internal use only
+ * @param bi The client to set the modes from
+ * @param u The user
+ * @param um The user mode
+ * @param Set Adding or removing?
+ * @param Param A param, if there is one
+ */
+void ModeManager::StackerAddInternal(BotInfo *bi, User *u, UserMode *um, bool Set, const std::string &Param)
+{
+ StackerAddInternal(bi, u, um, Set, Param, ST_USER);
+}
+
+/** Add a mode to the stacker, internal use only
+ * @param bi The client to set the modes from
+ * @param c The channel
+ * @param cm The channel mode
+ * @param Set Adding or removing?
+ * @param Param A param, if there is one
+ */
+void ModeManager::StackerAddInternal(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const std::string &Param)
+{
+ StackerAddInternal(bi, c, cm, Set, Param, ST_CHANNEL);
+}
+
+/** Really add a mode to the stacker, internal use only
+ * @param bi The client to set the modes from
+ * @param Object The object, user/channel
+ * @param Mode The mode
+ * @param Set Adding or removing?
+ * @param Param A param, if there is one
+ * @param Type The type this is, user or channel
+ */
+void ModeManager::StackerAddInternal(BotInfo *bi, void *Object, void *Mode, bool Set, const std::string &Param, StackerType Type)
+{
+ StackerInfo *s = GetInfo(Object);
+ s->Type = Type;
+ s->AddMode(Mode, Set, Param);
+ if (bi)
+ s->bi = bi;
+ else if (Type == ST_CHANNEL)
+ s->bi = whosends(static_cast<Channel *>(Object)->ci);
+ else if (Type == ST_USER)
+ s->bi = NULL;
+}
+
+/** Add a user mode to Anope
+ * @param Mode The mode
+ * @param um A UserMode or UserMode derived class
+ * @return true on success, false on error
+ */
+bool ModeManager::AddUserMode(char Mode, UserMode *um)
+{
+ um->ModeChar = Mode;
+ bool ret = ModeManager::UserModesByChar.insert(std::make_pair(Mode, um)).second;
+ if (ret)
+ ret = ModeManager::UserModesByName.insert(std::make_pair(um->Name, um)).second;
+
+ if (ret)
+ {
+ FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um));
+ }
+
+ return ret;
+}
+
+/** Add a channel mode to Anope
+ * @param Mode The mode
+ * @param cm A ChannelMode or ChannelMode derived class
+ * @return true on success, false on error
+ */
+bool ModeManager::AddChannelMode(char Mode, ChannelMode *cm)
+{
+ cm->ModeChar = Mode;
+ bool ret = ModeManager::ChannelModesByChar.insert(std::make_pair(Mode, cm)).second;
+ if (ret)
+ ret = ModeManager::ChannelModesByName.insert(std::make_pair(cm->Name, cm)).second;
+
+ if (ret)
+ {
+ /* Apply this mode to the new default mlock if its used */
+ SetDefaultMLock();
+
+ FOREACH_MOD(I_OnChannelModeAdd, OnChannelModeAdd(cm));
+ }
+
+ return ret;
+}
+/** Find a channel mode
+ * @param Mode The mode
+ * @return The mode class
+ */
+ChannelMode *ModeManager::FindChannelModeByChar(char Mode)
+{
+ std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.find(Mode);
+
+ if (it != ModeManager::ChannelModesByChar.end())
+ {
+ return it->second;
+ }
+
+ return NULL;
+}
+
+/** Find a user mode
+ * @param Mode The mode
+ * @return The mode class
+ */
+UserMode *ModeManager::FindUserModeByChar(char Mode)
+{
+ std::map<char, UserMode *>::iterator it = ModeManager::UserModesByChar.find(Mode);
+
+ if (it != ModeManager::UserModesByChar.end())
+ {
+ return it->second;
+ }
+
+ return NULL;
+}
+
+/** Find a channel mode
+ * @param Mode The modename
+ * @return The mode class
+ */
+ChannelMode *ModeManager::FindChannelModeByName(ChannelModeName Name)
+{
+ std::map<ChannelModeName, ChannelMode *>::iterator it = ModeManager::ChannelModesByName.find(Name);
+
+ if (it != ModeManager::ChannelModesByName.end())
+ {
+ return it->second;
+ }
+
+ return NULL;
+}
+
+/** Find a user mode
+ * @param Mode The modename
+ * @return The mode class
+ */
+UserMode *ModeManager::FindUserModeByName(UserModeName Name)
+{
+ std::map<UserModeName, UserMode *>::iterator it = ModeManager::UserModesByName.find(Name);
+
+ if (it != ModeManager::UserModesByName.end())
+ {
+ return it->second;
+ }
+
+ return NULL;
+}
+
+/** Gets the channel mode char for a symbol (eg + returns v)
+ * @param Value The symbol
+ * @return The char
+ */
+char ModeManager::GetStatusChar(char Value)
+{
+ std::map<char, ChannelMode *>::iterator it;
+ ChannelMode *cm;
+ ChannelModeStatus *cms;
+
+ for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it)
+ {
+ cm = it->second;
+ if (cm->Type == MODE_STATUS)
+ {
+ cms = static_cast<ChannelModeStatus *>(cm);
+
+ if (Value == cms->Symbol)
+ {
+ return it->first;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Add a mode to the stacker to be set on a channel
+ * @param bi The client to set the modes from
+ * @param c The channel
+ * @param cm The channel mode
+ * @param Set true for setting, false for removing
+ * @param Param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const std::string &Param)
+{
+ StackerAddInternal(bi, c, cm, Set, Param);
+}
+
+/** Add a mode to the stacker to be set on a channel
+ * @param bi The client to set the modes from
+ * @param c The channel
+ * @param Name The channel mode name
+ * @param Set true for setting, false for removing
+ * @param Param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelModeName Name, bool Set, const std::string &Param)
+{
+ StackerAdd(bi, c, FindChannelModeByName(Name), Set, Param);
+}
+
+/** Add a mode to the stacker to be set on a channel
+ * @param bi The client to set the modes from
+ * @param c The channel
+ * @param Mode The mode char
+ * @param Set true for setting, false for removing
+ * @param Param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, Channel *c, const char Mode, bool Set, const std::string &Param)
+{
+ StackerAdd(bi, c, FindChannelModeByChar(Mode), Set, Param);
+}
+
+/** Add a mode to the stacker to be set on a user
+ * @param bi The client to set the modes from
+ * @param u The user
+ * @param um The user mode
+ * @param Set true for setting, false for removing
+ * @param param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const std::string &Param)
+{
+ StackerAddInternal(bi, u, um, Set, Param);
+}
+
+/** Add a mode to the stacker to be set on a user
+ * @param bi The client to set the modes from
+ * @param u The user
+ * @param Name The user mode name
+ * @param Set true for setting, false for removing
+ * @param Param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, User *u, UserModeName Name, bool Set, const std::string &Param)
+{
+ StackerAdd(bi, u, FindUserModeByName(Name), Set, Param);
+}
+
+/** Add a mode to the stacker to be set on a user
+ * @param bi The client to set the modes from
+ * @param u The user
+ * @param Mode The mode to be set
+ * @param Set true for setting, false for removing
+ * @param Param The param, if there is one
+ */
+void ModeManager::StackerAdd(BotInfo *bi, User *u, const char Mode, bool Set, const std::string &Param)
+{
+ StackerAdd(bi, u, FindUserModeByChar(Mode), Set, Param);
+}
+
+/** Process all of the modes in the stacker and send them to the IRCd to be set on channels/users
+ */
+void ModeManager::ProcessModes()
+{
+ if (!StackerObjects.empty())
+ {
+ for (std::list<std::pair<void *, StackerInfo *> >::const_iterator it = StackerObjects.begin(); it != StackerObjects.end(); ++it)
+ {
+ StackerInfo *s = it->second;
+ User *u = NULL;
+ Channel *c = NULL;
+ std::list<std::string> ModeStrings = BuildModeStrings(s);
+
+ if (s->Type == ST_USER)
+ u = static_cast<User *>(it->first);
+ else if (s->Type == ST_CHANNEL)
+ c = static_cast<Channel *>(it->first);
+ else
+ throw CoreException("ModeManager::ProcessModes got invalid Stacker Info type");
+
+ for (std::list<std::string>::iterator lit = ModeStrings.begin(); lit != ModeStrings.end(); ++lit)
+ {
+ if (c)
+ ircdproto->SendMode(s->bi, c->name, lit->c_str());
+ else if (u)
+ ircdproto->SendMode(u, lit->c_str());
+ }
+ delete it->second;
+ }
+ StackerObjects.clear();
+ }
+}
+
diff --git a/src/modules/cs_enforce.c b/src/modules/cs_enforce.c
index 6937d4dc8..d02ddd224 100644
--- a/src/modules/cs_enforce.c
+++ b/src/modules/cs_enforce.c
@@ -118,12 +118,9 @@ class CommandCSEnforce : public Command
u = user->user;
if (check_access(u, c->ci, CA_NOJOIN))
{
- av[0] = "+b";
get_idealban(ci, u, mask, sizeof(mask));
- av[1] = mask;
reason = getstring(u, CHAN_NOT_ALLOWED_TO_JOIN);
- ircdproto->SendMode(whosends(ci), ci->name, "+b %s %lu", mask, time(NULL));
- chan_set_modes(Config.s_ChanServ, c, 2, av, 1);
+ c->SetMode(NULL, CMODE_BAN, mask);
ircdproto->SendKick(whosends(ci), ci->name, u->nick, "%s", reason);
av[0] = ci->name;
av[1] = u->nick;
@@ -159,14 +156,11 @@ class CommandCSEnforce : public Command
u = user->user;
if (!nick_identified(u))
{
- av[0] = "+b";
get_idealban(ci, u, mask, sizeof(mask));
- av[1] = mask;
reason = getstring(u, CHAN_NOT_ALLOWED_TO_JOIN);
if (!c->HasMode(CMODE_REGISTERED))
{
- ircdproto->SendMode(whosends(ci), ci->name, "+b %s %lu", mask, time(NULL));
- chan_set_modes(Config.s_ChanServ, c, 2, av, 1);
+ c->SetMode(NULL, CMODE_BAN, mask);
}
ircdproto->SendKick(whosends(ci), ci->name, u->nick, "%s", reason);
av[0] = ci->name;
diff --git a/src/modules/cs_tban.c b/src/modules/cs_tban.c
index 7da2a90ed..7f84f3e85 100644
--- a/src/modules/cs_tban.c
+++ b/src/modules/cs_tban.c
@@ -179,33 +179,18 @@ class TempBan : public Timer
void Tick(time_t ctime)
{
- const char *av[3];
Channel *c;
- av[0] = "-b";
- av[1] = mask.c_str();
-
if ((c = findchan(chan.c_str())) && c->ci)
{
- ircdproto->SendMode(whosends(c->ci), c->name, "-b %s", av[1]);
- chan_set_modes(Config.s_ChanServ, c, 2, av, 1);
+ c->RemoveMode(NULL, CMODE_BAN, mask);
}
}
};
void addBan(Channel *c, time_t timeout, char *banmask)
{
- const char *av[3];
- char *cb[2];
-
- cb[0] = c->name;
- cb[1] = banmask;
-
- av[0] = "+b";
- av[1] = banmask;
-
- ircdproto->SendMode(whosends(c->ci), c->name, "+b %s", av[1]);
- chan_set_modes(Config.s_ChanServ, c, 2, av, 1);
+ c->SetMode(NULL, CMODE_BAN, banmask);
me->AddCallBack(new TempBan(timeout, c->name, banmask));
}
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
index b4b07c6bd..b2950c2e8 100644
--- a/src/nickalias.cpp
+++ b/src/nickalias.cpp
@@ -65,10 +65,10 @@ NickAlias::~NickAlias()
/* Second thing to do: look for an user using the alias
* being deleted, and make appropriate changes */
- if ((u = finduser(this->nick)))
+ if ((u = finduser(this->nick)) && u->nc)
{
- if (ircd->modeonunreg)
- common_svsmode(finduser(this->nick), ircd->modeonunreg, "1");
+ ircdproto->SendAccountLogout(u, u->nc);
+ ircdproto->SendUnregisteredNick(u);
u->nc = NULL;
}
diff --git a/src/nickcore.cpp b/src/nickcore.cpp
index db0445d17..b009c25f8 100644
--- a/src/nickcore.cpp
+++ b/src/nickcore.cpp
@@ -46,6 +46,7 @@ NickCore::~NickCore()
if (user->nc && user->nc == this)
{
ircdproto->SendAccountLogout(user, user->nc);
+ ircdproto->SendUnregisteredNick(user);
user->nc = NULL;
FOREACH_MOD(I_OnNickLogout, OnNickLogout(user));
}
diff --git a/src/protocol.cpp b/src/protocol.cpp
index cf47bb61d..e80254863 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -75,6 +75,16 @@ void IRCDProto::SendMode(BotInfo *bi, const char *dest, const char *fmt, ...)
SendModeInternal(bi, dest, buf);
}
+void IRCDProto::SendMode(User *u, const char *fmt, ...)
+{
+ va_list args;
+ char buf[BUFSIZE] = "";
+ va_start(args, fmt);
+ vsnprintf(buf, BUFSIZE - 1, fmt, args);
+ va_end(args);
+ SendModeInternal(u, buf);
+}
+
void IRCDProto::SendKick(BotInfo *bi, const char *chan, const char *user, const char *fmt, ...)
{
va_list args;
diff --git a/src/protocol/bahamut.c b/src/protocol/bahamut.c
index c3ff0747c..d60641378 100644
--- a/src/protocol/bahamut.c
+++ b/src/protocol/bahamut.c
@@ -23,7 +23,6 @@ IRCDVar myIrcd[] = {
"+o", /* Channel Umode used by Botserv bots */
1, /* SVSNICK */
0, /* Vhost */
- "-r+d", /* Mode on UnReg */
1, /* Supports SGlines */
1, /* Supports SQlines */
1, /* Supports SZlines */
@@ -142,49 +141,6 @@ void bahamut_cmd_chghost(const char *nick, const char *vhost)
class BahamutIRCdProto : public IRCDProto
{
- void ProcessUsermodes(User *user, int ac, const char **av)
- {
- int add = 1; /* 1 if adding modes, 0 if deleting */
- const char *modes = av[0];
- --ac;
- if (debug) alog("debug: Changing mode for %s to %s", user->nick, modes);
- while (*modes) {
- if (add)
- user->SetMode(*modes);
- else
- user->RemoveMode(*modes);
-
- switch (*modes++) {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'd':
- if (!ac) {
- alog("user: umode +d with no parameter (?) for user %s", user->nick);
- break;
- }
- --ac;
- ++av;
- break;
- case 'o':
- if (add) {
- ++opcnt;
- if (Config.WallOper) ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
- }
- else --opcnt;
- break;
- case 'r':
- if (add && !nick_identified(user)) {
- common_svsmode(user, "-r", NULL);
- user->RemoveMode(CMODE_REGISTERED);
- }
- }
- }
- }
-
void SendModeInternal(BotInfo *source, const char *dest, const char *buf)
{
if (!buf) return;
@@ -192,6 +148,12 @@ class BahamutIRCdProto : public IRCDProto
else send_cmd(source->nick, "MODE %s %s", dest, buf);
}
+ void SendModeInternal(User *u, const char *buf)
+ {
+ if (!buf) return;
+ send_cmd(Config.ServerName, "SVSMODE %s %ld %s", u->nick, static_cast<long>(u->timestamp), buf);
+ }
+
/* SVSHOLD - set */
void SendSVSHold(const char *nick)
{
@@ -217,11 +179,6 @@ class BahamutIRCdProto : public IRCDProto
else send_cmd(Config.ServerName, "SVSMODE %s %s", name, mode);
}
- void SendBotOp(const char *nick, const char *chan)
- {
- SendMode(findbot(nick), chan, "%s %s", ircd->botchanumode, nick);
- }
-
/* SQLINE */
void SendSQLine(const char *mask, const char *reason)
{
@@ -329,7 +286,7 @@ class BahamutIRCdProto : public IRCDProto
*/
void SendSVSMode(User *u, int ac, const char **av)
{
- send_cmd(Config.ServerName, "SVSMODE %s %ld %s", u->nick, static_cast<long>(u->timestamp), merge_args(ac, av));
+ this->SendModeInternal(u, merge_args(ac, av));
}
void SendEOB()
@@ -360,7 +317,8 @@ class BahamutIRCdProto : public IRCDProto
/* nc_change was = 1, and there is no na->status */
void SendUnregisteredNick(User *u)
{
- common_svsmode(u, "+d", "1");
+ u->RemoveMode(UMODE_REGISTERED);
+ ircdproto->SendMode(u, "+d 1");
}
/* SERVER */
@@ -397,7 +355,8 @@ class BahamutIRCdProto : public IRCDProto
u->nc->Extend("authenticationtoken", sstrdup(svidbuf));
- common_svsmode(u, "+rd", svidbuf);
+ u->SetMode(UMODE_REGISTERED);
+ ircdproto->SendMode(u, "+d %s", svidbuf);
}
} ircd_proto;
@@ -442,7 +401,7 @@ int anope_event_nick(const char *source, int ac, const char **av)
*/
user->CheckAuthenticationToken(av[7]);
- ircdproto->ProcessUsermodes(user, 1, &av[3]);
+ UserSetInternalModes(user, 1, &av[3]);
}
} else {
do_nick(source, av[0], NULL, NULL, NULL, NULL,
@@ -723,6 +682,7 @@ void moduleAddModes()
ModeManager::AddUserMode('r', new UserMode(UMODE_REGISTERED));
ModeManager::AddUserMode('s', new UserMode(UMODE_SNOMASK));
ModeManager::AddUserMode('w', new UserMode(UMODE_WALLOPS));
+ ModeManager::AddUserMode('d', new UserMode(UMODE_DEAF));
/* b/e/I */
ModeManager::AddChannelMode('b', new ChannelModeBan());
diff --git a/src/protocol/inspircd11.c b/src/protocol/inspircd11.c
index 6c2b22c2b..b6c24bf18 100644
--- a/src/protocol/inspircd11.c
+++ b/src/protocol/inspircd11.c
@@ -40,7 +40,6 @@ IRCDVar myIrcd[] = {
"+ao", /* Channel Umode used by Botserv bots */
1, /* SVSNICK */
1, /* Vhost */
- "-r", /* Mode on UnReg */
1, /* Supports SGlines */
1, /* Supports SQlines */
1, /* Supports SZlines */
@@ -159,60 +158,6 @@ void inspircd_cmd_pass(const char *pass)
class InspIRCdProto : public IRCDProto
{
-
- void ProcessUsermodes(User *user, int ac, const char **av)
- {
- int add = 1; /* 1 if adding modes, 0 if deleting */
- const char *modes = av[0];
- --ac;
- if (debug) alog("debug: Changing mode for %s to %s", user->nick, modes);
- while (*modes) {
- if (add)
- user->SetMode(*modes);
- else
- user->RemoveMode(*modes);
-
- switch (*modes++) {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'o':
- if (add) {
- ++opcnt;
- if (Config.WallOper) ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
- }
- else --opcnt;
- break;
- case 'r':
- if (add && !nick_identified(user))
- SendUnregisteredNick(user);
- break;
- case 'x':
- if (add && user->vhost)
- {
- /* If +x is recieved then User::vhost IS the cloaked host,
- * set the cloaked host correctly and destroy the vhost - Adam
- */
- user->SetCloakedHost(user->vhost);
- delete [] user->vhost;
- user->vhost = NULL;
- }
- else
- {
- if (user->vhost)
- delete [] user->vhost;
- user->vhost = NULL;
- }
- user->UpdateHost();
- }
- }
- }
-
- /* *INDENT-ON* */
-
void SendAkillDel(const char *user, const char *host)
{
send_cmd(Config.s_OperServ, "GLINE %s@%s", user, host);
@@ -253,7 +198,7 @@ class InspIRCdProto : public IRCDProto
void SendSVSMode(User *u, int ac, const char **av)
{
- send_cmd(Config.s_NickServ, "MODE %s %s", u->nick, merge_args(ac, av));
+ this->SendModeInternal(u, merge_args(ac, av));
}
void SendNumericInternal(const char *source, int numeric, const char *dest, const char *buf)
@@ -273,6 +218,12 @@ class InspIRCdProto : public IRCDProto
send_cmd(source ? source->nick : Config.s_OperServ, "FMODE %s %u %s", dest, static_cast<unsigned>(c ? c->creation_time : time(NULL)), buf);
}
+ void SendModeInternal(User *u, const char *buf)
+ {
+ if (!buf) return;
+ send_cmd(Config.s_NickServ, "MODE %s %s", u->nick, buf);
+ }
+
void SendClientIntroduction(const char *nick, const char *user, const char *host, const char *real, const char *modes, const char *uid)
{
send_cmd(Config.ServerName, "NICK %ld %s %s %s %s %s 0.0.0.0 :%s", static_cast<long>(time(NULL)), nick, host, host, user, modes, real);
@@ -291,12 +242,6 @@ class InspIRCdProto : public IRCDProto
send_cmd(Config.ServerName, "NOTICE @%s :%s", dest, buf);
}
- void SendBotOp(const char *nick, const char *chan)
- {
- SendMode(findbot(nick), chan, "%s %s %s", ircd->botchanumode, nick, nick);
- }
-
-
/* SERVER services-dev.chatspike.net password 0 :Description here */
void SendServer(Server *server)
{
@@ -388,8 +333,7 @@ class InspIRCdProto : public IRCDProto
/* SVSMODE +- */
void SendUnregisteredNick(User *u)
{
- if (u->HasMode(UMODE_REGISTERED))
- common_svsmode(u, "-r", NULL);
+ u->RemoveMode(UMODE_REGISTERED);
}
void SendSVSJoin(const char *source, const char *nick, const char *chan, const char *param)
@@ -832,7 +776,7 @@ int anope_event_nick(const char *source, int ac, const char **av)
*/
user->CheckAuthenticationToken(av[0]);
- ircdproto->ProcessUsermodes(user, 1, &av[5]);
+ UserSetInternalModes(user, 1, &av[5]);
user->SetCloakedHost(av[3]);
}
}
diff --git a/src/protocol/inspircd12.cpp b/src/protocol/inspircd12.cpp
index da04bddb4..30d64f7fa 100644
--- a/src/protocol/inspircd12.cpp
+++ b/src/protocol/inspircd12.cpp
@@ -40,7 +40,6 @@ IRCDVar myIrcd[] = {
"+ao", /* Channel Umode used by Botserv bots */
1, /* SVSNICK */
1, /* Vhost */
- "-r", /* Mode on UnReg */
0, /* Supports SGlines */
1, /* Supports SQlines */
1, /* Supports SZlines */
@@ -164,65 +163,6 @@ void inspircd_cmd_pass(const char *pass)
class InspIRCdProto : public IRCDProto
{
-
- void ProcessUsermodes(User *user, int ac, const char **av)
- {
- int add = 1; /* 1 if adding modes, 0 if deleting */
- const char *modes = av[0];
- --ac;
- if (debug) alog("debug: Changing mode for %s to %s", user->nick, modes);
- while (*modes) {
- if (add)
- user->SetMode(*modes);
- else
- user->RemoveMode(*modes);
-
- switch (*modes++) {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'o':
- if (add) {
- ++opcnt;
- if (Config.WallOper) ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
- }
- else --opcnt;
- break;
- case 'r':
- /* The users server is syncing, do not
- * set them -r yet - Adam
- */
- if (user->server->sync == SSYNC_IN_PROGRESS)
- break;
- if (add && !nick_identified(user))
- SendUnregisteredNick(user);
- break;
- case 'x':
- if (add && user->vhost)
- {
- /* If +x is recieved then User::vhost IS the cloaked host,
- * set the cloaked host correctly and destroy the vhost - Adam
- */
- user->SetCloakedHost(user->vhost);
- delete [] user->vhost;
- user->vhost = NULL;
- }
- else
- {
- if (user->vhost)
- delete [] user->vhost;
- user->vhost = NULL;
- }
- user->UpdateHost();
- }
- }
- }
-
- /* *INDENT-ON* */
-
void SendAkillDel(const char *user, const char *host)
{
BotInfo *bi = findbot(Config.s_OperServ);
@@ -266,8 +206,7 @@ class InspIRCdProto : public IRCDProto
void SendSVSMode(User *u, int ac, const char **av)
{
- BotInfo *bi = findbot(Config.s_NickServ);
- send_cmd(bi->uid, "MODE %s %s", u->GetUID().c_str(), merge_args(ac, av));
+ this->SendModeInternal(u, merge_args(ac, av));
}
void SendNumericInternal(const char *source, int numeric, const char *dest, const char *buf)
@@ -286,6 +225,12 @@ class InspIRCdProto : public IRCDProto
send_cmd(source ? source->uid : TS6SID, "FMODE %s %u %s", dest, static_cast<unsigned>(c ? c->creation_time : time(NULL)), buf);
}
+ void SendModeInternal(User *u, const char *buf)
+ {
+ if (!buf) return;
+ send_cmd(findbot(Config.s_NickServ)->uid, "MODE %s %s", u->GetUID().c_str(), buf);
+ }
+
void SendClientIntroduction(const char *nick, const char *user, const char *host, const char *real, const char *modes, const char *uid)
{
send_cmd(TS6SID, "UID %s %ld %s %s %s %s 0.0.0.0 %ld %s :%s", uid, static_cast<long>(time(NULL)), nick, host, host, user, static_cast<long>(time(NULL)), modes, real);
@@ -305,11 +250,6 @@ class InspIRCdProto : public IRCDProto
send_cmd(TS6SID, "NOTICE @%s :%s", dest, buf);
}
- void SendBotOp(const char *nick, const char *chan)
- {
- SendMode(findbot(nick), chan, "%s %s %s", ircd->botchanumode, nick, nick);
- }
-
/* SERVER services-dev.chatspike.net password 0 :Description here */
void SendServer(Server *server)
{
@@ -401,8 +341,7 @@ class InspIRCdProto : public IRCDProto
/* SVSMODE -r */
void SendUnregisteredNick(User *u)
{
- if (u->HasMode(UMODE_REGISTERED))
- common_svsmode(u, "-r", NULL);
+ u->RemoveMode(UMODE_REGISTERED);
}
void SendSVSJoin(const char *source, const char *nick, const char *chan, const char *param)
@@ -466,7 +405,7 @@ class InspIRCdProto : public IRCDProto
if (!u->nc)
return;
- common_svsmode(u, "+r", NULL);
+ u->SetMode(UMODE_REGISTERED);
}
} ircd_proto;
@@ -907,7 +846,7 @@ int anope_event_uid(const char *source, int ac, const char **av)
{
validate_user(user);
if (user->HasMode(UMODE_REGISTERED))
- common_svsmode(user, "-r", NULL);
+ user->RemoveMode(UMODE_REGISTERED);
}
user = NULL;
@@ -924,7 +863,7 @@ int anope_event_uid(const char *source, int ac, const char **av)
{
prev_u_intro = user;
}
- ircdproto->ProcessUsermodes(user, 1, &av[8]);
+ UserSetInternalModes(user, 1, &av[8]);
user->SetCloakedHost(av[4]);
}
@@ -1193,7 +1132,7 @@ int anope_event_endburst(const char *source, int ac, const char **av)
{
validate_user(u);
if (u->HasMode(UMODE_REGISTERED))
- common_svsmode(u, "-r", NULL);
+ u->RemoveMode(UMODE_REGISTERED);
}
alog("Processed ENDBURST for %s", s->name);
diff --git a/src/protocol/ratbox.c b/src/protocol/ratbox.c
index 73820de7e..249f8b685 100644
--- a/src/protocol/ratbox.c
+++ b/src/protocol/ratbox.c
@@ -21,7 +21,6 @@ IRCDVar myIrcd[] = {
"+o", /* Channel Umode used by Botserv bots */
0, /* SVSNICK */
0, /* Vhost */
- NULL, /* Mode on UnReg */
1, /* Supports SGlines */
1, /* Supports SQlines */
0, /* Supports SZlines */
@@ -166,35 +165,6 @@ void ratbox_cmd_pass(const char *pass)
class RatboxProto : public IRCDTS6Proto
{
- void ProcessUsermodes(User *user, int ac, const char **av)
- {
- int add = 1; /* 1 if adding modes, 0 if deleting */
- const char *modes = av[0];
- --ac;
- if (debug) alog("debug: Changing mode for %s to %s", user->nick, modes);
- while (*modes) {
- if (add)
- user->SetMode(*modes);
- else
- user->RemoveMode(*modes);
-
- switch (*modes++) {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'o':
- if (add) {
- ++opcnt;
- if (Config.WallOper) ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
- }
- else --opcnt;
- }
- }
- }
-
void SendGlobopsInternal(const char *source, const char *buf)
{
if (source)
@@ -266,7 +236,7 @@ class RatboxProto : public IRCDTS6Proto
void SendSVSMode(User *u, int ac, const char **av)
{
- send_cmd(TS6SID, "SVSMODE %s %s", u->nick, av[0]);
+ this->SendModeInternal(u, merge_args(ac, av));
}
/* SERVER name hop descript */
@@ -315,6 +285,12 @@ class RatboxProto : public IRCDTS6Proto
else send_cmd(TS6SID, "MODE %s %s", dest, buf);
}
+ void SendModeInternal(User *u, const char *buf)
+ {
+ if (!buf) return;
+ send_cmd(TS6SID, "SVSMODE %s %s", u->nick, buf);
+ }
+
void SendKickInternal(BotInfo *bi, const char *chan, const char *user, const char *buf)
{
User *u = finduser(user);
@@ -327,12 +303,6 @@ class RatboxProto : public IRCDTS6Proto
send_cmd(NULL, "NOTICE @%s :%s", dest, buf);
}
- void SendBotOp(const char *nick, const char *chan)
- {
- BotInfo *bi = findbot(nick);
- ratbox_cmd_tmode(nick, chan, "%s %s", ircd->botchanumode, bi ? bi->uid.c_str() : nick);
- }
-
/* QUIT */
void SendQuitInternal(BotInfo *bi, const char *buf)
{
@@ -440,7 +410,7 @@ int anope_event_nick(const char *source, int ac, const char **av)
*/
user->CheckAuthenticationToken(av[2]);
- ircdproto->ProcessUsermodes(user, 1, &av[3]);
+ UserSetInternalModes(user, 1, &av[3]);
}
} else {
if (ac == 2)
diff --git a/src/protocol/unreal32.c b/src/protocol/unreal32.c
index bf619d27d..35eedfbb0 100644
--- a/src/protocol/unreal32.c
+++ b/src/protocol/unreal32.c
@@ -23,7 +23,6 @@ IRCDVar myIrcd[] = {
"+ao", /* Channel Umode used by Botserv bots */
1, /* SVSNICK */
1, /* Vhost */
- "-r+d", /* Mode on UnReg */
1, /* Supports SGlines */
1, /* Supports SQlines */
1, /* Supports SZlines */
@@ -169,85 +168,6 @@ void unreal_cmd_chgident(const char *nick, const char *vIdent)
class UnrealIRCdProto : public IRCDProto
{
- void ProcessUsermodes(User *user, int ac, const char **av)
- {
- int add = 1; /* 1 if adding modes, 0 if deleting */
- const char *modes = av[0];
- --ac;
- if (!user || !modes) return; /* Prevent NULLs from doing bad things */
- if (debug) alog("debug: Changing mode for %s to %s", user->nick, modes);
-
- while (*modes) {
- if (add)
- user->SetMode(*modes);
- else
- user->RemoveMode(*modes);
-
- switch (*modes++)
- {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'd':
- if (ac <= 0)
- break;
- if (isdigit(*av[1]))
- {
- /* +d was setting a service stamp, ignore the usermode +d */
- if (add)
- user->RemoveMode('d');
- else
- user->SetMode('d');
- }
- break;
- case 'o':
- if (add) {
- ++opcnt;
- if (Config.WallOper) ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
- }
- else --opcnt;
- break;
- case 'r':
- if (add && !nick_identified(user)) {
- common_svsmode(user, "-r", NULL);
- }
- break;
- case 't':
- if (add && !user->vhost && !user->GetCloakedHost().empty())
- {
- /* The user was introduced with a vhost as their host, so we don't
- * know their cloaked host.. Set their vhost correctly and clear
- * the chost so we can request it later (if needed)
- */
- user->SetDisplayedHost(user->GetCloakedHost());
- user->chost.clear();
- }
- break;
- case 'x':
- if (add)
- {
- /* We don't know their cloaked host.. get it */
- if (user->GetCloakedHost().empty())
- send_cmd(NULL, "USERHOST :%s", user->nick);
- }
- else
- {
- if (user->vhost)
- delete [] user->vhost;
- user->vhost = NULL;
- }
- user->UpdateHost();
- break;
- default:
- break;
- }
- }
- }
-
-
/* SVSNOOP */
void SendSVSNOOP(const char *server, int set)
{
@@ -266,8 +186,9 @@ class UnrealIRCdProto : public IRCDProto
void SendVhostDel(User *u)
{
- common_svsmode(u, "-xt", NULL);
- common_svsmode(u, "+x", NULL);
+ u->RemoveMode(UMODE_CLOAK);
+ u->RemoveMode(UMODE_VHOST);
+ u->SetMode(UMODE_CLOAK);
}
void SendAkill(const char *user, const char *host, const char *who, time_t when, time_t expires, const char *reason)
@@ -301,7 +222,7 @@ class UnrealIRCdProto : public IRCDProto
{
if (ac >= 1) {
if (!u || !av[0]) return;
- send_cmd(Config.ServerName, "v %s %s", u->nick, merge_args(ac, av));
+ this->SendModeInternal(u, merge_args(ac, av));
}
}
@@ -311,6 +232,12 @@ class UnrealIRCdProto : public IRCDProto
send_cmd(source->nick, "G %s %s", dest, buf);
}
+ void SendModeInternal(User *u, const char *buf)
+ {
+ if (!buf) return;
+ send_cmd(Config.ServerName, "v %s %s", u->nick, buf);
+ }
+
void SendClientIntroduction(const char *nick, const char *user, const char *host, const char *real, const char *modes, const char *uid)
{
EnforceQlinedNick(nick, Config.s_BotServ);
@@ -331,11 +258,6 @@ class UnrealIRCdProto : public IRCDProto
send_cmd(source->nick, "B @%s :%s", dest, buf);
}
- void SendBotOp(const char *nick, const char *chan)
- {
- SendMode(findbot(nick), chan, "%s %s %s", myIrcd->botchanumode, nick, nick);
- }
-
/* SERVER name hop descript */
/* Unreal 3.2 actually sends some info about itself in the descript area */
void SendServer(Server *server)
@@ -548,7 +470,14 @@ class UnrealIRCdProto : public IRCDProto
u->nc->Extend("authenticationtoken", sstrdup(svidbuf));
- common_svsmode(u, "+rd", svidbuf);
+ u->SetMode(UMODE_REGISTERED);
+ ircdproto->SendMode(u, "+d %s", svidbuf);
+ }
+
+ void SendUnregisteredNick(User *u)
+ {
+ u->RemoveMode(UMODE_REGISTERED);
+ ircdproto->SendMode(u, "+d 1");
}
} ircd_proto;
@@ -665,6 +594,11 @@ int anope_event_mode(const char *source, int ac, const char **av)
if (ac < 2)
return MOD_CONT;
+ /* When a server sends a mode string it is appended with a timestamp
+ * we don't need it
+ */
+ if (findserver(servlist, source))
+ --ac;
if (*av[0] == '#' || *av[0] == '&') {
do_cmode(source, ac, av);
} else {
@@ -895,7 +829,7 @@ int anope_event_nick(const char *source, int ac, const char **av)
*/
user->CheckAuthenticationToken(av[6]);
- ircdproto->ProcessUsermodes(user, 1, &av[7]);
+ UserSetInternalModes(user, 1, &av[7]);
}
} else {
@@ -910,7 +844,7 @@ int anope_event_nick(const char *source, int ac, const char **av)
*/
user->CheckAuthenticationToken(av[6]);
- ircdproto->ProcessUsermodes(user, 1, &av[7]);
+ UserSetInternalModes(user, 1, &av[7]);
}
}
} else {
@@ -1194,7 +1128,7 @@ void moduleAddModes()
ModeManager::AddChannelMode('i', new ChannelMode(CMODE_INVITE));
ModeManager::AddChannelMode('j', new ChannelModeParam(CMODE_JOINFLOOD, true));
ModeManager::AddChannelMode('k', new ChannelModeKey());
- ModeManager::AddChannelMode('l', new ChannelModeParam(CMODE_LIMIT));
+ ModeManager::AddChannelMode('l', new ChannelModeParam(CMODE_LIMIT, true));
ModeManager::AddChannelMode('m', new ChannelMode(CMODE_MODERATED));
ModeManager::AddChannelMode('n', new ChannelMode(CMODE_NOEXTERNAL));
ModeManager::AddChannelMode('p', new ChannelMode(CMODE_PRIVATE));
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index 07bdc1c15..8c806fc02 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -78,7 +78,7 @@ ChannelInfo::~ChannelInfo()
if (this->c && this->c->HasMode(CMODE_PERM))
{
- this->c->RemoveMode(CMODE_PERM);
+ this->c->RemoveMode(NULL, CMODE_PERM);
ircdproto->SendMode(whosends(this), this->name, "-%c", ModeManager::FindChannelModeByName(CMODE_PERM)->ModeChar);
}
diff --git a/src/users.c b/src/users.c
index 4409a221d..eee3fda49 100644
--- a/src/users.c
+++ b/src/users.c
@@ -469,26 +469,83 @@ const bool User::HasMode(UserModeName Name) const
return modes[Name];
}
+/** Set a mode internally on the user, the IRCd is not informed
+ * @param um The user mode
+ * @param Param The param, if there is one
+ */
+void User::SetModeInternal(UserMode *um, const std::string &Param)
+{
+ if (!um)
+ return;
+
+ modes[um->Name] = true;
+ if (!Param.empty())
+ {
+ Params.insert(std::make_pair(um->Name, Param));
+ }
+
+ FOREACH_MOD(I_OnUserModeSet, OnUserModeSet(this, um->Name));
+}
+
+/** Remove a mode internally on the user, the IRCd is not informed
+ * @param um The user mode
+ */
+void User::RemoveModeInternal(UserMode *um)
+{
+ if (!um)
+ return;
+
+ modes[um->Name] = false;
+ std::map<UserModeName, std::string>::iterator it = Params.find(um->Name);
+ if (it != Params.end())
+ {
+ Params.erase(it);
+ }
+
+ FOREACH_MOD(I_OnUserModeUnset, OnUserModeUnset(this, um->Name));
+}
+
+/** Set a mode on the user
+ * @param um The user mode
+ * @param Param Optional param for the mode
+ */
+void User::SetMode(UserMode *um, const std::string &Param)
+{
+ if (!um)
+ return;
+
+ SetModeInternal(um, Param);
+ ModeManager::StackerAdd(NULL, this, um, true, Param);
+}
+
/** Set a mode on the user
* @param Name The mode name
+ * @param param Optional param for the mode
*/
-void User::SetMode(UserModeName Name)
+void User::SetMode(UserModeName Name, const std::string &Param)
{
- modes[Name] = true;
- FOREACH_MOD(I_OnUserModeSet, OnUserModeSet(this, Name));
+ SetMode(ModeManager::FindUserModeByName(Name), Param);
}
/* Set a mode on the user
* @param ModeChar The mode char
+ * @param param Optional param for the mode
*/
-void User::SetMode(char ModeChar)
+void User::SetMode(char ModeChar, const std::string &Param)
{
- UserMode *um;
+ SetMode(ModeManager::FindUserModeByChar(ModeChar), Param);
+}
- if ((um = ModeManager::FindUserModeByChar(ModeChar)))
- {
- SetMode(um->Name);
- }
+/** Remove a mode on the user
+ * @param um The user mode
+ */
+void User::RemoveMode(UserMode *um)
+{
+ if (!um)
+ return;
+
+ RemoveModeInternal(um);
+ ModeManager::StackerAdd(NULL, this, um, false);
}
/** Remove a mode from the user
@@ -496,8 +553,7 @@ void User::SetMode(char ModeChar)
*/
void User::RemoveMode(UserModeName Name)
{
- modes[Name] = false;
- FOREACH_MOD(I_OnUserModeUnset, OnUserModeUnset(this, Name));
+ RemoveMode(ModeManager::FindUserModeByName(Name));
}
/** Remove a mode from the user
@@ -505,11 +561,55 @@ void User::RemoveMode(UserModeName Name)
*/
void User::RemoveMode(char ModeChar)
{
- UserMode *um;
+ RemoveMode(ModeManager::FindUserModeByChar(ModeChar));
+}
- if ((um = ModeManager::FindUserModeByChar(ModeChar)))
+/** Set a string of modes on a user
+ * @param modes The modes
+ */
+void User::SetModes(const std::string &modes, ...)
+{
+ char buf[BUFSIZE] = "";
+ va_list args;
+ std::string modebuf, sbuf;
+ int add = -1;
+ va_start(args, modes.c_str());
+ vsnprintf(buf, BUFSIZE - 1, modes.c_str(), args);
+ va_end(args);
+
+ spacesepstream sep(buf);
+ sep.GetToken(modebuf);
+ for (unsigned i = 0; i < modebuf.size(); ++i)
{
- RemoveMode(um->Name);
+ UserMode *um;
+
+ switch (modebuf[i])
+ {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add == -1)
+ continue;
+ um = ModeManager::FindUserModeByChar(modebuf[i]);
+ if (!um)
+ continue;
+ }
+
+ if (add)
+ {
+ if (um->Type == MODE_PARAM && sep.GetToken(sbuf))
+ this->SetMode(um, sbuf);
+ else
+ this->SetMode(um);
+ }
+ else if (add == 0)
+ {
+ this->RemoveMode(um);
+ }
}
}
@@ -854,7 +954,7 @@ void do_umode(const char *source, int ac, const char **av)
return;
}
- ircdproto->ProcessUsermodes(user, ac - 1, &av[1]);
+ UserSetInternalModes(user, ac - 1, &av[1]);
}
/*************************************************************************/
@@ -1083,3 +1183,90 @@ char *create_mask(User * u)
}
/*************************************************************************/
+
+/** Set modes internally on a user
+ * @param user The user
+ * @param ac Number of args
+ * @param av Args
+ */
+void UserSetInternalModes(User *user, int ac, const char **av)
+{
+ int add = -1, j = 0;
+ const char *modes = av[0];
+ if (!user || !modes)
+ return;
+
+ if (debug)
+ alog("debug: Changing user modes for %s to %s", user->nick, merge_args(ac, av));
+
+ for (; *modes; *modes++)
+ {
+ UserMode *um;
+
+ switch (*modes)
+ {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add == -1)
+ continue;
+ um = ModeManager::FindUserModeByChar(*modes);
+ if (!um)
+ continue;
+ }
+
+ if (um->Type == MODE_REGULAR)
+ {
+ if (add)
+ user->SetModeInternal(um);
+ else
+ user->RemoveModeInternal(um);
+ }
+ else if (++j < ac)
+ {
+ if (add)
+ user->SetModeInternal(um, av[j]);
+ else
+ user->RemoveModeInternal(um);
+ }
+
+ switch (um->Name)
+ {
+ case UMODE_OPER:
+ if (add)
+ {
+ ++opcnt;
+ if (Config.WallOper)
+ ircdproto->SendGlobops(Config.s_OperServ, "\2%s\2 is now an IRC operator.", user->nick);
+ }
+ else
+ --opcnt;
+ break;
+ case UMODE_REGISTERED:
+ if (add && !nick_identified(user))
+ user->RemoveMode(UMODE_REGISTERED);
+ break;
+ case UMODE_CLOAK:
+ case UMODE_VHOST:
+ if (add && user->vhost)
+ {
+ user->SetCloakedHost(user->vhost);
+ delete [] user->vhost;
+ user->vhost = NULL;
+ }
+ else if (user->vhost)
+ {
+ delete [] user->vhost;
+ user->vhost = NULL;
+ }
+ user->UpdateHost();
+ default:
+ break;
+ }
+ }
+}
+