Example #1
0
bool CClient::OnCTCPMessage(CCTCPMessage& Message)
{
	CString sTargets = Message.GetTarget();

	VCString vTargets;
	sTargets.Split(",", vTargets, false);

	if (Message.IsReply()) {
		CString sCTCP = Message.GetText();
		if (sCTCP.Token(0) == "VERSION") {
			Message.SetText(sCTCP + " via " + CZNC::GetTag(false));
		}
	}

	for (CString& sTarget : vTargets) {
		Message.SetTarget(sTarget);

		bool bContinue = false;
		if (Message.IsReply()) {
			NETWORKMODULECALL(OnUserCTCPReplyMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
		} else {
			NETWORKMODULECALL(OnUserCTCPMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
		}
		if (bContinue) continue;

		if (!GetIRCSock()) {
			// Some lagmeters do a NOTICE to their own nick, ignore those.
			if (!sTarget.Equals(m_sNick))
				PutStatus("Your CTCP to [" + Message.GetTarget() + "] got lost, "
						"you are not connected to IRC!");
			continue;
		}

		if (m_pNetwork) {
			AddBuffer(Message);
			EchoMessage(Message);
			m_pNetwork->PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
		}
	}

	return true;
}
Example #2
0
TEST(MessageTest, PrivCTCP) {
	CCTCPMessage msg;
	msg.Parse(":sender PRIVMSG receiver :\001text\001");
	EXPECT_EQ("sender", msg.GetNick().GetNick());
	EXPECT_EQ("PRIVMSG", msg.GetCommand());
	EXPECT_EQ("receiver", msg.GetTarget());
	EXPECT_EQ("text", msg.GetText());
	EXPECT_FALSE(msg.IsReply());
	EXPECT_EQ(CMessage::Type::CTCP, msg.GetType());

	msg.SetText("foo bar");
	EXPECT_EQ("foo bar", msg.GetText());
	EXPECT_EQ(":sender PRIVMSG receiver :\001foo bar\001", msg.ToString());
}
Example #3
0
TEST(MessageTest, CTCPReply) {
	CCTCPMessage msg;
	msg.Parse(":sender NOTICE nick :\001FOO bar\001");
	EXPECT_EQ("sender", msg.GetNick().GetNick());
	EXPECT_EQ("NOTICE", msg.GetCommand());
	EXPECT_EQ("nick", msg.GetTarget());
	EXPECT_EQ("FOO bar", msg.GetText());
	EXPECT_TRUE(msg.IsReply());
	EXPECT_EQ(CMessage::Type::CTCP, msg.GetType());

	msg.SetText("BAR foo");
	EXPECT_EQ("BAR foo", msg.GetText());
	EXPECT_EQ(":sender NOTICE nick :\001BAR foo\001", msg.ToString());
}
Example #4
0
bool CClient::OnCTCPMessage(CCTCPMessage& Message) {
    CString sTargets = Message.GetTarget();

    VCString vTargets;
    sTargets.Split(",", vTargets, false);

    if (Message.IsReply()) {
        CString sCTCP = Message.GetText();
        if (sCTCP.Token(0) == "VERSION") {
            // There are 2 different scenarios:
            //
            // a) CTCP reply for VERSION is not set.
            // 1. ZNC receives CTCP VERSION from someone
            // 2. ZNC forwards CTCP VERSION to client
            // 3. Client replies with something
            // 4. ZNC adds itself to the reply
            // 5. ZNC sends the modified reply to whoever asked
            //
            // b) CTCP reply for VERSION is set.
            // 1. ZNC receives CTCP VERSION from someone
            // 2. ZNC replies with the configured reply (or just drops it if
            //    empty), without forwarding anything to client
            // 3. Client does not see any CTCP request, and does not reply
            //
            // So, if user doesn't want "via ZNC" in CTCP VERSION reply, they
            // can set custom reply.
            //
            // See more bikeshedding at github issues #820 and #1012
            Message.SetText(sCTCP + " via " + CZNC::GetTag(false));
        }
    }

    for (CString& sTarget : vTargets) {
        Message.SetTarget(sTarget);

        bool bContinue = false;
        if (Message.IsReply()) {
            NETWORKMODULECALL(OnUserCTCPReplyMessage(Message), m_pUser,
                              m_pNetwork, this, &bContinue);
        } else {
            NETWORKMODULECALL(OnUserCTCPMessage(Message), m_pUser, m_pNetwork,
                              this, &bContinue);
        }
        if (bContinue) continue;

        if (!GetIRCSock()) {
            // Some lagmeters do a NOTICE to their own nick, ignore those.
            if (!sTarget.Equals(m_sNick))
                PutStatus("Your CTCP to [" + Message.GetTarget() +
                          "] got lost, "
                          "you are not connected to IRC!");
            continue;
        }

        if (m_pNetwork) {
            AddBuffer(Message);
            EchoMessage(Message);
            PutIRC(Message.ToString(CMessage::ExcludePrefix |
                                    CMessage::ExcludeTags));
        }
    }

    return true;
}
Example #5
0
bool CIRCSock::OnCTCPMessage(CCTCPMessage& Message) {
    bool bResult = false;
    CChan* pChan = nullptr;
    CString sTarget = Message.GetTarget();
    if (sTarget.Equals(GetNick())) {
        if (Message.IsReply()) {
            IRCSOCKMODULECALL(OnCTCPReplyMessage(Message), &bResult);
            return bResult;
        } else {
            IRCSOCKMODULECALL(OnPrivCTCPMessage(Message), &bResult);
            if (bResult) return true;
        }
    } else {
        pChan = m_pNetwork->FindChan(sTarget);
        if (pChan) {
            Message.SetChan(pChan);
            FixupChanNick(Message.GetNick(), pChan);
            IRCSOCKMODULECALL(OnChanCTCPMessage(Message), &bResult);
            if (bResult) return true;
        }
    }

    const CNick& Nick = Message.GetNick();
    const CString& sMessage = Message.GetText();
    const MCString& mssCTCPReplies = m_pNetwork->GetUser()->GetCTCPReplies();
    CString sQuery = sMessage.Token(0).AsUpper();
    MCString::const_iterator it = mssCTCPReplies.find(sQuery);
    bool bHaveReply = false;
    CString sReply;

    if (it != mssCTCPReplies.end()) {
        sReply = m_pNetwork->ExpandString(it->second);
        bHaveReply = true;

        if (sReply.empty()) {
            return true;
        }
    }

    if (!bHaveReply && !m_pNetwork->IsUserAttached()) {
        if (sQuery == "VERSION") {
            sReply = CZNC::GetTag(false);
        } else if (sQuery == "PING") {
            sReply = sMessage.Token(1, true);
        }
    }

    if (!sReply.empty()) {
        time_t now = time(nullptr);
        // If the last CTCP is older than m_uCTCPFloodTime, reset the counter
        if (m_lastCTCP + m_uCTCPFloodTime < now) m_uNumCTCP = 0;
        m_lastCTCP = now;
        // If we are over the limit, don't reply to this CTCP
        if (m_uNumCTCP >= m_uCTCPFloodCount) {
            DEBUG("CTCP flood detected - not replying to query");
            return true;
        }
        m_uNumCTCP++;

        PutIRC("NOTICE " + Nick.GetNick() + " :\001" + sQuery + " " + sReply +
               "\001");
        return true;
    }

    return (pChan && pChan->IsDetached());
}