ZNC  trunk
Message.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2021 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_MESSAGE_H
18 #define ZNC_MESSAGE_H
19 
20 // Remove this after Feb 2016 when Debian 7 is EOL
21 #if __cpp_ref_qualifiers >= 200710
22 #define ZNC_LVREFQUAL &
23 #elif defined(__clang__)
24 #define ZNC_LVREFQUAL &
25 #elif __GNUC__ > 4 || \
26  __GNUC__ == 4 && (__GNUC_MINOR__ > 8 || \
27  __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 1)
28 #define ZNC_LVREFQUAL &
29 #else
30 #define ZNC_LVREFQUAL
31 #endif
32 
33 #ifdef SWIG
34 #define ZNC_MSG_DEPRECATED(msg)
35 #else
36 #define ZNC_MSG_DEPRECATED(msg) __attribute__((deprecated(msg)))
37 #endif
38 
39 #include <znc/zncconfig.h>
40 #include <znc/ZNCString.h>
41 #include <znc/Nick.h>
42 #include <sys/time.h>
43 
44 class CChan;
45 class CClient;
46 class CIRCNetwork;
47 
70 class CMessage {
71  public:
72  explicit CMessage(const CString& sMessage = "");
73  CMessage(const CNick& Nick, const CString& sCommand,
74  const VCString& vsParams = VCString(),
75  const MCString& mssTags = MCString::EmptyMap);
76 
77  enum class Type {
78  Unknown,
79  Account,
80  Action,
81  Away,
82  Capability,
83  CTCP,
84  Error,
85  Invite,
86  Join,
87  Kick,
88  Mode,
89  Nick,
90  Notice,
91  Numeric,
92  Part,
93  Ping,
94  Pong,
95  Quit,
96  Text,
97  Topic,
98  Wallops,
99  };
100  Type GetType() const { return m_eType; }
101 
102  bool Equals(const CMessage& Other) const;
103  void Clone(const CMessage& Other);
104 
105  // ZNC <-> IRC
106  CIRCNetwork* GetNetwork() const { return m_pNetwork; }
107  void SetNetwork(CIRCNetwork* pNetwork) { m_pNetwork = pNetwork; }
108 
109  // ZNC <-> CLI
110  CClient* GetClient() const { return m_pClient; }
111  void SetClient(CClient* pClient) { m_pClient = pClient; }
112 
113  CChan* GetChan() const { return m_pChan; }
114  void SetChan(CChan* pChan) { m_pChan = pChan; }
115 
116  CNick& GetNick() { return m_Nick; }
117  const CNick& GetNick() const { return m_Nick; }
118  void SetNick(const CNick& Nick) { m_Nick = Nick; }
119 
120  const CString& GetCommand() const { return m_sCommand; }
121  void SetCommand(const CString& sCommand);
122 
123  const VCString& GetParams() const { return m_vsParams; }
124 
135  VCString GetParamsSplit(unsigned int uIdx, unsigned int uLen = -1) const;
136  void SetParams(const VCString& vsParams);
137 
139  CString GetParams(unsigned int uIdx, unsigned int uLen = -1) const
140  ZNC_MSG_DEPRECATED("Use GetParamsColon() instead") {
141  return GetParamsColon(uIdx, uLen);
142  }
143  CString GetParamsColon(unsigned int uIdx, unsigned int uLen = -1) const;
144 
145  CString GetParam(unsigned int uIdx) const;
146  void SetParam(unsigned int uIdx, const CString& sParam);
147 
148  const timeval& GetTime() const { return m_time; }
149  void SetTime(const timeval& ts) { m_time = ts; }
150 
151  const MCString& GetTags() const { return m_mssTags; }
152  void SetTags(const MCString& mssTags) { m_mssTags = mssTags; }
153 
154  CString GetTag(const CString& sKey) const;
155  void SetTag(const CString& sKey, const CString& sValue);
156 
157  enum FormatFlags {
158  IncludeAll = 0x0,
161  };
162 
163  CString ToString(unsigned int uFlags = IncludeAll) const;
164  void Parse(const CString& sMessage);
165 
166 // Implicit and explicit conversion to a subclass reference.
167 #ifndef SWIG
168  template <typename M>
170  static_assert(std::is_base_of<CMessage, M>{},
171  "Must be subclass of CMessage");
172  static_assert(sizeof(M) == sizeof(CMessage),
173  "No data members allowed in CMessage subclasses.");
174  return static_cast<M&>(*this);
175  }
176 
177  template <typename M>
178  const M& As() const ZNC_LVREFQUAL {
179  static_assert(std::is_base_of<CMessage, M>{},
180  "Must be subclass of CMessage");
181  static_assert(sizeof(M) == sizeof(CMessage),
182  "No data members allowed in CMessage subclasses.");
183  return static_cast<const M&>(*this);
184  }
185 
186  template <typename M, typename = typename std::enable_if<
187  std::is_base_of<CMessage, M>{}>::type>
188  operator M&() ZNC_LVREFQUAL {
189  return As<M>();
190  }
191  template <typename M, typename = typename std::enable_if<
192  std::is_base_of<CMessage, M>{}>::type>
193  operator const M&() const ZNC_LVREFQUAL {
194  return As<M>();
195  }
196 // REGISTER_ZNC_MESSAGE allows SWIG to instantiate correct .As<> calls.
197 #define REGISTER_ZNC_MESSAGE(M)
198 #else
199  // SWIG (as of 3.0.7) doesn't parse ref-qualifiers, and doesn't
200  // differentiate constness.
201  template <typename M>
202  M& As();
203 #endif
204 
205  private:
206  void InitTime();
207  void InitType();
208 
209  CNick m_Nick;
210  CString m_sCommand;
211  VCString m_vsParams;
212  MCString m_mssTags;
213  timeval m_time;
214  CIRCNetwork* m_pNetwork = nullptr;
215  CClient* m_pClient = nullptr;
216  CChan* m_pChan = nullptr;
217  Type m_eType = Type::Unknown;
218  bool m_bColon = false;
219 };
220 
221 // For gtest
222 #ifdef GTEST_FAIL
223 template <typename M, typename = typename std::enable_if<
224  std::is_base_of<CMessage, M>{}>::type>
225 inline ::std::ostream& operator<<(::std::ostream& os, const M& msg) {
226  return os << msg.ToString().Escape_n(CString::EDEBUG);
227 }
228 #endif
229 
230 // The various CMessage subclasses are "mutable views" to the data held by
231 // CMessage.
232 // They provide convenient access to message type speficic attributes, but are
233 // not
234 // allowed to hold extra data of their own.
235 class CTargetMessage : public CMessage {
236  public:
237  CString GetTarget() const { return GetParam(0); }
238  void SetTarget(const CString& sTarget) { SetParam(0, sTarget); }
239 };
241 
243  public:
244  CString GetText() const {
245  return GetParam(1).TrimPrefix_n("\001ACTION ").TrimSuffix_n("\001");
246  }
247  void SetText(const CString& sText) {
248  SetParam(1, "\001ACTION " + sText + "\001");
249  }
250 };
252 
253 class CCTCPMessage : public CTargetMessage {
254  public:
255  bool IsReply() const { return GetCommand().Equals("NOTICE"); }
256  CString GetText() const {
257  return GetParam(1).TrimPrefix_n("\001").TrimSuffix_n("\001");
258  }
259  void SetText(const CString& sText) { SetParam(1, "\001" + sText + "\001"); }
260 };
262 
263 class CJoinMessage : public CTargetMessage {
264  public:
265  CString GetKey() const { return GetParam(1); }
266  void SetKey(const CString& sKey) { SetParam(1, sKey); }
267 };
269 
270 class CModeMessage : public CTargetMessage {
271  public:
273  CString GetModes() const { return GetParamsColon(1).TrimPrefix_n(":"); }
274 
275  CString GetModeList() const { return GetParam(1); };
276 
277  VCString GetModeParams() const { return GetParamsSplit(2); };
278 
279  bool HasModes() const { return !GetModeList().empty(); };
280 };
282 
283 class CNickMessage : public CMessage {
284  public:
285  CString GetOldNick() const { return GetNick().GetNick(); }
286  CString GetNewNick() const { return GetParam(0); }
287  void SetNewNick(const CString& sNick) { SetParam(0, sNick); }
288 };
290 
292  public:
293  CString GetText() const { return GetParam(1); }
294  void SetText(const CString& sText) { SetParam(1, sText); }
295 };
297 
298 class CNumericMessage : public CMessage {
299  public:
300  unsigned int GetCode() const { return GetCommand().ToUInt(); }
301 };
303 
304 class CKickMessage : public CTargetMessage {
305  public:
306  CString GetKickedNick() const { return GetParam(1); }
307  void SetKickedNick(const CString& sNick) { SetParam(1, sNick); }
308  CString GetReason() const { return GetParam(2); }
309  void SetReason(const CString& sReason) { SetParam(2, sReason); }
310  CString GetText() const { return GetReason(); }
311  void SetText(const CString& sText) { SetReason(sText); }
312 };
314 
315 class CPartMessage : public CTargetMessage {
316  public:
317  CString GetReason() const { return GetParam(1); }
318  void SetReason(const CString& sReason) { SetParam(1, sReason); }
319  CString GetText() const { return GetReason(); }
320  void SetText(const CString& sText) { SetReason(sText); }
321 };
323 
324 class CQuitMessage : public CMessage {
325  public:
326  CString GetReason() const { return GetParam(0); }
327  void SetReason(const CString& sReason) { SetParam(0, sReason); }
328  CString GetText() const { return GetReason(); }
329  void SetText(const CString& sText) { SetReason(sText); }
330 };
332 
333 class CTextMessage : public CTargetMessage {
334  public:
335  CString GetText() const { return GetParam(1); }
336  void SetText(const CString& sText) { SetParam(1, sText); }
337 };
339 
341  public:
342  CString GetTopic() const { return GetParam(1); }
343  void SetTopic(const CString& sTopic) { SetParam(1, sTopic); }
344  CString GetText() const { return GetTopic(); }
345  void SetText(const CString& sText) { SetTopic(sText); }
346 };
348 
349 #endif // !ZNC_MESSAGE_H
CMessage::Clone
void Clone(const CMessage &Other)
CMessage::SetNick
void SetNick(const CNick &Nick)
Definition: Message.h:118
CMessage::ExcludeTags
@ ExcludeTags
Definition: Message.h:160
CMessage::Type::Join
@ Join
CMessage::GetParams
CString GetParams(unsigned int uIdx, unsigned int uLen=-1) const ZNC_MSG_DEPRECATED("Use GetParamsColon() instead")
Definition: Message.h:139
CKickMessage::SetKickedNick
void SetKickedNick(const CString &sNick)
Definition: Message.h:307
CNickMessage::SetNewNick
void SetNewNick(const CString &sNick)
Definition: Message.h:287
CMessage::Type::Error
@ Error
CQuitMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:329
Nick.h
CClient
Definition: Client.h:99
ZNCString.h
CMessage::Type::Mode
@ Mode
CTopicMessage
Definition: Message.h:340
CString::TrimSuffix_n
CString TrimSuffix_n(const CString &sSuffix) const
Trim a given suffix.
CMessage::GetChan
CChan * GetChan() const
Definition: Message.h:113
CMessage::GetNick
CNick & GetNick()
Definition: Message.h:116
CActionMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:247
CTopicMessage::GetTopic
CString GetTopic() const
Definition: Message.h:342
CNoticeMessage::GetText
CString GetText() const
Definition: Message.h:293
MCString
A dictionary for strings.
Definition: ZNCString.h:595
CMessage::ToString
CString ToString(unsigned int uFlags=IncludeAll) const
CActionMessage
Definition: Message.h:242
CPartMessage::GetText
CString GetText() const
Definition: Message.h:319
ZNC_MSG_DEPRECATED
#define ZNC_MSG_DEPRECATED(msg)
Definition: Message.h:36
CQuitMessage
Definition: Message.h:324
CMessage::Type::Numeric
@ Numeric
CMessage::SetParam
void SetParam(unsigned int uIdx, const CString &sParam)
CCTCPMessage
Definition: Message.h:253
CMessage::SetParams
void SetParams(const VCString &vsParams)
CJoinMessage::SetKey
void SetKey(const CString &sKey)
Definition: Message.h:266
CMessage::GetNetwork
CIRCNetwork * GetNetwork() const
Definition: Message.h:106
CKickMessage::GetText
CString GetText() const
Definition: Message.h:310
REGISTER_ZNC_MESSAGE
#define REGISTER_ZNC_MESSAGE(M)
Definition: Message.h:197
CMessage::Type::Notice
@ Notice
CMessage::ExcludePrefix
@ ExcludePrefix
Definition: Message.h:159
CMessage::SetTag
void SetTag(const CString &sKey, const CString &sValue)
ZNC_LVREFQUAL
#define ZNC_LVREFQUAL
Definition: Message.h:30
CMessage::Type::Ping
@ Ping
CMessage::As
const M & As() const ZNC_LVREFQUAL
Definition: Message.h:178
CMessage::GetType
Type GetType() const
Definition: Message.h:100
CMessage::GetTags
const MCString & GetTags() const
Definition: Message.h:151
CMessage
Here is a small explanation of how messages on IRC work, and how you can use this class to get useful...
Definition: Message.h:70
CMessage::GetCommand
const CString & GetCommand() const
Definition: Message.h:120
CString
String class that is used inside ZNC.
Definition: ZNCString.h:68
CNickMessage
Definition: Message.h:283
CMessage::Type::Pong
@ Pong
CMessage::SetCommand
void SetCommand(const CString &sCommand)
CQuitMessage::GetText
CString GetText() const
Definition: Message.h:328
CNoticeMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:294
CMessage::SetTags
void SetTags(const MCString &mssTags)
Definition: Message.h:152
CTargetMessage
Definition: Message.h:235
CTextMessage
Definition: Message.h:333
CCTCPMessage::GetText
CString GetText() const
Definition: Message.h:256
CMessage::FormatFlags
FormatFlags
Definition: Message.h:157
CMessage::GetParamsColon
CString GetParamsColon(unsigned int uIdx, unsigned int uLen=-1) const
CMessage::GetNick
const CNick & GetNick() const
Definition: Message.h:117
CChan
Definition: Chan.h:35
CMessage::Type::Account
@ Account
CMessage::Type::Kick
@ Kick
CMessage::GetParam
CString GetParam(unsigned int uIdx) const
CMessage::Type::Topic
@ Topic
CKickMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:311
CMessage::GetParamsSplit
VCString GetParamsSplit(unsigned int uIdx, unsigned int uLen=-1) const
Get a subset of the message parameters.
CMessage::Type::Unknown
@ Unknown
CString::Equals
bool Equals(const CString &s, CaseSensitivity cs=CaseInsensitive) const
Check if this string is equal to some other string.
CQuitMessage::GetReason
CString GetReason() const
Definition: Message.h:326
CModeMessage::GetModes
CString GetModes() const
Definition: Message.h:273
CTopicMessage::SetTopic
void SetTopic(const CString &sTopic)
Definition: Message.h:343
CJoinMessage
Definition: Message.h:263
CMessage::Type::Invite
@ Invite
CTargetMessage::GetTarget
CString GetTarget() const
Definition: Message.h:237
CMessage::Type::Text
@ Text
CActionMessage::GetText
CString GetText() const
Definition: Message.h:244
CMessage::SetNetwork
void SetNetwork(CIRCNetwork *pNetwork)
Definition: Message.h:107
CString::TrimPrefix_n
CString TrimPrefix_n(const CString &sPrefix=":") const
Trim a given prefix.
CModeMessage::HasModes
bool HasModes() const
Definition: Message.h:279
CMessage::Type::Quit
@ Quit
CTextMessage::GetText
CString GetText() const
Definition: Message.h:335
CKickMessage
Definition: Message.h:304
CString::EDEBUG
@ EDEBUG
Definition: ZNCString.h:76
CMessage::GetParams
const VCString & GetParams() const
Definition: Message.h:123
CNumericMessage::GetCode
unsigned int GetCode() const
Definition: Message.h:300
CModeMessage
Definition: Message.h:270
CMessage::GetTime
const timeval & GetTime() const
Definition: Message.h:148
CPartMessage::SetReason
void SetReason(const CString &sReason)
Definition: Message.h:318
CPartMessage::GetReason
CString GetReason() const
Definition: Message.h:317
CCTCPMessage::IsReply
bool IsReply() const
Definition: Message.h:255
CPartMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:320
CMessage::Type::Wallops
@ Wallops
CJoinMessage::GetKey
CString GetKey() const
Definition: Message.h:265
CString::ToUInt
unsigned int ToUInt() const
CNickMessage::GetOldNick
CString GetOldNick() const
Definition: Message.h:285
CMessage::IncludeAll
@ IncludeAll
Definition: Message.h:158
CMessage::Type
Type
Definition: Message.h:77
CIRCNetwork
Definition: IRCNetwork.h:40
CTopicMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:345
CKickMessage::GetReason
CString GetReason() const
Definition: Message.h:308
CMessage::Type::Part
@ Part
CTextMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:336
VCString
std::vector< CString > VCString
Definition: ZNCString.h:38
CTargetMessage::SetTarget
void SetTarget(const CString &sTarget)
Definition: Message.h:238
CMessage::SetTime
void SetTime(const timeval &ts)
Definition: Message.h:149
CNick
Definition: Nick.h:29
CMessage::As
M & As() ZNC_LVREFQUAL
Definition: Message.h:169
CMessage::CMessage
CMessage(const CString &sMessage="")
MCString::EmptyMap
static const MCString EmptyMap
A static instance of an empty map.
Definition: ZNCString.h:606
CKickMessage::SetReason
void SetReason(const CString &sReason)
Definition: Message.h:309
CMessage::GetClient
CClient * GetClient() const
Definition: Message.h:110
CQuitMessage::SetReason
void SetReason(const CString &sReason)
Definition: Message.h:327
CNoticeMessage
Definition: Message.h:291
CModeMessage::GetModeList
CString GetModeList() const
Definition: Message.h:275
CMessage::GetTag
CString GetTag(const CString &sKey) const
CMessage::Type::Away
@ Away
CMessage::SetClient
void SetClient(CClient *pClient)
Definition: Message.h:111
CMessage::Type::Action
@ Action
CTopicMessage::GetText
CString GetText() const
Definition: Message.h:344
CMessage::Type::Nick
@ Nick
CMessage::Type::CTCP
@ CTCP
CNumericMessage
Definition: Message.h:298
CNickMessage::GetNewNick
CString GetNewNick() const
Definition: Message.h:286
CMessage::Equals
bool Equals(const CMessage &Other) const
CKickMessage::GetKickedNick
CString GetKickedNick() const
Definition: Message.h:306
CPartMessage
Definition: Message.h:315
CNick::GetNick
const CString & GetNick() const
CMessage::Parse
void Parse(const CString &sMessage)
CMessage::Type::Capability
@ Capability
CMessage::SetChan
void SetChan(CChan *pChan)
Definition: Message.h:114
CModeMessage::GetModeParams
VCString GetModeParams() const
Definition: Message.h:277
CCTCPMessage::SetText
void SetText(const CString &sText)
Definition: Message.h:259