CmdResult CommandAddLine::Handle(User* usr, std::vector<std::string>& params) { XLineFactory* xlf = ServerInstance->XLines->GetFactory(params[0]); const std::string& setter = usr->nick; if (!xlf) { ServerInstance->SNO->WriteToSnoMask('d',"%s sent me an unknown ADDLINE type (%s).",setter.c_str(),params[0].c_str()); return CMD_FAILURE; } XLine* xl = NULL; try { xl = xlf->Generate(ServerInstance->Time(), ConvToInt(params[4]), params[2], params[5], params[1]); } catch (ModuleException &e) { ServerInstance->SNO->WriteToSnoMask('d',"Unable to ADDLINE type %s from %s: %s", params[0].c_str(), setter.c_str(), e.GetReason().c_str()); return CMD_FAILURE; } xl->SetCreateTime(ConvToInt(params[3])); if (ServerInstance->XLines->AddLine(xl, NULL)) { if (xl->duration) { std::string timestr = InspIRCd::TimeString(xl->expiry); ServerInstance->SNO->WriteToSnoMask('X',"%s added %s%s on %s to expire on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", params[1].c_str(), timestr.c_str(), params[5].c_str()); } else { ServerInstance->SNO->WriteToSnoMask('X',"%s added permanent %s%s on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", params[1].c_str(),params[5].c_str()); } TreeServer* remoteserver = TreeServer::Get(usr); if (!remoteserver->IsBursting()) { ServerInstance->XLines->ApplyLines(); } return CMD_SUCCESS; } else { delete xl; return CMD_FAILURE; } }
bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params) { if ((cmd == "METADATA") && (params.size() >= 3) && (params[0][0] == '#')) { // :20D METADATA #channel extname :extdata return InsertCurrentChannelTS(params); } else if ((cmd == "FTOPIC") && (params.size() >= 4)) { // :20D FTOPIC #channel 100 Attila :topic text return InsertCurrentChannelTS(params); } else if ((cmd == "PING") || (cmd == "PONG")) { if (params.size() == 1) { // If it's a PING with 1 parameter, reply with a PONG now, if it's a PONG with 1 parameter (weird), do nothing if (cmd[1] == 'I') this->WriteData(":" + ServerInstance->Config->GetSID() + " PONG " + params[0] + newline); // Don't process this message further return false; } // :20D PING 20D 22D // :20D PONG 20D 22D // Drop the first parameter params.erase(params.begin()); // If the target is a server name, translate it to a SID if (!InspIRCd::IsSID(params[0])) { TreeServer* server = Utils->FindServer(params[0]); if (!server) { // We've no idea what this is, log and stop processing ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Received a " + cmd + " with an unknown target: \"" + params[0] + "\", command dropped"); return false; } params[0] = server->GetID(); } } else if ((cmd == "GLINE") || (cmd == "KLINE") || (cmd == "ELINE") || (cmd == "ZLINE") || (cmd == "QLINE")) { // Fix undocumented protocol usage: translate GLINE, ZLINE, etc. into ADDLINE or DELLINE if ((params.size() != 1) && (params.size() != 3)) return false; parameterlist p; p.push_back(cmd.substr(0, 1)); p.push_back(params[0]); if (params.size() == 3) { cmd = "ADDLINE"; p.push_back(who->nick); p.push_back(ConvToStr(ServerInstance->Time())); p.push_back(ConvToStr(InspIRCd::Duration(params[1]))); p.push_back(params[2]); } else cmd = "DELLINE"; params.swap(p); } else if (cmd == "SVSMODE") { cmd = "MODE"; } else if (cmd == "OPERQUIT") { // Translate OPERQUIT into METADATA if (params.empty()) return false; cmd = "METADATA"; params.insert(params.begin(), who->uuid); params.insert(params.begin()+1, "operquit"); who = MyRoot->ServerUser; } else if ((cmd == "TOPIC") && (params.size() >= 2)) { // :20DAAAAAC TOPIC #chan :new topic cmd = "FTOPIC"; if (!InsertCurrentChannelTS(params)) return false; params.insert(params.begin()+2, ConvToStr(ServerInstance->Time())); } else if (cmd == "MODENOTICE") { // MODENOTICE is always supported by 2.0 but it's optional in 2.2. params.insert(params.begin(), "*"); params.insert(params.begin()+1, cmd); cmd = "ENCAP"; } else if (cmd == "RULES") { return false; } else if (cmd == "INVITE") { // :20D INVITE 22DAAABBB #chan // :20D INVITE 22DAAABBB #chan 123456789 // Insert channel timestamp after the channel name; the 3rd parameter, if there, is the invite expiration time return InsertCurrentChannelTS(params, 1, 2); } else if (cmd == "VERSION") { // :20D VERSION :InspIRCd-2.0 // change to // :20D SINFO version :InspIRCd-2.0 cmd = "SINFO"; params.insert(params.begin(), "version"); } else if (cmd == "JOIN") { // 2.0 allows and forwards legacy JOINs but we don't, so translate them to FJOINs before processing if ((params.size() != 1) || (IS_SERVER(who))) return false; // Huh? cmd = "FJOIN"; Channel* chan = ServerInstance->FindChan(params[0]); params.push_back(ConvToStr(chan ? chan->age : ServerInstance->Time())); params.push_back("+"); params.push_back(","); params.back().append(who->uuid); who = TreeServer::Get(who)->ServerUser; } else if ((cmd == "FMODE") && (params.size() >= 2)) { // Translate user mode changes with timestamp to MODE if (params[0][0] != '#') { User* user = ServerInstance->FindUUID(params[0]); if (!user) return false; // Emulate the old nonsensical behavior if (user->age < ServerCommand::ExtractTS(params[1])) return false; cmd = "MODE"; params.erase(params.begin()+1); } } else if ((cmd == "SERVER") && (params.size() > 4)) { // This does not affect the initial SERVER line as it is sent before the link state is CONNECTED // :20D SERVER <name> * 0 <sid> <desc> // change to // :20D SERVER <name> <sid> <desc> params[1].swap(params[3]); params.erase(params.begin()+2, params.begin()+4); // If the source of this SERVER message is not bursting, then new servers it introduces are bursting TreeServer* server = TreeServer::Get(who); if (!server->IsBursting()) params.insert(params.begin()+2, "burst=" + ConvToStr(ServerInstance->Time()*1000)); } else if (cmd == "BURST") { // A server is introducing another one, drop unnecessary BURST return false; } return true; // Passthru }