X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree%2Fcompat.cpp;h=63fc9cf6ce97e4f347fbc45ea1498467fc359f73;hb=b9e11915a976daaf790ebc763aff56e19fd49e0f;hp=b23cf5c0233be66d2e03da0ebd804a581bfcdcdc;hpb=62e2d693436a1f0bf96754a61cbc662c198e92bd;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp index b23cf5c02..63fc9cf6c 100644 --- a/src/modules/m_spanningtree/compat.cpp +++ b/src/modules/m_spanningtree/compat.cpp @@ -1,81 +1,580 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ +/* + * InspIRCd -- Internet Relay Chat Daemon * - * InspIRCd: (C) 2002-2009 InspIRCd Development Team - * See: http://wiki.inspircd.org/Credits + * Copyright (C) 2009-2010 Daniel De Graaf * - * This program is free but copyrighted software; see - * the file COPYING for details. + * 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. * - * --------------------------------------------------- + * 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 . */ + #include "inspircd.h" #include "main.h" #include "treesocket.h" +#include "treeserver.h" -static const char* const forge_common_1201[] = { - "m_chghost.so", - "m_chgname.so", - "m_remove.so", - "m_sajoin.so", - "m_sakick.so", - "m_sanick.so", - "m_sapart.so", - "m_saquit.so", - "m_setident.so", -}; - -void TreeSocket::CompatAddModules(std::vector& modlist) +static std::string newline("\n"); + +void TreeSocket::WriteLineNoCompat(const std::string& line) { - if (proto_version < 1202) - { - // you MUST have chgident loaded in order to be able to translate FIDENT - modlist.push_back("m_chgident.so"); - for(int i=0; i * sizeof(char*) < sizeof(forge_common_1201); i++) - { - if (ServerInstance->Modules->Find(forge_common_1201[i])) - modlist.push_back(forge_common_1201[i]); - } - } + ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] O %s", this->GetFd(), line.c_str()); + this->WriteData(line); + this->WriteData(newline); } -void TreeSocket::WriteLine(std::string line) +void TreeSocket::WriteLine(const std::string& original_line) { if (LinkState == CONNECTED) { - if (line[0] != ':') + if (original_line.c_str()[0] != ':') { - ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Sending line without server prefix!"); - line = ":" + ServerInstance->Config->GetSID() + " " + line; + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Sending line without server prefix!"); + WriteLine(":" + ServerInstance->Config->GetSID() + " " + original_line); + return; } if (proto_version != ProtocolVersion) { - std::string::size_type a = line.find(' ') + 1; - std::string::size_type b = line.find(' ', a); - std::string command = line.substr(a, b-a); + std::string line = original_line; + std::string::size_type a = line.find(' '); + std::string::size_type b = line.find(' ', a + 1); + std::string command(line, a + 1, b-a-1); // now try to find a translation entry // TODO a more efficient lookup method will be needed later - if (proto_version < 1202 && command == "FIDENT") + if (proto_version < 1205) { - ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Rewriting FIDENT for 1201-protocol server"); - line = ":" + ServerInstance->Config->GetSID() + " CHGIDENT " + line.substr(1,a-2) + line.substr(b); + if (command == "IJOIN") + { + // Convert + // : IJOIN [ []] + // to + // : FJOIN + [], + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = line.find(' ', c + 1); + // Erase membership id first + line.erase(c, d-c); + if (d == std::string::npos) + { + // No TS or modes in the command + // :22DAAAAAB IJOIN #chan + const std::string channame(line, b+1, c-b-1); + Channel* chan = ServerInstance->FindChan(channame); + if (!chan) + return; + + line.push_back(' '); + line.append(ConvToStr(chan->age)); + line.append(" + ,"); + } + else + { + d = line.find(' ', c + 1); + if (d == std::string::npos) + { + // TS present, no modes + // :22DAAAAAC IJOIN #chan 12345 + line.append(" + ,"); + } + else + { + // Both TS and modes are present + // :22DAAAAAC IJOIN #chan 12345 ov + std::string::size_type e = line.find(' ', d + 1); + if (e != std::string::npos) + line.erase(e); + + line.insert(d, " +"); + line.push_back(','); + } + } + + // Move the uuid to the end and replace the I with an F + line.append(line.substr(1, 9)); + line.erase(4, 6); + line[5] = 'F'; + } + else if (command == "RESYNC") + return; + else if (command == "METADATA") + { + // Drop TS for channel METADATA, translate METADATA operquit into an OPERQUIT command + // :sid METADATA #target TS extname ... + // A B C D + if (b == std::string::npos) + return; + + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = line.find(' ', c + 1); + if (d == std::string::npos) + return; + + if (line[b + 1] == '#') + { + // We're sending channel metadata + line.erase(c, d-c); + } + else if (!line.compare(c, d-c, " operquit", 9)) + { + // ":22D METADATA 22DAAAAAX operquit :message" -> ":22DAAAAAX OPERQUIT :message" + line = ":" + line.substr(b+1, c-b) + "OPERQUIT" + line.substr(d); + } + } + else if (command == "FTOPIC") + { + // Drop channel TS for FTOPIC + // :sid FTOPIC #target TS TopicTS setter :newtopic + // A B C D E F + // :uid FTOPIC #target TS TopicTS :newtopic + // A B C D E + if (b == std::string::npos) + return; + + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = line.find(' ', c + 1); + if (d == std::string::npos) + return; + + std::string::size_type e = line.find(' ', d + 1); + if (line[e+1] == ':') + { + line.erase(c, e-c); + line.erase(a+1, 1); + } + else + line.erase(c, d-c); + } + else if ((command == "PING") || (command == "PONG")) + { + // :22D PING 20D + if (line.length() < 13) + return; + + // Insert the source SID (and a space) between the command and the first parameter + line.insert(10, line.substr(1, 4)); + } + else if (command == "OPERTYPE") + { + std::string::size_type colon = line.find(':', b); + if (colon != std::string::npos) + { + for (std::string::iterator i = line.begin()+colon; i != line.end(); ++i) + { + if (*i == ' ') + *i = '_'; + } + line.erase(colon, 1); + } + } + else if (command == "INVITE") + { + // :22D INVITE 22DAAAAAN #chan TS ExpirationTime + // A B C D E + if (b == std::string::npos) + return; + + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = line.find(' ', c + 1); + if (d == std::string::npos) + return; + + std::string::size_type e = line.find(' ', d + 1); + // If there is no expiration time then everything will be erased from 'd' + line.erase(d, e-d); + } + else if (command == "FJOIN") + { + // Strip membership ids + // :22D FJOIN #chan 1234 +f 4:3 :o,22DAAAAAB:15 o,22DAAAAAA:15 + // :22D FJOIN #chan 1234 +f 4:3 o,22DAAAAAB:15 + // :22D FJOIN #chan 1234 +Pf 4:3 : + + // If the last parameter is prefixed by a colon then it's a userlist which may have 0 or more users; + // if it isn't, then it is a single member + std::string::size_type spcolon = line.find(" :"); + if (spcolon != std::string::npos) + { + spcolon++; + // Loop while there is a ':' in the userlist, this is never true if the channel is empty + std::string::size_type pos = std::string::npos; + while ((pos = line.rfind(':', pos-1)) > spcolon) + { + // Find the next space after the ':' + std::string::size_type sp = line.find(' ', pos); + // Erase characters between the ':' and the next space after it, including the ':' but not the space; + // if there is no next space, everything will be erased between pos and the end of the line + line.erase(pos, sp-pos); + } + } + else + { + // Last parameter is a single member + std::string::size_type sp = line.rfind(' '); + std::string::size_type colon = line.find(':', sp); + line.erase(colon); + } + } + else if (command == "KICK") + { + // Strip membership id if the KICK has one + if (b == std::string::npos) + return; + + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = line.find(' ', c + 1); + if ((d < line.size()-1) && (original_line[d+1] != ':')) + { + // There is a third parameter which doesn't begin with a colon, erase it + std::string::size_type e = line.find(' ', d + 1); + line.erase(d, e-d); + } + } + else if (command == "SINFO") + { + // :22D SINFO version :InspIRCd-2.2 + // A B C + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + // Only translating SINFO version, discard everything else + if (line.compare(b, 9, " version ", 9)) + return; + + line = line.substr(0, 5) + "VERSION" + line.substr(c); + } + else if (command == "SERVER") + { + // :001 SERVER inspircd.test 002 [ ...] :gecos + // A B C + std::string::size_type c = line.find(' ', b + 1); + if (c == std::string::npos) + return; + + std::string::size_type d = c + 4; + std::string::size_type spcolon = line.find(" :", d); + if (spcolon == std::string::npos) + return; + + line.erase(d, spcolon-d); + line.insert(c, " * 0"); + + if (burstsent) + { + WriteLineNoCompat(line); + + // Synthesize a : BURST