From 98372c3cf2c1455e41c388d822876a4d146ae76d Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Sun, 3 Dec 2017 17:16:28 +0000 Subject: Extract RFC modes from the core to core_channel and core_user. --- src/coremods/core_channel/cmode_k.cpp | 74 +++++++++++++++ src/coremods/core_channel/cmode_l.cpp | 49 ++++++++++ src/coremods/core_channel/core_channel.cpp | 25 +++++ src/coremods/core_channel/core_channel.h | 63 +++++++++++++ src/coremods/core_user/core_user.cpp | 17 +++- src/coremods/core_user/core_user.h | 38 ++++++++ src/coremods/core_user/umode_o.cpp | 51 ++++++++++ src/coremods/core_user/umode_s.cpp | 145 +++++++++++++++++++++++++++++ 8 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 src/coremods/core_channel/cmode_k.cpp create mode 100644 src/coremods/core_channel/cmode_l.cpp create mode 100644 src/coremods/core_user/umode_o.cpp create mode 100644 src/coremods/core_user/umode_s.cpp (limited to 'src/coremods') diff --git a/src/coremods/core_channel/cmode_k.cpp b/src/coremods/core_channel/cmode_k.cpp new file mode 100644 index 000000000..9bab05200 --- /dev/null +++ b/src/coremods/core_channel/cmode_k.cpp @@ -0,0 +1,74 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Robin Burchell + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards + * + * 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 . + */ + + +#include "inspircd.h" +#include "core_channel.h" + +ModeChannelKey::ModeChannelKey(Module* Creator) + : ParamMode(Creator, "key", 'k', PARAM_ALWAYS) +{ +} + +ModeAction ModeChannelKey::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) +{ + const std::string* key = ext.get(channel); + bool exists = (key != NULL); + if (IS_LOCAL(source)) + { + if (exists == adding) + return MODEACTION_DENY; + if (exists && (parameter != *key)) + { + /* Key is currently set and the correct key wasnt given */ + return MODEACTION_DENY; + } + } else { + if (exists && adding && parameter == *key) + { + /* no-op, don't show */ + return MODEACTION_DENY; + } + } + + channel->SetMode(this, adding); + if (adding) + { + if (parameter.length() > maxkeylen) + parameter.erase(maxkeylen); + ext.set(channel, parameter); + } + else + 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/coremods/core_channel/cmode_l.cpp b/src/coremods/core_channel/cmode_l.cpp new file mode 100644 index 000000000..eb16fd182 --- /dev/null +++ b/src/coremods/core_channel/cmode_l.cpp @@ -0,0 +1,49 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards + * + * 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 . + */ + + +#include "inspircd.h" +#include "core_channel.h" + +ModeChannelLimit::ModeChannelLimit(Module* Creator) + : ParamMode(Creator, "limit", 'l') +{ +} + +bool ModeChannelLimit::ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel*) +{ + /* When TS is equal, the higher channel limit wins */ + return (atoi(their_param.c_str()) < atoi(our_param.c_str())); +} + +ModeAction ModeChannelLimit::OnSet(User* user, Channel* chan, std::string& parameter) +{ + int limit = ConvToInt(parameter); + if (limit < 0) + return MODEACTION_DENY; + + ext.set(chan, limit); + return MODEACTION_ALLOW; +} + +void ModeChannelLimit::SerializeParam(Channel* chan, intptr_t n, std::string& out) +{ + out += ConvToStr(n); +} diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index 3af809645..af71e2ced 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -30,6 +30,19 @@ class CoreModChannel : public Module, public CheckExemption::EventListener CommandKick cmdkick; CommandNames cmdnames; CommandTopic cmdtopic; + + ModeChannelBan banmode; + SimpleChannelModeHandler inviteonlymode; + ModeChannelKey keymode; + ModeChannelLimit limitmode; + SimpleChannelModeHandler moderatedmode; + SimpleChannelModeHandler noextmsgmode; + ModeChannelOp opmode; + SimpleChannelModeHandler privatemode; + SimpleChannelModeHandler secretmode; + SimpleChannelModeHandler topiclockmode; + ModeChannelVoice voicemode; + insp::flat_map exemptions; ModResult IsInvited(User* user, Channel* chan) @@ -49,6 +62,17 @@ class CoreModChannel : public Module, public CheckExemption::EventListener , cmdkick(this) , cmdnames(this) , cmdtopic(this) + , banmode(this) + , inviteonlymode(this, "inviteonly", 'i') + , keymode(this) + , limitmode(this) + , moderatedmode(this, "moderated", 'm') + , noextmsgmode(this, "noextmsg", 'n') + , opmode(this) + , privatemode(this, "private", 'p') + , secretmode(this, "secret", 's') + , topiclockmode(this, "topiclock", 't') + , voicemode(this) { } @@ -80,6 +104,7 @@ class CoreModChannel : public Module, public CheckExemption::EventListener exempts[restriction] = prefix; } exemptions.swap(exempts); + banmode.DoRehash(); } void On005Numeric(std::map& tokens) CXX11_OVERRIDE diff --git a/src/coremods/core_channel/core_channel.h b/src/coremods/core_channel/core_channel.h index 46def3e7b..fa600cd17 100644 --- a/src/coremods/core_channel/core_channel.h +++ b/src/coremods/core_channel/core_channel.h @@ -2,6 +2,9 @@ * InspIRCd -- Internet Relay Chat Daemon * * Copyright (C) 2014 Attila Molnar + * Copyright (C) 2008 Robin Burchell + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards * * 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 @@ -20,6 +23,7 @@ #pragma once #include "inspircd.h" +#include "listmode.h" #include "modules/exemption.h" namespace Topic @@ -135,3 +139,62 @@ class CommandKick : public Command CmdResult Handle(const std::vector& parameters, User* user) CXX11_OVERRIDE; RouteDescriptor GetRouting(User* user, const std::vector& parameters) CXX11_OVERRIDE; }; + +/** Channel mode +b + */ +class ModeChannelBan : public ListModeBase +{ + public: + ModeChannelBan(Module* Creator) + : ListModeBase(Creator, "ban", 'b', "End of channel ban list", 367, 368, true, "maxbans") + { + } +}; + +/** Channel mode +k + */ +class ModeChannelKey : public ParamMode +{ + static const std::string::size_type maxkeylen = 32; + public: + ModeChannelKey(Module* Creator); + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE; + void SerializeParam(Channel* chan, const std::string* key, std::string& out) ; + ModeAction OnSet(User* source, Channel* chan, std::string& param) CXX11_OVERRIDE; +}; + +/** Channel mode +l + */ +class ModeChannelLimit : public ParamMode +{ + public: + ModeChannelLimit(Module* Creator); + bool ResolveModeConflict(std::string& their_param, const std::string& our_param, Channel* channel) CXX11_OVERRIDE; + void SerializeParam(Channel* chan, intptr_t n, std::string& out); + ModeAction OnSet(User* source, Channel* channel, std::string& parameter) CXX11_OVERRIDE; +}; + +/** Channel mode +o + */ +class ModeChannelOp : public PrefixMode +{ + public: + ModeChannelOp(Module* Creator) + : PrefixMode(Creator, "op", 'o', OP_VALUE, '@') + { + ranktoset = ranktounset = OP_VALUE; + } +}; + +/** Channel mode +v + */ +class ModeChannelVoice : public PrefixMode +{ + public: + ModeChannelVoice(Module* Creator) + : PrefixMode(Creator, "voice", 'v', VOICE_VALUE, '+') + { + selfremove = false; + ranktoset = ranktounset = HALFOP_VALUE; + } +}; diff --git a/src/coremods/core_user/core_user.cpp b/src/coremods/core_user/core_user.cpp index 5068bd4aa..8504de8e0 100644 --- a/src/coremods/core_user/core_user.cpp +++ b/src/coremods/core_user/core_user.cpp @@ -147,11 +147,24 @@ class CoreModUser : public Module CommandPong cmdpong; CommandQuit cmdquit; CommandUser cmduser; + SimpleUserModeHandler invisiblemode; + ModeUserOperator operatormode; + ModeUserServerNoticeMask snomaskmode; public: CoreModUser() - : cmdaway(this), cmdmode(this), cmdnick(this), cmdpart(this), cmdpass(this), cmdping(this) - , cmdpong(this), cmdquit(this), cmduser(this) + : cmdaway(this) + , cmdmode(this) + , cmdnick(this) + , cmdpart(this) + , cmdpass(this) + , cmdping(this) + , cmdpong(this) + , cmdquit(this) + , cmduser(this) + , invisiblemode(this, "invisible", 'i') + , operatormode(this) + , snomaskmode(this) { } diff --git a/src/coremods/core_user/core_user.h b/src/coremods/core_user/core_user.h index 2a1ba7bfd..befb07ef5 100644 --- a/src/coremods/core_user/core_user.h +++ b/src/coremods/core_user/core_user.h @@ -2,6 +2,9 @@ * InspIRCd -- Internet Relay Chat Daemon * * Copyright (C) 2014 Attila Molnar + * Copyright (C) 2008 Robin Burchell + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards * * 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 @@ -20,6 +23,7 @@ #pragma once #include "inspircd.h" +#include "listmode.h" class MessageWrapper { @@ -182,3 +186,37 @@ class CommandUser : public SplitCommand */ static CmdResult CheckRegister(LocalUser* user); }; + +/** User mode +s + */ +class ModeUserServerNoticeMask : public ModeHandler +{ + /** Process a snomask modifier string, e.g. +abc-de + * @param user The target user + * @param input A sequence of notice mask characters + * @return The cleaned mode sequence which can be output, + * e.g. in the above example if masks c and e are not + * valid, this function will return +ab-d + */ + std::string ProcessNoticeMasks(User* user, const std::string& input); + + public: + ModeUserServerNoticeMask(Module* Creator); + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) CXX11_OVERRIDE; + void OnParameterMissing(User* user, User* dest, Channel* channel) CXX11_OVERRIDE; + + /** Create a displayable mode string of the snomasks set on a given user + * @param user The user whose notice masks to format + * @return The notice mask character sequence + */ + std::string GetUserParameter(const User* user) const CXX11_OVERRIDE; +}; + +/** User mode +o + */ +class ModeUserOperator : public ModeHandler +{ + public: + ModeUserOperator(Module* Creator); + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) CXX11_OVERRIDE; +}; diff --git a/src/coremods/core_user/umode_o.cpp b/src/coremods/core_user/umode_o.cpp new file mode 100644 index 000000000..20668fdaa --- /dev/null +++ b/src/coremods/core_user/umode_o.cpp @@ -0,0 +1,51 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards + * + * 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 . + */ + + +#include "inspircd.h" +#include "core_user.h" + +ModeUserOperator::ModeUserOperator(Module* Creator) + : ModeHandler(Creator, "oper", 'o', PARAM_NONE, MODETYPE_USER) +{ + oper = true; +} + +ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, std::string&, bool adding) +{ + /* Only opers can execute this class at all */ + if (!source->server->IsULine() && !source->IsOper()) + return MODEACTION_DENY; + + /* Not even opers can GIVE the +o mode, only take it away */ + if (adding) + return MODEACTION_DENY; + + /* Set the bitfields. + * Note that oper status is only given in User::Oper() + * NOT here. It is impossible to directly set +o without + * verifying as an oper and getting an opertype assigned + * 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.c_str()); + dest->UnOper(); + + return MODEACTION_ALLOW; +} diff --git a/src/coremods/core_user/umode_s.cpp b/src/coremods/core_user/umode_s.cpp new file mode 100644 index 000000000..0122ebe3e --- /dev/null +++ b/src/coremods/core_user/umode_s.cpp @@ -0,0 +1,145 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2008 Robin Burchell + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006 Craig Edwards + * + * 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 . + */ + + +#include "inspircd.h" +#include "core_user.h" + +ModeUserServerNoticeMask::ModeUserServerNoticeMask(Module* Creator) + : ModeHandler(Creator, "snomask", 's', PARAM_SETONLY, MODETYPE_USER) +{ + oper = true; +} + +ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string ¶meter, bool adding) +{ + if (adding) + { + 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->IsModeSet(this)) + { + dest->SetMode(this, false); + dest->snomasks.reset(); + return MODEACTION_ALLOW; + } + } + + // Mode not set and trying to unset, deny + return MODEACTION_DENY; +} + +std::string ModeUserServerNoticeMask::GetUserParameter(const User* user) const +{ + 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->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, *i, "is unknown snomask char to me"); + 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; +} -- cgit v1.2.3