1 /*
2  * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZNC_IRCSOCK_H
18 #define ZNC_IRCSOCK_H
19 
20 #include <znc/zncconfig.h>
21 #include <znc/Socket.h>
22 #include <znc/Nick.h>
23 #include <znc/Message.h>
24 
25 #include <deque>
26 
27 // Forward Declarations
28 class CChan;
29 class CUser;
30 class CIRCNetwork;
31 class CClient;
32 // !Forward Declarations
33 
34 // TODO: This class needs new name
35 class CIRCSock : public CIRCSocket {
36   public:
37     CIRCSock(CIRCNetwork* pNetwork);
38     virtual ~CIRCSock();
39 
40     CIRCSock(const CIRCSock&) = delete;
41     CIRCSock& operator=(const CIRCSock&) = delete;
42 
43     typedef enum {
44         // These values must line up with their position in the CHANMODE
45         // argument to raw 005
46         ListArg = 0,
47         HasArg = 1,
48         ArgWhenSet = 2,
49         NoArg = 3
50     } EChanModeArgs;
51 
52     void ReadLine(const CString& sData) override;
53     void Connected() override;
54     void Disconnected() override;
55     void ConnectionRefused() override;
56     void SockError(int iErrno, const CString& sDescription) override;
57     void Timeout() override;
58     void ReachedMaxBuffer() override;
59 #ifdef HAVE_LIBSSL
60     void SSLCertError(X509* pCert) override;
61 #endif
62     /** Sends a raw data line to the server.
63      *  @param sLine The line to be sent.
64      *
65      *  The line is first passed \e unmodified to the \ref
66      *  CModule::OnSendToIRC() module hook. If no module halts the process,
67      *  the line is then sent to the server.
68      *
69      *  Prefer \l PutIRC() instead.
70      */
71     void PutIRCRaw(const CString& sLine);
72     /** Sends a message to the server.
73      *  See \l PutIRC(const CMessage&) for details.
74      */
75     void PutIRC(const CString& sLine);
76     /** Sends a message to the server.
77      *  @param  Message The message to be sent.
78      *  @note   Only known and compatible messages and tags are sent.
79      *
80      *  This method can delay the delivery of the message to honor protection
81      *  from flood.
82      *
83      *  This method ensures that only tags, that were negotiated with CAP REQ
84      *  and CAP ACK, are sent. Not all IRC server are capable of handling all
85      *  messages and tags. Thus, in order to stay compatible with a variety of
86      *  IRC servers, ZNC has to filter out messages and tags that the server
87      *  has not explicitly acknowleged.
88      *
89      *  Additional tags can be added via \l CIRCSock::SetTagSupport().
90      *
91      *  @warning Bypassing the filter may cause troubles to some older IRC
92      *  servers.
93      *
94      *  It is possible to bypass the filter by converting a message to a string
95      *  using \l CMessage::ToString(), and passing the resulting raw line to the
96      *  \l CIRCSock::PutIRCRaw(const CString& sLine):
97      *  \code
98      *  pServer->PutIRCRaw(Message.ToString());
99      *  \endcode
100      */
101     void PutIRC(const CMessage& Message);
102     void PutIRCQuick(const CString& sLine);  //!< Should be used for PONG only
103     void ResetChans();
104     void Quit(const CString& sQuitMsg = "");
105 
106     /** You can call this from CModule::OnServerCapResult to suspend
107      *  sending other CAP requests and CAP END for a while. Each
108      *  call to PauseCap should be balanced with a call to ResumeCap.
109      */
110     void PauseCap();
111     /** If you used PauseCap, call this when CAP negotiation and logging in
112      *  should be resumed again.
113      */
114     void ResumeCap();
115 
IsTagEnabled(const CString & sTag)116     bool IsTagEnabled(const CString& sTag) const {
117         return 1 == m_ssSupportedTags.count(sTag);
118     }
119     /** Registers a tag as being supported or unsupported by the server.
120      *  This doesn't affect tags which the server sends.
121      *  @param sTag The tag to register.
122      *  @param bState Whether the client supports the tag.
123      */
124     void SetTagSupport(const CString& sTag, bool bState);
125 
126     // Setters
SetPass(const CString & s)127     void SetPass(const CString& s) { m_sPass = s; }
128     // !Setters
129 
130     // Getters
GetMaxNickLen()131     unsigned int GetMaxNickLen() const { return m_uMaxNickLen; }
132     EChanModeArgs GetModeType(char cMode) const;
133     char GetPermFromMode(char cMode) const;
GetChanModes()134     const std::map<char, EChanModeArgs>& GetChanModes() const {
135         return m_mceChanModes;
136     }
IsPermChar(const char c)137     bool IsPermChar(const char c) const {
138         return (c != '\0' && GetPerms().find(c) != CString::npos);
139     }
IsPermMode(const char c)140     bool IsPermMode(const char c) const {
141         return (c != '\0' && GetPermModes().find(c) != CString::npos);
142     }
GetPerms()143     const CString& GetPerms() const { return m_sPerms; }
GetPermModes()144     const CString& GetPermModes() const { return m_sPermModes; }
GetNickMask()145     CString GetNickMask() const { return m_Nick.GetNickMask(); }
GetNick()146     const CString& GetNick() const { return m_Nick.GetNick(); }
GetPass()147     const CString& GetPass() const { return m_sPass; }
GetNetwork()148     CIRCNetwork* GetNetwork() const { return m_pNetwork; }
HasNamesx()149     bool HasNamesx() const { return m_bNamesx; }
HasUHNames()150     bool HasUHNames() const { return m_bUHNames; }
HasAwayNotify()151     bool HasAwayNotify() const { return m_bAwayNotify; }
HasAccountNotify()152     bool HasAccountNotify() const { return m_bAccountNotify; }
HasExtendedJoin()153     bool HasExtendedJoin() const { return m_bExtendedJoin; }
HasServerTime()154     bool HasServerTime() const { return m_bServerTime; }
GetUserModes()155     const std::set<char>& GetUserModes() const {
156         return m_scUserModes;
157     }
158     // This is true if we are past raw 001
IsAuthed()159     bool IsAuthed() const { return m_bAuthed; }
GetAcceptedCaps()160     const SCString& GetAcceptedCaps() const { return m_ssAcceptedCaps; }
IsCapAccepted(const CString & sCap)161     bool IsCapAccepted(const CString& sCap) {
162         return 1 == m_ssAcceptedCaps.count(sCap);
163     }
GetISupport()164     const MCString& GetISupport() const { return m_mISupport; }
165     CString GetISupport(const CString& sKey,
166                         const CString& sDefault = "") const;
167     // !Getters
168 
169     // TODO move this function to CIRCNetwork and make it non-static?
170     static bool IsFloodProtected(double fRate);
171 
172   private:
173     // Message Handlers
174     bool OnAccountMessage(CMessage& Message);
175     bool OnActionMessage(CActionMessage& Message);
176     bool OnAwayMessage(CMessage& Message);
177     bool OnCapabilityMessage(CMessage& Message);
178     bool OnCTCPMessage(CCTCPMessage& Message);
179     bool OnErrorMessage(CMessage& Message);
180     bool OnInviteMessage(CMessage& Message);
181     bool OnJoinMessage(CJoinMessage& Message);
182     bool OnKickMessage(CKickMessage& Message);
183     bool OnModeMessage(CModeMessage& Message);
184     bool OnNickMessage(CNickMessage& Message);
185     bool OnNoticeMessage(CNoticeMessage& Message);
186     bool OnNumericMessage(CNumericMessage& Message);
187     bool OnPartMessage(CPartMessage& Message);
188     bool OnPingMessage(CMessage& Message);
189     bool OnPongMessage(CMessage& Message);
190     bool OnQuitMessage(CQuitMessage& Message);
191     bool OnTextMessage(CTextMessage& Message);
192     bool OnTopicMessage(CTopicMessage& Message);
193     bool OnWallopsMessage(CMessage& Message);
194     bool OnServerCapAvailable(const CString& sCap);
195     // !Message Handlers
196 
197     void SetNick(const CString& sNick);
198     void ParseISupport(const CMessage& Message);
199     // This is called when we connect and the nick we want is already taken
200     void SendAltNick(const CString& sBadNick);
201     void SendNextCap();
202     void TrySend();
203 
204   protected:
205     bool m_bAuthed;
206     bool m_bNamesx;
207     bool m_bUHNames;
208     bool m_bAwayNotify;
209     bool m_bAccountNotify;
210     bool m_bExtendedJoin;
211     bool m_bServerTime;
212     CString m_sPerms;
213     CString m_sPermModes;
214     std::set<char> m_scUserModes;
215     std::map<char, EChanModeArgs> m_mceChanModes;
216     CIRCNetwork* m_pNetwork;
217     CNick m_Nick;
218     CString m_sPass;
219     std::map<CString, CChan*> m_msChans;
220     unsigned int m_uMaxNickLen;
221     unsigned int m_uCapPaused;
222     SCString m_ssAcceptedCaps;
223     SCString m_ssPendingCaps;
224     time_t m_lastCTCP;
225     unsigned int m_uNumCTCP;
226     static const time_t m_uCTCPFloodTime;
227     static const unsigned int m_uCTCPFloodCount;
228     MCString m_mISupport;
229     std::deque<CMessage> m_vSendQueue;
230     short int m_iSendsAllowed;
231     unsigned short int m_uFloodBurst;
232     double m_fFloodRate;
233     bool m_bFloodProtection;
234     SCString m_ssSupportedTags;
235     VCString m_vsSSLError;
236 
237     friend class CIRCFloodTimer;
238 };
239 
240 #endif  // !ZNC_IRCSOCK_H
241