From a7ac6a0ac712892652da6dd8696b94d4c6d3ea84 Mon Sep 17 00:00:00 2001 From: Adam- Date: Sun, 13 Dec 2009 19:32:19 +0000 Subject: Added in a modestacker and rewrote almost all of the remaining old mode code git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2696 5417fbe8-f217-4b02-8779-1006273d7864 --- src/actions.c | 61 +-- src/botserv.c | 99 +---- src/channels.c | 882 +++++++++++++++++++++++--------------------- src/chanserv.c | 240 ++++-------- src/core/cs_ban.c | 6 +- src/core/cs_clear.c | 151 ++------ src/core/cs_drop.c | 3 +- src/core/cs_modes.c | 14 +- src/core/cs_register.c | 6 +- src/core/cs_set.c | 6 +- src/core/ns_logout.c | 4 +- src/core/os_clearmodes.c | 100 +++-- src/core/os_defcon.c | 30 +- src/core/os_mode.c | 8 +- src/core/os_oline.c | 2 +- src/core/os_umode.c | 4 +- src/main.c | 3 + src/modes.cpp | 610 ++++++++++++++++++++++++------ src/modules/cs_enforce.c | 10 +- src/modules/cs_tban.c | 19 +- src/nickalias.cpp | 6 +- src/nickcore.cpp | 1 + src/protocol.cpp | 10 + src/protocol/bahamut.c | 66 +--- src/protocol/inspircd11.c | 74 +--- src/protocol/inspircd12.cpp | 85 +---- src/protocol/ratbox.c | 46 +-- src/protocol/unreal32.c | 118 ++---- src/regchannel.cpp | 2 +- src/users.c | 217 ++++++++++- 30 files changed, 1457 insertions(+), 1426 deletions(-) (limited to 'src') 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(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(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(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(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 ¶m, 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(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(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::iterator it = Params.find(Name); + std::map::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(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(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 ¶m, 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(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(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::iterator it = Params.find(Name); - if (it != Params.end()) + if (cm->Type == MODE_PARAM) { - Params.erase(it); + std::map::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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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(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(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(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(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(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(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(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(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::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(cm); - ci->GetParam(cmp->Name, ¶m); - - if (!param.empty()) - { - argbuf += " " + param; - } + if (ci->GetParam(cmp->Name, ¶m)) + 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(cm); - c->GetParam(cmp->Name, ¶m); - ci->GetParam(cmp->Name, &ciparam); + c->GetParam(cm->Name, ¶m); + 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, ¶m); - - if (!param.empty()) - { - argbuf += " " + param; - } + if (c->GetParam(cmp->Name, ¶m)) + 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(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(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(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(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(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