From 8fdf51dfeb4195380fbe8c2e6f0cffffbe145d2a Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 1 Nov 2014 13:05:51 +0100 Subject: [PATCH 1/2] Fix CNick::Parse() If the mask started with ':', the following '!' was included to nick. --- Makefile.in | 2 +- src/Nick.cpp | 2 +- test/NickTest.cpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/NickTest.cpp diff --git a/Makefile.in b/Makefile.in index c26b3d96..ae6235af 100644 --- a/Makefile.in +++ b/Makefile.in @@ -47,7 +47,7 @@ LIB_SRCS := $(addprefix src/,$(LIB_SRCS)) BIN_SRCS := src/main.cpp LIB_OBJS := $(patsubst %cpp,%o,$(LIB_SRCS)) BIN_OBJS := $(patsubst %cpp,%o,$(BIN_SRCS)) -TESTS := StringTest ConfigTest UtilsTest ThreadTest +TESTS := StringTest ConfigTest UtilsTest ThreadTest NickTest TESTS := $(addprefix test/,$(addsuffix .o,$(TESTS))) CLEAN := znc src/*.o test/*.o core core.* .version_extra .depend modules/.depend unittest DISTCLEAN := Makefile config.log config.status znc-buildmod \ diff --git a/src/Nick.cpp b/src/Nick.cpp index 5d225be5..4f735946 100644 --- a/src/Nick.cpp +++ b/src/Nick.cpp @@ -49,7 +49,7 @@ void CNick::Parse(const CString& sNickMask) { return; } - m_sNick = sNickMask.substr((sNickMask[0] == ':'), uPos); + m_sNick = sNickMask.substr((sNickMask[0] == ':'), uPos - (sNickMask[0] == ':')); m_sHost = sNickMask.substr(uPos +1); if ((uPos = m_sHost.find('@')) != CString::npos) { diff --git a/test/NickTest.cpp b/test/NickTest.cpp new file mode 100644 index 00000000..56a352d0 --- /dev/null +++ b/test/NickTest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004-2014 ZNC, see the NOTICE file for details. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +TEST(NickTest, Parse) { + CNick Nick1("nick!~ident@host"); + EXPECT_EQ("nick", Nick1.GetNick()); + EXPECT_EQ("~ident", Nick1.GetIdent()); + EXPECT_EQ("host", Nick1.GetHost()); + EXPECT_EQ("nick!~ident@host", Nick1.GetNickMask()); + EXPECT_EQ("nick!~ident@host", Nick1.GetHostMask()); + EXPECT_TRUE(Nick1.NickEquals("nick")); + + CNick Nick2(":nick!~ident@host"); + EXPECT_EQ("nick", Nick2.GetNick()); + EXPECT_EQ("~ident", Nick2.GetIdent()); + EXPECT_EQ("host", Nick2.GetHost()); + EXPECT_EQ("nick!~ident@host", Nick2.GetNickMask()); + EXPECT_EQ("nick!~ident@host", Nick2.GetHostMask()); + EXPECT_TRUE(Nick2.NickEquals("nick")); +} From 382ce76dedb9e7544c38055e1f3752e8ecc46537 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 11 Aug 2014 17:05:20 +0200 Subject: [PATCH 2/2] Add self-message support https://github.com/ircv3/ircv3-specifications/blob/master/extensions/self-message-3.2.md --- include/znc/Client.h | 3 +++ src/Client.cpp | 55 ++++++++++++++++++++------------------------ src/Query.cpp | 11 ++++++++- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/include/znc/Client.h b/include/znc/Client.h index f83ad356..938df057 100644 --- a/include/znc/Client.h +++ b/include/znc/Client.h @@ -95,6 +95,7 @@ public: m_bAway = false; m_bServerTime = false; m_bBatch = false; + m_bSelfMessage = false; EnableReadLine(); // RFC says a line can have 512 chars max, but we are // a little more gentle ;) @@ -116,6 +117,7 @@ public: bool IsAway() const { return m_bAway; } bool HasServerTime() const { return m_bServerTime; } bool HasBatch() const { return m_bBatch; } + bool HasSelfMessage() const { return m_bSelfMessage; } void UserCommand(CString& sLine); void UserPortCommand(CString& sLine); @@ -166,6 +168,7 @@ protected: bool m_bAway; bool m_bServerTime; bool m_bBatch; + bool m_bSelfMessage; CUser* m_pUser; CIRCNetwork* m_pNetwork; CString m_sNick; diff --git a/src/Client.cpp b/src/Client.cpp index bda6f7a1..05cc2e21 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -271,15 +271,11 @@ void CClient::ReadLine(const CString& sData) { } // Relay to the rest of the clients that may be connected to this user - if (m_pNetwork->IsChan(sTarget)) { - const vector& vClients = GetClients(); + const vector& vClients = GetClients(); - for (unsigned int a = 0; a < vClients.size(); a++) { - CClient* pClient = vClients[a]; - - if (pClient != this) { - pClient->PutClient(":" + GetNickMask() + " NOTICE " + sTarget + " :" + sMsg); - } + for (CClient* pClient : vClients) { + if (pClient != this && (m_pNetwork->IsChan(sTarget) || pClient->HasSelfMessage())) { + pClient->PutClient(":" + GetNickMask() + " NOTICE " + sTarget + " :" + sMsg); } } @@ -324,17 +320,6 @@ void CClient::ReadLine(const CString& sData) { if (pChan && (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline())) { pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage); } - - // Relay to the rest of the clients that may be connected to this user - const vector& vClients = GetClients(); - - for (unsigned int a = 0; a < vClients.size(); a++) { - CClient* pClient = vClients[a]; - - if (pClient != this) { - pClient->PutClient(":" + GetNickMask() + " PRIVMSG " + sTarget + " :\001" + sCTCP + "\001"); - } - } } else { if (!m_pUser->AutoClearQueryBuffer() || !m_pNetwork->IsUserOnline()) { CQuery* pQuery = m_pNetwork->AddQuery(sTarget); @@ -343,6 +328,15 @@ void CClient::ReadLine(const CString& sData) { } } } + + // Relay to the rest of the clients that may be connected to this user + const vector& vClients = GetClients(); + + for (CClient* pClient : vClients) { + if (pClient != this && (m_pNetwork->IsChan(sTarget) || pClient->HasSelfMessage())) { + pClient->PutClient(":" + GetNickMask() + " PRIVMSG " + sTarget + " :\001" + sCTCP + "\001"); + } + } } else { NETWORKMODULECALL(OnUserCTCP(sTarget, sCTCP), m_pUser, m_pNetwork, this, &bContinue); if (bContinue) continue; @@ -393,16 +387,11 @@ void CClient::ReadLine(const CString& sData) { PutIRC("PRIVMSG " + sTarget + " :" + sMsg); // Relay to the rest of the clients that may be connected to this user + const vector& vClients = GetClients(); - if (m_pNetwork->IsChan(sTarget)) { - const vector& vClients = GetClients(); - - for (unsigned int a = 0; a < vClients.size(); a++) { - CClient* pClient = vClients[a]; - - if (pClient != this) { - pClient->PutClient(":" + GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg); - } + for (CClient* pClient : vClients) { + if (pClient != this && (m_pNetwork->IsChan(sTarget) || pClient->HasSelfMessage())) { + pClient->PutClient(":" + GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg); } } } @@ -877,7 +866,7 @@ void CClient::HandleCap(const CString& sLine) for (SCString::iterator i = ssOfferCaps.begin(); i != ssOfferCaps.end(); ++i) { sRes += *i + " "; } - RespondCap("LS :" + sRes + "userhost-in-names multi-prefix znc.in/server-time-iso znc.in/batch"); + RespondCap("LS :" + sRes + "userhost-in-names multi-prefix znc.in/server-time-iso znc.in/batch znc.in/self-message"); m_bInCap = true; } else if (sSubCmd.Equals("END")) { m_bInCap = false; @@ -899,7 +888,7 @@ void CClient::HandleCap(const CString& sLine) if (sCap.TrimPrefix("-")) bVal = false; - bool bAccepted = ("multi-prefix" == sCap) || ("userhost-in-names" == sCap) || ("znc.in/server-time-iso" == sCap) || ("znc.in/batch" == sCap); + bool bAccepted = ("multi-prefix" == sCap) || ("userhost-in-names" == sCap) || ("znc.in/server-time-iso" == sCap) || ("znc.in/batch" == sCap) || ("znc.in/self-message" == sCap); GLOBALMODULECALL(IsClientCapSupported(this, sCap, bVal), &bAccepted); if (!bAccepted) { @@ -923,6 +912,8 @@ void CClient::HandleCap(const CString& sLine) m_bServerTime = bVal; } else if ("znc.in/batch" == *it) { m_bBatch = bVal; + } else if ("znc.in/self-message" == *it) { + m_bSelfMessage = bVal; } GLOBALMODULECALL(OnClientCapRequest(this, *it, bVal), NOTHING); @@ -966,6 +957,10 @@ void CClient::HandleCap(const CString& sLine) m_bBatch = false; ssRemoved.insert("znc.in/batch"); } + if (m_bSelfMessage) { + m_bSelfMessage = false; + ssRemoved.insert("znc.in/self-message"); + } CString sList = ""; for (SCString::iterator i = ssRemoved.begin(); i != ssRemoved.end(); ++i) { m_ssAcceptedCaps.erase(*i); diff --git a/src/Query.cpp b/src/Query.cpp index c8ee025e..2432e71f 100644 --- a/src/Query.cpp +++ b/src/Query.cpp @@ -53,7 +53,16 @@ void CQuery::SendBuffer(CClient* pClient, const CBuffer& Buffer) { size_t uSize = Buffer.Size(); for (size_t uIdx = 0; uIdx < uSize; uIdx++) { - CString sLine = Buffer.GetLine(uIdx, *pUseClient, msParams); + const CBufLine& BufLine = Buffer.GetBufLine(uIdx); + + if (!pUseClient->HasSelfMessage()) { + CNick Sender(BufLine.GetFormat().Token(0)); + if (Sender.NickEquals(pUseClient->GetNick())) { + continue; + } + } + + CString sLine = BufLine.GetLine(*pUseClient, msParams); if (bBatch) { MCString msBatchTags = CUtils::GetMessageTags(sLine); msBatchTags["batch"] = sBatchName;