diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/actions.c | 61 | ||||
-rw-r--r-- | src/botserv.c | 99 | ||||
-rw-r--r-- | src/channels.c | 882 | ||||
-rw-r--r-- | src/chanserv.c | 240 | ||||
-rw-r--r-- | src/core/cs_ban.c | 6 | ||||
-rw-r--r-- | src/core/cs_clear.c | 151 | ||||
-rw-r--r-- | src/core/cs_drop.c | 3 | ||||
-rw-r--r-- | src/core/cs_modes.c | 14 | ||||
-rw-r--r-- | src/core/cs_register.c | 6 | ||||
-rw-r--r-- | src/core/cs_set.c | 6 | ||||
-rw-r--r-- | src/core/ns_logout.c | 4 | ||||
-rw-r--r-- | src/core/os_clearmodes.c | 100 | ||||
-rw-r--r-- | src/core/os_defcon.c | 30 | ||||
-rw-r--r-- | src/core/os_mode.c | 8 | ||||
-rw-r--r-- | src/core/os_oline.c | 2 | ||||
-rw-r--r-- | src/core/os_umode.c | 4 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/modes.cpp | 610 | ||||
-rw-r--r-- | src/modules/cs_enforce.c | 10 | ||||
-rw-r--r-- | src/modules/cs_tban.c | 19 | ||||
-rw-r--r-- | src/nickalias.cpp | 6 | ||||
-rw-r--r-- | src/nickcore.cpp | 1 | ||||
-rw-r--r-- | src/protocol.cpp | 10 | ||||
-rw-r--r-- | src/protocol/bahamut.c | 66 | ||||
-rw-r--r-- | src/protocol/inspircd11.c | 74 | ||||
-rw-r--r-- | src/protocol/inspircd12.cpp | 85 | ||||
-rw-r--r-- | src/protocol/ratbox.c | 46 | ||||
-rw-r--r-- | src/protocol/unreal32.c | 118 | ||||
-rw-r--r-- | src/regchannel.cpp | 2 | ||||
-rw-r--r-- | src/users.c | 217 |
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 ¶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<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 ¶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<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 ¶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<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, ¶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<ChannelModeParam *>(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<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> ¶ms) { - 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, ¶m); - std::string buf = "+" + std::string(&cm->ModeChar); - if (!param.empty()) + if (GetDefConParam(Name, ¶m)) { - 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> ¶ms) { - 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; + } + } +} + |