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 "ircmessage.h"
30 #include "ircmessage_p.h"
31 #include "ircconnection.h"
32 #include "ircconnection_p.h"
33 #include "ircmessagecomposer_p.h"
34 #include "ircnetwork_p.h"
35 #include "irccommand.h"
36 #include "irccore_p.h"
37 #include "irc.h"
38 #include <QMetaEnum>
39 #include <QVariant>
40 #include <QDebug>
41
42 IRC_BEGIN_NAMESPACE
43
44 /*!
45 \file ircmessage.h
46 \brief \#include <IrcMessage>
47 */
48
49 /*!
50 \class IrcMessage ircmessage.h <IrcMessage>
51 \ingroup core
52 \ingroup message
53 \brief The base class of all messages.
54
55 IRC messages are received from an IRC server. IrcConnection translates received
56 messages into IrcMessage instances and emits the IrcConnection::messageReceived()
57 signal upon message received.
58
59 Subclasses of IrcMessage contain specialized accessors for parameters that
60 are specific to the particular type of message. See IrcMessage::Type for
61 the list of supported message types.
62
63 \sa IrcConnection::messageReceived(), IrcMessage::Type
64 */
65
66 /*!
67 \enum IrcMessage::Type
68 This enum describes the supported message types.
69 */
70
71 /*!
72 \since 3.3
73 \var IrcMessage::Account
74 \brief An account notify message (IrcAccountMessage).
75 \sa \ref ircv3
76 */
77
78 /*!
79 \since 3.3
80 \var IrcMessage::Away
81 \brief An away message (IrcAwayMessage).
82 */
83
84 /*!
85 \since 3.5
86 \var IrcMessage::Batch
87 \brief A batch message (IrcBatchMessage).
88 \sa \ref ircv3
89 */
90
91 /*!
92 \var IrcMessage::Capability
93 \brief A capability message (IrcCapabilityMessage).
94 \sa \ref ircv3
95 */
96
97 /*!
98 \var IrcMessage::Error
99 \brief An error message (IrcErrorMessage).
100 */
101
102 /*!
103 \since 3.4
104 \var IrcMessage::HostChange
105 \brief A host change message (IrcHostChangeMessage).
106 */
107
108 /*!
109 \var IrcMessage::Invite
110 \brief An invite message (IrcInviteMessage).
111 */
112
113 /*!
114 \var IrcMessage::Join
115 \brief A join message (IrcJoinMessage).
116 */
117
118 /*!
119 \var IrcMessage::Kick
120 \brief A kick message (IrcKickMessage).
121 */
122
123 /*!
124 \var IrcMessage::Mode
125 \brief A mode message (IrcModeMessage).
126 */
127
128 /*!
129 \var IrcMessage::Motd
130 \brief A message of the day (IrcMotdMessage).
131 */
132
133 /*!
134 \var IrcMessage::Names
135 \brief A names message (IrcNamesMessage).
136 */
137
138 /*!
139 \var IrcMessage::Nick
140 \brief A nick message (IrcNickMessage).
141 */
142
143 /*!
144 \var IrcMessage::Notice
145 \brief A notice message (IrcNoticeMessage).
146 */
147
148 /*!
149 \var IrcMessage::Numeric
150 \brief A numeric message (IrcNumericMessage).
151 */
152
153 /*!
154 \var IrcMessage::Part
155 \brief A part message (IrcPartMessage).
156 */
157
158 /*!
159 \var IrcMessage::Ping
160 \brief A ping message (IrcPingMessage).
161 */
162
163 /*!
164 \var IrcMessage::Pong
165 \brief A pong message (IrcPongMessage).
166 */
167
168 /*!
169 \var IrcMessage::Private
170 \brief A private message (IrcPrivateMessage).
171 */
172
173 /*!
174 \var IrcMessage::Quit
175 \brief A quit message (IrcQuitMessage).
176 */
177
178 /*!
179 \var IrcMessage::Topic
180 \brief A topic message (IrcTopicMessage).
181 */
182
183 /*!
184 \var IrcMessage::Unknown
185 \brief An unknown message (IrcMessage).
186 */
187
188 /*!
189 \since 3.3
190 \var IrcMessage::Whois
191 \brief A whois reply message (IrcWhoisMessage).
192 */
193
194 /*!
195 \since 3.3
196 \var IrcMessage::Whowas
197 \brief A whowas reply message (IrcWhowasMessage).
198 */
199
200 /*!
201 \since 3.1
202 \var IrcMessage::WhoReply
203 \brief A who reply message (IrcWhoReplyMessage).
204 */
205
206 /*!
207 \enum IrcMessage::Flag
208 This enum describes the supported message flags.
209 */
210
211 /*!
212 \var IrcMessage::None
213 \brief The message has no flags.
214 */
215
216 /*!
217 \var IrcMessage::Own
218 \brief The message is user's own message.
219 */
220
221 /*!
222 \var IrcMessage::Identified
223 \brief The message is identified.
224 \deprecated Use IrcMessage::account instead.
225 */
226
227 /*!
228 \var IrcMessage::Unidentified
229 \brief The message is unidentified.
230 \deprecated Use IrcMessage::account instead.
231 */
232
233 /*!
234 \since 3.2
235 \var IrcMessage::Playback
236 \brief The message is playback.
237 */
238
239 /*!
240 \since 3.3
241 \var IrcMessage::Implicit
242 \brief The message is an implicit "reply" after joining a channel.
243 */
244
245 extern bool irc_is_supported_encoding(const QByteArray& encoding); // ircmessagedecoder.cpp
246
irc_create_message(const QString & command,IrcConnection * connection)247 static IrcMessage* irc_create_message(const QString& command, IrcConnection* connection)
248 {
249 typedef std::function<IrcMessage *(IrcConnection *)> IrcMessageFactory;
250
251 static const QHash<QString, IrcMessageFactory> factories = {
252 {"ACCOUNT", [](IrcConnection* c) { return new IrcAccountMessage(c); }},
253 {"AWAY", [](IrcConnection* c) { return new IrcAwayMessage(c); }},
254 {"BATCH", [](IrcConnection* c) { return new IrcBatchMessage(c); }},
255 {"CAP", [](IrcConnection* c) { return new IrcCapabilityMessage(c); }},
256 {"ERROR", [](IrcConnection* c) { return new IrcErrorMessage(c); }},
257 {"CHGHOST", [](IrcConnection* c) { return new IrcHostChangeMessage(c); }},
258 {"INVITE", [](IrcConnection* c) { return new IrcInviteMessage(c); }},
259 {"JOIN", [](IrcConnection* c) { return new IrcJoinMessage(c); }},
260 {"KICK", [](IrcConnection* c) { return new IrcKickMessage(c); }},
261 {"MODE", [](IrcConnection* c) { return new IrcModeMessage(c); }},
262 {"NICK", [](IrcConnection* c) { return new IrcNickMessage(c); }},
263 {"NOTICE", [](IrcConnection* c) { return new IrcNoticeMessage(c); }},
264 {"PART", [](IrcConnection* c) { return new IrcPartMessage(c); }},
265 {"PING", [](IrcConnection* c) { return new IrcPingMessage(c); }},
266 {"PONG", [](IrcConnection* c) { return new IrcPongMessage(c); }},
267 {"PRIVMSG", [](IrcConnection* c) { return new IrcPrivateMessage(c); }},
268 {"QUIT", [](IrcConnection* c) { return new IrcQuitMessage(c); }},
269 {"TOPIC", [](IrcConnection* c) { return new IrcTopicMessage(c); }},
270 };
271
272 IrcMessageFactory factory = factories.value(command);
273 if (factory)
274 return factory(connection);
275
276 bool isNumeric = false;
277 int number = command.toInt(&isNumeric);
278 if (isNumeric && number > 0)
279 return new IrcNumericMessage(connection);
280
281 return new IrcMessage(connection);
282 }
283
284 /*!
285 Constructs a new IrcMessage with \a connection.
286 */
IrcMessage(IrcConnection * connection)287 IrcMessage::IrcMessage(IrcConnection* connection) : QObject(connection), d_ptr(new IrcMessagePrivate)
288 {
289 Q_D(IrcMessage);
290 d->connection = connection;
291 }
292
293 /*!
294 Destructs the message.
295 */
~IrcMessage()296 IrcMessage::~IrcMessage()
297 {
298 }
299
300 /*!
301 This property holds the message connection.
302
303 \par Access function:
304 \li \ref IrcConnection* <b>connection</b>() const
305 */
connection() const306 IrcConnection* IrcMessage::connection() const
307 {
308 Q_D(const IrcMessage);
309 return d->connection;
310 }
311
312 /*!
313 This property holds the message network.
314
315 \par Access function:
316 \li \ref IrcNetwork* <b>network</b>() const
317 */
network() const318 IrcNetwork* IrcMessage::network() const
319 {
320 Q_D(const IrcMessage);
321 return d->connection ? d->connection->network() : nullptr;
322 }
323
324 /*!
325 This property holds the message type.
326
327 \par Access function:
328 \li \ref IrcMessage::Type <b>type</b>() const
329 */
type() const330 IrcMessage::Type IrcMessage::type() const
331 {
332 Q_D(const IrcMessage);
333 return d->type;
334 }
335
336 /*!
337 \since 3.2
338 \property bool IrcMessage::own
339
340 This property holds whether the message is user's own.
341
342 This property is provided for convenience. It is equivalent
343 of testing for the IrcMessage::Own flag.
344
345 \par Access function:
346 \li bool <b>isOwn</b>() const
347 */
isOwn() const348 bool IrcMessage::isOwn() const
349 {
350 return flags() & Own;
351 }
352
353 /*!
354 \since 3.5
355 \property bool IrcMessage::implicit
356
357 This property holds whether the message is an implicit "reply"
358 after joining a channel.
359
360 This property is provided for convenience. It is equivalent
361 of testing for the IrcMessage::Implicit flag.
362
363 \par Access function:
364 \li bool <b>isImplicit</b>() const
365 */
isImplicit() const366 bool IrcMessage::isImplicit() const
367 {
368 return flags() & Implicit;
369 }
370
371 /*!
372 This property holds the message flags.
373
374 \par Access function:
375 \li \ref IrcMessage::Flag "IrcMessage::Flags" <b>flags</b>() const
376 \li void <b>setFlags</b>(\ref IrcMessage::Flag "IrcMessage::Flags" flags) (\b Since 3.2)
377
378 \sa testFlag(), setFlag()
379 */
flags() const380 IrcMessage::Flags IrcMessage::flags() const
381 {
382 Q_D(const IrcMessage);
383 if (d->flags == -1) {
384 d->flags = IrcMessage::None;
385 if (d->connection && !d->prefix().isEmpty() && d->nick() == d->connection->nickName())
386 d->flags |= IrcMessage::Own;
387 }
388 return IrcMessage::Flags(d->flags);
389 }
390
setFlags(IrcMessage::Flags flags)391 void IrcMessage::setFlags(IrcMessage::Flags flags)
392 {
393 Q_D(IrcMessage);
394 d->flags = flags;
395 }
396
397 /*!
398 \since 3.5
399
400 Returns \c true if the \a flag is on; otherwise \c false.
401
402 \sa IrcMessage::flags
403 */
testFlag(Flag flag) const404 bool IrcMessage::testFlag(Flag flag) const
405 {
406 return flags().testFlag(flag);
407 }
408
409 /*!
410 \since 3.5
411
412 Sets whether the \a flag is \a on.
413
414 \sa IrcMessage::flags
415 */
setFlag(Flag flag,bool on)416 void IrcMessage::setFlag(Flag flag, bool on)
417 {
418 if (on)
419 setFlags(flags() | flag);
420 else
421 setFlags(flags() & ~flag);
422 }
423
424 /*!
425 This property holds the message command.
426
427 \par Access functions:
428 \li QString <b>command</b>() const
429 \li void <b>setCommand</b>(const QString& command)
430 */
command() const431 QString IrcMessage::command() const
432 {
433 Q_D(const IrcMessage);
434 return d->command();
435 }
436
setCommand(const QString & command)437 void IrcMessage::setCommand(const QString& command)
438 {
439 Q_D(IrcMessage);
440 d->setCommand(command);
441 }
442
443 /*!
444 This property holds the message sender prefix.
445
446 The prefix consists of \ref nick, \ref ident and \ref host as specified in RFC 1459:
447 <pre>
448 <prefix> ::= <\ref nick> [ '!' <\ref ident> ] [ '@' <\ref host> ]
449 </pre>
450
451 \par Access functions:
452 \li QString <b>prefix</b>() const
453 \li void <b>setPrefix</b>(const QString& prefix)
454 */
prefix() const455 QString IrcMessage::prefix() const
456 {
457 Q_D(const IrcMessage);
458 return d->prefix();
459 }
460
setPrefix(const QString & prefix)461 void IrcMessage::setPrefix(const QString& prefix)
462 {
463 Q_D(IrcMessage);
464 d->setPrefix(prefix);
465 }
466
467 /*!
468 This property holds the message sender nick.
469
470 Nick is part of the sender \ref prefix as specified in RFC 1459:
471 <pre>
472 <b><nick></b> [ '!' <\ref ident> ] [ '@' <\ref host> ]
473 </pre>
474
475 \par Access function:
476 \li QString <b>nick</b>() const
477 */
nick() const478 QString IrcMessage::nick() const
479 {
480 Q_D(const IrcMessage);
481 return d->nick();
482 }
483
484 /*!
485 This property holds the message sender ident.
486
487 Ident is part of the sender \ref prefix as specified in RFC 1459:
488 <pre>
489 <\ref nick> [ '!' <b><ident></b> ] [ '@' <\ref host> ]
490 </pre>
491
492 \par Access function:
493 \li QString <b>ident</b>() const
494 */
ident() const495 QString IrcMessage::ident() const
496 {
497 Q_D(const IrcMessage);
498 return d->ident();
499 }
500
501 /*!
502 This property holds the message sender host.
503
504 Host is part of the sender \ref prefix as specified in RFC 1459:
505 <pre>
506 <\ref nick> [ '!' <\ref ident> ] [ '@' <b><host></b> ]
507 </pre>
508
509 \par Access function:
510 \li QString <b>host</b>() const
511 */
host() const512 QString IrcMessage::host() const
513 {
514 Q_D(const IrcMessage);
515 return d->host();
516 }
517
518 /*!
519 \since 3.4
520
521 This property holds the services account of the message sender.
522
523 \note Only set if the \c account-tag capability is
524 enabled and the user has identified with services.
525
526 \par Access function:
527 \li QString <b>account</b>() const
528
529 \sa \ref ircv3
530 */
account() const531 QString IrcMessage::account() const
532 {
533 Q_D(const IrcMessage);
534 return d->tags().value(QLatin1String("account")).toString();
535 }
536
537 /*!
538 This property holds the message parameters.
539
540 \par Access functions:
541 \li QStringList <b>parameters</b>() const
542 \li void <b>setParameters</b>(const QStringList& parameters)
543 */
parameters() const544 QStringList IrcMessage::parameters() const
545 {
546 Q_D(const IrcMessage);
547 return d->params();
548 }
549
setParameters(const QStringList & parameters)550 void IrcMessage::setParameters(const QStringList& parameters)
551 {
552 Q_D(IrcMessage);
553 d->setParams(parameters);
554 }
555
556 /*!
557 \since 3.5
558
559 Returns the parameter at the specified \a index.
560 */
parameter(int index) const561 QString IrcMessage::parameter(int index) const
562 {
563 Q_D(const IrcMessage);
564 return d->param(index);
565 }
566
567 /*!
568 \since 3.5
569
570 Sets the \a parameter at the specified \a index.
571 */
setParameter(int index,const QString & parameter)572 void IrcMessage::setParameter(int index, const QString& parameter)
573 {
574 Q_D(IrcMessage);
575 QStringList params = d->params();
576 while (index >= params.count())
577 params.append(QString());
578 params[index] = parameter;
579 d->setParams(params);
580 }
581
582 /*!
583 This property holds the message time stamp.
584
585 \note When the \c server-time capability is enabled, the time
586 stamp is automatically set from the \c time message tag.
587
588 \par Access functions:
589 \li QDateTime <b>timeStamp</b>() const
590 \li void <b>setTimeStamp</b>(const QDateTime& timeStamp)
591
592 \sa \ref ircv3
593 */
timeStamp() const594 QDateTime IrcMessage::timeStamp() const
595 {
596 Q_D(const IrcMessage);
597 return d->timeStamp;
598 }
599
setTimeStamp(const QDateTime & timeStamp)600 void IrcMessage::setTimeStamp(const QDateTime& timeStamp)
601 {
602 Q_D(IrcMessage);
603 d->timeStamp = timeStamp;
604 }
605
606 /*!
607 This property holds the FALLBACK encoding for the message.
608
609 The fallback encoding is used when the message is detected not
610 to be valid UTF-8 and the consequent auto-detection of message
611 encoding fails. See QTextCodec::availableCodes() for the list of
612 supported encodings.
613
614 The default value is ISO-8859-15.
615
616 \par Access functions:
617 \li QByteArray <b>encoding</b>() const
618 \li void <b>setEncoding</b>(const QByteArray& encoding)
619
620 \sa QTextCodec::availableCodecs(), QTextCodec::codecForLocale()
621 */
encoding() const622 QByteArray IrcMessage::encoding() const
623 {
624 Q_D(const IrcMessage);
625 return d->encoding;
626 }
627
setEncoding(const QByteArray & encoding)628 void IrcMessage::setEncoding(const QByteArray& encoding)
629 {
630 Q_D(IrcMessage);
631 if (!irc_is_supported_encoding(encoding)) {
632 qWarning() << "IrcMessage::setEncoding(): unsupported encoding" << encoding;
633 return;
634 }
635 d->encoding = encoding;
636 d->invalidate();
637 }
638
639 /*!
640 \since 3.1
641
642 This property holds the message tags.
643
644 \par Access functions:
645 \li QVariantMap <b>tags</b>() const
646 \li void <b>setTags</b>(const QVariantMap& tags)
647
648 \sa \ref ircv3
649 */
tags() const650 QVariantMap IrcMessage::tags() const
651 {
652 Q_D(const IrcMessage);
653 return d->tags();
654 }
655
setTags(const QVariantMap & tags)656 void IrcMessage::setTags(const QVariantMap& tags)
657 {
658 Q_D(IrcMessage);
659 d->setTags(tags);
660 }
661
662 /*!
663 \since 3.5
664
665 Returns the value of the specified tag.
666
667 \sa \ref ircv3
668 */
tag(const QString & name) const669 QVariant IrcMessage::tag(const QString& name) const
670 {
671 Q_D(const IrcMessage);
672 return d->tags().value(name);
673 }
674
675 /*!
676 \since 3.5
677
678 Sets the value of the specified tag.
679
680 \sa \ref ircv3
681 */
setTag(const QString & name,const QVariant & value)682 void IrcMessage::setTag(const QString& name, const QVariant& value)
683 {
684 Q_D(IrcMessage);
685 QVariantMap tags = d->tags();
686 tags.insert(name, value);
687 d->setTags(tags);
688 }
689
690 /*!
691 Creates a new message from \a data and \a connection.
692 */
fromData(const QByteArray & data,IrcConnection * connection)693 IrcMessage* IrcMessage::fromData(const QByteArray& data, IrcConnection* connection)
694 {
695 IrcMessageData md = IrcMessageData::fromData(data);
696 IrcMessage* message = irc_create_message(md.command, connection);
697 Q_ASSERT(message);
698 message->d_ptr->data = md;
699 QByteArray tag = md.tags.value("time");
700 if (!tag.isEmpty()) {
701 QDateTime ts = QDateTime::fromString(QString::fromUtf8(tag), Qt::ISODate);
702 if (ts.isValid())
703 message->d_ptr->timeStamp = ts.toTimeSpec(Qt::LocalTime);
704 }
705 return message;
706 }
707
708 /*!
709 Creates a new message from \a prefix, \a command and \a parameters with \a connection.
710 */
fromParameters(const QString & prefix,const QString & command,const QStringList & parameters,IrcConnection * connection)711 IrcMessage* IrcMessage::fromParameters(const QString& prefix, const QString& command, const QStringList& parameters, IrcConnection* connection)
712 {
713 IrcMessage* message = irc_create_message(command, connection);
714 Q_ASSERT(message);
715 message->setPrefix(prefix);
716 message->setCommand(command);
717 message->setParameters(parameters);
718 return message;
719 }
720
721 /*!
722 \since 3.5
723
724 Clones the message.
725 */
clone(QObject * parent) const726 IrcMessage* IrcMessage::clone(QObject* parent) const
727 {
728 Q_D(const IrcMessage);
729 IrcMessage* msg = irc_create_message(d->command(), d->connection);
730 if (msg) {
731 msg->setParent(parent);
732 IrcMessagePrivate* p = IrcMessagePrivate::get(msg);
733 p->timeStamp = d->timeStamp;
734 p->encoding = d->encoding;
735 p->flags = d->flags;
736 p->data = d->data;
737 foreach (IrcMessage* bm, d->batch)
738 p->batch += bm->clone(msg);
739 p->m_nick = d->m_nick;
740 p->m_ident = d->m_ident;
741 p->m_host = d->m_host;
742 p->m_prefix = d->m_prefix;
743 p->m_command = d->m_command;
744 p->m_params = d->m_params;
745 p->m_tags = d->m_tags;
746 }
747 return msg;
748 }
749
750 /*!
751 \property bool IrcMessage::valid
752 This property is \c true if the message is valid; otherwise \c false.
753
754 A message is considered valid if the prefix is not empty
755 and the parameters match the message.
756
757 \par Access function:
758 \li bool <b>isValid</b>() const
759 */
isValid() const760 bool IrcMessage::isValid() const
761 {
762 Q_D(const IrcMessage);
763 return d->connection && !prefix().isNull();
764 }
765
766 /*!
767 Returns the message as received from an IRC server.
768 */
toData() const769 QByteArray IrcMessage::toData() const
770 {
771 Q_D(const IrcMessage);
772 return d->content();
773 }
774
775 /*!
776 \since 3.3
777 \class IrcAwayMessage ircmessage.h <IrcMessage>
778 \ingroup message
779 \brief Represents an away message.
780 */
781
782 /*!
783 Constructs a new IrcAwayMessage with \a connection.
784 */
IrcAwayMessage(IrcConnection * connection)785 IrcAwayMessage::IrcAwayMessage(IrcConnection* connection) : IrcMessage(connection)
786 {
787 Q_D(IrcMessage);
788 d->type = Away;
789 }
790
791 /*!
792 This property holds the message content.
793
794 \par Access function:
795 \li QString <b>content</b>() const
796 */
content() const797 QString IrcAwayMessage::content() const
798 {
799 Q_D(const IrcMessage);
800 return d->param(0);
801 }
802
803 /*!
804 \property bool IrcAwayMessage::reply
805 This property holds whether the message is a reply.
806
807 Away messages are sent in three situations:
808 \li as a reply when sending a message (\c true),
809 \li as a reply when setting away status (\c true),
810 \li as an away notification when the \c away-notify capability is enabled (\c false).
811
812 \par Access function:
813 \li bool <b>isReply</b>() const
814
815 \sa Irc::RPL_AWAY, Irc::RPL_NOWAWAY, Irc::RPL_UNAWAY, \ref ircv3
816 */
isReply() const817 bool IrcAwayMessage::isReply() const
818 {
819 Q_D(const IrcMessage);
820 return d->command().toInt() != 0;
821 }
822
823 /*!
824 \property bool IrcAwayMessage::away
825 This property holds whether the user is away or back.
826
827 \par Access function:
828 \li bool <b>isAway</b>() const
829 */
isAway() const830 bool IrcAwayMessage::isAway() const
831 {
832 Q_D(const IrcMessage);
833 int rpl = d->command().toInt();
834 return rpl == Irc::RPL_AWAY || rpl == Irc::RPL_NOWAWAY
835 || (d->command() == "AWAY" && !d->param(0).isEmpty());
836 }
837
isValid() const838 bool IrcAwayMessage::isValid() const
839 {
840 return IrcMessage::isValid();
841 }
842
843 /*!
844 \since 3.3
845 \class IrcAccountMessage ircmessage.h <IrcMessage>
846 \ingroup message
847 \brief Represents an account notify message.
848 \sa \ref ircv3
849 */
850
851 /*!
852 Constructs a new IrcAccountMessage with \a connection.
853 */
IrcAccountMessage(IrcConnection * connection)854 IrcAccountMessage::IrcAccountMessage(IrcConnection* connection) : IrcMessage(connection)
855 {
856 Q_D(IrcMessage);
857 d->type = Account;
858 }
859
860 /*!
861 This property holds the account name.
862
863 \note The account name is empty if the user has logged out.
864
865 \par Access function:
866 \li QString <b>account</b>() const
867 */
account() const868 QString IrcAccountMessage::account() const
869 {
870 Q_D(const IrcMessage);
871 const QString p = d->param(0);
872 if (p != QLatin1String("*"))
873 return p;
874 return QString();
875 }
876
isValid() const877 bool IrcAccountMessage::isValid() const
878 {
879 Q_D(const IrcMessage);
880 return IrcMessage::isValid() && !d->param(0).isEmpty();
881 }
882
883 /*!
884 \since 3.5
885 \class IrcBatchMessage ircmessage.h <IrcMessage>
886 \ingroup message
887 \brief Represents a batch message.
888 \sa \ref ircv3
889 */
890
891 /*!
892 Constructs a new IrcBatchMessage with \a connection.
893 */
IrcBatchMessage(IrcConnection * connection)894 IrcBatchMessage::IrcBatchMessage(IrcConnection* connection) : IrcMessage(connection)
895 {
896 Q_D(IrcMessage);
897 d->type = Batch;
898 }
899
900 /*!
901 This property holds the batch tag.
902
903 \par Access function:
904 \li QString <b>tag</b>() const
905 */
tag() const906 QString IrcBatchMessage::tag() const
907 {
908 Q_D(const IrcMessage);
909 return d->param(0).mid(1);
910 }
911
912 /*!
913 This property holds the batch type.
914
915 \par Access function:
916 \li QString <b>type</b>() const
917 */
batch() const918 QString IrcBatchMessage::batch() const
919 {
920 Q_D(const IrcMessage);
921 return d->param(1);
922 }
923
924 /*!
925 This property holds the list of batched messages.
926
927 \par Access function:
928 \li QList<IrcMessage*> <b>messages</b>() const
929 */
messages() const930 QList<IrcMessage*> IrcBatchMessage::messages() const
931 {
932 Q_D(const IrcMessage);
933 return d->batch;
934 }
935
isValid() const936 bool IrcBatchMessage::isValid() const
937 {
938 return IrcMessage::isValid() && !batch().isEmpty();
939 }
940
941 /*!
942 \class IrcCapabilityMessage ircmessage.h <IrcMessage>
943 \ingroup message
944 \brief Represents a capability message.
945 \sa \ref ircv3
946 */
947
948 /*!
949 Constructs a new IrcCapabilityMessage with \a connection.
950 */
IrcCapabilityMessage(IrcConnection * connection)951 IrcCapabilityMessage::IrcCapabilityMessage(IrcConnection* connection) : IrcMessage(connection)
952 {
953 Q_D(IrcMessage);
954 d->type = Capability;
955 }
956
957 /*!
958 This property holds the subcommand.
959
960 The following capability subcommands are defined:
961 LS, LIST, REQ, ACK, NAK, CLEAR, END, NEW, DEL.
962
963 \par Access function:
964 \li QString <b>subCommand</b>() const
965 */
subCommand() const966 QString IrcCapabilityMessage::subCommand() const
967 {
968 Q_D(const IrcMessage);
969 return d->param(1);
970 }
971
972 /*!
973 This property holds the capabilities.
974
975 A list of capabilities may exist for the following
976 subcommands: LS, LIST, REQ, ACK, NAK, NEW, DEL.
977
978 \par Access function:
979 \li QStringList <b>capabilities</b>() const
980 */
capabilities() const981 QStringList IrcCapabilityMessage::capabilities() const
982 {
983 Q_D(const IrcMessage);
984 QStringList caps;
985 QStringList params = d->params();
986 if (params.count() > 2)
987 caps = params.last().split(QLatin1Char(' '), Qt::SkipEmptyParts);
988 return caps;
989 }
990
isValid() const991 bool IrcCapabilityMessage::isValid() const
992 {
993 return IrcMessage::isValid();
994 }
995
996 /*!
997 \class IrcErrorMessage ircmessage.h <IrcMessage>
998 \ingroup message
999 \brief Represents an error message.
1000 */
1001
1002 /*!
1003 Constructs a new IrcErrorMessage with \a connection.
1004 */
IrcErrorMessage(IrcConnection * connection)1005 IrcErrorMessage::IrcErrorMessage(IrcConnection* connection) : IrcMessage(connection)
1006 {
1007 Q_D(IrcMessage);
1008 d->type = Error;
1009 }
1010
1011 /*!
1012 This property holds the error.
1013
1014 \par Access function:
1015 \li QString <b>error</b>() const
1016 */
error() const1017 QString IrcErrorMessage::error() const
1018 {
1019 Q_D(const IrcMessage);
1020 return d->param(0);
1021 }
1022
isValid() const1023 bool IrcErrorMessage::isValid() const
1024 {
1025 return IrcMessage::isValid() && !error().isEmpty();
1026 }
1027
1028 /*!
1029 \since 3.4
1030 \class IrcHostChangeMessage ircmessage.h <IrcMessage>
1031 \ingroup message
1032 \brief Represents a host change message.
1033
1034 \sa \ref ircv3
1035 */
1036
1037 /*!
1038 Constructs a new IrcHostChangeMessage with \a connection.
1039 */
IrcHostChangeMessage(IrcConnection * connection)1040 IrcHostChangeMessage::IrcHostChangeMessage(IrcConnection* connection) : IrcMessage(connection)
1041 {
1042 Q_D(IrcMessage);
1043 d->type = HostChange;
1044 }
1045
1046 /*!
1047 This property holds the user name.
1048
1049 \par Access function:
1050 \li QString <b>user</b>() const
1051 */
user() const1052 QString IrcHostChangeMessage::user() const
1053 {
1054 Q_D(const IrcMessage);
1055 return d->param(0);
1056 }
1057
1058 /*!
1059 This property holds the new host.
1060
1061 \par Access function:
1062 \li QString <b>host</b>() const
1063 */
host() const1064 QString IrcHostChangeMessage::host() const
1065 {
1066 Q_D(const IrcMessage);
1067 return d->param(1);
1068 }
1069
isValid() const1070 bool IrcHostChangeMessage::isValid() const
1071 {
1072 return IrcMessage::isValid() && !user().isEmpty() && !host().isEmpty();
1073 }
1074
1075 /*!
1076 \class IrcInviteMessage ircmessage.h <IrcMessage>
1077 \ingroup message
1078 \brief Represents an invite message.
1079 */
1080
1081 /*!
1082 Constructs a new IrcInviteMessage with \a connection.
1083 */
IrcInviteMessage(IrcConnection * connection)1084 IrcInviteMessage::IrcInviteMessage(IrcConnection* connection) : IrcMessage(connection)
1085 {
1086 Q_D(IrcMessage);
1087 d->type = Invite;
1088 }
1089
1090 /*!
1091 This property holds the user in question.
1092
1093 \par Access function:
1094 \li QString <b>user</b>() const
1095
1096 \sa \ref ircv3
1097 */
user() const1098 QString IrcInviteMessage::user() const
1099 {
1100 Q_D(const IrcMessage);
1101 return d->param(0);
1102 }
1103
1104 /*!
1105 This property holds the channel in question.
1106
1107 \par Access function:
1108 \li QString <b>channel</b>() const
1109 */
channel() const1110 QString IrcInviteMessage::channel() const
1111 {
1112 Q_D(const IrcMessage);
1113 return d->param(1);
1114 }
1115
1116 /*!
1117 \property bool IrcInviteMessage::reply
1118 This property holds whether the message is a reply.
1119
1120 Invite messages are sent in three situations:
1121 \li as a notification of a received invitation (\c false),
1122 \li as a reply when sending an invitation (\c true), or
1123 \li as an invite notification when the \c invite-notify capability is enabled (\c false).
1124
1125 \par Access function:
1126 \li bool <b>isReply</b>() const
1127
1128 \sa Irc::RPL_INVITING, Irc::RPL_INVITED, IrcInviteCommand, \ref ircv3
1129 */
isReply() const1130 bool IrcInviteMessage::isReply() const
1131 {
1132 Q_D(const IrcMessage);
1133 int rpl = d->command().toInt();
1134 return rpl == Irc::RPL_INVITING || rpl == Irc::RPL_INVITED;
1135 }
1136
isValid() const1137 bool IrcInviteMessage::isValid() const
1138 {
1139 return IrcMessage::isValid() && !user().isEmpty() && !channel().isEmpty();
1140 }
1141
1142 /*!
1143 \class IrcJoinMessage ircmessage.h <IrcMessage>
1144 \ingroup message
1145 \brief Represents a join message.
1146 */
1147
1148 /*!
1149 Constructs a new IrcJoinMessage with \a connection.
1150 */
IrcJoinMessage(IrcConnection * connection)1151 IrcJoinMessage::IrcJoinMessage(IrcConnection* connection) : IrcMessage(connection)
1152 {
1153 Q_D(IrcMessage);
1154 d->type = Join;
1155 }
1156
1157 /*!
1158 This property holds the channel in question.
1159
1160 \par Access function:
1161 \li QString <b>channel</b>() const
1162 */
channel() const1163 QString IrcJoinMessage::channel() const
1164 {
1165 Q_D(const IrcMessage);
1166 return d->param(0);
1167 }
1168
1169 /*!
1170 \since 3.3
1171
1172 This property holds the account name of the user.
1173
1174 \note Only set if the \c extended-join capability is
1175 enabled and the user has identified with services.
1176
1177 \par Access function:
1178 \li QString <b>account</b>() const
1179
1180 \sa \ref ircv3
1181 */
account() const1182 QString IrcJoinMessage::account() const
1183 {
1184 Q_D(const IrcMessage);
1185 const QString p = d->param(1);
1186 if (p != QLatin1String("*"))
1187 return p;
1188 return QString();
1189 }
1190
1191 /*!
1192 \since 3.3
1193
1194 This property holds the real name of the user.
1195
1196 \note Only set if the \c extended-join capability is enabled.
1197
1198 \par Access function:
1199 \li QString <b>realName</b>() const
1200
1201 \sa \ref ircv3
1202 */
realName() const1203 QString IrcJoinMessage::realName() const
1204 {
1205 Q_D(const IrcMessage);
1206 return d->param(2);
1207 }
1208
isValid() const1209 bool IrcJoinMessage::isValid() const
1210 {
1211 return IrcMessage::isValid() && !channel().isEmpty();
1212 }
1213
1214 /*!
1215 \class IrcKickMessage ircmessage.h <IrcMessage>
1216 \ingroup message
1217 \brief Represents a kick message.
1218 */
1219
1220 /*!
1221 Constructs a new IrcKickMessage with \a connection.
1222 */
IrcKickMessage(IrcConnection * connection)1223 IrcKickMessage::IrcKickMessage(IrcConnection* connection) : IrcMessage(connection)
1224 {
1225 Q_D(IrcMessage);
1226 d->type = Kick;
1227 }
1228
1229 /*!
1230 This property holds the channel in question.
1231
1232 \par Access function:
1233 \li QString <b>channel</b>() const
1234 */
channel() const1235 QString IrcKickMessage::channel() const
1236 {
1237 Q_D(const IrcMessage);
1238 return d->param(0);
1239 }
1240
1241 /*!
1242 This property holds the user in question.
1243
1244 \par Access function:
1245 \li QString <b>user</b>() const
1246 */
user() const1247 QString IrcKickMessage::user() const
1248 {
1249 Q_D(const IrcMessage);
1250 return d->param(1);
1251 }
1252
1253 /*!
1254 This property holds the optional kick reason.
1255
1256 \par Access function:
1257 \li QString <b>reason</b>() const
1258 */
reason() const1259 QString IrcKickMessage::reason() const
1260 {
1261 Q_D(const IrcMessage);
1262 return d->param(2);
1263 }
1264
isValid() const1265 bool IrcKickMessage::isValid() const
1266 {
1267 return IrcMessage::isValid() && !channel().isEmpty() && !user().isEmpty();
1268 }
1269
1270 /*!
1271 \class IrcModeMessage ircmessage.h <IrcMessage>
1272 \ingroup message
1273 \brief Represents a mode message.
1274 */
1275
1276 /*!
1277 \enum IrcModeMessage::Kind
1278 This enum describes the kind of modes.
1279 */
1280
1281 /*!
1282 \var IrcModeMessage::Channel
1283 \brief Channel mode
1284 */
1285
1286 /*!
1287 \var IrcModeMessage::User
1288 \brief User mode
1289 */
1290
1291 /*!
1292 Constructs a new IrcModeMessage with \a connection.
1293 */
IrcModeMessage(IrcConnection * connection)1294 IrcModeMessage::IrcModeMessage(IrcConnection* connection) : IrcMessage(connection)
1295 {
1296 Q_D(IrcMessage);
1297 d->type = Mode;
1298 }
1299
1300 /*!
1301 This property holds the target channel or user in question.
1302
1303 \par Access function:
1304 \li QString <b>target</b>() const
1305 */
target() const1306 QString IrcModeMessage::target() const
1307 {
1308 Q_D(const IrcMessage);
1309 return d->param(0);
1310 }
1311
1312 /*!
1313 This property holds the channel or user mode.
1314
1315 \par Access function:
1316 \li QString <b>mode</b>() const
1317 */
mode() const1318 QString IrcModeMessage::mode() const
1319 {
1320 Q_D(const IrcMessage);
1321 return d->param(1);
1322 }
1323
1324 /*!
1325 This property holds the first mode argument.
1326
1327 \par Access function:
1328 \li QString <b>argument</b>() const
1329 */
argument() const1330 QString IrcModeMessage::argument() const
1331 {
1332 Q_D(const IrcMessage);
1333 return d->param(2);
1334 }
1335
1336 /*!
1337 \since 3.1
1338
1339 This property holds the all mode arguments.
1340
1341 \par Access function:
1342 \li QStringList <b>arguments</b>() const
1343 */
arguments() const1344 QStringList IrcModeMessage::arguments() const
1345 {
1346 Q_D(const IrcMessage);
1347 return d->params().mid(2);
1348 }
1349
1350 /*!
1351 \property bool IrcModeMessage::reply
1352 This property holds whether the message is a reply.
1353
1354 Mode messages are sent when a mode changes (\c false)
1355 and when joining a channel (\c true).
1356
1357 \par Access function:
1358 \li bool <b>isReply</b>() const
1359
1360 \sa Irc::RPL_CHANNELMODEIS
1361 */
isReply() const1362 bool IrcModeMessage::isReply() const
1363 {
1364 Q_D(const IrcMessage);
1365 int rpl = d->command().toInt();
1366 return rpl == Irc::RPL_CHANNELMODEIS;
1367 }
1368
1369 /*!
1370 This property holds the kind of the mode.
1371
1372 \par Access function:
1373 \li Kind <b>kind</b>() const
1374 */
kind() const1375 IrcModeMessage::Kind IrcModeMessage::kind() const
1376 {
1377 const QString m = mode().remove(QLatin1Char('+')).remove(QLatin1Char('-'));
1378 if (!m.isEmpty()) {
1379 QStringList channelModes;
1380 if (const IrcNetwork* net = network())
1381 channelModes = net->channelModes(IrcNetwork::AllTypes);
1382 if (!channelModes.isEmpty()) {
1383 for (int i = 0; i < m.length(); ++i) {
1384 if (!channelModes.contains(m.at(i)))
1385 return User;
1386 }
1387 }
1388 }
1389 return Channel;
1390 }
1391
isValid() const1392 bool IrcModeMessage::isValid() const
1393 {
1394 return IrcMessage::isValid() && !target().isEmpty() && !mode().isEmpty();
1395 }
1396
1397 /*!
1398 \class IrcMotdMessage ircmessage.h <IrcMessage>
1399 \ingroup message
1400 \brief Represents a message of the day.
1401 */
1402
1403 /*!
1404 Constructs a new IrcMotdMessage with \a connection.
1405 */
IrcMotdMessage(IrcConnection * connection)1406 IrcMotdMessage::IrcMotdMessage(IrcConnection* connection) : IrcMessage(connection)
1407 {
1408 Q_D(IrcMessage);
1409 d->type = Motd;
1410 setCommand(QLatin1String("MOTD"));
1411 }
1412
1413 /*!
1414 This property holds the message of the day lines.
1415
1416 \par Access function:
1417 \li QStringList <b>lines</b>() const
1418 */
lines() const1419 QStringList IrcMotdMessage::lines() const
1420 {
1421 Q_D(const IrcMessage);
1422 return d->params().mid(1);
1423 }
1424
isValid() const1425 bool IrcMotdMessage::isValid() const
1426 {
1427 Q_D(const IrcMessage);
1428 return IrcMessage::isValid() && !d->params().isEmpty();
1429 }
1430
1431 /*!
1432 \class IrcNamesMessage ircmessage.h <IrcMessage>
1433 \ingroup message
1434 \brief Represents a names list message.
1435 */
1436
1437 /*!
1438 Constructs a new IrcNamesMessage with \a connection.
1439 */
IrcNamesMessage(IrcConnection * connection)1440 IrcNamesMessage::IrcNamesMessage(IrcConnection* connection) : IrcMessage(connection)
1441 {
1442 Q_D(IrcMessage);
1443 d->type = Names;
1444 setCommand(QLatin1String("NAMES"));
1445 }
1446
1447 /*!
1448 This property holds the channel.
1449
1450 \par Access function:
1451 \li QString <b>channel</b>() const
1452 */
channel() const1453 QString IrcNamesMessage::channel() const
1454 {
1455 Q_D(const IrcMessage);
1456 return d->param(0);
1457 }
1458
1459 /*!
1460 This property holds the list of names.
1461
1462 \par Access function:
1463 \li QStringList <b>names</b>() const
1464 */
names() const1465 QStringList IrcNamesMessage::names() const
1466 {
1467 Q_D(const IrcMessage);
1468 return d->params().mid(1);
1469 }
1470
isValid() const1471 bool IrcNamesMessage::isValid() const
1472 {
1473 Q_D(const IrcMessage);
1474 return IrcMessage::isValid() && !d->params().isEmpty();
1475 }
1476
1477 /*!
1478 \class IrcNickMessage ircmessage.h <IrcMessage>
1479 \ingroup message
1480 \brief Represents a nick message.
1481 */
1482
1483 /*!
1484 Constructs a new IrcNickMessage with \a connection.
1485 */
IrcNickMessage(IrcConnection * connection)1486 IrcNickMessage::IrcNickMessage(IrcConnection* connection) : IrcMessage(connection)
1487 {
1488 Q_D(IrcMessage);
1489 d->type = Nick;
1490 }
1491
1492 /*!
1493 This property holds the old nick.
1494
1495 This property is provided for symmetry with \ref newNick
1496 and is equal to \ref nick.
1497
1498 \par Access function:
1499 \li QString <b>oldNick</b>() const
1500 */
oldNick() const1501 QString IrcNickMessage::oldNick() const
1502 {
1503 Q_D(const IrcMessage);
1504 return d->nick();
1505 }
1506
1507 /*!
1508 This property holds the new nick.
1509
1510 \par Access function:
1511 \li QString <b>newNick</b>() const
1512 */
newNick() const1513 QString IrcNickMessage::newNick() const
1514 {
1515 Q_D(const IrcMessage);
1516 return d->param(0);
1517 }
1518
isValid() const1519 bool IrcNickMessage::isValid() const
1520 {
1521 return IrcMessage::isValid() && !newNick().isEmpty();
1522 }
1523
1524 /*!
1525 \class IrcNoticeMessage ircmessage.h <IrcMessage>
1526 \ingroup message
1527 \brief Represents a notice message.
1528 */
1529
1530 /*!
1531 Constructs a new IrcNoticeMessage with \a connection.
1532 */
IrcNoticeMessage(IrcConnection * connection)1533 IrcNoticeMessage::IrcNoticeMessage(IrcConnection* connection) : IrcMessage(connection)
1534 {
1535 Q_D(IrcMessage);
1536 d->type = Notice;
1537 }
1538
1539 /*!
1540 This property holds the target channel or user in question.
1541
1542 \par Access function:
1543 \li QString <b>target</b>() const
1544 */
target() const1545 QString IrcNoticeMessage::target() const
1546 {
1547 Q_D(const IrcMessage);
1548 if (d->connection) {
1549 const IrcNetwork* network = d->connection->network();
1550 return IrcNetworkPrivate::removePrefix(d->param(0), network->statusPrefixes());
1551 }
1552 return d->param(0);
1553 }
1554
1555 /*!
1556 This property holds the message content.
1557
1558 \par Access function:
1559 \li QString <b>content</b>() const
1560 */
content() const1561 QString IrcNoticeMessage::content() const
1562 {
1563 Q_D(const IrcMessage);
1564 QString msg = d->param(1);
1565 if (isReply()) {
1566 msg.remove(0, 1);
1567 msg.chop(1);
1568 }
1569 return msg;
1570 }
1571
1572 /*!
1573 \since 3.4
1574
1575 This property holds the status prefix of the message.
1576
1577 \par Access function:
1578 \li QString <b>statusPrefix</b>() const
1579 */
statusPrefix() const1580 QString IrcNoticeMessage::statusPrefix() const
1581 {
1582 Q_D(const IrcMessage);
1583 if (d->connection) {
1584 const IrcNetwork* network = d->connection->network();
1585 return IrcNetworkPrivate::getPrefix(d->param(0), network->statusPrefixes());
1586 }
1587 return QString();
1588 }
1589
1590 /*!
1591 \property bool IrcNoticeMessage::private
1592 This property is \c true if the notice is private,
1593 or \c false if it is a channel notice.
1594
1595 \par Access function:
1596 \li bool <b>isPrivate</b>() const
1597 */
isPrivate() const1598 bool IrcNoticeMessage::isPrivate() const
1599 {
1600 Q_D(const IrcMessage);
1601 if (d->connection)
1602 return !target().compare(d->connection->nickName(), Qt::CaseInsensitive);
1603 return false;
1604 }
1605
1606 /*!
1607 \property bool IrcNoticeMessage::reply
1608 This property is \c true if the message is a reply; otherwise \c false.
1609
1610 \par Access function:
1611 \li bool <b>isReply</b>() const
1612 */
isReply() const1613 bool IrcNoticeMessage::isReply() const
1614 {
1615 Q_D(const IrcMessage);
1616 QString msg = d->param(1);
1617 return msg.startsWith('\1') && msg.endsWith('\1');
1618 }
1619
isValid() const1620 bool IrcNoticeMessage::isValid() const
1621 {
1622 return IrcMessage::isValid() && !target().isEmpty() && !content().isEmpty();
1623 }
1624
1625 /*!
1626 \class IrcNumericMessage ircmessage.h <IrcMessage>
1627 \ingroup message
1628 \brief Represents a numeric message.
1629 */
1630
1631 /*!
1632 Constructs a new IrcNumericMessage with \a connection.
1633 */
IrcNumericMessage(IrcConnection * connection)1634 IrcNumericMessage::IrcNumericMessage(IrcConnection* connection) : IrcMessage(connection)
1635 {
1636 Q_D(IrcMessage);
1637 d->type = Numeric;
1638 }
1639
1640 /*!
1641 This property holds the numeric code.
1642
1643 \par Access function:
1644 \li int <b>code</b>() const
1645 */
code() const1646 int IrcNumericMessage::code() const
1647 {
1648 Q_D(const IrcMessage);
1649 bool ok = false;
1650 int number = d->command().toInt(&ok);
1651 return ok ? number : -1;
1652 }
1653
1654 /*!
1655 \since 3.3
1656 \property bool IrcNumericMessage::composed
1657
1658 This property holds whether the message is composed.
1659
1660 \li \c RPL_MOTDSTART, \c RPL_MOTD, and \c RPL_ENDOFMOTD are composed as IrcMotdMessage
1661 \li \c RPL_NAMREPLY and \c RPL_ENDOFNAMES are composed as IrcNamesMessage
1662 \li \c RPL_TOPIC and \c RPL_NOTOPIC are composed as IrcTopicMessage
1663 \li \c RPL_INVITING and \c RPL_INVITED are composed as IrcInviteMessage
1664 \li \c RPL_WHOREPLY is composed as IrcWhoReplyMessage
1665 \li \c RPL_CHANNELMODEIS is composed as IrcModeMessage
1666 \li \c RPL_AWAY, \c RPL_UNAWAY, \c RPL_NOWAWAY are composed as as IrcAwayMessage
1667
1668 \par Access function:
1669 \li bool <b>isComposed</b>() const
1670 */
isComposed() const1671 bool IrcNumericMessage::isComposed() const
1672 {
1673 return IrcMessageComposer::isComposed(code());
1674 }
1675
isValid() const1676 bool IrcNumericMessage::isValid() const
1677 {
1678 return IrcMessage::isValid() && code() != -1;
1679 }
1680
1681 /*!
1682 \class IrcPartMessage ircmessage.h <IrcMessage>
1683 \ingroup message
1684 \brief Represents a part message.
1685 */
1686
1687 /*!
1688 Constructs a new IrcPartMessage with \a connection.
1689 */
IrcPartMessage(IrcConnection * connection)1690 IrcPartMessage::IrcPartMessage(IrcConnection* connection) : IrcMessage(connection)
1691 {
1692 Q_D(IrcMessage);
1693 d->type = Part;
1694 }
1695
1696 /*!
1697 This property holds the channel in question.
1698
1699 \par Access function:
1700 \li QString <b>channel</b>() const
1701 */
channel() const1702 QString IrcPartMessage::channel() const
1703 {
1704 Q_D(const IrcMessage);
1705 return d->param(0);
1706 }
1707
1708 /*!
1709 This property holds the optional part reason.
1710
1711 \par Access function:
1712 \li QString <b>reason</b>() const
1713 */
reason() const1714 QString IrcPartMessage::reason() const
1715 {
1716 Q_D(const IrcMessage);
1717 return d->param(1);
1718 }
1719
isValid() const1720 bool IrcPartMessage::isValid() const
1721 {
1722 return IrcMessage::isValid() && !channel().isEmpty();
1723 }
1724
1725 /*!
1726 \class IrcPingMessage ircmessage.h <IrcMessage>
1727 \ingroup message
1728 \brief Represents a ping message.
1729 */
1730
1731 /*!
1732 Constructs a new IrcPingMessage with \a connection.
1733 */
IrcPingMessage(IrcConnection * connection)1734 IrcPingMessage::IrcPingMessage(IrcConnection* connection) : IrcMessage(connection)
1735 {
1736 Q_D(IrcMessage);
1737 d->type = Ping;
1738 }
1739
1740 /*!
1741 This property holds the optional message argument.
1742
1743 \par Access function:
1744 \li QString <b>argument</b>() const
1745 */
argument() const1746 QString IrcPingMessage::argument() const
1747 {
1748 Q_D(const IrcMessage);
1749 return d->param(0);
1750 }
1751
isValid() const1752 bool IrcPingMessage::isValid() const
1753 {
1754 return IrcMessage::isValid();
1755 }
1756
1757 /*!
1758 \class IrcPongMessage ircmessage.h <IrcMessage>
1759 \ingroup message
1760 \brief Represents a pong message.
1761 */
1762
1763 /*!
1764 Constructs a new IrcPongMessage with \a connection.
1765 */
IrcPongMessage(IrcConnection * connection)1766 IrcPongMessage::IrcPongMessage(IrcConnection* connection) : IrcMessage(connection)
1767 {
1768 Q_D(IrcMessage);
1769 d->type = Pong;
1770 }
1771
1772 /*!
1773 This property holds the optional message argument.
1774
1775 \par Access function:
1776 \li QString <b>argument</b>() const
1777 */
argument() const1778 QString IrcPongMessage::argument() const
1779 {
1780 Q_D(const IrcMessage);
1781 QStringList params = d->params();
1782 return params.value(params.count() - 1);
1783 }
1784
isValid() const1785 bool IrcPongMessage::isValid() const
1786 {
1787 return IrcMessage::isValid();
1788 }
1789
1790 /*!
1791 \class IrcPrivateMessage ircmessage.h <IrcMessage>
1792 \ingroup message
1793 \brief Represents a private message.
1794 */
1795
1796 /*!
1797 Constructs a new IrcPrivateMessage with \a connection.
1798 */
IrcPrivateMessage(IrcConnection * connection)1799 IrcPrivateMessage::IrcPrivateMessage(IrcConnection* connection) : IrcMessage(connection)
1800 {
1801 Q_D(IrcMessage);
1802 d->type = Private;
1803 }
1804
1805 /*!
1806 This property holds the target channel or user in question.
1807
1808 \par Access function:
1809 \li QString <b>target</b>() const
1810 */
target() const1811 QString IrcPrivateMessage::target() const
1812 {
1813 Q_D(const IrcMessage);
1814 if (d->connection) {
1815 const IrcNetwork* network = d->connection->network();
1816 return IrcNetworkPrivate::removePrefix(d->param(0), network->statusPrefixes());
1817 }
1818 return d->param(0);
1819 }
1820
1821 /*!
1822 This property holds the message content.
1823
1824 \par Access function:
1825 \li QString <b>content</b>() const
1826 */
content() const1827 QString IrcPrivateMessage::content() const
1828 {
1829 Q_D(const IrcMessage);
1830 QString msg = d->param(1);
1831 const bool act = isAction();
1832 const bool req = isRequest();
1833 if (act) msg.remove(0, 8);
1834 if (req) msg.remove(0, 1);
1835 if (act || req) msg.chop(1);
1836 return msg;
1837 }
1838
1839 /*!
1840 \since 3.4
1841
1842 This property holds the status prefix of the message.
1843
1844 \par Access function:
1845 \li QString <b>statusPrefix</b>() const
1846 */
statusPrefix() const1847 QString IrcPrivateMessage::statusPrefix() const
1848 {
1849 Q_D(const IrcMessage);
1850 if (d->connection) {
1851 const IrcNetwork* network = d->connection->network();
1852 return IrcNetworkPrivate::getPrefix(d->param(0), network->statusPrefixes());
1853 }
1854 return QString();
1855 }
1856
1857 /*!
1858 \property bool IrcPrivateMessage::private
1859 This property is \c true if the message is private,
1860 or \c false if it is a channel message.
1861
1862 \par Access function:
1863 \li bool <b>isPrivate</b>() const
1864 */
isPrivate() const1865 bool IrcPrivateMessage::isPrivate() const
1866 {
1867 Q_D(const IrcMessage);
1868 if (d->connection)
1869 return !target().compare(d->connection->nickName(), Qt::CaseInsensitive);
1870 return false;
1871 }
1872
1873 /*!
1874 \property bool IrcPrivateMessage::action
1875 This property is \c true if the message is an action; otherwise \c false.
1876
1877 \par Access function:
1878 \li bool <b>isAction</b>() const
1879 */
isAction() const1880 bool IrcPrivateMessage::isAction() const
1881 {
1882 Q_D(const IrcMessage);
1883 QString msg = d->param(1);
1884 return msg.startsWith("\1ACTION ") && msg.endsWith('\1');
1885 }
1886
1887 /*!
1888 \property bool IrcPrivateMessage::request
1889 This property is \c true if the message is a request; otherwise \c false.
1890
1891 \par Access function:
1892 \li bool <b>isRequest</b>() const
1893 */
isRequest() const1894 bool IrcPrivateMessage::isRequest() const
1895 {
1896 Q_D(const IrcMessage);
1897 QString msg = d->param(1);
1898 return msg.startsWith('\1') && msg.endsWith('\1') && !isAction();
1899 }
1900
isValid() const1901 bool IrcPrivateMessage::isValid() const
1902 {
1903 return IrcMessage::isValid() && !target().isEmpty() && !content().isEmpty();
1904 }
1905
1906 /*!
1907 \class IrcQuitMessage ircmessage.h <IrcMessage>
1908 \ingroup message
1909 \brief Represents a quit message.
1910 */
1911
1912 /*!
1913 Constructs a new IrcQuitMessage with \a connection.
1914 */
IrcQuitMessage(IrcConnection * connection)1915 IrcQuitMessage::IrcQuitMessage(IrcConnection* connection) : IrcMessage(connection)
1916 {
1917 Q_D(IrcMessage);
1918 d->type = Quit;
1919 }
1920
1921 /*!
1922 This property holds the optional quit reason.
1923
1924 \par Access function:
1925 \li QString <b>reason</b>() const
1926 */
reason() const1927 QString IrcQuitMessage::reason() const
1928 {
1929 Q_D(const IrcMessage);
1930 return d->param(0);
1931 }
1932
isValid() const1933 bool IrcQuitMessage::isValid() const
1934 {
1935 return IrcMessage::isValid();
1936 }
1937
1938 /*!
1939 \class IrcTopicMessage ircmessage.h <IrcMessage>
1940 \ingroup message
1941 \brief Represents a topic message.
1942 */
1943
1944 /*!
1945 Constructs a new IrcTopicMessage with \a connection.
1946 */
IrcTopicMessage(IrcConnection * connection)1947 IrcTopicMessage::IrcTopicMessage(IrcConnection* connection) : IrcMessage(connection)
1948 {
1949 Q_D(IrcMessage);
1950 d->type = Topic;
1951 }
1952
1953 /*!
1954 This property holds the channel in question.
1955
1956 \par Access function:
1957 \li QString <b>channel</b>() const
1958 */
channel() const1959 QString IrcTopicMessage::channel() const
1960 {
1961 Q_D(const IrcMessage);
1962 return d->param(0);
1963 }
1964
1965 /*!
1966 This property holds the new channel topic.
1967
1968 \par Access function:
1969 \li QString <b>topic</b>() const
1970 */
topic() const1971 QString IrcTopicMessage::topic() const
1972 {
1973 Q_D(const IrcMessage);
1974 if (d->command().toInt() == Irc::RPL_NOTOPIC)
1975 return QString();
1976 return d->param(1);
1977 }
1978
1979 /*!
1980 \property bool IrcTopicMessage::reply
1981 This property holds whether the message is a reply.
1982
1983 Topic messages are sent in three situations:
1984 \li as a notification of a topic change (\c false),
1985 \li as a reply when joining a channel (\c true), or
1986 \li as a reply when explicitly querying the channel topic (\c true).
1987
1988 \par Access function:
1989 \li bool <b>isReply</b>() const
1990
1991 \sa Irc::RPL_TOPIC, Irc::RPL_NOTOPIC, IrcTopicCommand
1992 */
isReply() const1993 bool IrcTopicMessage::isReply() const
1994 {
1995 Q_D(const IrcMessage);
1996 int rpl = d->command().toInt();
1997 return rpl == Irc::RPL_TOPIC || rpl == Irc::RPL_NOTOPIC;
1998 }
1999
isValid() const2000 bool IrcTopicMessage::isValid() const
2001 {
2002 return IrcMessage::isValid() && !channel().isEmpty();
2003 }
2004
2005 /*!
2006 \since 3.3
2007 \class IrcWhoisMessage ircmessage.h <IrcMessage>
2008 \ingroup message
2009 \brief Represents a reply message to a WHOIS command.
2010 */
2011
2012 /*!
2013 Constructs a new IrcWhoisMessage with \a connection.
2014 */
IrcWhoisMessage(IrcConnection * connection)2015 IrcWhoisMessage::IrcWhoisMessage(IrcConnection* connection) : IrcMessage(connection)
2016 {
2017 Q_D(IrcMessage);
2018 d->type = Whois;
2019 setCommand(QLatin1String("WHOIS"));
2020 }
2021
2022 /*!
2023 This property holds the real name of the user.
2024
2025 \par Access function:
2026 \li QString <b>realName</b>() const
2027 */
realName() const2028 QString IrcWhoisMessage::realName() const
2029 {
2030 Q_D(const IrcMessage);
2031 return d->param(0);
2032 }
2033
2034 /*!
2035 This property holds the server address user is on.
2036
2037 \par Access function:
2038 \li QString <b>server</b>() const
2039 */
server() const2040 QString IrcWhoisMessage::server() const
2041 {
2042 Q_D(const IrcMessage);
2043 return d->param(1);
2044 }
2045
2046 /*!
2047 This property holds info of the server the user is on.
2048
2049 \par Access function:
2050 \li QString <b>info</b>() const
2051 */
info() const2052 QString IrcWhoisMessage::info() const
2053 {
2054 Q_D(const IrcMessage);
2055 return d->param(2);
2056 }
2057
2058 /*!
2059 This property holds the account name of the user.
2060
2061 \par Access function:
2062 \li QString <b>account</b>() const
2063 */
account() const2064 QString IrcWhoisMessage::account() const
2065 {
2066 Q_D(const IrcMessage);
2067 return d->param(3);
2068 }
2069
2070 /*!
2071 This property holds the address the user is connecting from.
2072
2073 \par Access function:
2074 \li QString <b>address</b>() const
2075 */
address() const2076 QString IrcWhoisMessage::address() const
2077 {
2078 Q_D(const IrcMessage);
2079 return d->param(4);
2080 }
2081
2082 /*!
2083 This property holds the time since user has been online.
2084
2085 \par Access function:
2086 \li QDateTime <b>since</b>() const
2087 */
since() const2088 QDateTime IrcWhoisMessage::since() const
2089 {
2090 Q_D(const IrcMessage);
2091 return QDateTime::fromSecsSinceEpoch(d->param(5).toInt());
2092 }
2093
2094 /*!
2095 This property holds the number of seconds the user has been idle.
2096
2097 \par Access function:
2098 \li int <b>idle</b>() const
2099 */
idle() const2100 int IrcWhoisMessage::idle() const
2101 {
2102 Q_D(const IrcMessage);
2103 return d->param(6).toInt();
2104 }
2105
2106 /*!
2107 \property bool IrcWhoisMessage::secure
2108 This property holds whether the user is using a secure connection.
2109
2110 \par Access function:
2111 \li bool <b>isSecure</b>() const
2112 */
isSecure() const2113 bool IrcWhoisMessage::isSecure() const
2114 {
2115 Q_D(const IrcMessage);
2116 return !d->param(7).isEmpty();
2117 }
2118
2119 /*!
2120 This property holds the visible list of channels of the user.
2121
2122 \par Access function:
2123 \li QStringList <b>channels</b>() const
2124 */
channels() const2125 QStringList IrcWhoisMessage::channels() const
2126 {
2127 Q_D(const IrcMessage);
2128 return d->params().value(8).split(QLatin1Char(' '), Qt::SkipEmptyParts);
2129 }
2130
2131 /*!
2132 \since 3.5
2133
2134 This property holds the away reason of the user.
2135
2136 \par Access function:
2137 \li QString <b>awayReason</b>() const
2138 */
awayReason() const2139 QString IrcWhoisMessage::awayReason() const
2140 {
2141 Q_D(const IrcMessage);
2142 return d->param(9);
2143 }
2144
isValid() const2145 bool IrcWhoisMessage::isValid() const
2146 {
2147 Q_D(const IrcMessage);
2148 return IrcMessage::isValid() && d->params().count() == 10;
2149 }
2150
2151 /*!
2152 \since 3.3
2153 \class IrcWhowasMessage ircmessage.h <IrcMessage>
2154 \ingroup message
2155 \brief Represents a reply message to a WHOWAS command.
2156 */
2157
2158 /*!
2159 Constructs a new IrcWhowasMessage with \a connection.
2160 */
IrcWhowasMessage(IrcConnection * connection)2161 IrcWhowasMessage::IrcWhowasMessage(IrcConnection* connection) : IrcMessage(connection)
2162 {
2163 Q_D(IrcMessage);
2164 d->type = Whowas;
2165 setCommand(QLatin1String("WHOWAS"));
2166 }
2167
2168 /*!
2169 This property holds the real name of the user.
2170
2171 \par Access function:
2172 \li QString <b>realName</b>() const
2173 */
realName() const2174 QString IrcWhowasMessage::realName() const
2175 {
2176 Q_D(const IrcMessage);
2177 return d->param(0);
2178 }
2179
2180 /*!
2181 This property holds the server address user was on.
2182
2183 \par Access function:
2184 \li QString <b>server</b>() const
2185 */
server() const2186 QString IrcWhowasMessage::server() const
2187 {
2188 Q_D(const IrcMessage);
2189 return d->param(1);
2190 }
2191
2192 /*!
2193 This property holds info of the server the user was on.
2194
2195 \par Access function:
2196 \li QString <b>info</b>() const
2197 */
info() const2198 QString IrcWhowasMessage::info() const
2199 {
2200 Q_D(const IrcMessage);
2201 return d->param(2);
2202 }
2203
2204 /*!
2205 This property holds the account of the user.
2206
2207 \par Access function:
2208 \li QString <b>account</b>() const
2209 */
account() const2210 QString IrcWhowasMessage::account() const
2211 {
2212 Q_D(const IrcMessage);
2213 return d->param(3);
2214 }
2215
isValid() const2216 bool IrcWhowasMessage::isValid() const
2217 {
2218 Q_D(const IrcMessage);
2219 return IrcMessage::isValid() && d->params().count() == 9;
2220 }
2221
2222 /*!
2223 \since 3.1
2224 \class IrcWhoReplyMessage ircmessage.h <IrcMessage>
2225 \ingroup message
2226 \brief Represents a reply message to a WHO command.
2227 */
2228
2229 /*!
2230 Constructs a new IrcWhoReplyMessage with \a connection.
2231 */
IrcWhoReplyMessage(IrcConnection * connection)2232 IrcWhoReplyMessage::IrcWhoReplyMessage(IrcConnection* connection) : IrcMessage(connection)
2233 {
2234 Q_D(IrcMessage);
2235 d->type = WhoReply;
2236 }
2237
2238 /*!
2239 This property holds the mask.
2240
2241 \par Access function:
2242 \li QString <b>mask</b>() const
2243 */
mask() const2244 QString IrcWhoReplyMessage::mask() const
2245 {
2246 Q_D(const IrcMessage);
2247 return d->param(0);
2248 }
2249
2250 /*!
2251 This property holds the server of the user.
2252
2253 \par Access function:
2254 \li QString <b>server</b>() const
2255 */
server() const2256 QString IrcWhoReplyMessage::server() const
2257 {
2258 Q_D(const IrcMessage);
2259 return d->param(1);
2260 }
2261
2262 /*!
2263 \property bool IrcWhoReplyMessage::away
2264 This property holds whether the user is away.
2265
2266 \par Access function:
2267 \li QString <b>isAway</b>() const
2268 */
isAway() const2269 bool IrcWhoReplyMessage::isAway() const
2270 {
2271 Q_D(const IrcMessage);
2272 return d->param(2).contains("G");
2273 }
2274
2275 /*!
2276 \property bool IrcWhoReplyMessage::servOp
2277 This property holds whether the user is a server operator.
2278
2279 \par Access function:
2280 \li QString <b>isServOp</b>() const
2281 */
isServOp() const2282 bool IrcWhoReplyMessage::isServOp() const
2283 {
2284 Q_D(const IrcMessage);
2285 return d->param(2).contains("*");
2286 }
2287
2288 /*!
2289 This property holds the real name of the user.
2290
2291 \par Access function:
2292 \li QString <b>realName</b>() const
2293 */
realName() const2294 QString IrcWhoReplyMessage::realName() const
2295 {
2296 Q_D(const IrcMessage);
2297 return d->param(3);
2298 }
2299
isValid() const2300 bool IrcWhoReplyMessage::isValid() const
2301 {
2302 return IrcMessage::isValid() && !mask().isEmpty() && !nick().isEmpty();
2303 }
2304
2305 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug debug,IrcMessage::Type type)2306 QDebug operator<<(QDebug debug, IrcMessage::Type type)
2307 {
2308 const int index = IrcMessage::staticMetaObject.indexOfEnumerator("Type");
2309 QMetaEnum enumerator = IrcMessage::staticMetaObject.enumerator(index);
2310 const char* key = enumerator.valueToKey(type);
2311 debug << (key ? key : "Unknown");
2312 return debug;
2313 }
2314
operator <<(QDebug debug,IrcMessage::Flag flag)2315 QDebug operator<<(QDebug debug, IrcMessage::Flag flag)
2316 {
2317 const int index = IrcMessage::staticMetaObject.indexOfEnumerator("Flag");
2318 QMetaEnum enumerator = IrcMessage::staticMetaObject.enumerator(index);
2319 const char* key = enumerator.valueToKey(flag);
2320 debug << (key ? key : "None");
2321 return debug;
2322 }
2323
operator <<(QDebug debug,IrcMessage::Flags flags)2324 QDebug operator<<(QDebug debug, IrcMessage::Flags flags)
2325 {
2326 QStringList lst;
2327 if (flags == IrcMessage::None)
2328 lst << "None";
2329 if (flags & IrcMessage::Own)
2330 lst << "Own";
2331 if (flags & IrcMessage::Playback)
2332 lst << "Playback";
2333 if (flags & IrcMessage::Implicit)
2334 lst << "Implicit";
2335 debug.nospace() << '(' << qPrintable(lst.join("|")) << ')';
2336 return debug;
2337 }
2338
operator <<(QDebug debug,IrcModeMessage::Kind kind)2339 QDebug operator<<(QDebug debug, IrcModeMessage::Kind kind)
2340 {
2341 const int index = IrcModeMessage::staticMetaObject.indexOfEnumerator("Kind");
2342 QMetaEnum enumerator = IrcModeMessage::staticMetaObject.enumerator(index);
2343 const char* key = enumerator.valueToKey(kind);
2344 debug << (key ? key : "Unknown");
2345 return debug;
2346 }
2347
operator <<(QDebug debug,const IrcMessage * message)2348 QDebug operator<<(QDebug debug, const IrcMessage* message)
2349 {
2350 if (!message)
2351 return debug << "IrcMessage(0x0) ";
2352 debug.nospace() << message->metaObject()->className() << '(' << (void*) message;
2353 if (!message->objectName().isEmpty())
2354 debug.nospace() << ", name=" << qPrintable(message->objectName());
2355 debug.nospace() << ", flags=" << message->flags();
2356 if (!message->prefix().isEmpty())
2357 debug.nospace() << ", prefix=" << qPrintable(message->prefix());
2358 if (!message->command().isEmpty())
2359 debug.nospace() << ", command=" << qPrintable(message->command());
2360 debug.nospace() << ')';
2361 return debug.space();
2362 }
2363 #endif // QT_NO_DEBUG_STREAM
2364
2365 #include "moc_ircmessage.cpp"
2366
2367 IRC_END_NAMESPACE
2368