X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree%2Fcompat.cpp;h=fc9700740d42492a76effffe591fcbda5bd213cc;hb=f6b33a8facd6ca200292786c1061782c41cdd278;hp=41cabbc9397b0886b6801e8f03dfc4c37f4d2a4c;hpb=abc57eddfb56462ac3e433601d010abf1942e611;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp index 41cabbc93..fc9700740 100644 --- a/src/modules/m_spanningtree/compat.cpp +++ b/src/modules/m_spanningtree/compat.cpp @@ -24,36 +24,50 @@ static std::string newline("\n"); -void TreeSocket::WriteLine(std::string line) +void TreeSocket::WriteLineNoCompat(const std::string& line) +{ + ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] O %s", this->GetFd(), line.c_str()); + this->WriteData(line); + this->WriteData(newline); +} + +void TreeSocket::WriteLine(const std::string& original_line) { if (LinkState == CONNECTED) { - if (line[0] != ':') - { - ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Sending line without server prefix!"); - line = ":" + ServerInstance->Config->GetSID() + " " + line; - } - if (proto_version != ProtocolVersion) + if (proto_version != PROTO_NEWEST) { + std::string line = original_line; std::string::size_type a = line.find(' '); + if (line[0] == '@') + { + // The line contains tags which the 1202 protocol can't handle. + line.erase(0, a + 1); + a = line.find(' '); + } std::string::size_type b = line.find(' ', a + 1); - std::string command = line.substr(a + 1, b-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 < 1205) + if (proto_version < PROTO_INSPIRCD_30) { if (command == "IJOIN") { // Convert - // : IJOIN [ []] + // : 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.substr(b+1, c-b-1); + const std::string channame(line, b+1, c-b-1); Channel* chan = ServerInstance->FindChan(channame); if (!chan) return; @@ -64,7 +78,7 @@ void TreeSocket::WriteLine(std::string line) } else { - std::string::size_type d = line.find(' ', c + 1); + d = line.find(' ', c + 1); if (d == std::string::npos) { // TS present, no modes @@ -93,7 +107,7 @@ void TreeSocket::WriteLine(std::string line) return; else if (command == "METADATA") { - // Drop TS for channel 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) @@ -103,21 +117,28 @@ void TreeSocket::WriteLine(std::string line) 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 - std::string::size_type d = line.find(' ', c + 1); - if (d == std::string::npos) - return; - 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 ... - // A B C D + // :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; @@ -129,7 +150,14 @@ void TreeSocket::WriteLine(std::string line) if (d == std::string::npos) return; - line.erase(c, d-c); + 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")) { @@ -153,30 +181,162 @@ void TreeSocket::WriteLine(std::string line) 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-3.0 + // 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 [ ...] :description + // 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