1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2018, 2020-2021 Sadie Powell <sadie@witchery.services>
5  *   Copyright (C) 2018 Attila Molnar <attilamolnar@hush.com>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #pragma once
22 
23 namespace ClientProtocol
24 {
25 	namespace Messages
26 	{
27 		class Numeric;
28 		class Join;
29 		struct Part;
30 		struct Kick;
31 		struct Quit;
32 		struct Nick;
33 		class Mode;
34 		struct Topic;
35 		class Privmsg;
36 		struct Invite;
37 		struct Ping;
38 		struct Pong;
39 		struct Error;
40 	}
41 }
42 
43 /** Numeric message.
44  * Doesn't have a fixed command name, it's always a 3 digit number padded with zeroes if necessary.
45  * The first parameter is the target of the numeric which is almost always the nick of the user
46  * the numeric will be sent to.
47  */
48 class ClientProtocol::Messages::Numeric : public ClientProtocol::Message
49 {
50 	char numericstr[4];
51 
InitCommand(unsigned int number)52 	void InitCommand(unsigned int number)
53 	{
54 		snprintf(numericstr, sizeof(numericstr), "%03u", number);
55 		SetCommand(numericstr);
56 	}
57 
InitFromNumeric(const::Numeric::Numeric & numeric)58 	void InitFromNumeric(const ::Numeric::Numeric& numeric)
59 	{
60 		InitCommand(numeric.GetNumeric());
61 		for (std::vector<std::string>::const_iterator i = numeric.GetParams().begin(); i != numeric.GetParams().end(); ++i)
62 			PushParamRef(*i);
63 	}
64 
65  public:
66 	/** Constructor, target is a User.
67 	 * @param num Numeric object to send. Must remain valid as long as this object is alive and must not be modified.
68 	 * @param user User to send the numeric to. May be unregistered, must remain valid as long as this object is alive.
69 	 */
Numeric(const::Numeric::Numeric & num,User * user)70 	Numeric(const ::Numeric::Numeric& num, User* user)
71 		: ClientProtocol::Message(NULL, (num.GetServer() ? num.GetServer() : ServerInstance->FakeClient->server)->GetName())
72 	{
73 		if (user->registered & REG_NICK)
74 			PushParamRef(user->nick);
75 		else
76 			PushParam("*");
77 		InitFromNumeric(num);
78 	}
79 
80 	/** Constructor, target is a string.
81 	 * @param num Numeric object to send. Must remain valid as long as this object is alive and must not be modified.
82 	 * @param target Target string, must stay valid as long as this object is alive.
83 	 */
Numeric(const::Numeric::Numeric & num,const std::string & target)84 	Numeric(const ::Numeric::Numeric& num, const std::string& target)
85 		: ClientProtocol::Message(NULL, (num.GetServer() ? num.GetServer() : ServerInstance->FakeClient->server)->GetName())
86 	{
87 		PushParamRef(target);
88 		InitFromNumeric(num);
89 	}
90 
91 	/** Constructor. Only the numeric number has to be specified.
92 	 * @param num Numeric number.
93 	 */
Numeric(unsigned int num)94 	Numeric(unsigned int num)
95 		: ClientProtocol::Message(NULL, ServerInstance->Config->GetServerName())
96 	{
97 		InitCommand(num);
98 		PushParam("*");
99 	}
100 };
101 
102 /** JOIN message.
103  * Sent when a user joins a channel.
104  */
105 class ClientProtocol::Messages::Join : public ClientProtocol::Message
106 {
107 	Membership* memb;
108 
109  public:
110 	/** Constructor. Does not populate parameters, call SetParams() before sending the message.
111 	 */
Join()112 	Join()
113 		: ClientProtocol::Message("JOIN")
114 		, memb(NULL)
115 	{
116 	}
117 
118 	/** Constructor.
119 	 * @param Memb Membership of the joining user.
120 	 */
Join(Membership * Memb)121 	Join(Membership* Memb)
122 		: ClientProtocol::Message("JOIN", Memb->user)
123 	{
124 		SetParams(Memb);
125 	}
126 
127 	/** Constructor.
128 	 * @param Memb Membership of the joining user.
129 	 * @param sourcestrref Message source string, must remain valid as long as this object is alive.
130 	 */
Join(Membership * Memb,const std::string & sourcestrref)131 	Join(Membership* Memb, const std::string& sourcestrref)
132 		: ClientProtocol::Message("JOIN", sourcestrref, Memb->user)
133 	{
134 		SetParams(Memb);
135 	}
136 
137 	/** Populate parameters from a Membership
138 	 * @param Memb Membership of the joining user.
139 	 */
SetParams(Membership * Memb)140 	void SetParams(Membership* Memb)
141 	{
142 		memb = Memb;
143 		PushParamRef(memb->chan->name);
144 	}
145 
146 	/** Get the Membership of the joining user.
147 	 * @return Membership of the joining user.
148 	 */
GetMember()149 	Membership* GetMember() const { return memb; }
150 };
151 
152 /** PART message.
153  * Sent when a user parts a channel.
154  */
155 struct ClientProtocol::Messages::Part : public ClientProtocol::Message
156 {
157 	/** Constructor.
158 	 * @param memb Member parting.
159 	 * @param reason Part reason, may be empty. If non-empty, must remain valid as long as this object is alive.
160 	 */
PartPart161 	Part(Membership* memb, const std::string& reason)
162 		: ClientProtocol::Message("PART", memb->user)
163 	{
164 		PushParamRef(memb->chan->name);
165 		if (!reason.empty())
166 			PushParamRef(reason);
167 	}
168 };
169 
170 /** KICK message.
171  * Sent when a user is kicked from a channel.
172  */
173 struct ClientProtocol::Messages::Kick : public ClientProtocol::Message
174 {
175 	/** Constructor.
176 	 * @param source User that does the kick.
177 	 * @param memb Membership of the user being kicked.
178 	 * @param reason Kick reason. Must remain valid as long as this object is alive.
179 	 */
KickKick180 	Kick(User* source, Membership* memb, const std::string& reason)
181 		: ClientProtocol::Message("KICK", source)
182 	{
183 		PushParamRef(memb->chan->name);
184 		PushParamRef(memb->user->nick);
185 		PushParamRef(reason);
186 	}
187 };
188 
189 /** QUIT message.
190  * Sent when a user quits.
191  */
192 struct ClientProtocol::Messages::Quit : public ClientProtocol::Message
193 {
194 	/** Constructor.
195 	 * @param source User quitting.
196 	 * @param reason Quit reason, may be empty. Must remain valid as long as this object is alive.
197 	 */
QuitQuit198 	Quit(User* source, const std::string& reason)
199 		: ClientProtocol::Message("QUIT", source)
200 	{
201 		if (!reason.empty())
202 			PushParamRef(reason);
203 	}
204 };
205 
206 /** NICK message.
207  * Sent when a user changes their nickname.
208  */
209 struct ClientProtocol::Messages::Nick : public ClientProtocol::Message
210 {
211 	/** Constructor.
212 	 * @param source User changing nicks.
213 	 * @param newnick New nickname. Must remain valid as long as this object is alive.
214 	 */
NickNick215 	Nick(User* source, const std::string& newnick)
216 		: ClientProtocol::Message("NICK", source)
217 	{
218 		PushParamRef(newnick);
219 	}
220 };
221 
222 /** MODE message.
223  * Sent when modes are changed on a user or channel.
224  */
225 class ClientProtocol::Messages::Mode : public ClientProtocol::Message
226 {
227 	Channel* chantarget;
228 	User* usertarget;
229 	Modes::ChangeList::List::const_iterator beginit;
230 	Modes::ChangeList::List::const_iterator lastit;
231 
232 	/** Convert a range of a mode change list to mode letters and '+', '-' symbols.
233 	 * @param list Mode change list.
234 	 * @param maxlinelen Maximum output length.
235 	 * @param beginit Iterator to the first element in 'list' to process.
236 	 * @param lastit Iterator which is set to the first element not processed due to length limitations by the method.
237 	 */
ToModeLetters(const Modes::ChangeList::List & list,std::string::size_type maxlinelen,Modes::ChangeList::List::const_iterator beginit,Modes::ChangeList::List::const_iterator & lastit)238 	static std::string ToModeLetters(const Modes::ChangeList::List& list, std::string::size_type maxlinelen, Modes::ChangeList::List::const_iterator beginit, Modes::ChangeList::List::const_iterator& lastit)
239 	{
240 		std::string ret;
241 		std::string::size_type paramlength = 0;
242 		char output_pm = '\0'; // current output state, '+' or '-'
243 
244 		Modes::ChangeList::List::const_iterator i;
245 		for (i = beginit; i != list.end(); ++i)
246 		{
247 			const Modes::Change& item = *i;
248 
249 			const char needed_pm = (item.adding ? '+' : '-');
250 			if (needed_pm != output_pm)
251 			{
252 				output_pm = needed_pm;
253 				ret.push_back(output_pm);
254 			}
255 
256 			if (!item.param.empty())
257 				paramlength += item.param.length() + 1;
258 			if (ret.length() + 1 + paramlength > maxlinelen)
259 			{
260 				// Mode sequence is getting too long
261 				const char c = *ret.rbegin();
262 				if ((c == '+') || (c == '-'))
263 					ret.erase(ret.size()-1);
264 				break;
265 			}
266 
267 			ret.push_back(item.mh->GetModeChar());
268 		}
269 
270 		lastit = i;
271 		return ret;
272 	}
273 
274 	/** Push mode parameters for modes that have one, starting at beginit to lastit (not including lastit).
275 	 */
PushModeParams()276 	void PushModeParams()
277 	{
278 		for (Modes::ChangeList::List::const_iterator i = beginit; i != lastit; ++i)
279 		{
280 			const Modes::Change& item = *i;
281 			if (!item.param.empty())
282 				PushParamRef(item.param);
283 		}
284 	}
285 
286  public:
287 	/** Convert an entire mode change list into mode letters and '+' and '-' characters.
288 	 * @param changelist Mode change list to convert into mode letters.
289 	 * @return Mode letters.
290 	 */
ToModeLetters(const Modes::ChangeList & changelist)291 	static std::string ToModeLetters(const Modes::ChangeList& changelist)
292 	{
293 		// TODO: This assumes that std::string::max_size() >= UINT_MAX
294 		Modes::ChangeList::List::const_iterator dummy;
295 		return ToModeLetters(changelist.getlist(), UINT_MAX, changelist.getlist().begin(), dummy);
296 	}
297 
298 	/** Constructor, populate parameters starting from a given position in a mode change list.
299 	 * @param source User doing the mode change.
300 	 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL.
301 	 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL.
302 	 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call.
303 	 * @param beginiter Starting position of mode changes in 'changelist'.
304 	 */
Mode(User * source,Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist,Modes::ChangeList::List::const_iterator beginiter)305 	Mode(User* source, Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist, Modes::ChangeList::List::const_iterator beginiter)
306 		: ClientProtocol::Message("MODE", source)
307 		, chantarget(Chantarget)
308 		, usertarget(Usertarget)
309 		, beginit(beginiter)
310 	{
311 		PushParamRef(GetStrTarget());
312 		PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit));
313 		PushModeParams();
314 	}
315 
316 	/** Constructor, populate parameters starting from the beginning of a mode change list.
317 	 * @param source User doing the mode change.
318 	 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL.
319 	 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL.
320 	 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call.
321 	 */
Mode(User * source,Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist)322 	Mode(User* source, Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist)
323 		: ClientProtocol::Message("MODE", source)
324 		, chantarget(Chantarget)
325 		, usertarget(Usertarget)
326 		, beginit(changelist.getlist().begin())
327 	{
328 		PushParamRef(GetStrTarget());
329 		PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit));
330 		PushModeParams();
331 	}
332 
333 	/** Constructor. Does not populate parameters, call SetParams() before sending the message.
334 	 * The message source is set to the local server.
335 	 */
Mode()336 	Mode()
337 		: ClientProtocol::Message("MODE", ServerInstance->FakeClient)
338 		, chantarget(NULL)
339 		, usertarget(NULL)
340 	{
341 	}
342 
343 	/** Set parameters
344 	 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL.
345 	 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL.
346 	 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call.
347 	 */
SetParams(Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist)348 	void SetParams(Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist)
349 	{
350 		ClearParams();
351 
352 		chantarget = Chantarget;
353 		usertarget = Usertarget;
354 		beginit = changelist.getlist().begin();
355 
356 		PushParamRef(GetStrTarget());
357 		PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit));
358 		PushModeParams();
359 	}
360 
361 	/** Get first mode change included in this MODE message.
362 	 * @return Iterator to the first mode change that is included in this MODE message.
363 	 */
GetBeginIterator()364 	Modes::ChangeList::List::const_iterator	GetBeginIterator() const { return beginit; }
365 
366 	/** Get first mode change not included in this MODE message.
367 	 * @return Iterator to the first mode change that is not included in this MODE message.
368 	 */
GetEndIterator()369 	Modes::ChangeList::List::const_iterator GetEndIterator() const { return lastit; }
370 
371 	/** Get mode change target as a string.
372 	 * This is the name of the channel if the mode change targets a channel or the nickname of the user
373 	 * if the target is a user.
374 	 * @return Name of target as a string.
375 	 */
GetStrTarget()376 	const std::string& GetStrTarget() const { return (chantarget ? chantarget->name : usertarget->nick); }
377 
378 	/** Get user target.
379 	 * @return User target or NULL if the mode change targets a channel.
380 	 */
GetUserTarget()381 	User* GetUserTarget() const { return usertarget; }
382 
383 	/** Get channel target.
384 	 * @return Channel target or NULL if the mode change targets a user.
385 	 */
GetChanTarget()386 	Channel* GetChanTarget() const { return chantarget; }
387 };
388 
389 /** TOPIC message.
390  */
391 struct ClientProtocol::Messages::Topic : public ClientProtocol::Message
392 {
393 	/** Constructor.
394 	 * @param source User changing the topic.
395 	 * @param chan Channel the topic is being changed on.
396 	 * @param newtopic New topic. May be empty, must remain valid as long as this object is alive.
397 	 */
TopicTopic398 	Topic(User* source, const Channel* chan, const std::string& newtopic)
399 		: ClientProtocol::Message("TOPIC", source)
400 	{
401 		PushParamRef(chan->name);
402 		PushParamRef(newtopic);
403 	}
404 };
405 
406 /** PRIVMSG and NOTICE message.
407  */
408 class ClientProtocol::Messages::Privmsg : public ClientProtocol::Message
409 {
PushTargetChan(char status,const Channel * targetchan)410 	void PushTargetChan(char status, const Channel* targetchan)
411 	{
412 		if (status)
413 		{
414 			std::string rawtarget(1, status);
415 			rawtarget.append(targetchan->name);
416 			PushParam(rawtarget);
417 		}
418 		else
419 		{
420 			PushParamRef(targetchan->name);
421 		}
422 	}
423 
PushTargetUser(const User * targetuser)424 	void PushTargetUser(const User* targetuser)
425 	{
426 		if (targetuser->registered & REG_NICK)
427 			PushParamRef(targetuser->nick);
428 		else
429 			PushParam("*");
430 	}
431 
432  public:
433 	/** Used to differentiate constructors that copy the text from constructors that do not.
434 	 */
435 	enum NoCopy { nocopy };
436 
437 	/** Get command name from MessageType.
438 	 * @param mt Message type to get command name for.
439 	 * @return Command name for the message type.
440 	 */
CommandStrFromMsgType(MessageType mt)441 	static const char* CommandStrFromMsgType(MessageType mt)
442 	{
443 		return ((mt == MSG_PRIVMSG) ? "PRIVMSG" : "NOTICE");
444 	}
445 
446 	/** Constructor, user source, string target, copies text.
447 	 * @param source Source user.
448 	 * @param target Privmsg target string.
449 	 * @param text Privmsg text, will be copied.
450 	 * @param mt Message type.
451 	 */
452 	Privmsg(User* source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)453 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
454 	{
455 		PushParam(target);
456 		PushParam(text);
457 	}
458 
459 	/** Constructor, user source, user target, copies text.
460 	 * @param source Source user.
461 	 * @param targetchan Target channel.
462 	 * @param text Privmsg text, will be copied.
463 	 * @param mt Message type.
464 	 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0.
465 	 */
466 	Privmsg(User* source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0)
Message(CommandStrFromMsgType (mt),source)467 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
468 	{
469 		PushTargetChan(status, targetchan);
470 		PushParam(text);
471 	}
472 
473 	/** Constructor, user source, user target, copies text.
474 	 * @param source Source user.
475 	 * @param targetuser Target user.
476 	 * @param text Privmsg text, will be copied.
477 	 * @param mt Message type.
478 	 */
479 	Privmsg(User* source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)480 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
481 	{
482 		PushTargetUser(targetuser);
483 		PushParam(text);
484 	}
485 
486 	/** Constructor, string source, string target, copies text.
487 	 * @param source Source user.
488 	 * @param target Target string.
489 	 * @param text Privmsg text, will be copied.
490 	 * @param mt Message type.
491 	 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0.
492 	 */
493 	Privmsg(const std::string& source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0)
Message(CommandStrFromMsgType (mt),source)494 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
495 	{
496 		if (status)
497 		{
498 			std::string rawtarget(1, status);
499 			rawtarget.append(target);
500 			PushParam(rawtarget);
501 		}
502 		else
503 		{
504 			PushParam(target);
505 		}
506 		PushParam(text);
507 	}
508 
509 	/** Constructor, string source, channel target, copies text.
510 	 * @param source Source string.
511 	 * @param targetchan Target channel.
512 	 * @param text Privmsg text, will be copied.
513 	 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0.
514 	 * @param mt Message type.
515 	 */
516 	Privmsg(const std::string& source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0)
Message(CommandStrFromMsgType (mt),source)517 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
518 	{
519 		PushTargetChan(status, targetchan);
520 		PushParam(text);
521 	}
522 
523 	/** Constructor, string source, user target, copies text.
524 	 * @param source Source string.
525 	 * @param targetuser Target user.
526 	 * @param text Privmsg text, will be copied.
527 	 * @param mt Message type.
528 	 */
529 	Privmsg(const std::string& source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)530 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
531 	{
532 		PushTargetUser(targetuser);
533 		PushParam(text);
534 	}
535 
536 	/** Constructor, user source, string target, copies text.
537 	 * @param source Source user.
538 	 * @param target Target string.
539 	 * @param text Privmsg text, will not be copied.
540 	 * @param mt Message type.
541 	 */
542 	Privmsg(NoCopy, User* source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)543 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
544 	{
545 		PushParam(target);
546 		PushParamRef(text);
547 	}
548 
549 	/** Constructor, user source, channel target, does not copy text.
550 	 * @param source Source user.
551 	 * @param targetchan Target channel.
552 	 * @param text Privmsg text, will not be copied.
553 	 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0.
554 	 * @param mt Message type.
555 	 */
556 	Privmsg(NoCopy, User* source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0)
Message(CommandStrFromMsgType (mt),source)557 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
558 	{
559 		PushTargetChan(status, targetchan);
560 		PushParamRef(text);
561 	}
562 
563 	/** Constructor, user source, user target, does not copy text.
564 	 * @param source Source user.
565 	 * @param targetuser Target user.
566 	 * @param text Privmsg text, will not be copied.
567 	 * @param mt Message type.
568 	 */
569 	Privmsg(NoCopy, User* source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)570 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
571 	{
572 		PushTargetUser(targetuser);
573 		PushParamRef(text);
574 	}
575 
576 	/** Constructor, string source, string target, does not copy text.
577 	 * @param source Source string.
578 	 * @param target Target string.
579 	 * @param text Privmsg text, will not be copied.
580 	 * @param mt Message type.
581 	 */
582 	Privmsg(NoCopy, const std::string& source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)583 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
584 	{
585 		PushParam(target);
586 		PushParamRef(text);
587 	}
588 
589 	/** Constructor, string source, channel target, does not copy text.
590 	 * @param source Source string.
591 	 * @param targetchan Target channel.
592 	 * @param text Privmsg text, will not be copied.
593 	 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0.
594 	 * @param mt Message type.
595 	 */
596 	Privmsg(NoCopy, const std::string& source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0)
Message(CommandStrFromMsgType (mt),source)597 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
598 	{
599 		PushTargetChan(status, targetchan);
600 		PushParamRef(text);
601 	}
602 
603 	/** Constructor, string source, user target, does not copy text.
604 	 * @param source Source string.
605 	 * @param targetuser Target user.
606 	 * @param text Privmsg text, will not be copied.
607 	 * @param mt Message type.
608 	 */
609 	Privmsg(NoCopy, const std::string& source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG)
Message(CommandStrFromMsgType (mt),source)610 		: ClientProtocol::Message(CommandStrFromMsgType(mt), source)
611 	{
612 		PushTargetUser(targetuser);
613 		PushParamRef(text);
614 	}
615 };
616 
617 /** INVITE message.
618  * Sent when a user is invited to join a channel.
619  */
620 struct ClientProtocol::Messages::Invite : public ClientProtocol::Message
621 {
622 	/** Constructor.
623 	 * @param source User inviting the target user.
624 	 * @param target User being invited by source.
625 	 * @param chan Channel the target user is being invited to.
626 	 */
InviteInvite627 	Invite(User* source, User* target, Channel* chan)
628 		: ClientProtocol::Message("INVITE", source)
629 	{
630 		PushParamRef(target->nick);
631 		PushParamRef(chan->name);
632 	}
633 };
634 
635 /** PING message.
636  * Used to check if a connection is still alive.
637  */
638 struct ClientProtocol::Messages::Ping : public ClientProtocol::Message
639 {
640 	/** Constructor.
641 	 * The ping cookie is the name of the local server.
642 	 */
PingPing643 	Ping()
644 		: ClientProtocol::Message("PING")
645 	{
646 		PushParamRef(ServerInstance->Config->GetServerName());
647 	}
648 
649 	/** Constructor.
650 	 * @param cookie Ping cookie. Must remain valid as long as this object is alive.
651 	 */
PingPing652 	Ping(const std::string& cookie)
653 		: ClientProtocol::Message("PING")
654 	{
655 		PushParamRef(cookie);
656 	}
657 };
658 
659 /** PONG message.
660  * Sent as a reply to PING.
661  */
662 struct ClientProtocol::Messages::Pong : public ClientProtocol::Message
663 {
664 	/** Constructor.
665 	 * @param cookie Ping cookie. Must remain valid as long as this object is alive.
666 	 * @param server Pinged server. Must remain valid as long as this object is alive if non-empty.
667 	 */
668 	Pong(const std::string& cookie, const std::string& server = "")
669 		: ClientProtocol::Message("PONG", ServerInstance->Config->GetServerName())
670 	{
671 		if (server.empty())
672 			PushParamRef(ServerInstance->Config->GetServerName());
673 		else
674 			PushParam(server);
675 		PushParamRef(cookie);
676 	}
677 };
678 
679 /** ERROR message.
680  * Sent to clients upon disconnection.
681  */
682 struct ClientProtocol::Messages::Error : public ClientProtocol::Message
683 {
684 	/** Constructor.
685 	 * @param text Error text.
686 	 */
ErrorError687 	Error(const std::string& text)
688 			: ClientProtocol::Message("ERROR")
689 	{
690 		PushParam(text);
691 	}
692 };
693