]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_chanfilter.cpp
Ignore clients on ulined servers when reporting stats in LUSERS.
[user/henk/code/inspircd.git] / src / modules / m_chanfilter.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
6  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
7  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
8  *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
9  *   Copyright (C) 2005 Craig McLure <craig@chatspike.net>
10  *   Copyright (C) 2005 Craig Edwards <craigedwards@brainbox.cc>
11  *
12  * This file is part of InspIRCd.  InspIRCd is free software: you can
13  * redistribute it and/or modify it under the terms of the GNU General Public
14  * License as published by the Free Software Foundation, version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24
25
26 #include "inspircd.h"
27 #include "listmode.h"
28 #include "modules/exemption.h"
29
30 /** Handles channel mode +g
31  */
32 class ChanFilter : public ListModeBase
33 {
34  public:
35         unsigned long maxlen;
36
37         ChanFilter(Module* Creator)
38                 : ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", 941, 940, false)
39         {
40                 syntax = "<pattern>";
41         }
42
43         bool ValidateParam(User* user, Channel* chan, std::string& word) CXX11_OVERRIDE
44         {
45                 if (word.length() > maxlen)
46                 {
47                         user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Word is too long for the spamfilter list."));
48                         return false;
49                 }
50
51                 return true;
52         }
53 };
54
55 class ModuleChanFilter : public Module
56 {
57         CheckExemption::EventProvider exemptionprov;
58         ChanFilter cf;
59         bool hidemask;
60         bool notifyuser;
61
62         ChanFilter::ListItem* Match(User* user, Channel* chan, const std::string& text)
63         {
64                 ModResult res = CheckExemption::Call(exemptionprov, user, chan, "filter");
65                 if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
66                         return NULL;
67
68                 ListModeBase::ModeList* list = cf.GetList(chan);
69                 if (!list)
70                         return NULL;
71
72                 for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); i++)
73                 {
74                         if (InspIRCd::Match(text, i->mask))
75                                 return &*i;
76                 }
77
78                 return NULL;
79         }
80
81  public:
82
83         ModuleChanFilter()
84                 : exemptionprov(this)
85                 , cf(this)
86         {
87         }
88
89         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
90         {
91                 ConfigTag* tag = ServerInstance->Config->ConfValue("chanfilter");
92                 hidemask = tag->getBool("hidemask");
93                 cf.maxlen = tag->getUInt("maxlen", 35, 10, ModeParser::MODE_PARAM_MAX);
94                 notifyuser = tag->getBool("notifyuser", true);
95                 cf.DoRehash();
96         }
97
98         void OnUserPart(Membership* memb, std::string& partmessage, CUList& except_list) CXX11_OVERRIDE
99         {
100                 if (!memb)
101                         return;
102
103                 User* user = memb->user;
104                 Channel* chan = memb->chan;
105                 ChanFilter::ListItem* match = Match(user, chan, partmessage);
106                 if (!match)
107                         return;
108
109                 // Match() checks the user is local, we can assume from here
110                 LocalUser* luser = IS_LOCAL(user);
111
112                 std::string oldreason(partmessage);
113                 partmessage = "Reason filtered";
114                 if (!notifyuser)
115                 {
116                         // Send fake part
117                         ClientProtocol::Messages::Part partmsg(memb, oldreason);
118                         ClientProtocol::Event ev(ServerInstance->GetRFCEvents().part, partmsg);
119                         luser->Send(ev);
120
121                         // Don't send the user the changed message
122                         except_list.insert(user);
123                         return;
124                 }
125
126                 if (hidemask)
127                         user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your part message contained a censored word)");
128                 else
129                         user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your part message contained a censored word: " + match->mask + ")");
130         }
131
132         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE
133         {
134                 if (target.type != MessageTarget::TYPE_CHANNEL)
135                         return MOD_RES_PASSTHRU;
136
137                 Channel* chan = target.Get<Channel>();
138                 ChanFilter::ListItem* match = Match(user, chan, details.text);
139                 if (match)
140                 {
141                         if (!notifyuser)
142                         {
143                                 details.echo_original = true;
144                                 return MOD_RES_DENY;
145                         }
146
147                         if (hidemask)
148                                 user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word)");
149                         else
150                                 user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word: " + match->mask + ")");
151
152                         return MOD_RES_DENY;
153                 }
154                 return MOD_RES_PASSTHRU;
155         }
156
157         Version GetVersion() CXX11_OVERRIDE
158         {
159                 // We don't send any link data if the length is 35 for compatibility with the 2.0 branch.
160                 std::string maxfilterlen;
161                 if (cf.maxlen != 35)
162                         maxfilterlen.assign(ConvToStr(cf.maxlen));
163
164                 return Version("Provides channel-specific censor lists (like mode +G but varies from channel to channel)", VF_VENDOR, maxfilterlen);
165         }
166 };
167
168 MODULE_INIT(ModuleChanFilter)