1 /*
2   Copyright (C) 2008-2020 The Communi Project
3 
4   You may use this file under the terms of BSD license as follows:
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8     * Redistributions of source code must retain the above copyright
9       notice, this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright
11       notice, this list of conditions and the following disclaimer in the
12       documentation and/or other materials provided with the distribution.
13     * Neither the name of the copyright holder nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
21   ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include "irccommand.h"
30 #include "irccommand_p.h"
31 #include "ircconnection.h"
32 #include "ircmessage.h"
33 #include "ircconnection_p.h"
34 #include "irccore_p.h"
35 #include <QTextCodec>
36 #include <QMetaEnum>
37 #include <QDebug>
38 
39 IRC_BEGIN_NAMESPACE
40 
41 /*!
42     \file irccommand.h
43     \brief \#include &lt;IrcCommand&gt;
44  */
45 
46 /*!
47     \class IrcCommand irccommand.h <IrcCommand>
48     \ingroup core
49     \brief Provides the most common commands.
50 
51     The IrcCommand class supports the most common IRC commands out of the box,
52     and can be extended for custom commands as well. See IrcCommand::Type for
53     the list of built-in command types. IRC commands, as in IrcCommand instances,
54     are sent to the IRC server via IrcConnection::sendCommand().
55 
56     \section creating-commands Creating commands
57 
58     It is recommended to create IrcCommand instances via static
59     IrcCommand::createXxx() methods.
60 
61     \warning IrcCommand instances must be allocated on the heap, since
62     IrcConnection::sendCommand() takes ownership of the command and deletes
63     it once it has been sent.
64 
65     \section custom-commands Custom commands
66 
67     A "custom command" here refers to command types not listed in IrcCommand::Type,
68     the list of built-in command types. There are two ways to send custom commands:
69     \li by passing the string representation of a command directly to
70     IrcConnection::sendRaw() or IrcConnection::sendData(), or
71     \li by subclassing IrcCommand and reimplementing
72     IrcCommand::toString(), which eventually creates the string representation
73     of the command.
74 
75     Example implementation of a custom command:
76     \code
77     class IrcServerCommand : public IrcCommand
78     {
79         Q_OBJECTT
80     public:
81         explicit IrcServerCommand(QObject* parent = 0) : IrcCommand(parent)
82         {
83         }
84 
85         // provided for convenience, to ensure correct parameter order
86         static IrcCommand* create(const QString& serverName, int hopCount, const QString& info)
87         {
88             IrcCommand* command = new IrcServerCommand;
89             command->setParameters(QStringList() << serverName << QString::number(hopCount) << info);
90             return command;
91         }
92 
93         // reimplemented from IrcCommand::toString()
94         virtual toString() const
95         {
96             // SERVER <servername> <hopcount> <info>
97             return QString("SERVER %1 %2 %3").arg(params.value(0), params.value(1), params.value(2));
98         }
99     };
100     \endcode
101 
102     \sa IrcConnection::sendCommand(), IrcConnection::sendRaw(), IrcCommand::Type
103  */
104 
105 /*!
106     \enum IrcCommand::Type
107     This enum describes the built-in command types.
108  */
109 
110 /*!
111     \var IrcCommand::Admin
112     \brief An admin command (ADMIN) is used to query server admin info.
113  */
114 
115 /*!
116     \var IrcCommand::Away
117     \brief An away command (AWAY) is used to set the away status.
118  */
119 
120 /*!
121     \var IrcCommand::Capability
122     \brief A capability command (CAP) is used to manage connection capabilities.
123  */
124 
125 /*!
126     \var IrcCommand::CtcpAction
127     \brief A CTCP action command is used to send an action message to channels and users.
128  */
129 
130 /*!
131     \var IrcCommand::CtcpReply
132     \brief A CTCP reply command is used to send a reply to a request.
133  */
134 
135 /*!
136     \var IrcCommand::CtcpRequest
137     \brief A CTCP request command is used to send a request.
138  */
139 
140 /*!
141     \var IrcCommand::Custom
142     \brief A custom command
143  */
144 
145 /*!
146     \var IrcCommand::Info
147     \brief An info command (INFO) is used to query server info.
148  */
149 
150 /*!
151     \var IrcCommand::Invite
152     \brief An invite command (INVITE) is used to invite users to a channel.
153  */
154 
155 /*!
156     \var IrcCommand::Join
157     \brief A join command (JOIN) is used to start listening a specific channel.
158  */
159 
160 /*!
161     \var IrcCommand::Kick
162     \brief A kick command (KICK) is used to forcibly remove a user from a channel.
163  */
164 
165 /*!
166     \var IrcCommand::Knock
167     \brief A knock command (KNOCK) is used to request channel invitation.
168  */
169 
170 /*!
171     \var IrcCommand::List
172     \brief A list command (LIST) is used to list channels and their topics.
173  */
174 
175 /*!
176     \var IrcCommand::Message
177     \brief A message command (PRIVMSG) is used to send private messages to channels and users.
178  */
179 
180 /*!
181     \var IrcCommand::Mode
182     \brief A mode command (MODE) is used to change the mode of users and channels.
183  */
184 
185 /*!
186     \var IrcCommand::Motd
187     \brief A message of the day command (MOTD) is used to query the message of the day.
188  */
189 
190 /*!
191     \var IrcCommand::Names
192     \brief A names command (NAMES) is used to list all nicknames on a channel.
193  */
194 
195 /*!
196     \var IrcCommand::Nick
197     \brief A nick command (NICK) is used to give user a nickname or change the previous one.
198  */
199 
200 /*!
201     \var IrcCommand::Notice
202     \brief A notice command (NOTICE) is used to send notice messages to channels and users.
203  */
204 
205 /*!
206     \var IrcCommand::Part
207     \brief A part command (PART) causes the client to be removed from the channel.
208  */
209 
210 /*!
211     \var IrcCommand::Quit
212     \brief A quit command (QUIT) is used to end a client connection.
213  */
214 
215 /*!
216     \var IrcCommand::Quote
217     \brief A quote command is used to send a raw message to the server.
218  */
219 
220 /*!
221     \var IrcCommand::Stats
222     \brief A stats command (STATS) is used to query server statistics.
223  */
224 
225 /*!
226     \var IrcCommand::Time
227     \brief A time command (TIME) is used to query local server time.
228  */
229 
230 /*!
231     \var IrcCommand::Topic
232     \brief A topic command (TOPIC) is used to change or view the topic of a channel.
233  */
234 
235 /*!
236     \var IrcCommand::Trace
237     \brief A trace command (TRACE) is used to trace the connection path to a target.
238  */
239 
240 /*!
241     \var IrcCommand::Users
242     \brief A users command (USERS) is used to query server users.
243  */
244 
245 /*!
246     \var IrcCommand::Version
247     \brief A version command (VERSION) is used to query user or server version.
248  */
249 
250 /*!
251     \var IrcCommand::Who
252     \brief A who command (WHO) is used to generate a query which returns a list of matching users.
253  */
254 
255 /*!
256     \var IrcCommand::Whois
257     \brief A whois command (WHOIS) is used to query information about a particular user.
258  */
259 
260 /*!
261     \var IrcCommand::Whowas
262     \brief A whowas command (WHOWAS) is used to query information about a user that no longer exists.
263  */
264 
265 extern bool irc_is_supported_encoding(const QByteArray& encoding); // ircmessagedecoder.cpp
266 
267 #ifndef IRC_DOXYGEN
IrcCommandPrivate()268 IrcCommandPrivate::IrcCommandPrivate() :  encoding("UTF-8")
269 {
270 }
271 
params(int index) const272 QString IrcCommandPrivate::params(int index) const
273 {
274     return QStringList(parameters.mid(index)).join(QLatin1String(" "));
275 }
276 
createCommand(IrcCommand::Type type,const QStringList & parameters)277 IrcCommand* IrcCommandPrivate::createCommand(IrcCommand::Type type, const QStringList& parameters)
278 {
279     IrcCommand* command = new IrcCommand;
280     command->setType(type);
281     command->setParameters(parameters);
282     return command;
283 }
284 #endif // IRC_DOXYGEN
285 
286 /*!
287     Constructs a new IrcCommand with \a parent.
288  */
IrcCommand(QObject * parent)289 IrcCommand::IrcCommand(QObject* parent) : QObject(parent), d_ptr(new IrcCommandPrivate)
290 {
291 }
292 
293 /*!
294     Destructs the IRC command.
295  */
~IrcCommand()296 IrcCommand::~IrcCommand()
297 {
298 }
299 
300 /*!
301     \since 3.3
302 
303     This property holds the connection that this command was sent to.
304 
305     The connection is only set if the command has been passed to IrcConnection::sendCommand().
306     It is mostly usable to know the associated connection in IrcCommandFilter::commandFilter().
307 
308     \par Access function:
309     \li \ref IrcConnection* <b>connection</b>() const
310  */
connection() const311 IrcConnection* IrcCommand::connection() const
312 {
313     Q_D(const IrcCommand);
314     return d->connection;
315 }
316 
317 /*!
318     \since 3.5
319 
320     This property holds the network that this command was sent to.
321 
322     The network is only set if the command has been passed to IrcConnection::sendCommand().
323 
324     \par Access function:
325     \li \ref IrcNetwork* <b>network</b>() const
326  */
network() const327 IrcNetwork* IrcCommand::network() const
328 {
329     Q_D(const IrcCommand);
330     return d->connection ? d->connection->network() : nullptr;
331 }
332 
333 /*!
334     This property holds the command type.
335 
336     \par Access functions:
337     \li IrcCommand::Type <b>type</b>() const
338     \li void <b>setType</b>(IrcCommand::Type type)
339  */
type() const340 IrcCommand::Type IrcCommand::type() const
341 {
342     Q_D(const IrcCommand);
343     return d->type;
344 }
345 
setType(Type type)346 void IrcCommand::setType(Type type)
347 {
348     Q_D(IrcCommand);
349     d->type = type;
350 }
351 
352 /*!
353     This property holds the command parameters.
354 
355     \par Access functions:
356     \li QStringList <b>parameters</b>() const
357     \li void <b>setParameters</b>(const QStringList& parameters)
358  */
parameters() const359 QStringList IrcCommand::parameters() const
360 {
361     Q_D(const IrcCommand);
362     return d->parameters;
363 }
364 
setParameters(const QStringList & parameters)365 void IrcCommand::setParameters(const QStringList& parameters)
366 {
367     Q_D(IrcCommand);
368     d->parameters = parameters;
369 }
370 
371 /*!
372     This property holds the encoding that is used when
373     sending the command via IrcConnection::sendCommand().
374 
375     See QTextCodec::availableCodes() for the list of
376     supported encodings. The default value is \c "UTF-8".
377 
378     \par Access functions:
379     \li QByteArray <b>encoding</b>() const
380     \li void <b>setEncoding</b>(const QByteArray& encoding)
381 
382     \sa QTextCodec::availableCodecs()
383  */
encoding() const384 QByteArray IrcCommand::encoding() const
385 {
386     Q_D(const IrcCommand);
387     return d->encoding;
388 }
389 
setEncoding(const QByteArray & encoding)390 void IrcCommand::setEncoding(const QByteArray& encoding)
391 {
392     Q_D(IrcCommand);
393     if (!irc_is_supported_encoding(encoding)) {
394         qWarning() << "IrcCommand::setEncoding(): unsupported encoding" << encoding;
395         return;
396     }
397     d->encoding = encoding;
398 }
399 
400 /*!
401     Returns the command as a string.
402 
403     Reimplement for custom commands.
404     \sa IrcCommand::Custom
405  */
toString() const406 QString IrcCommand::toString() const
407 {
408     Q_D(const IrcCommand);
409     const QString p0 = d->parameters.value(0);
410     const QString p1 = d->parameters.value(1);
411     const QString p2 = d->parameters.value(2);
412 
413     switch (d->type) {
414         case Admin:         return QString("ADMIN %1").arg(p0); // server
415         case Away:          return QString("AWAY :%1").arg(d->params(0)); // reason
416         case Capability:    return QString("CAP %1 :%2").arg(p0, d->params(1)); // subcmd, caps
417         case CtcpAction:    return QString("PRIVMSG %1 :\1ACTION %2\1").arg(p0, d->params(1)); // target, msg
418         case CtcpRequest:   return QString("PRIVMSG %1 :\1%2\1").arg(p0, d->params(1)); // target, msg
419         case CtcpReply:     return QString("NOTICE %1 :\1%2\1").arg(p0, d->params(1)); // target, msg
420         case Info:          return QString("INFO %1").arg(p0); // server
421         case Invite:        return QString("INVITE %1 %2").arg(p0, p1); // user, chan
422         case Join:          return p1.isNull() ? QString("JOIN %1").arg(p0) : QString("JOIN %1 %2").arg(p0, p1); // chan, key
423         case Kick:          return p2.isNull() ? QString("KICK %1 %2").arg(p0, p1) : QString("KICK %1 %2 :%3").arg(p0, p1, d->params(2)); // chan, user, reason
424         case Knock:         return QString("KNOCK %1 %2").arg(p0, p1); // chan, msg
425         case List:          return p1.isNull() ? QString("LIST %1").arg(p0) : QString("LIST %1 %2").arg(p0, p1); // chan, server
426         case Message:       return QString("PRIVMSG %1 :%2").arg(p0, d->params(1)); // target, msg
427         case Mode:          return QString("MODE ") + d->parameters.join(" "); // target, mode, arg
428         case Monitor:       return QString("MONITOR %1 %2").arg(p0, p1); // cmd, target
429         case Motd:          return QString("MOTD %1").arg(p0); // server
430         case Names:         return QString("NAMES %1").arg(p0); // chan
431         case Nick:          return QString("NICK %1").arg(p0); // nick
432         case Notice:        return QString("NOTICE %1 :%2").arg(p0, d->params(1)); // target, msg
433         case Part:          return p1.isNull() ? QString("PART %1").arg(p0) : QString("PART %1 :%2").arg(p0, d->params(1)); // chan, reason
434         case Ping:          return QString("PING %1").arg(p0); // argument
435         case Pong:          return QString("PONG %1").arg(p0); // argument
436         case Quit:          return QString("QUIT :%1").arg(d->params(0)); // reason
437         case Quote:         return d->parameters.join(" ");
438         case Stats:         return QString("STATS %1 %2").arg(p0, p1); // query, server
439         case Time:          return QString("TIME %1").arg(p0); // server
440         case Topic:         return p1.isNull() ? QString("TOPIC %1").arg(p0) : QString("TOPIC %1 :%2").arg(p0, d->params(1)); // chan, topic
441         case Trace:         return QString("TRACE %1").arg(p0); // target
442         case Users:         return QString("USERS %1").arg(p0); // server
443         case Version:       return p0.isNull() ? QString("VERSION") : QString("PRIVMSG %1 :\1VERSION\1").arg(p0); // user
444         case Who:           return QString("WHO %1").arg(p0); // user
445         case Whois:         return QString("WHOIS %1 %1").arg(p0); // user
446         case Whowas:        return QString("WHOWAS %1 %1").arg(p0); // user
447 
448         case Custom:        qWarning("Reimplement IrcCommand::toString() for IrcCommand::Custom");
449         Q_FALLTHROUGH();
450         default:            return QString();
451     }
452 }
453 
454 /*!
455     Creates a new message from this command for \a prefix and \a connection.
456 
457     Notice that IRC servers do not echo sent message commands back to the client.
458     This function is particularly useful for converting sent message commands as
459     messages for presentation purposes.
460 
461     \code
462     if (command->type() == IrcCommand::Message) {
463         IrcMessage* message = command->toMessage(connection->nickName(), connection);
464         receiveMessage(message);
465         message->deleteLater();
466     }
467     \endcode
468  */
toMessage(const QString & prefix,IrcConnection * connection) const469 IrcMessage* IrcCommand::toMessage(const QString& prefix, IrcConnection* connection) const
470 {
471     return IrcMessage::fromData(":" + prefix.toUtf8() + " " + toString().toUtf8(), connection);
472 }
473 
474 /*!
475     Creates a new ADMIN command with type IrcCommand::Admin and optional parameter \a server.
476 
477     This command shows admin info for the specified \a server,
478     or the current server if not specified.
479  */
createAdmin(const QString & server)480 IrcCommand* IrcCommand::createAdmin(const QString& server)
481 {
482     return IrcCommandPrivate::createCommand(Admin, QStringList() << server);
483 }
484 
485 /*!
486     Creates a new AWAY command with type IrcCommand::Away and optional parameter \a reason.
487 
488     Provides the server with \a reason to automatically send in reply to a private
489     message directed at the user. If \a reason is omitted, the away status is removed.
490  */
createAway(const QString & reason)491 IrcCommand* IrcCommand::createAway(const QString& reason)
492 {
493     return IrcCommandPrivate::createCommand(Away, QStringList() << reason);
494 }
495 
496 /*!
497     Creates a new capability command with type IrcCommand::Capability and parameters \a subCommand and a \a capability.
498 
499     Available subcommands are: LS, LIST, REQ, ACK, NAK, CLEAR and END.
500 
501     \sa \ref ircv3
502  */
createCapability(const QString & subCommand,const QString & capability)503 IrcCommand* IrcCommand::createCapability(const QString& subCommand, const QString& capability)
504 {
505     return createCapability(subCommand, QStringList() << capability);
506 }
507 
508 /*!
509     Creates a new capability command with type IrcCommand::Capability and parameters \a subCommand and optional \a capabilities.
510 
511     Available subcommands are: LS, LIST, REQ, ACK, NAK, CLEAR and END.
512 
513     \sa \ref ircv3
514  */
createCapability(const QString & subCommand,const QStringList & capabilities)515 IrcCommand* IrcCommand::createCapability(const QString& subCommand, const QStringList& capabilities)
516 {
517     return IrcCommandPrivate::createCommand(Capability, QStringList() << subCommand << capabilities.join(QLatin1String(" ")));
518 }
519 
520 /*!
521     Creates a new CTCP action command with type IrcCommand::CtcpAction and parameters \a target and \a action.
522  */
createCtcpAction(const QString & target,const QString & action)523 IrcCommand* IrcCommand::createCtcpAction(const QString& target, const QString& action)
524 {
525     return IrcCommandPrivate::createCommand(CtcpAction, QStringList() << target << action);
526 }
527 
528 /*!
529     Creates a new CTCP reply command with type IrcCommand::CtcpReply and parameters \a target and \a reply.
530  */
createCtcpReply(const QString & target,const QString & reply)531 IrcCommand* IrcCommand::createCtcpReply(const QString& target, const QString& reply)
532 {
533     return IrcCommandPrivate::createCommand(CtcpReply, QStringList() << target << reply);
534 }
535 
536 /*!
537     Creates a new CTCP request command with type IrcCommand::CtcpRequest and parameters \a target and \a request.
538  */
createCtcpRequest(const QString & target,const QString & request)539 IrcCommand* IrcCommand::createCtcpRequest(const QString& target, const QString& request)
540 {
541     return IrcCommandPrivate::createCommand(CtcpRequest, QStringList() << target << request);
542 }
543 
544 /*!
545     Creates a new INFO command with type IrcCommand::Info and optional parameter \a server.
546 
547     This command shows info for the specified \a server,
548     or the current server if not specified.
549  */
createInfo(const QString & server)550 IrcCommand* IrcCommand::createInfo(const QString& server)
551 {
552     return IrcCommandPrivate::createCommand(Info, QStringList() << server);
553 }
554 
555 /*!
556     Creates a new INVITE command with type IrcCommand::Invite and parameters \a user and \a channel.
557 
558     This command invites \a user to the \a channel. The channel does not have to exist, but
559     if it does, only members of the channel are allowed to invite other clients. if the
560     channel mode +i (invite-only) is set, only channel operators may invite other clients.
561  */
createInvite(const QString & user,const QString & channel)562 IrcCommand* IrcCommand::createInvite(const QString& user, const QString& channel)
563 {
564     return IrcCommandPrivate::createCommand(Invite, QStringList() << user << channel);
565 }
566 
567 /*!
568     Creates a new JOIN command with type IrcCommand::Join and parameters \a channel and optional \a key.
569 
570     This command joins the \a channel using \a key if specified.
571     If the channel does not exist, it will be created.
572  */
createJoin(const QString & channel,const QString & key)573 IrcCommand* IrcCommand::createJoin(const QString& channel, const QString& key)
574 {
575     return IrcCommandPrivate::createCommand(Join, QStringList() << channel << key);
576 }
577 
578 /*!
579     This overload is provided for convenience.
580  */
createJoin(const QStringList & channels,const QStringList & keys)581 IrcCommand* IrcCommand::createJoin(const QStringList& channels, const QStringList& keys)
582 {
583     if (keys.isEmpty() || keys.join("").isEmpty())
584         return IrcCommandPrivate::createCommand(Join, QStringList() << channels.join(","));
585     return IrcCommandPrivate::createCommand(Join, QStringList() << channels.join(",") << keys.join(","));
586 }
587 
588 /*!
589     Creates a new KICK command with type IrcCommand::Kick and parameters \a channel, \a user and optional \a reason.
590 
591     This command forcibly removes \a user from \a channel,
592     and may only be issued by channel operators.
593  */
createKick(const QString & channel,const QString & user,const QString & reason)594 IrcCommand* IrcCommand::createKick(const QString& channel, const QString& user, const QString& reason)
595 {
596     return IrcCommandPrivate::createCommand(Kick, QStringList() << channel << user << reason);
597 }
598 
599 /*!
600     Creates a new KNOCK command with type IrcCommand::Knock and parameters \a channel and optional \a message.
601 
602     This command sends an invitation request to a \a channel with an optional \a message.
603 
604     \note The command is not formally defined by an RFC, but is supported by most major IRC daemons.
605     Support is indicated in a RPL_ISUPPORT reply (numeric 005) with the KNOCK keyword.
606  */
createKnock(const QString & channel,const QString & message)607 IrcCommand* IrcCommand::createKnock(const QString& channel, const QString& message)
608 {
609     return IrcCommandPrivate::createCommand(Knock, QStringList() << channel << message);
610 }
611 
612 /*!
613     Creates a new LIST command with type IrcCommand::List and optional parameters \a channels and \a server.
614 
615     This command lists all channels on the server. If \a channels are given, it will list the channel topics.
616     If \a server is given, the command will be forwarded to \a server for evaluation.
617  */
createList(const QStringList & channels,const QString & server)618 IrcCommand* IrcCommand::createList(const QStringList& channels, const QString& server)
619 {
620     return IrcCommandPrivate::createCommand(List, QStringList() << channels.join(",") << server);
621 }
622 
623 /*!
624     Creates a new PRIVMSG command with type IrcCommand::Message and parameters \a target and \a message.
625 
626     This command sends \a message to \a target, which is usually a user or channel.
627  */
createMessage(const QString & target,const QString & message)628 IrcCommand* IrcCommand::createMessage(const QString& target, const QString& message)
629 {
630     return IrcCommandPrivate::createCommand(Message, QStringList() << target << message);
631 }
632 
633 /*!
634     Creates a new MODE command with type IrcCommand::Mode and parameters \a target and optional \a mode and \a arg.
635 
636     This command is used to set both user and channel modes.
637  */
createMode(const QString & target,const QString & mode,const QString & arg)638 IrcCommand* IrcCommand::createMode(const QString& target, const QString& mode, const QString& arg)
639 {
640     return IrcCommandPrivate::createCommand(Mode, QStringList() << target << mode << arg);
641 }
642 
643 /*!
644     \since 3.4
645 
646     Creates a new MONITOR command with type IrcCommand::Monitor and parameters \a command and and optional \a target.
647 
648     Available commands are:
649     \li \c + - Adds the given list of targets to the list of targets being monitored.
650     \li \c + - Removes the given list of targets from the list of targets being monitored.
651                No output will be returned for use of this command.
652     \li \c C - Clears the list of targets being monitored. No output will be returned for use of this command.
653     \li \c L - Outputs the current list of targets being monitored. All output will use RPL_MONLIST,
654                and the output will be terminated with RPL_ENDOFMONLIST.
655     \li \c S - Outputs for each target in the list being monitored, whether the client is online or offline.
656                All targets that are online will be sent using RPL_MONONLINE, all targets that are offline will
657                be sent using RPL_MONOFFLINE.
658 
659     \sa \ref ircv3
660  */
createMonitor(const QString & command,const QString & target)661 IrcCommand* IrcCommand::createMonitor(const QString& command, const QString& target)
662 {
663     return IrcCommandPrivate::createCommand(Monitor, QStringList() << command << target);
664 }
665 
666 /*!
667     \since 3.4
668 
669     Creates a new MONITOR command with type IrcCommand::Monitor and parameters \a command and \a targets.
670 
671     Available commands are:
672     \li \c + - Adds the given list of targets to the list of targets being monitored.
673     \li \c + - Removes the given list of targets from the list of targets being monitored.
674                No output will be returned for use of this command.
675     \li \c C - Clears the list of targets being monitored. No output will be returned for use of this command.
676     \li \c L - Outputs the current list of targets being monitored. All output will use RPL_MONLIST,
677                and the output will be terminated with RPL_ENDOFMONLIST.
678     \li \c S - Outputs for each target in the list being monitored, whether the client is online or offline.
679                All targets that are online will be sent using RPL_MONONLINE, all targets that are offline will
680                be sent using RPL_MONOFFLINE.
681 
682     \sa \ref ircv3
683  */
createMonitor(const QString & command,const QStringList & targets)684 IrcCommand* IrcCommand::createMonitor(const QString& command, const QStringList& targets)
685 {
686     return IrcCommandPrivate::createCommand(Monitor, QStringList() << command << targets.join(","));
687 }
688 
689 /*!
690     Creates a new MOTD command with type IrcCommand::Motd and optional parameter \a server.
691 
692     This command shows the message of the day on the specified \a server,
693     or the current server if not specified.
694  */
createMotd(const QString & server)695 IrcCommand* IrcCommand::createMotd(const QString& server)
696 {
697     return IrcCommandPrivate::createCommand(Motd, QStringList() << server);
698 }
699 
700 /*!
701     Creates a new NAMES command with type IrcCommand::Names and parameter \a channel.
702 
703     This command lists all users on the \a channel, optionally limiting to the given \a server.
704 
705     If \a channel is omitted, all users are shown, grouped by channel name with
706     all users who are not on a channel being shown as part of channel "*".
707     If \a server is specified, the command is sent to \a server for evaluation.
708 */
createNames(const QString & channel,const QString & server)709 IrcCommand* IrcCommand::createNames(const QString& channel, const QString& server)
710 {
711     return IrcCommandPrivate::createCommand(Names, QStringList() << channel << server);
712 }
713 
714 /*!
715     This overload is provided for convenience.
716  */
createNames(const QStringList & channels,const QString & server)717 IrcCommand* IrcCommand::createNames(const QStringList& channels, const QString& server)
718 {
719     return IrcCommandPrivate::createCommand(Names, QStringList() << channels.join(",") << server);
720 }
721 
722 /*!
723     Creates a new NICK command with type IrcCommand::Nick and parameter \a nick.
724 
725     This command allows a client to change their IRC nickname.
726  */
createNick(const QString & nick)727 IrcCommand* IrcCommand::createNick(const QString& nick)
728 {
729     return IrcCommandPrivate::createCommand(Nick, QStringList() << nick);
730 }
731 
732 /*!
733     Creates a new NOTICE command with type IrcCommand::Notice and parameters \a target and \a message.
734 
735     This command sends \a notice to \a target, which is usually a user or channel.
736 
737     \note The command works similarly to PRIVMSG, except automatic replies must never be sent in reply to NOTICE messages.
738  */
createNotice(const QString & target,const QString & message)739 IrcCommand* IrcCommand::createNotice(const QString& target, const QString& message)
740 {
741     return IrcCommandPrivate::createCommand(Notice, QStringList() << target << message);
742 }
743 
744 /*!
745     Creates a new PART command with type IrcCommand::Part and parameters \a channel and optional \a reason.
746 
747     This command causes the client to leave the specified channel.
748  */
createPart(const QString & channel,const QString & reason)749 IrcCommand* IrcCommand::createPart(const QString& channel, const QString& reason)
750 {
751     return IrcCommandPrivate::createCommand(Part, QStringList() << channel << reason);
752 }
753 
754 /*!
755     This overload is provided for convenience.
756  */
createPart(const QStringList & channels,const QString & reason)757 IrcCommand* IrcCommand::createPart(const QStringList& channels, const QString& reason)
758 {
759     return IrcCommandPrivate::createCommand(Part, QStringList() << channels.join(",") << reason);
760 }
761 
762 /*!
763     Creates a new PING command with type IrcCommand::Ping and \a argument.
764  */
createPing(const QString & argument)765 IrcCommand* IrcCommand::createPing(const QString& argument)
766 {
767     return IrcCommandPrivate::createCommand(Ping, QStringList() << argument);
768 }
769 
770 /*!
771     Creates a new PONG command with type IrcCommand::Pong and \a argument.
772  */
createPong(const QString & argument)773 IrcCommand* IrcCommand::createPong(const QString& argument)
774 {
775     return IrcCommandPrivate::createCommand(Pong, QStringList() << argument);
776 }
777 
778 /*!
779     Creates a new QUIT command with type IrcCommand::Quit and optional parameter \a reason.
780  */
createQuit(const QString & reason)781 IrcCommand* IrcCommand::createQuit(const QString& reason)
782 {
783     return IrcCommandPrivate::createCommand(Quit, QStringList() << reason);
784 }
785 
786 /*!
787     Creates a new QUOTE command with type IrcCommand::Quote and \a raw.
788  */
createQuote(const QString & raw)789 IrcCommand* IrcCommand::createQuote(const QString& raw)
790 {
791     return IrcCommandPrivate::createCommand(Quote, QStringList() << raw);
792 }
793 
794 /*!
795     Creates a new QUOTE command with type IrcCommand::Quote and \a parameters.
796  */
createQuote(const QStringList & parameters)797 IrcCommand* IrcCommand::createQuote(const QStringList& parameters)
798 {
799     return IrcCommandPrivate::createCommand(Quote, parameters);
800 }
801 
802 /*!
803     Creates a new STATS command with type IrcCommand::Stats and parameters \a query and optional \a server.
804 
805     This command queries statistics about the specified \a server,
806     or the current server if not specified.
807  */
createStats(const QString & query,const QString & server)808 IrcCommand* IrcCommand::createStats(const QString& query, const QString& server)
809 {
810     return IrcCommandPrivate::createCommand(Stats, QStringList() << query << server);
811 }
812 
813 /*!
814     Creates a new TIME command with type IrcCommand::Time and optional parameter \a server.
815 
816     This command queries local time of the specified \a server,
817     or the current server if not specified.
818  */
createTime(const QString & server)819 IrcCommand* IrcCommand::createTime(const QString& server)
820 {
821     return IrcCommandPrivate::createCommand(Time, QStringList() << server);
822 }
823 
824 /*!
825     Creates a new TOPIC command with type IrcCommand::Topic and parameters \a channel and optional \a topic.
826 
827     This command allows the client to query or set the channel topic on \a channel.
828     If \a topic is given, it sets the channel topic to \a topic.
829     If channel mode +t is set, only a channel operator may set the topic.
830  */
createTopic(const QString & channel,const QString & topic)831 IrcCommand* IrcCommand::createTopic(const QString& channel, const QString& topic)
832 {
833     return IrcCommandPrivate::createCommand(Topic, QStringList() << channel << topic);
834 }
835 
836 /*!
837     Creates a new TRACE command with type IrcCommand::Trace and optional parameter \a target.
838 
839     This command traces the connection path across the IRC network
840     to the current server or to a specific \a target (server or client)
841     in a similar method to traceroute.
842  */
createTrace(const QString & target)843 IrcCommand* IrcCommand::createTrace(const QString& target)
844 {
845     return IrcCommandPrivate::createCommand(Trace, QStringList() << target);
846 }
847 
848 /*!
849     Creates a new USERS command with type IrcCommand::Users and optional parameter \a server.
850 
851     This command queries the users of the specified \a server,
852     or the current server if not specified.
853  */
createUsers(const QString & server)854 IrcCommand* IrcCommand::createUsers(const QString& server)
855 {
856     return IrcCommandPrivate::createCommand(Users, QStringList() << server);
857 }
858 
859 /*!
860     Creates a new command with type IrcCommand::Version and optional parameter \a user.
861 
862     This command queries the version of the specified \a user's client (CTCP REQUEST VERSION),
863     or the current server (VERSION) if not specified.
864  */
createVersion(const QString & user)865 IrcCommand* IrcCommand::createVersion(const QString& user)
866 {
867     return IrcCommandPrivate::createCommand(Version, QStringList() << user);
868 }
869 
870 /*!
871     Creates a new WHO command with type IrcCommand::Who and parameters \a mask and optional \a operators.
872 
873     This command returns a list of users who match \a mask,
874     optionally matching only IRC \a operators.
875  */
createWho(const QString & mask,bool operators)876 IrcCommand* IrcCommand::createWho(const QString& mask, bool operators)
877 {
878     return IrcCommandPrivate::createCommand(Who, QStringList() << mask << (operators ? "o" : ""));
879 }
880 
881 /*!
882     Creates a new WHOIS command with type IrcCommand::Whois and parameter \a user.
883 
884     This command returns information about \a user.
885  */
createWhois(const QString & user)886 IrcCommand* IrcCommand::createWhois(const QString& user)
887 {
888     return IrcCommandPrivate::createCommand(Whois, QStringList() << user);
889 }
890 
891 /*!
892     Creates a new WHOWAS command with type IrcCommand::Whowas and parameters \a user and optional \a count.
893 
894     This command returns information about a \a user that is no longer online
895     (due to client disconnection, or nickname changes). If given, the server
896     will return information from the last \a count times the nickname has been used.
897  */
createWhowas(const QString & user,int count)898 IrcCommand* IrcCommand::createWhowas(const QString& user, int count)
899 {
900     return IrcCommandPrivate::createCommand(Whowas, QStringList() << user << QString::number(count));
901 }
902 
903 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug debug,IrcCommand::Type type)904 QDebug operator<<(QDebug debug, IrcCommand::Type type)
905 {
906     const int index = IrcCommand::staticMetaObject.indexOfEnumerator("Type");
907     QMetaEnum enumerator = IrcCommand::staticMetaObject.enumerator(index);
908     const char* key = enumerator.valueToKey(type);
909     debug << (key ? key : "Unknown");
910     return debug;
911 }
912 
operator <<(QDebug debug,const IrcCommand * command)913 QDebug operator<<(QDebug debug, const IrcCommand* command)
914 {
915     if (!command)
916         return debug << "IrcCommand(0x0) ";
917     debug.nospace() << command->metaObject()->className() << '(' << (void*) command;
918     if (!command->objectName().isEmpty())
919         debug.nospace() << ", name=" << qPrintable(command->objectName());
920     debug.nospace() << ", type=" << command->type();
921     QString str = command->toString();
922     if (!str.isEmpty())
923         debug.nospace() << ", " << str.left(20);
924     debug.nospace() << ')';
925     return debug.space();
926 }
927 #endif // QT_NO_DEBUG_STREAM
928 
929 #include "moc_irccommand.cpp"
930 
931 IRC_END_NAMESPACE
932