From 99ea9c6ff78b44d8c23d9e599d969528e9badca6 Mon Sep 17 00:00:00 2001 From: psychon Date: Sun, 13 Jun 2010 07:36:32 +0000 Subject: [PATCH] Implement CAP between clients and znc Right now, znc doesn't support any capabilities, but the general protocol works. This also has the plus point that it stops direct CAP commands between the IRCd and clients. That's a good thing because different clients might not support the same CAPs and thus znc would have to translate between them. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2022 726aef4b-f618-498e-8847-2d620e286838 --- Client.cpp | 33 +++++++++++++++++++++++++++++++-- Client.h | 4 ++++ IRCSock.cpp | 3 +++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Client.cpp b/Client.cpp index 25012dcc..3423f170 100644 --- a/Client.cpp +++ b/Client.cpp @@ -126,10 +126,16 @@ void CClient::ReadLine(const CString& sData) { return; // Don't forward this msg. ZNC has already registered us. } + } else if (sCommand.Equals("CAP")) { + HandleCap(sLine); + + // Don't let the client talk to the server directly about CAP, + // we don't want anything enabled that znc does not support. + return; } if (!m_pUser) { - // Only NICK, USER and PASS are allowed before login + // Only CAP, NICK, USER and PASS are allowed before login return; } @@ -588,7 +594,7 @@ bool CClient::SendMotd() { } void CClient::AuthUser() { - if (!m_bGotNick || !m_bGotUser) + if (!m_bGotNick || !m_bGotUser || m_bInCap || IsAttached()) return; m_spAuth = new CClientAuth(this, m_sUser, m_sPass); @@ -771,3 +777,26 @@ CString CClient::GetNickMask() const { return GetNick() + "!" + m_pUser->GetIdent() + "@" + sHost; } + +void CClient::RespondCap(const CString& sResponse) +{ + PutClient(":irc.znc.in CAP " + GetNick() + " " + sResponse); +} + +void CClient::HandleCap(const CString& sLine) +{ + CString sSubCmd = sLine.Token(1); + + if (sSubCmd.Equals("LS")) { + RespondCap("LS :"); + m_bInCap = true; + } else if (sSubCmd.Equals("END")) { + m_bInCap = false; + AuthUser(); + } else if (sSubCmd.Equals("REQ")) { + // No capabilities supported for now + RespondCap("NAK :" + sLine.Token(2, true).TrimPrefix_n(":")); + } else if (sSubCmd.Equals("LIST")) { + RespondCap("LIST :"); + } +} diff --git a/Client.h b/Client.h index d00a84d5..aafe6ce4 100644 --- a/Client.h +++ b/Client.h @@ -78,6 +78,7 @@ public: m_bGotPass = false; m_bGotNick = false; m_bGotUser = false; + m_bInCap = false; m_bNamesx = false; m_bUHNames = false; EnableReadLine(); @@ -127,11 +128,14 @@ public: const CIRCSock* GetIRCSock() const; CIRCSock* GetIRCSock(); private: + void HandleCap(const CString& sLine); + void RespondCap(const CString& sResponse); protected: bool m_bGotPass; bool m_bGotNick; bool m_bGotUser; + bool m_bInCap; bool m_bNamesx; bool m_bUHNames; CUser* m_pUser; diff --git a/IRCSock.cpp b/IRCSock.cpp index e9fd034f..9ae123ba 100644 --- a/IRCSock.cpp +++ b/IRCSock.cpp @@ -671,6 +671,9 @@ void CIRCSock::ReadLine(const CString& sData) { } } } + + // Don't forward any CAP stuff to the client + return; } }