mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-11 11:39:02 -04:00
CBan rewritten to use the XLine API. Untested as yet.
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@9432 e03df62e-2008-0410-955e-edbf42e46eb7
This commit is contained in:
parent
80c42b2f46
commit
ff32b2e66c
@ -12,42 +12,76 @@
|
||||
*/
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "xline.h"
|
||||
|
||||
/* $ModDesc: Gives /cban, aka C:lines. Think Q:lines, for channels. */
|
||||
|
||||
/** Holds a CBAN item
|
||||
*/
|
||||
class CBan : public classbase
|
||||
class CBan : public XLine
|
||||
{
|
||||
public:
|
||||
irc::string chname;
|
||||
std::string set_by;
|
||||
time_t set_on;
|
||||
long length;
|
||||
std::string reason;
|
||||
irc::string matchtext;
|
||||
|
||||
CBan()
|
||||
CBan(InspIRCd* Instance, time_t s_time, long d, const char* src, const char* re, const char *ch) : XLine(Instance, s_time, d, src, re, "CBAN")
|
||||
{
|
||||
this->matchtext = ch;
|
||||
}
|
||||
|
||||
~CBan()
|
||||
{
|
||||
}
|
||||
|
||||
CBan(irc::string cn, std::string sb, time_t so, long ln, std::string rs) : chname(cn), set_by(sb), set_on(so), length(ln), reason(rs)
|
||||
// XXX I shouldn't have to define this
|
||||
bool Matches(User *u)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matches(const std::string &s)
|
||||
{
|
||||
if (matchtext == s)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayExpiry()
|
||||
{
|
||||
ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed CBan %s (set by %s %ld seconds ago)", this->matchtext.c_str(), this->source, this->duration);
|
||||
}
|
||||
|
||||
const char* Displayable()
|
||||
{
|
||||
return matchtext.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
bool CBanComp(const CBan &ban1, const CBan &ban2);
|
||||
/** An XLineFactory specialized to generate cban pointers
|
||||
*/
|
||||
class CBanFactory : public XLineFactory
|
||||
{
|
||||
public:
|
||||
CBanFactory(InspIRCd* Instance) : XLineFactory(Instance, "CBAN") { }
|
||||
|
||||
typedef std::vector<CBan> cbanlist;
|
||||
/** Generate a shun
|
||||
*/
|
||||
XLine* Generate(time_t set_time, long duration, const char* source, const char* reason, const char* xline_specific_mask)
|
||||
{
|
||||
return new CBan(ServerInstance, set_time, duration, source, reason, xline_specific_mask);
|
||||
}
|
||||
|
||||
/* cbans is declared here, as our type is right above. Don't try move it. */
|
||||
cbanlist cbans;
|
||||
bool AutoApplyToUserList(XLine *x)
|
||||
{
|
||||
return false; // No, we apply to channels.
|
||||
}
|
||||
};
|
||||
|
||||
/** Handle /CBAN
|
||||
*/
|
||||
class CommandCban : public Command
|
||||
class CommandCBan : public Command
|
||||
{
|
||||
public:
|
||||
CommandCban(InspIRCd* Me) : Command(Me, "CBAN", "o", 1)
|
||||
CommandCBan(InspIRCd* Me) : Command(Me, "CBAN", "o", 1)
|
||||
{
|
||||
this->source = "m_cban.so";
|
||||
this->syntax = "<channel> [<duration> :<reason>]";
|
||||
@ -61,184 +95,107 @@ class CommandCban : public Command
|
||||
|
||||
if(pcnt == 1)
|
||||
{
|
||||
/* form: CBAN #channel removes a CBAN */
|
||||
for (cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
|
||||
if (ServerInstance->XLines->DelLine(parameters[0], "CBAN", user))
|
||||
{
|
||||
if (parameters[0] == iter->chname)
|
||||
{
|
||||
long remaining = iter->length + ServerInstance->Time();
|
||||
user->WriteNumeric(386, "%s %s :Removed CBAN due to expire at %s (%s)", user->nick, iter->chname.c_str(), ServerInstance->TimeString(remaining).c_str(), iter->reason.c_str());
|
||||
cbans.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pcnt >= 2)
|
||||
{
|
||||
/* full form to add a CBAN */
|
||||
if (ServerInstance->IsChannel(parameters[0]))
|
||||
{
|
||||
// parameters[0] = #channel
|
||||
// parameters[1] = 1h3m2s
|
||||
// parameters[2] = Tortoise abuser
|
||||
long length = ServerInstance->Duration(parameters[1]);
|
||||
std::string reason = (pcnt > 2) ? parameters[2] : "No reason supplied";
|
||||
|
||||
cbans.push_back(CBan(parameters[0], user->nick, ServerInstance->Time(), length, reason));
|
||||
|
||||
std::sort(cbans.begin(), cbans.end(), CBanComp);
|
||||
|
||||
if(length > 0)
|
||||
{
|
||||
user->WriteNumeric(385, "%s %s :Added %lu second channel ban (%s)", user->nick, parameters[0], length, reason.c_str());
|
||||
ServerInstance->SNO->WriteToSnoMask('A', "%s added %lu second channel ban on %s (%s)", user->nick, length, parameters[0], reason.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
user->WriteNumeric(385, "%s %s :Added permanent channel ban (%s)", user->nick, parameters[0], reason.c_str());
|
||||
ServerInstance->SNO->WriteToSnoMask('A', "%s added permanent channel ban on %s (%s)", user->nick, parameters[0], reason.c_str());
|
||||
}
|
||||
ServerInstance->SNO->WriteToSnoMask('x',"%s Removed CBan on %s.",user->nick,parameters[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
user->WriteNumeric(403, "%s %s :Invalid channel name", user->nick, parameters[0]);
|
||||
return CMD_FAILURE;
|
||||
user->WriteServ("NOTICE %s :*** CBan %s not found in list, try /stats C.",user->nick,parameters[0]);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
else if (pcnt >= 2)
|
||||
{
|
||||
// Adding - XXX todo make this respect <insane> tag perhaps..
|
||||
long duration = ServerInstance->Duration(parameters[1]);
|
||||
CBan *r = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
r = new CBan(ServerInstance, ServerInstance->Time(), duration, user->nick, parameters[2], parameters[0]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
; // Do nothing. If we get here, the regex was fucked up, and they already got told it fucked up.
|
||||
}
|
||||
|
||||
if (r)
|
||||
{
|
||||
if (ServerInstance->XLines->AddLine(r, user))
|
||||
{
|
||||
if (!duration)
|
||||
{
|
||||
ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent CBan for %s.", user->nick, parameters[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t c_requires_crap = duration + ServerInstance->Time();
|
||||
ServerInstance->SNO->WriteToSnoMask('x', "%s added timed CBan for %s, expires on %s", user->nick, parameters[0],
|
||||
ServerInstance->TimeString(c_requires_crap).c_str());
|
||||
}
|
||||
|
||||
ServerInstance->XLines->ApplyLines();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete r;
|
||||
user->WriteServ("NOTICE %s :*** CBan for %s already exists", user->nick, parameters[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we want this routed! */
|
||||
return CMD_SUCCESS;
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
bool CBanComp(const CBan &ban1, const CBan &ban2)
|
||||
{
|
||||
return ((ban1.set_on + ban1.length) < (ban2.set_on + ban2.length));
|
||||
}
|
||||
|
||||
class ModuleCBan : public Module
|
||||
{
|
||||
CommandCban* mycommand;
|
||||
|
||||
CommandCBan* mycommand;
|
||||
CBanFactory *f;
|
||||
|
||||
public:
|
||||
ModuleCBan(InspIRCd* Me) : Module(Me)
|
||||
{
|
||||
|
||||
mycommand = new CommandCban(Me);
|
||||
f = new CBanFactory(ServerInstance);
|
||||
ServerInstance->XLines->RegisterFactory(f);
|
||||
|
||||
mycommand = new CommandCBan(Me);
|
||||
ServerInstance->AddCommand(mycommand);
|
||||
Implementation eventlist[] = { I_OnUserPreJoin, I_OnSyncOtherMetaData, I_OnDecodeMetaData, I_OnStats };
|
||||
ServerInstance->Modules->Attach(eventlist, this, 4);
|
||||
}
|
||||
|
||||
virtual ~ModuleCBan()
|
||||
{
|
||||
ServerInstance->XLines->UnregisterFactory(f);
|
||||
}
|
||||
|
||||
virtual int OnStats(char symbol, User* user, string_list &results)
|
||||
{
|
||||
ExpireBans();
|
||||
|
||||
if(symbol == 'C')
|
||||
{
|
||||
for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
|
||||
{
|
||||
unsigned long remaining = (iter->set_on + iter->length) - ServerInstance->Time();
|
||||
results.push_back(std::string(ServerInstance->Config->ServerName)+" 210 "+user->nick+" "+iter->chname.c_str()+" "+iter->set_by+" "+ConvToStr(iter->set_on)+" "+ConvToStr(iter->length)+" "+ConvToStr(remaining)+" :"+iter->reason);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int OnUserPreJoin(User *user, Channel *chan, const char *cname, std::string &privs)
|
||||
{
|
||||
ExpireBans();
|
||||
|
||||
/* check cbans in here, and apply as necessary. */
|
||||
for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
|
||||
XLine *rl = ServerInstance->XLines->MatchesLine("CBAN", cname);
|
||||
|
||||
if (rl)
|
||||
{
|
||||
if(iter->chname == cname && !user->modes[UM_OPERATOR])
|
||||
{
|
||||
// Channel is banned.
|
||||
user->WriteServ( "384 %s %s :Cannot join channel, CBANed (%s)", user->nick, cname, iter->reason.c_str());
|
||||
ServerInstance->SNO->WriteToSnoMask('A', "%s tried to join %s which is CBANed (%s)", user->nick, cname, iter->reason.c_str());
|
||||
return 1;
|
||||
}
|
||||
// Channel is banned.
|
||||
user->WriteServ( "384 %s %s :Cannot join channel, CBANed (%s)", user->nick, cname, rl->reason);
|
||||
ServerInstance->SNO->WriteToSnoMask('A', "%s tried to join %s which is CBANed (%s)", user->nick, cname, rl->reason);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void OnSyncOtherMetaData(Module* proto, void* opaque, bool displayable)
|
||||
{
|
||||
for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
|
||||
{
|
||||
proto->ProtoSendMetaData(opaque, TYPE_OTHER, NULL, "cban", EncodeCBan(*iter));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata)
|
||||
{
|
||||
if((target_type == TYPE_OTHER) && (extname == "cban"))
|
||||
{
|
||||
cbans.push_back(DecodeCBan(extdata));
|
||||
std::sort(cbans.begin(), cbans.end(), CBanComp);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~ModuleCBan()
|
||||
{
|
||||
}
|
||||
|
||||
virtual Version GetVersion()
|
||||
{
|
||||
return Version(1, 2, 0, 1, VF_COMMON | VF_VENDOR, API_VERSION);
|
||||
}
|
||||
|
||||
std::string EncodeCBan(const CBan &ban)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << ban.chname << " " << ban.set_by << " " << ban.set_on << " " << ban.length << " :" << ban.reason;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
CBan DecodeCBan(const std::string &data)
|
||||
{
|
||||
CBan res;
|
||||
int set_on;
|
||||
irc::tokenstream tokens(data);
|
||||
tokens.GetToken(res.chname);
|
||||
tokens.GetToken(res.set_by);
|
||||
tokens.GetToken(set_on);
|
||||
res.set_on = set_on;
|
||||
tokens.GetToken(res.length);
|
||||
tokens.GetToken(res.reason);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ExpireBans()
|
||||
{
|
||||
bool go_again = true;
|
||||
|
||||
while (go_again)
|
||||
{
|
||||
go_again = false;
|
||||
|
||||
for (cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
|
||||
{
|
||||
/* 0 == permanent, don't mess with them! -- w00t */
|
||||
if (iter->length != 0)
|
||||
{
|
||||
if (iter->set_on + iter->length <= ServerInstance->Time())
|
||||
{
|
||||
ServerInstance->SNO->WriteToSnoMask('A', "%li second CBAN on %s (%s) set on %s expired", iter->length, iter->chname.c_str(), iter->reason.c_str(), ServerInstance->TimeString(iter->set_on).c_str());
|
||||
cbans.erase(iter);
|
||||
go_again = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (go_again == true)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(ModuleCBan)
|
||||
|
Loading…
x
Reference in New Issue
Block a user