1 /* 2 * InspIRCd -- Internet Relay Chat Daemon 3 * 4 * Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services> 5 * Copyright (C) 2012-2015 Attila Molnar <attilamolnar@hush.com> 6 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be> 7 * Copyright (C) 2011 jackmcbarn <jackmcbarn@inspircd.org> 8 * Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org> 9 * 10 * This file is part of InspIRCd. InspIRCd is free software: you can 11 * redistribute it and/or modify it under the terms of the GNU General Public 12 * License as published by the Free Software Foundation, version 2. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 24 #include "inspircd.h" 25 #include "listmode.h" 26 27 enum 28 { 29 // InspIRCd-specific. 30 RPL_ACCESSLIST = 910, 31 RPL_ENDOFACCESSLIST = 911 32 }; 33 34 class AutoOpList : public ListModeBase 35 { 36 public: AutoOpList(Module * Creator)37 AutoOpList(Module* Creator) 38 : ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", RPL_ACCESSLIST, RPL_ENDOFACCESSLIST, true) 39 { 40 ranktoset = ranktounset = OP_VALUE; 41 syntax = "<prefix>:<mask>"; 42 tidy = false; 43 } 44 FindMode(const std::string & mid)45 PrefixMode* FindMode(const std::string& mid) 46 { 47 if (mid.length() == 1) 48 return ServerInstance->Modes->FindPrefixMode(mid[0]); 49 50 ModeHandler* mh = ServerInstance->Modes->FindMode(mid, MODETYPE_CHANNEL); 51 return mh ? mh->IsPrefixMode() : NULL; 52 } 53 AccessCheck(User * source,Channel * channel,std::string & parameter,bool adding)54 ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding) CXX11_OVERRIDE 55 { 56 std::string::size_type pos = parameter.find(':'); 57 if (pos == 0 || pos == std::string::npos) 58 return adding ? MOD_RES_DENY : MOD_RES_PASSTHRU; 59 unsigned int mylevel = channel->GetPrefixValue(source); 60 std::string mid(parameter, 0, pos); 61 PrefixMode* mh = FindMode(mid); 62 63 if (adding && !mh) 64 { 65 source->WriteNumeric(ERR_UNKNOWNMODE, mid, InspIRCd::Format("Cannot find prefix mode '%s' for autoop", mid.c_str())); 66 return MOD_RES_DENY; 67 } 68 else if (!mh) 69 return MOD_RES_PASSTHRU; 70 71 std::string dummy; 72 if (mh->AccessCheck(source, channel, dummy, true) == MOD_RES_DENY) 73 return MOD_RES_DENY; 74 if (mh->GetLevelRequired(adding) > mylevel) 75 { 76 source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to %s mode %c (%s) to %s an autoop containing it", 77 adding ? "set" : "unset", mh->GetModeChar(), mh->name.c_str(), adding ? "add" : "remove")); 78 return MOD_RES_DENY; 79 } 80 return MOD_RES_PASSTHRU; 81 } 82 }; 83 84 class ModuleAutoOp : public Module 85 { 86 AutoOpList mh; 87 88 public: ModuleAutoOp()89 ModuleAutoOp() : mh(this) 90 { 91 } 92 OnPostJoin(Membership * memb)93 void OnPostJoin(Membership *memb) CXX11_OVERRIDE 94 { 95 if (!IS_LOCAL(memb->user)) 96 return; 97 98 ListModeBase::ModeList* list = mh.GetList(memb->chan); 99 if (list) 100 { 101 Modes::ChangeList changelist; 102 for (ListModeBase::ModeList::iterator it = list->begin(); it != list->end(); it++) 103 { 104 std::string::size_type colon = it->mask.find(':'); 105 if (colon == std::string::npos) 106 continue; 107 if (memb->chan->CheckBan(memb->user, it->mask.substr(colon+1))) 108 { 109 PrefixMode* given = mh.FindMode(it->mask.substr(0, colon)); 110 if (given) 111 changelist.push_add(given, memb->user->nick); 112 } 113 } 114 ServerInstance->Modes->Process(ServerInstance->FakeClient, memb->chan, NULL, changelist); 115 } 116 } 117 ReadConfig(ConfigStatus & status)118 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE 119 { 120 mh.DoRehash(); 121 } 122 GetVersion()123 Version GetVersion() CXX11_OVERRIDE 124 { 125 return Version("Adds channel mode w (autoop) which allows channel operators to define an access list which gives status ranks to users on join.", VF_VENDOR); 126 } 127 }; 128 129 MODULE_INIT(ModuleAutoOp) 130