/* Inspircd 2.0 functions
*
* (C) 2003-2014 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
#include "module.h"
#include "modules/sasl.h"
#include "modules/cs_mode.h"
struct SASLUser
{
Anope::string uid;
Anope::string acc;
time_t created;
};
static std::list<SASLUser> saslusers;
static Anope::string rsquit_server, rsquit_id;
static unsigned int spanningtree_proto_ver = 0;
class InspIRCd20Proto : public IRCDProto
{
private:
void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) override
{
IRCDProto::SendSVSKillInternal(source, user, buf);
user->KillInternal(source, buf);
}
void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent)
{
if (!Servers::Capab.count("CHGIDENT"))
Log() << "CHGIDENT not loaded!";
else
UplinkSocket::Message(Me) << "CHGIDENT " << nick << " " << vIdent;
}
void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost)
{
if (!Servers::Capab.count("CHGHOST"))
Log() << "CHGHOST not loaded!";
else
UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost;
}
void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason)
{
UplinkSocket::Message(Me) << "ADDLINE " << xtype << " " << mask << " " << addedby << " " << Anope::CurTime << " " << duration << " :" << reason;
}
void SendDelLine(const Anope::string &xtype, const Anope::string &mask)
{
UplinkSocket::Message(Me) << "DELLINE " << xtype << " " << mask;
}
public:
InspIRCd20Proto(Module *creator) : IRCDProto(creator, "InspIRCd 2.0")
{
DefaultPseudoclientModes = "+I";
CanSVSNick = true;
CanSVSJoin = true;
CanSetVHost = true;
CanSetVIdent = true;
CanSQLine = true;
CanSZLine = true;
CanSVSHold = true;
CanCertFP = true;
RequiresID = true;
MaxModes = 20;
}
void SendConnect() override
{
UplinkSocket::Message() << "CAPAB START 1202";
UplinkSocket::Message() << "CAPAB CAPABILITIES :PROTOCOL=1202";
UplinkSocket::Message() << "CAPAB END";
SendServer(Me);
}
void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
}
void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
}
void SendAkillDel(const XLine *x) override
{
/* InspIRCd may support regex bans */
if (x->IsRegex() && Servers::Capab.count("RLINE"))
{
Anope::string mask = x->mask;
size_t h = x->mask.find('#');
if (h != Anope::string::npos)
mask = mask.replace(h, 1, ' ');
SendDelLine("R", mask);
return;
}
else if (x->IsRegex() || x->HasNickOrReal())
return;
/* ZLine if we can instead */
if (x->GetUser() == "*")
{
cidr addr(x->GetHost());
if (addr.valid())
{
IRCD->SendSZLineDel(x);
return;
}
}
SendDelLine("G", x->GetUser() + "@" + x->GetHost());
}
void SendTopic(const MessageSource &source, Channel *c) override
{
if (Servers::Capab.count("SVSTOPIC"))
{
UplinkSocket::Message(c->ci->WhoSends()) << "SVSTOPIC " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic;
}
else
{
/* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */
time_t ts = c->topic_ts;
if (c->topic_time > ts)
ts = Anope::CurTime;
/* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */
UplinkSocket::Message(source) << "FTOPIC " << c->name << " " << ts << " " << c->topic_setter << " :" << c->topic;
}
}
void SendVhostDel(User *u) override
{
if (u->HasMode("CLOAK"))
this->SendChgHostInternal(u->nick, u->chost);
else
this->SendChgHostInternal(u->nick, u->host);
if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent())
this->SendChgIdentInternal(u->nick, u->GetIdent());
}
void SendAkill(User *u, XLine *x) override
{
// Calculate the time left before this would expire, capping it at 2 days
time_t timeleft = x->expires - Anope::CurTime;
if (timeleft > 172800 || !x->expires)
timeleft = 172800;
/* InspIRCd may support regex bans, if they do we can send this and forget about it */
if (x->IsRegex() && Servers::Capab.count("RLINE"))
{
Anope::string mask = x->mask;
size_t h = x->mask.find('#');
if (h != Anope::string::npos)
mask = mask.replace(h, 1, ' ');
SendAddLine("R", mask, timeleft, x->by, x->GetReason());
return;
}
else if (x->IsRegex() || x->HasNickOrReal())
{
if (!u)
{
/* No user (this akill was just added), and contains nick and/or realname. Find users that match and
|