diff options
Diffstat (limited to 'src/modes')
-rw-r--r-- | src/modes/cmode_b.cpp | 178 | ||||
-rw-r--r-- | src/modes/cmode_k.cpp | 69 | ||||
-rw-r--r-- | src/modes/cmode_l.cpp | 19 | ||||
-rw-r--r-- | src/modes/cmode_o.cpp | 40 | ||||
-rw-r--r-- | src/modes/cmode_v.cpp | 40 | ||||
-rw-r--r-- | src/modes/umode_o.cpp | 7 | ||||
-rw-r--r-- | src/modes/umode_s.cpp | 109 |
7 files changed, 134 insertions, 328 deletions
diff --git a/src/modes/cmode_b.cpp b/src/modes/cmode_b.cpp deleted file mode 100644 index 09df05100..000000000 --- a/src/modes/cmode_b.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> - * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc> - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "inspircd.h" -#include <string> -#include <vector> -#include "inspircd_config.h" -#include "configreader.h" -#include "hash_map.h" -#include "mode.h" -#include "channels.h" -#include "users.h" -#include "modules.h" -#include "inspstring.h" -#include "hashcomp.h" -#include "modes/cmode_b.h" - -ModeChannelBan::ModeChannelBan() : ModeHandler(NULL, "ban", 'b', PARAM_ALWAYS, MODETYPE_CHANNEL) -{ - list = true; -} - -ModeAction ModeChannelBan::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) -{ - int status = channel->GetPrefixValue(source); - /* Call the correct method depending on wether we're adding or removing the mode */ - if (adding) - { - this->AddBan(source, parameter, channel, status); - } - else - { - this->DelBan(source, parameter, channel, status); - } - /* If the method above 'ate' the parameter by reducing it to an empty string, then - * it won't matter wether we return ALLOW or DENY here, as an empty string overrides - * the return value and is always MODEACTION_DENY if the mode is supposed to have - * a parameter. - */ - return MODEACTION_ALLOW; -} - -void ModeChannelBan::RemoveMode(Channel* channel, irc::modestacker* stack) -{ - BanList copy; - - for (BanList::iterator i = channel->bans.begin(); i != channel->bans.end(); i++) - { - copy.push_back(*i); - } - - for (BanList::iterator i = copy.begin(); i != copy.end(); i++) - { - if (stack) - { - stack->Push(this->GetModeChar(), i->data); - } - else - { - std::vector<std::string> parameters; parameters.push_back(channel->name); parameters.push_back("-b"); parameters.push_back(i->data); - ServerInstance->SendMode(parameters, ServerInstance->FakeClient); - } - } -} - -void ModeChannelBan::RemoveMode(User*, irc::modestacker* stack) -{ -} - -void ModeChannelBan::DisplayList(User* user, Channel* channel) -{ - /* Display the channel banlist */ - for (BanList::reverse_iterator i = channel->bans.rbegin(); i != channel->bans.rend(); ++i) - { - user->WriteServ("367 %s %s %s %s %lu",user->nick.c_str(), channel->name.c_str(), i->data.c_str(), i->set_by.c_str(), (unsigned long)i->set_time); - } - user->WriteServ("368 %s %s :End of channel ban list",user->nick.c_str(), channel->name.c_str()); - return; -} - -void ModeChannelBan::DisplayEmptyList(User* user, Channel* channel) -{ - user->WriteServ("368 %s %s :End of channel ban list",user->nick.c_str(), channel->name.c_str()); -} - -std::string& ModeChannelBan::AddBan(User *user, std::string &dest, Channel *chan, int) -{ - if ((!user) || (!chan)) - { - ServerInstance->Logs->Log("MODE",DEFAULT,"*** BUG *** AddBan was given an invalid parameter"); - dest.clear(); - return dest; - } - - /* Attempt to tidy the mask */ - ModeParser::CleanMask(dest); - /* If the mask was invalid, we exit */ - if (dest.empty() || dest.length() > 250) - return dest; - - long maxbans = chan->GetMaxBans(); - if (IS_LOCAL(user) && ((unsigned)chan->bans.size() >= (unsigned)maxbans)) - { - user->WriteServ("478 %s %s :Channel ban list for %s is full (maximum entries for this channel is %ld)",user->nick.c_str(), chan->name.c_str(), chan->name.c_str(), maxbans); - dest.clear(); - return dest; - } - - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnAddBan, MOD_RESULT, (user,chan,dest)); - if (MOD_RESULT == MOD_RES_DENY) - { - dest.clear(); - return dest; - } - - for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) - { - if (i->data == dest) - { - /* dont allow a user to set the same ban twice */ - dest.clear(); - return dest; - } - } - - b.set_time = ServerInstance->Time(); - b.data.assign(dest, 0, MAXBUF); - b.set_by.assign(user->nick, 0, 64); - chan->bans.push_back(b); - return dest; -} - -std::string& ModeChannelBan::DelBan(User *user, std::string& dest, Channel *chan, int) -{ - if ((!user) || (!chan)) - { - ServerInstance->Logs->Log("MODE",DEFAULT,"*** BUG *** TakeBan was given an invalid parameter"); - dest.clear(); - return dest; - } - - for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) - { - if (!strcasecmp(i->data.c_str(), dest.c_str())) - { - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnDelBan, MOD_RESULT, (user, chan, dest)); - if (MOD_RESULT == MOD_RES_DENY) - { - dest.clear(); - return dest; - } - chan->bans.erase(i); - return dest; - } - } - dest.clear(); - return dest; -} - diff --git a/src/modes/cmode_k.cpp b/src/modes/cmode_k.cpp index 400333fce..e14f93a77 100644 --- a/src/modes/cmode_k.cpp +++ b/src/modes/cmode_k.cpp @@ -24,76 +24,53 @@ #include "mode.h" #include "channels.h" #include "users.h" -#include "modes/cmode_k.h" +#include "builtinmodes.h" -ModeChannelKey::ModeChannelKey() : ModeHandler(NULL, "key", 'k', PARAM_ALWAYS, MODETYPE_CHANNEL) -{ -} - -void ModeChannelKey::RemoveMode(Channel* channel, irc::modestacker* stack) -{ - /** +k needs a parameter when being removed, - * so we have a special-case RemoveMode here for it - */ - - if (channel->IsModeSet('k')) - { - if (stack) - { - stack->Push('k', channel->GetModeParameter('k')); - } - else - { - std::vector<std::string> parameters; - parameters.push_back(channel->name); - parameters.push_back("-k"); - parameters.push_back(channel->GetModeParameter('k')); - ServerInstance->SendMode(parameters, ServerInstance->FakeClient); - } - } -} - -void ModeChannelKey::RemoveMode(User*, irc::modestacker* stack) +ModeChannelKey::ModeChannelKey() + : ParamMode<ModeChannelKey, LocalStringExt>(NULL, "key", 'k', PARAM_ALWAYS) { } ModeAction ModeChannelKey::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) { - bool exists = channel->IsModeSet('k'); + const std::string* key = ext.get(channel); + bool exists = (key != NULL); if (IS_LOCAL(source)) { if (exists == adding) return MODEACTION_DENY; - if (exists && (parameter != channel->GetModeParameter('k'))) + if (exists && (parameter != *key)) { /* Key is currently set and the correct key wasnt given */ return MODEACTION_DENY; } } else { - if (exists && adding && parameter == channel->GetModeParameter('k')) + if (exists && adding && parameter == *key) { /* no-op, don't show */ return MODEACTION_DENY; } } - /* invalid keys */ - if (!parameter.length()) - return MODEACTION_DENY; - - if (parameter.rfind(' ') != std::string::npos) - return MODEACTION_DENY; - + channel->SetMode(this, adding); if (adding) { - std::string ckey; - ckey.assign(parameter, 0, 32); - parameter = ckey; - channel->SetModeParam('k', parameter); + parameter = parameter.substr(0, 32); + ext.set(channel, parameter); } else - { - channel->SetModeParam('k', ""); - } + ext.unset(channel); + return MODEACTION_ALLOW; } + +void ModeChannelKey::SerializeParam(Channel* chan, const std::string* key, std::string& out) +{ + out += *key; +} + +ModeAction ModeChannelKey::OnSet(User* source, Channel* chan, std::string& param) +{ + // Dummy function, never called + return MODEACTION_DENY; +} diff --git a/src/modes/cmode_l.cpp b/src/modes/cmode_l.cpp index 001d058bb..128854b50 100644 --- a/src/modes/cmode_l.cpp +++ b/src/modes/cmode_l.cpp @@ -23,9 +23,10 @@ #include "mode.h" #include "channels.h" #include "users.h" -#include "modes/cmode_l.h" +#include "builtinmodes.h" -ModeChannelLimit::ModeChannelLimit() : ParamChannelModeHandler(NULL, "limit", 'l') +ModeChannelLimit::ModeChannelLimit() + : ParamMode<ModeChannelLimit, LocalIntExt>(NULL, "limit", 'l') { } @@ -35,13 +36,13 @@ bool ModeChannelLimit::ResolveModeConflict(std::string &their_param, const std:: return (atoi(their_param.c_str()) < atoi(our_param.c_str())); } -bool ModeChannelLimit::ParamValidate(std::string ¶meter) +ModeAction ModeChannelLimit::OnSet(User* user, Channel* chan, std::string& parameter) { - int limit = atoi(parameter.c_str()); - - if (limit < 0) - return false; + ext.set(chan, ConvToInt(parameter)); + return MODEACTION_ALLOW; +} - parameter = ConvToStr(limit); - return true; +void ModeChannelLimit::SerializeParam(Channel* chan, intptr_t n, std::string& out) +{ + out += ConvToStr(n); } diff --git a/src/modes/cmode_o.cpp b/src/modes/cmode_o.cpp index 0a13b39ce..6e96afa67 100644 --- a/src/modes/cmode_o.cpp +++ b/src/modes/cmode_o.cpp @@ -26,45 +26,11 @@ #include "channels.h" #include "users.h" #include "modules.h" -#include "modes/cmode_o.h" +#include "builtinmodes.h" -ModeChannelOp::ModeChannelOp() : ModeHandler(NULL, "op", 'o', PARAM_ALWAYS, MODETYPE_CHANNEL) +ModeChannelOp::ModeChannelOp() : PrefixMode(NULL, "op", 'o') { - list = true; prefix = '@'; levelrequired = OP_VALUE; - m_paramtype = TR_NICK; -} - -unsigned int ModeChannelOp::GetPrefixRank() -{ - return OP_VALUE; -} - -void ModeChannelOp::RemoveMode(Channel* channel, irc::modestacker* stack) -{ - const UserMembList* clist = channel->GetUsers(); - - for (UserMembCIter i = clist->begin(); i != clist->end(); i++) - { - if (stack) - stack->Push(this->GetModeChar(), i->first->nick); - else - { - std::vector<std::string> parameters; - parameters.push_back(channel->name); - parameters.push_back("-o"); - parameters.push_back(i->first->nick); - ServerInstance->SendMode(parameters, ServerInstance->FakeClient); - } - } -} - -void ModeChannelOp::RemoveMode(User*, irc::modestacker* stack) -{ -} - -ModeAction ModeChannelOp::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) -{ - return MODEACTION_ALLOW; + prefixrank = OP_VALUE; } diff --git a/src/modes/cmode_v.cpp b/src/modes/cmode_v.cpp index 4a00f60f1..c8ce30ab1 100644 --- a/src/modes/cmode_v.cpp +++ b/src/modes/cmode_v.cpp @@ -26,45 +26,11 @@ #include "channels.h" #include "users.h" #include "modules.h" -#include "modes/cmode_v.h" +#include "builtinmodes.h" -ModeChannelVoice::ModeChannelVoice() : ModeHandler(NULL, "voice", 'v', PARAM_ALWAYS, MODETYPE_CHANNEL) +ModeChannelVoice::ModeChannelVoice() : PrefixMode(NULL, "voice", 'v') { - list = true; prefix = '+'; levelrequired = HALFOP_VALUE; - m_paramtype = TR_NICK; -} - -unsigned int ModeChannelVoice::GetPrefixRank() -{ - return VOICE_VALUE; -} - -void ModeChannelVoice::RemoveMode(Channel* channel, irc::modestacker* stack) -{ - const UserMembList* clist = channel->GetUsers(); - - for (UserMembCIter i = clist->begin(); i != clist->end(); i++) - { - if (stack) - stack->Push(this->GetModeChar(), i->first->nick); - else - { - std::vector<std::string> parameters; - parameters.push_back(channel->name); - parameters.push_back("-v"); - parameters.push_back(i->first->nick); - ServerInstance->SendMode(parameters, ServerInstance->FakeClient); - } - } -} - -void ModeChannelVoice::RemoveMode(User*, irc::modestacker* stack) -{ -} - -ModeAction ModeChannelVoice::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) -{ - return MODEACTION_ALLOW; + prefixrank = VOICE_VALUE; } diff --git a/src/modes/umode_o.cpp b/src/modes/umode_o.cpp index a5f590ba0..affd6b50c 100644 --- a/src/modes/umode_o.cpp +++ b/src/modes/umode_o.cpp @@ -22,7 +22,7 @@ #include "mode.h" #include "channels.h" #include "users.h" -#include "modes/umode_o.h" +#include "builtinmodes.h" ModeUserOperator::ModeUserOperator() : ModeHandler(NULL, "oper", 'o', PARAM_NONE, MODETYPE_USER) { @@ -32,7 +32,7 @@ ModeUserOperator::ModeUserOperator() : ModeHandler(NULL, "oper", 'o', PARAM_NONE ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, std::string&, bool adding) { /* Only opers can execute this class at all */ - if (!ServerInstance->ULine(source->server) && !IS_OPER(source)) + if (!source->server->IsULine() && !source->IsOper()) return MODEACTION_DENY; /* Not even opers can GIVE the +o mode, only take it away */ @@ -46,8 +46,7 @@ ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, st * to your User! */ char snomask = IS_LOCAL(dest) ? 'o' : 'O'; - ServerInstance->SNO->WriteToSnoMask(snomask, "User %s de-opered (by %s)", dest->nick.c_str(), - source->nick.empty() ? source->server.c_str() : source->nick.c_str()); + ServerInstance->SNO->WriteToSnoMask(snomask, "User %s de-opered (by %s)", dest->nick.c_str(), source->nick.c_str()); dest->UnOper(); return MODEACTION_ALLOW; diff --git a/src/modes/umode_s.cpp b/src/modes/umode_s.cpp index 1b782ae85..b355cb824 100644 --- a/src/modes/umode_s.cpp +++ b/src/modes/umode_s.cpp @@ -23,7 +23,7 @@ #include "mode.h" #include "channels.h" #include "users.h" -#include "modes/umode_s.h" +#include "builtinmodes.h" ModeUserServerNoticeMask::ModeUserServerNoticeMask() : ModeHandler(NULL, "snomask", 's', PARAM_SETONLY, MODETYPE_USER) { @@ -32,41 +32,116 @@ ModeUserServerNoticeMask::ModeUserServerNoticeMask() : ModeHandler(NULL, "snomas ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string ¶meter, bool adding) { - /* Set the array fields */ if (adding) { - /* Fix for bug #310 reported by Smartys */ - if (!dest->modes[UM_SNOMASK]) - dest->snomasks.reset(); - - dest->modes[UM_SNOMASK] = true; - parameter = dest->ProcessNoticeMasks(parameter.c_str()); + dest->SetMode(this, true); + // Process the parameter (remove chars we don't understand, remove redundant chars, etc.) + parameter = ProcessNoticeMasks(dest, parameter); return MODEACTION_ALLOW; } else { - if (dest->modes[UM_SNOMASK] != false) + if (dest->IsModeSet(this)) { - dest->modes[UM_SNOMASK] = false; + dest->SetMode(this, false); + dest->snomasks.reset(); return MODEACTION_ALLOW; } } - /* Allow the change */ + // Mode not set and trying to unset, deny return MODEACTION_DENY; } std::string ModeUserServerNoticeMask::GetUserParameter(User* user) { - std::string masks = user->FormatNoticeMasks(); - if (masks.length()) - masks = "+" + masks; - return masks; + std::string ret; + if (!user->IsModeSet(this)) + return ret; + + ret.push_back('+'); + for (unsigned char n = 0; n < 64; n++) + { + if (user->snomasks[n]) + ret.push_back(n + 'A'); + } + return ret; } void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channel* channel) { - user->WriteServ("NOTICE %s :*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.", - user->nick.c_str()); + user->WriteNotice("*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'."); } +std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::string& input) +{ + bool adding = true; + std::bitset<64> curr = user->snomasks; + + for (std::string::const_iterator i = input.begin(); i != input.end(); ++i) + { + switch (*i) + { + case '+': + adding = true; + break; + case '-': + adding = false; + break; + case '*': + for (size_t j = 0; j < 64; j++) + { + if (ServerInstance->SNO->IsSnomaskUsable(j+'A')) + curr[j] = adding; + } + break; + default: + // For local users check whether the given snomask is valid and enabled - IsSnomaskUsable() tests both. + // For remote users accept what we were told, unless the snomask char is not a letter. + if (IS_LOCAL(user)) + { + if (!ServerInstance->SNO->IsSnomaskUsable(*i)) + { + user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%c :is unknown snomask char to me", *i); + continue; + } + } + else if (!(((*i >= 'a') && (*i <= 'z')) || ((*i >= 'A') && (*i <= 'Z')))) + continue; + + size_t index = ((*i) - 'A'); + curr[index] = adding; + break; + } + } + + std::string plus = "+"; + std::string minus = "-"; + + // Apply changes and construct two strings consisting of the newly added and the removed snomask chars + for (size_t i = 0; i < 64; i++) + { + bool isset = curr[i]; + if (user->snomasks[i] != isset) + { + user->snomasks[i] = isset; + std::string& appendhere = (isset ? plus : minus); + appendhere.push_back(i+'A'); + } + } + + // Create the final string that will be shown to the user and sent to servers + // Form: "+ABc-de" + std::string output; + if (plus.length() > 1) + output = plus; + + if (minus.length() > 1) + output += minus; + + // Unset the snomask usermode itself if every snomask was unset + if (user->snomasks.none()) + user->SetMode(this, false); + + return output; +} |