diff options
Diffstat (limited to 'modules/protocol/unreal32.cpp')
-rw-r--r-- | modules/protocol/unreal32.cpp | 1143 |
1 files changed, 0 insertions, 1143 deletions
diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp deleted file mode 100644 index be7407af7..000000000 --- a/modules/protocol/unreal32.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -/* Unreal IRCD 3.2.x functions - * - * (C) 2003-2011 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 "services.h" -#include "modules.h" -#include "nickserv.h" - -IRCDVar myIrcd[] = { - {"UnrealIRCd 3.2.x", /* ircd name */ - "+Soiq", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 1, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 12, /* Max number of modes we can send per line */ - 0, /* IRCd sends a SSL users certificate fingerprint */ - } - , - {NULL} -}; - -/* PROTOCTL */ -/* - NICKv2 = Nick Version 2 - VHP = Sends hidden host - UMODE2 = sends UMODE2 on user modes - NICKIP = Sends IP on NICK - TOKEN = Use tokens to talk - SJ3 = Supports SJOIN - NOQUIT = No Quit - TKLEXT = Extended TKL we don't use it but best to have it - SJB64 = Base64 encoded time stamps - VL = Version Info - NS = Config->Numeric Server - -*/ -void unreal_cmd_capab() -{ - if (!Config->Numeric.empty()) - send_cmd("", "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT VL"); - else - send_cmd("", "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT"); -} - -/* PASS */ -void unreal_cmd_pass(const Anope::string &pass) -{ - send_cmd("", "PASS :%s", pass.c_str()); -} - -/* CHGHOST */ -void unreal_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) -{ - if (nick.empty() || vhost.empty()) - return; - send_cmd(Config->ServerName, "AL %s %s", nick.c_str(), vhost.c_str()); -} - -/* CHGIDENT */ -void unreal_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) -{ - if (nick.empty() || vIdent.empty()) - return; - send_cmd(Config->ServerName, "AZ %s %s", nick.c_str(), vIdent.c_str()); -} - -class UnrealIRCdProto : public IRCDProto -{ - /* SVSNOOP */ - void SendSVSNOOP(const Anope::string &server, int set) - { - send_cmd("", "f %s %s", server.c_str(), set ? "+" : "-"); - } - - void SendAkillDel(const XLine *x) - { - send_cmd("", "BD - G %s %s %s", x->GetUser().c_str(), x->GetHost().c_str(), Config->s_OperServ.c_str()); - } - - void SendTopic(BotInfo *whosets, Channel *c) - { - send_cmd(whosets->nick, ") %s %s %lu :%s", c->name.c_str(), c->topic_setter.c_str(), static_cast<unsigned long>(c->topic_time + 1), c->topic.c_str()); - } - - void SendVhostDel(User *u) - { - BotInfo *bi = findbot(Config->s_HostServ); - u->RemoveMode(bi, UMODE_CLOAK); - u->RemoveMode(bi, UMODE_VHOST); - ModeManager::ProcessModes(); - u->SetMode(bi, UMODE_CLOAK); - } - - void SendAkill(User *, const XLine *x) - { - // Calculate the time left before this would expire, capping it at 2 days - time_t timeleft = x->Expires - Anope::CurTime; - if (timeleft > 172800) - timeleft = 172800; - send_cmd("", "BD + G %s %s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime + timeleft), static_cast<long>(x->Created), x->Reason.c_str()); - } - - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) - { - send_cmd(source ? source->nick : Config->ServerName, "h %s :%s", user->nick.c_str(), buf.c_str()); - } - - void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(source->nick, "G %s %s", dest->name.c_str(), buf.c_str()); - } - - void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) - { - send_cmd(bi ? bi->nick : Config->ServerName, "v %s %s", u->nick.c_str(), buf.c_str()); - } - - void SendClientIntroduction(const User *u, const Anope::string &modes) - { - XLine x(u->nick, "Reserved for services"); - ircdproto->SendSQLine(NULL, &x); - send_cmd("", "& %s 1 %ld %s %s %s 0 %s %s * :%s", u->nick.c_str(), static_cast<long>(u->timestamp), u->GetIdent().c_str(), u->host.c_str(), Config->ServerName.c_str(), modes.c_str(), u->host.c_str(), u->realname.c_str()); - } - - void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf) - { - if (!buf.empty()) - send_cmd(source->nick, "H %s %s :%s", chan->name.c_str(), user->nick.c_str(), buf.c_str()); - else - send_cmd(source->nick, "H %s %s", chan->name.c_str(), user->nick.c_str()); - } - - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - if (buf.empty()) - return; - send_cmd(source->nick, "B @%s :%s", dest->name.c_str(), buf.c_str()); - } - - /* SERVER name hop descript */ - /* Unreal 3.2 actually sends some info about itself in the descript area */ - void SendServer(const Server *server) - { - if (!Config->Numeric.empty()) - send_cmd("", "SERVER %s %d :U0-*-%s %s", server->GetName().c_str(), server->GetHops(), Config->Numeric.c_str(), server->GetDescription().c_str()); - else - send_cmd("", "SERVER %s %d :%s", server->GetName().c_str(), server->GetHops(), server->GetDescription().c_str()); - } - - /* JOIN */ - void SendJoin(BotInfo *user, Channel *c, const ChannelStatus *status) - { - send_cmd(Config->ServerName, "~ %ld %s :%s", static_cast<long>(c->creation_time), c->name.c_str(), user->nick.c_str()); - if (status) - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (status->HasFlag(ModeManager::ChannelModes[i]->Name)) - c->SetMode(user, ModeManager::ChannelModes[i], user->nick, false); - } - - /* unsqline - */ - void SendSQLineDel(const XLine *x) - { - send_cmd("", "d %s", x->Mask.c_str()); - } - - /* SQLINE */ - /* - ** - Unreal will translate this to TKL for us - ** - */ - void SendSQLine(User *, const XLine *x) - { - send_cmd("", "c %s :%s", x->Mask.c_str(), x->Reason.c_str()); - } - - /* - ** svso - ** parv[0] = sender prefix - ** parv[1] = nick - ** parv[2] = options - */ - void SendSVSO(const Anope::string &source, const Anope::string &nick, const Anope::string &flag) - { - send_cmd(source, "BB %s %s", nick.c_str(), flag.c_str()); - } - - /* NICK <newnick> */ - void SendChangeBotNick(const BotInfo *oldnick, const Anope::string &newnick) - { - send_cmd(oldnick->nick, "& %s %ld", newnick.c_str(), static_cast<long>(Anope::CurTime)); - } - - /* Functions that use serval cmd functions */ - - void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) - { - if (!vIdent.empty()) - unreal_cmd_chgident(u->nick, vIdent); - if (!vhost.empty()) - unreal_cmd_chghost(u->nick, vhost); - } - - void SendConnect() - { - unreal_cmd_capab(); - unreal_cmd_pass(uplink_server->password); - SendServer(Me); - } - - /* SVSHOLD - set */ - void SendSVSHold(const Anope::string &nick) - { - send_cmd("", "BD + Q H %s %s %ld %ld :Being held for registered user", nick.c_str(), Config->ServerName.c_str(), static_cast<long>(Anope::CurTime + Config->NSReleaseTimeout), static_cast<long>(Anope::CurTime)); - } - - /* SVSHOLD - release */ - void SendSVSHoldDel(const Anope::string &nick) - { - send_cmd("", "BD - Q * %s %s", nick.c_str(), Config->ServerName.c_str()); - } - - /* UNSGLINE */ - /* - * SVSNLINE - :realname mask - */ - void SendSGLineDel(const XLine *x) - { - send_cmd("", "BR - :%s", x->Mask.c_str()); - } - - /* UNSZLINE */ - void SendSZLineDel(const XLine *x) - { - send_cmd("", "BD - Z * %s %s", x->Mask.c_str(), Config->s_OperServ.c_str()); - } - - /* SZLINE */ - void SendSZLine(User *, const XLine *x) - { - send_cmd("", "BD + Z * %s %s %ld %ld :%s", x->Mask.c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime + 172800), static_cast<long>(Anope::CurTime), x->Reason.c_str()); - } - - /* SGLINE */ - /* - * SVSNLINE + reason_where_is_space :realname mask with spaces - */ - void SendSGLine(User *, const XLine *x) - { - Anope::string edited_reason = x->Reason; - edited_reason = edited_reason.replace_all_cs(" ", "_"); - send_cmd("", "BR + %s :%s", edited_reason.c_str(), x->Mask.c_str()); - } - - /* svsjoin - parv[0] - sender - parv[1] - nick to make join - parv[2] - channel to join - parv[3] - (optional) channel key(s) - */ - /* In older Unreal SVSJOIN and SVSNLINE tokens were mixed so SVSJOIN and SVSNLINE are broken - when coming from a none TOKEN'd server - */ - void SendSVSJoin(const Anope::string &source, const Anope::string &nick, const Anope::string &chan, const Anope::string ¶m) - { - if (!param.empty()) - send_cmd(source, "BX %s %s :%s", nick.c_str(), chan.c_str(), param.c_str()); - else - send_cmd(source, "BX %s :%s", nick.c_str(), chan.c_str()); - } - - void SendSWhois(const Anope::string &source, const Anope::string &who, const Anope::string &mask) - { - send_cmd(source, "BA %s :%s", who.c_str(), mask.c_str()); - } - - void SendEOB() - { - send_cmd(Config->ServerName, "ES"); - } - - bool IsNickValid(const Anope::string &nick) - { - if (nick.equals_ci("ircd") || nick.equals_ci("irc")) - return false; - - return true; - } - - bool IsChannelValid(const Anope::string &chan) - { - if (chan.find(':') != Anope::string::npos || chan[0] != '#') - return false; - - return true; - } - - void SetAutoIdentificationToken(User *u) - { - if (!u->Account()) - return; - - ircdproto->SendMode(nickserv->Bot(), u, "+d %d", u->timestamp); - } - - void SendUnregisteredNick(const User *u) - { - ircdproto->SendMode(nickserv->Bot(), u, "+d 1"); - } - - void SendChannel(Channel *c) - { - /* Unreal does not support updating a channels TS without actually joining a user, - * so we will join and part us now - */ - BotInfo *bi = c->ci->WhoSends(); - if (c->FindUser(bi) == NULL) - { - bi->Join(c); - bi->Part(c); - } - else - { - bi->Part(c); - bi->Join(c); - } - } -}; - -template<typename T> class UnrealExtBan : public T -{ - public: - UnrealExtBan(ChannelModeName mName, char modeChar) : T(mName, modeChar) { } - - bool Matches(User *u, const Entry *e) - { - const Anope::string &mask = e->mask; - - if (mask.find("~c:") == 0) - { - Anope::string channel = mask.substr(3); - - ChannelMode *cm = NULL; - if (channel[0] != '#') - { - char modeChar = ModeManager::GetStatusChar(channel[0]); - channel.erase(channel.begin()); - cm = ModeManager::FindChannelModeByChar(modeChar); - if (cm != NULL && cm->Type != MODE_STATUS) - cm = NULL; - } - - Channel *c = findchan(channel); - if (c != NULL) - { - UserContainer *uc = c->FindUser(u); - if (uc != NULL) - if (cm == NULL || uc->Status->HasFlag(cm->Name)) - return true; - } - } - else if (mask.find("~j:") == 0 || mask.find("~n:") == 0 || mask.find("~q:") == 0) - { - Anope::string real_mask = mask.substr(3); - - Entry en(this->Name, real_mask); - if (en.Matches(u)) - return true; - } - else if (mask.find("~r:") == 0) - { - Anope::string real_mask = mask.substr(3); - - if (Anope::Match(u->realname, real_mask)) - return true; - } - else if (mask.find("~R:") == 0) - { - if (u->HasMode(UMODE_REGISTERED) && mask.equals_ci(u->nick)) - return true; - } - - return false; - } -}; - -class ChannelModeFlood : public ChannelModeParam -{ - public: - ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } - - /* Borrowed part of this check from UnrealIRCd */ - bool IsValid(const Anope::string &value) const - { - if (value.empty()) - return false; - try - { - Anope::string rest; - if (value[0] != ':' && convertTo<unsigned>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<unsigned>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } - - /* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */ - size_t end_bracket = value.find(']', 1); - if (end_bracket == Anope::string::npos) - return false; - Anope::string xbuf = value.substr(0, end_bracket); - if (value[end_bracket + 1] != ':') - return false; - commasepstream args(xbuf.substr(1)); - Anope::string arg; - while (args.GetToken(arg)) - { - /* <number><1 letter>[optional: '#'+1 letter] */ - size_t p = 0; - while (p < arg.length() && isdigit(arg[p])) - ++p; - if (p == arg.length() || !(arg[p] == 'c' || arg[p] == 'j' || arg[p] == 'k' || arg[p] == 'm' || arg[p] == 'n' || arg[p] == 't')) - continue; /* continue instead of break for forward compatability. */ - int v = arg.substr(0, p).is_number_only() ? convertTo<int>(arg.substr(0, p)) : 0; - if (v < 1 || v > 999) - return false; - } - - return true; - } -}; - -class Unreal32IRCdMessage : public IRCdMessage -{ - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) - { - if (params.size() < 2) - return true; - - bool server_source = Server::Find(source) != NULL; - Anope::string modes = params[1]; - for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i) - modes += " " + params[i]; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], modes, server_source ? params[params.size() - 1] : ""); - else - do_umode(params[0], modes); - - return true; - } - - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = username - ** parv[4] = hostname - ** parv[5] = servername - ** if NICK version 1: - ** parv[6] = servicestamp - ** parv[7] = info - ** if NICK version 2: - ** parv[6] = servicestamp - ** parv[7] = umodes - ** parv[8] = virthost, * if none - ** parv[9] = info - ** if NICKIP: - ** parv[9] = ip - ** parv[10] = info - ** - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) - { - if (params.size() == 7) - { - /* - <codemastr> that was a bug that is now fixed in 3.2.1 - <codemastr> in some instances it would use the non-nickv2 format - <codemastr> it's sent when a nick collision occurs - - so we have to leave it around for now -TSL - */ - do_nick(source, params[0], params[3], params[4], params[5], params[6], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", "*", "", ""); - } - else if (params.size() == 11) - { - Anope::string decoded_ip; - Anope::B64Decode(params[9], decoded_ip); - - sockaddrs ip; - ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); - - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), vhost, "", params[7]); - if (user) - { - NickAlias *na = findnick(user->nick); - - if (na && user->timestamp == convertTo<time_t>(params[6])) - { - user->Login(na->nc); - if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() != 2) - { - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - /* NON NICKIP */ - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", vhost, "", params[7]); - if (user) - { - NickAlias *na = findnick(user->nick); - - if (na && user->timestamp == convertTo<time_t>(params[6])) - { - user->Login(na->nc); - if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - - return true; - } - - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) - { - if (params[1].equals_cs("1")) - { - Anope::string vl = myStrGetToken(params[2], ' ', 0); - Anope::string upnumeric = myStrGetToken(vl, '-', 2); - Anope::string desc = myStrGetTokenRemainder(params[2], ' ', 1); - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, desc, upnumeric); - } - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - - ircdproto->SendPing(Config->ServerName, params[0]); - - return true; - } - - /* - ** source = sender prefix - ** parv[0] = channel name - ** parv[1] = topic nickname - ** parv[2] = topic time - ** parv[3] = topic text - */ - bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) - { - if (params.size() != 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) - { - for (unsigned i = 0; i < params.size(); ++i) - { - Anope::string capab = params[i]; - - if (capab.find("CHANMODES") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'b': - ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeBan>(CMODE_BAN, 'b')); - continue; - case 'e': - ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeList>(CMODE_EXCEPT, 'e')); - continue; - case 'I': - ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeList>(CMODE_INVITEOVERRIDE, 'I')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, modebuf[t])); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'k': - ModeManager::AddChannelMode(new ChannelModeKey('k')); - continue; - case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f', false)); - continue; - case 'L': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, 'L')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, modebuf[t])); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'l': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l', true)); - continue; - case 'j': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, 'j', true)); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, modebuf[t], true)); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'p': - ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, 'p')); - continue; - case 's': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's')); - continue; - case 'm': - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); - continue; - case 'n': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n')); - continue; - case 't': - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't')); - continue; - case 'i': - ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); - continue; - case 'r': - ModeManager::AddChannelMode(new ChannelModeRegistered('r')); - continue; - case 'R': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R')); - continue; - case 'c': - ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); - continue; - case 'O': - ModeManager::AddChannelMode(new ChannelModeOper('O')); - continue; - case 'A': - ModeManager::AddChannelMode(new ChannelModeAdmin('A')); - continue; - case 'Q': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, 'Q')); - continue; - case 'K': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, 'K')); - continue; - case 'V': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOINVITE, 'V')); - continue; - case 'C': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, 'C')); - continue; - case 'u': - ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, 'u')); - continue; - case 'z': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'z')); - continue; - case 'N': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, 'N')); - continue; - case 'S': - ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, 'S')); - continue; - case 'M': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGMODERATED, 'M')); - continue; - case 'T': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, 'T')); - continue; - case 'G': - ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, 'G')); - continue; - default: - ModeManager::AddChannelMode(new ChannelMode(CMODE_END, modebuf[t])); - } - } - } - } - - IRCdMessage::OnCapab(source, params); - - return true; - } - - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) - { - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[1], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this SJOIN string contains modes */ - if (keep_their_modes && params.size() >= 4) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) - { - /* Ban */ - if (keep_their_modes && ban && buf[0] == '&') - { - buf.erase(buf.begin()); - c->SetModeInternal(ban, buf); - } - /* Except */ - else if (keep_their_modes && except && buf[0] == '"') - { - buf.erase(buf.begin()); - c->SetModeInternal(except, buf); - } - /* Invex */ - else if (keep_their_modes && invex && buf[0] == '\'') - { - buf.erase(buf.begin()); - c->SetModeInternal(invex, buf); - } - else - { - std::list<ChannelMode *> Status; - char ch; - - /* Get prefixes from the nick */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) - { - buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log() << "Received unknown mode prefix " << ch << " in SJOIN string"; - continue; - } - - if (keep_their_modes) - Status.push_back(cm); - } - - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * This will enforce secureops etc on the user - */ - for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* Check to see if modules want the user to join, if they do - * check to see if they are allowed to join (CheckKick will kick/ban them) - * Don't trigger OnJoinChannel event then as the user will be destroyed - */ - if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); - } - - return true; - } -}; - - -/** This is here because: - * - * If we had three servers, A, B & C linked like so: A<->B<->C - * If Anope is linked to A and B splits from A and then reconnects - * B introduces itself, introduces C, sends EOS for C, introduces Bs clients - * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced - * with their server "not syncing". We now send a PING immediately when receiving a new server - * and then finish sync once we get a pong back from that server. - */ -bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - if (s && !s->IsSynced()) - s->Sync(false); - return true; -} - -/* netinfo - * argv[0] = max global count - * argv[1] = time of end sync - * argv[2] = unreal protocol using (numeric) - * argv[3] = cloak-crc (> u2302) - * argv[4] = free(**) - * argv[5] = free(**) - * argv[6] = free(**) - * argv[7] = ircnet - */ -bool event_netinfo(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - send_cmd("", "AO %ld %ld %d %s 0 0 0 :%s", static_cast<long>(maxusercnt), static_cast<long>(Anope::CurTime), Anope::string(params[2]).is_number_only() ? convertTo<int>(params[2]) : 0, params[3].c_str(), params[7].c_str()); - return true; -} - -/* Unreal sends USER modes with this */ -/* - umode2 - parv[0] - sender - parv[1] - modes to change -*/ -bool event_umode2(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - - do_umode(source, params[0]); - return true; -} - - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - User *u = finduser(params[0]); - if (!u) - { - Log(LOG_DEBUG) << "CHGNAME for nonexistent user " << params[0]; - return true; - } - - u->SetRealname(params[1]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetVIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - User *u = finduser(params[0]); - if (!u) - { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetVIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } - - /* When a user sets +x we recieve the new host and then the mode change */ - if (u->HasMode(UMODE_CLOAK)) - u->SetDisplayedHost(params[0]); - else - u->SetCloakedHost(params[0]); - - return true; -} - -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - User *u = finduser(params[0]); - if (!u) - { - Log(LOG_DEBUG) << "debug: CHGHOST for nonexistent user " << params[0]; - return true; - } - - u->SetDisplayedHost(params[1]); - return true; -} - -bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (s) - s->SetDescription(params[0]); - - return true; -} - -class ProtoUnreal : public Module -{ - Message message_away, message_join, message_kick, - message_kill, message_mode, message_nick, message_part, - message_ping, message_pong, message_pong2, message_privmsg, - message_quit, message_server, message_squit, message_topic, - message_svsmode, message_svsmode2, message_svs2mode, message_svs2mode2, message_whois, - message_capab, message_capab2, message_chghost, message_chghost2, message_chgident, message_chgident2, - message_chgname, message_chgname2, message_netinfo, message_netinfo2, message_sethost, message_sethost2, - message_setident, message_setident2, message_setname, message_setname2, message_error, - message_umode2, message_umode22, message_sjoin, message_sdesc, message_sdesc2; - - /* Non-token of these in messages.cpp */ - Message message_stats, message_time, message_version; - - UnrealIRCdProto ircd_proto; - Unreal32IRCdMessage ircd_message; - - void AddModes() - { - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); - /* Unreal sends +q as * and +a as ~ */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '~')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '*')); - - /* Add user modes */ - ModeManager::AddUserMode(new UserMode(UMODE_SERV_ADMIN, 'A')); - ModeManager::AddUserMode(new UserMode(UMODE_BOT, 'B')); - ModeManager::AddUserMode(new UserMode(UMODE_CO_ADMIN, 'C')); - ModeManager::AddUserMode(new UserMode(UMODE_FILTER, 'G')); - ModeManager::AddUserMode(new UserMode(UMODE_HIDEOPER, 'H')); - ModeManager::AddUserMode(new UserMode(UMODE_NETADMIN, 'N')); - ModeManager::AddUserMode(new UserMode(UMODE_REGPRIV, 'R')); - ModeManager::AddUserMode(new UserMode(UMODE_PROTECTED, 'S')); - ModeManager::AddUserMode(new UserMode(UMODE_NO_CTCP, 'T')); - ModeManager::AddUserMode(new UserMode(UMODE_WEBTV, 'V')); - ModeManager::AddUserMode(new UserMode(UMODE_WHOIS, 'W')); - ModeManager::AddUserMode(new UserMode(UMODE_ADMIN, 'a')); - ModeManager::AddUserMode(new UserMode(UMODE_DEAF, 'd')); - ModeManager::AddUserMode(new UserMode(UMODE_GLOBOPS, 'g')); - ModeManager::AddUserMode(new UserMode(UMODE_HELPOP, 'h')); - ModeManager::AddUserMode(new UserMode(UMODE_INVIS, 'i')); - ModeManager::AddUserMode(new UserMode(UMODE_OPER, 'o')); - ModeManager::AddUserMode(new UserMode(UMODE_PRIV, 'p')); - ModeManager::AddUserMode(new UserMode(UMODE_GOD, 'q')); - ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, 'r')); - ModeManager::AddUserMode(new UserMode(UMODE_SNOMASK, 's')); - ModeManager::AddUserMode(new UserMode(UMODE_VHOST, 't')); - ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w')); - ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); - ModeManager::AddUserMode(new UserMode(UMODE_SSL, 'z')); - } - - public: - ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_away("6", OnAway), - message_join("C", OnJoin), - message_kick("H", OnKick), message_kill(".", OnKill), - message_mode("G", OnMode), - message_nick("&", OnNick), message_part("D", OnPart), - message_ping("8", OnPing), message_pong("PONG", event_pong), - message_pong2("9", event_pong), message_privmsg("!", ::OnPrivmsg), - message_quit(",", OnQuit), - message_server("'", OnServer), message_squit("-", OnSQuit), - message_topic(")", OnTopic), message_svsmode("SVSMODE", OnMode), - message_svsmode2("n", OnMode), message_svs2mode("SVS2MODE", OnMode), message_svs2mode2("v", OnMode), - message_whois("#", OnWhois), message_capab("PROTOCTL", OnCapab), - message_capab2("_", OnCapab), message_chghost("CHGHOST", event_chghost), message_chghost2("AL", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgident2("AZ", event_chgident), - message_chgname("CHGNAME", event_chgname), message_chgname2("BK", event_chgname), - message_netinfo("NETINFO", event_netinfo), message_netinfo2("AO", event_netinfo), - message_sethost("SETHOST", event_sethost), message_sethost2("AA", event_sethost), - message_setident("SETIDENT", event_setident), message_setident2("AD", event_setident), - message_setname("SETNAME", event_setname), message_setname2("AE", event_setname), - message_error("5", OnError), message_umode2("UMODE2", event_umode2), - message_umode22("|", event_umode2), message_sjoin("~", OnSJoin), - message_sdesc("SDESC", event_sdesc), message_sdesc2("AG", event_sdesc), - - message_stats("2", OnStats), message_time(">", OnTime), message_version("+", OnVersion) - { - this->SetAuthor("Anope"); - this->SetType(PROTOCOL); - - pmodule_ircd_var(myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - - this->AddModes(); - - ModuleManager::Attach(I_OnUserNickChange, this); - } - - void OnUserNickChange(User *u, const Anope::string &) - { - u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); - } -}; - -MODULE_INIT(ProtoUnreal) |