2012-04-19 20:58:29 +02:00
|
|
|
/*
|
|
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2018 A_D <A-UNDERSCORE-D@users.noreply.github.com>
|
|
|
|
* Copyright (C) 2014 Daniel Vassdal <shutter@canternet.org>
|
2020-04-24 10:23:47 +01:00
|
|
|
* Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2012-2015 Attila Molnar <attilamolnar@hush.com>
|
|
|
|
* Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
|
|
|
|
* Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
|
2012-04-19 20:58:29 +02:00
|
|
|
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
|
|
|
|
* Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2006, 2010 Craig Edwards <brain@inspircd.org>
|
2021-03-05 02:04:16 +00:00
|
|
|
* Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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.
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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/>.
|
2007-07-16 17:30:04 +00:00
|
|
|
*/
|
|
|
|
|
2012-04-19 20:58:29 +02:00
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
#include "inspircd.h"
|
2018-09-23 14:12:05 +02:00
|
|
|
#include "modules/invite.h"
|
2007-07-16 17:30:04 +00:00
|
|
|
|
2018-08-14 19:18:15 +01:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
// From RFC 2182.
|
|
|
|
ERR_UNAVAILRESOURCE = 437
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-23 15:46:03 +01:00
|
|
|
class KickRejoinData
|
2014-02-15 14:38:24 +01:00
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
struct KickedUser
|
|
|
|
{
|
|
|
|
std::string uuid;
|
|
|
|
time_t expire;
|
|
|
|
|
|
|
|
KickedUser(User* user, unsigned int Delay)
|
|
|
|
: uuid(user->uuid)
|
|
|
|
, expire(ServerInstance->Time() + Delay)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<KickedUser> KickedList;
|
|
|
|
|
|
|
|
mutable KickedList kicked;
|
2015-01-23 15:46:03 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
const unsigned int delay;
|
2014-02-15 14:38:24 +01:00
|
|
|
|
|
|
|
KickRejoinData(unsigned int Delay) : delay(Delay) { }
|
2015-01-23 15:46:03 +01:00
|
|
|
|
|
|
|
bool canjoin(LocalUser* user) const
|
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
for (KickedList::iterator i = kicked.begin(); i != kicked.end(); )
|
2015-01-23 15:46:03 +01:00
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
KickedUser& rec = *i;
|
|
|
|
if (rec.expire > ServerInstance->Time())
|
2015-01-23 15:46:03 +01:00
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
if (rec.uuid == user->uuid)
|
2015-01-23 15:46:03 +01:00
|
|
|
return false;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Expired record, remove.
|
2015-01-23 15:50:18 +01:00
|
|
|
stdalgo::vector::swaperase(kicked, i);
|
|
|
|
if (kicked.empty())
|
|
|
|
break;
|
2015-01-23 15:46:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void add(User* user)
|
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
// One user can be in the list multiple times if the user gets kicked, force joins
|
|
|
|
// (skipping OnUserPreJoin) and gets kicked again, but that's okay because canjoin()
|
|
|
|
// works correctly in this case as well
|
|
|
|
kicked.push_back(KickedUser(user, delay));
|
2015-01-23 15:46:03 +01:00
|
|
|
}
|
2014-02-15 14:38:24 +01:00
|
|
|
};
|
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
/** Handles channel mode +J
|
|
|
|
*/
|
2014-02-15 14:38:24 +01:00
|
|
|
class KickRejoin : public ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2020-02-06 11:25:42 +00:00
|
|
|
const unsigned int max = 60;
|
2007-07-16 17:30:04 +00:00
|
|
|
public:
|
2013-02-18 19:56:05 +01:00
|
|
|
KickRejoin(Module* Creator)
|
2014-02-15 14:38:24 +01:00
|
|
|
: ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >(Creator, "kicknorejoin", 'J')
|
2009-11-15 18:26:44 +00:00
|
|
|
{
|
2019-06-12 21:46:07 +01:00
|
|
|
syntax = "<seconds>";
|
2009-11-15 18:26:44 +00:00
|
|
|
}
|
2007-07-16 17:30:04 +00:00
|
|
|
|
2019-01-25 02:52:11 +00:00
|
|
|
ModeAction OnSet(User* source, Channel* channel, std::string& parameter) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2018-12-12 20:34:46 +00:00
|
|
|
unsigned int v = ConvToNum<unsigned int>(parameter);
|
2014-02-15 14:38:24 +01:00
|
|
|
if (v <= 0)
|
2018-01-27 13:05:14 +00:00
|
|
|
{
|
|
|
|
source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
|
2014-02-15 14:38:24 +01:00
|
|
|
return MODEACTION_DENY;
|
2018-01-27 13:05:14 +00:00
|
|
|
}
|
2013-02-18 19:56:05 +01:00
|
|
|
|
2018-12-12 20:34:46 +00:00
|
|
|
if (IS_LOCAL(source) && v > max)
|
2014-02-15 14:38:24 +01:00
|
|
|
v = max;
|
2013-02-18 19:56:05 +01:00
|
|
|
|
2014-02-15 14:38:24 +01:00
|
|
|
ext.set(channel, new KickRejoinData(v));
|
2013-02-18 19:56:05 +01:00
|
|
|
return MODEACTION_ALLOW;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
2014-02-15 14:38:24 +01:00
|
|
|
|
|
|
|
void SerializeParam(Channel* chan, const KickRejoinData* krd, std::string& out)
|
|
|
|
{
|
|
|
|
out.append(ConvToStr(krd->delay));
|
|
|
|
}
|
2014-09-09 11:09:46 +02:00
|
|
|
|
|
|
|
std::string GetModuleSettings() const
|
|
|
|
{
|
|
|
|
return ConvToStr(max);
|
|
|
|
}
|
2007-07-16 17:30:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ModuleKickNoRejoin : public Module
|
|
|
|
{
|
2009-09-02 00:43:04 +00:00
|
|
|
KickRejoin kr;
|
2018-09-23 14:12:05 +02:00
|
|
|
Invite::API invapi;
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
public:
|
2009-09-26 14:13:13 +00:00
|
|
|
ModuleKickNoRejoin()
|
2020-04-11 14:00:48 +01:00
|
|
|
: Module(VF_VENDOR | VF_COMMON, "Adds channel mode J (kicknorejoin) which prevents users from rejoining after being kicked from a channel.")
|
2020-04-09 18:57:50 +01:00
|
|
|
, kr(this)
|
2018-09-23 14:12:05 +02:00
|
|
|
, invapi(this)
|
2012-10-13 03:12:29 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-25 02:52:11 +00:00
|
|
|
ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
|
|
|
if (chan)
|
|
|
|
{
|
2015-01-23 15:46:03 +01:00
|
|
|
const KickRejoinData* data = kr.ext.get(chan);
|
2018-09-23 14:12:05 +02:00
|
|
|
if ((data) && !invapi->IsInvited(user, chan) && (!data->canjoin(user)))
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2020-04-14 00:23:09 +01:00
|
|
|
user->WriteNumeric(ERR_UNAVAILRESOURCE, chan->name, InspIRCd::Format("You must wait %u seconds after being kicked to rejoin (+J is set)", data->delay));
|
2015-01-23 15:46:03 +01:00
|
|
|
return MOD_RES_DENY;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-02 00:49:36 +00:00
|
|
|
return MOD_RES_PASSTHRU;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2019-01-25 02:52:11 +00:00
|
|
|
void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2014-02-15 14:38:24 +01:00
|
|
|
if ((!IS_LOCAL(memb->user)) || (source == memb->user))
|
|
|
|
return;
|
|
|
|
|
|
|
|
KickRejoinData* data = kr.ext.get(memb->chan);
|
|
|
|
if (data)
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2015-01-23 15:46:03 +01:00
|
|
|
data->add(memb->user);
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2020-04-09 18:57:50 +01:00
|
|
|
void GetLinkData(std::string& data) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2020-04-09 18:57:50 +01:00
|
|
|
data = kr.GetModuleSettings();
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_INIT(ModuleKickNoRejoin)
|