1 /*************************************************************************** 2 * Copyright (C) 2005-2020 by the Quassel Project * 3 * devel@quassel-irc.org * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) version 3. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 19 ***************************************************************************/ 20 21 #pragma once 22 23 #include "common-export.h" 24 25 #include <utility> 26 27 #include <QByteArray> 28 #include <QHash> 29 #include <QList> 30 #include <QMutex> 31 #include <QNetworkProxy> 32 #include <QPointer> 33 #include <QString> 34 #include <QStringList> 35 #include <QVariantMap> 36 37 #include "ircchannel.h" 38 #include "ircuser.h" 39 #include "signalproxy.h" 40 #include "syncableobject.h" 41 #include "types.h" 42 #include "util.h" 43 44 // IRCv3 capabilities 45 #include "irccap.h" 46 47 // defined below! 48 struct NetworkInfo; 49 50 // TODO: ConnectionInfo to propagate and sync the current state of NetworkConnection, encodings etcpp 51 52 class COMMON_EXPORT Network : public SyncableObject 53 { 54 Q_OBJECT 55 SYNCABLE_OBJECT 56 57 Q_ENUMS(ConnectionState) 58 59 Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName) 60 Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer) 61 Q_PROPERTY(QString myNick READ myNick WRITE setMyNick) 62 Q_PROPERTY(int latency READ latency WRITE setLatency) 63 Q_PROPERTY(QByteArray codecForServer READ codecForServer WRITE setCodecForServer) 64 Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding) 65 Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding) 66 Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity) 67 Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected) 68 // Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState) 69 Q_PROPERTY(int connectionState READ connectionState WRITE setConnectionState) 70 Q_PROPERTY(bool useRandomServer READ useRandomServer WRITE setUseRandomServer) 71 Q_PROPERTY(QStringList perform READ perform WRITE setPerform) 72 Q_PROPERTY(QStringList skipCaps READ skipCaps WRITE setSkipCaps) 73 Q_PROPERTY(bool useAutoIdentify READ useAutoIdentify WRITE setUseAutoIdentify) 74 Q_PROPERTY(QString autoIdentifyService READ autoIdentifyService WRITE setAutoIdentifyService) 75 Q_PROPERTY(QString autoIdentifyPassword READ autoIdentifyPassword WRITE setAutoIdentifyPassword) 76 Q_PROPERTY(bool useSasl READ useSasl WRITE setUseSasl) 77 Q_PROPERTY(QString saslAccount READ saslAccount WRITE setSaslAccount) 78 Q_PROPERTY(QString saslPassword READ saslPassword WRITE setSaslPassword) 79 Q_PROPERTY(bool useAutoReconnect READ useAutoReconnect WRITE setUseAutoReconnect) 80 Q_PROPERTY(quint32 autoReconnectInterval READ autoReconnectInterval WRITE setAutoReconnectInterval) 81 Q_PROPERTY(quint16 autoReconnectRetries READ autoReconnectRetries WRITE setAutoReconnectRetries) 82 Q_PROPERTY(bool unlimitedReconnectRetries READ unlimitedReconnectRetries WRITE setUnlimitedReconnectRetries) 83 Q_PROPERTY(bool rejoinChannels READ rejoinChannels WRITE setRejoinChannels) 84 // Custom rate limiting 85 Q_PROPERTY(bool useCustomMessageRate READ useCustomMessageRate WRITE setUseCustomMessageRate) 86 Q_PROPERTY(quint32 msgRateBurstSize READ messageRateBurstSize WRITE setMessageRateBurstSize) 87 Q_PROPERTY(quint32 msgRateMessageDelay READ messageRateDelay WRITE setMessageRateDelay) 88 Q_PROPERTY(bool unlimitedMessageRate READ unlimitedMessageRate WRITE setUnlimitedMessageRate) 89 90 public: 91 enum ConnectionState 92 { 93 Disconnected, 94 Connecting, 95 Initializing, 96 Initialized, 97 Reconnecting, 98 Disconnecting 99 }; 100 101 // see: 102 // http://www.irc.org/tech_docs/005.html 103 // http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt 104 enum ChannelModeType 105 { 106 NOT_A_CHANMODE = 0x00, 107 A_CHANMODE = 0x01, 108 B_CHANMODE = 0x02, 109 C_CHANMODE = 0x04, 110 D_CHANMODE = 0x08 111 }; 112 113 // Default port assignments according to what many IRC networks have settled on. 114 // Technically not a standard, but it's fairly widespread. 115 // See https://freenode.net/news/port-6697-irc-via-tlsssl 116 enum PortDefaults 117 { 118 PORT_PLAINTEXT = 6667, /// Default port for unencrypted connections 119 PORT_SSL = 6697 /// Default port for encrypted connections 120 }; 121 122 struct Server 123 { 124 QString host; 125 uint port{6667}; 126 QString password; 127 bool useSsl{false}; 128 bool sslVerify{true}; /// If true, validate SSL certificates 129 int sslVersion{0}; 130 131 bool useProxy{false}; 132 int proxyType{QNetworkProxy::Socks5Proxy}; 133 QString proxyHost; 134 uint proxyPort{8080}; 135 QString proxyUser; 136 QString proxyPass; 137 138 // sslVerify only applies when useSsl is true. sslVerify should be enabled by default, 139 // so enabling useSsl offers a more secure default. ServerServer140 Server() 141 : proxyHost("localhost") 142 {} 143 ServerServer144 Server(QString host, uint port, QString password, bool useSsl, bool sslVerify) 145 : host(std::move(host)) 146 , port(port) 147 , password(std::move(password)) 148 , useSsl(useSsl) 149 , sslVerify(sslVerify) 150 , proxyType(QNetworkProxy::Socks5Proxy) 151 , proxyHost("localhost") 152 , proxyPort(8080) 153 {} 154 155 bool operator==(const Server& other) const; 156 bool operator!=(const Server& other) const; 157 }; 158 using ServerList = QList<Server>; 159 160 Network(const NetworkId& networkid, QObject* parent = nullptr); 161 ~Network() override; 162 networkId()163 inline NetworkId networkId() const { return _networkId; } 164 proxy()165 inline SignalProxy* proxy() const { return _proxy; } setProxy(SignalProxy * proxy)166 inline void setProxy(SignalProxy* proxy) { _proxy = proxy; } 167 isMyNick(const QString & nick)168 inline bool isMyNick(const QString& nick) const { return (myNick().toLower() == nick.toLower()); } isMe(IrcUser * ircuser)169 inline bool isMe(IrcUser* ircuser) const { return (ircuser->nick().toLower() == myNick().toLower()); } 170 171 bool isChannelName(const QString& channelname) const; 172 173 /** 174 * Checks if the target counts as a STATUSMSG 175 * 176 * Status messages are prefixed with one or more characters from the server-provided STATUSMSG 177 * if available, otherwise "@" and "+" are assumed. Generally, status messages sent to a 178 * channel are only visible to those with the same or higher permissions, e.g. voiced. 179 * 180 * @param[in] target Name of destination, e.g. a channel or query 181 * @returns True if a STATUSMSG, otherwise false 182 */ 183 bool isStatusMsg(const QString& target) const; 184 isConnected()185 inline bool isConnected() const { return _connected; } 186 // Network::ConnectionState connectionState() const; connectionState()187 inline int connectionState() const { return _connectionState; } 188 189 /**@{*/ 190 /** 191 * Translates a user’s prefix to the channelmode associated with it. 192 * @param prefix Prefix to be translated. 193 */ 194 QString prefixToMode(const QString& prefix) const; prefixToMode(const QCharRef & prefix)195 inline QString prefixToMode(const QCharRef& prefix) const { return prefixToMode(QString(prefix)); } prefixesToModes(const QString & prefix)196 inline QString prefixesToModes(const QString& prefix) const 197 { 198 QString modes; 199 for (QChar c : prefix) { 200 modes += prefixToMode(c); 201 } 202 return modes; 203 } 204 /**@}*/ 205 206 /**@{*/ 207 /** 208 * Translates a user’s prefix to the channelmode associated with it. 209 * @param prefix Prefix to be translated. 210 */ 211 QString modeToPrefix(const QString& mode) const; modeToPrefix(const QCharRef & mode)212 inline QString modeToPrefix(const QCharRef& mode) const { return modeToPrefix(QString(mode)); } modesToPrefixes(const QString & mode)213 inline QString modesToPrefixes(const QString& mode) const 214 { 215 QString prefixes; 216 for (QChar c : mode) { 217 prefixes += modeToPrefix(c); 218 } 219 return prefixes; 220 } 221 /**@}*/ 222 223 /** 224 * Sorts the user channelmodes according to priority set by PREFIX 225 * 226 * Given a list of channel modes, sorts according to the order of PREFIX, putting the highest 227 * modes first. Any unknown modes are moved to the end in no given order. 228 * 229 * If prefix modes cannot be determined from the network, no changes will be made. 230 * 231 * @param modes User channelmodes 232 * @return Priority-sorted user channelmodes 233 */ 234 QString sortPrefixModes(const QString& modes) const; 235 236 /**@{*/ 237 /** 238 * Sorts the list of users' channelmodes according to priority set by PREFIX 239 * 240 * Maintains order of the modes list. 241 * 242 * @seealso Network::sortPrefixModes() 243 * 244 * @param modesList List of users' channel modes 245 * @return Priority-sorted list of users' channel modes 246 */ sortPrefixModes(const QStringList & modesList)247 inline QStringList sortPrefixModes(const QStringList& modesList) const 248 { 249 QStringList sortedModesList; 250 // Sort each individual mode string, appending back 251 // Must maintain the order received! 252 for (QString modes : modesList) { 253 sortedModesList << sortPrefixModes(modes); 254 } 255 return sortedModesList; 256 } 257 /**@}*/ 258 259 ChannelModeType channelModeType(const QString& mode); channelModeType(const QCharRef & mode)260 inline ChannelModeType channelModeType(const QCharRef& mode) { return channelModeType(QString(mode)); } 261 networkName()262 inline const QString& networkName() const { return _networkName; } currentServer()263 inline const QString& currentServer() const { return _currentServer; } myNick()264 inline const QString& myNick() const { return _myNick; } latency()265 inline int latency() const { return _latency; } me()266 inline IrcUser* me() const { return ircUser(myNick()); } identity()267 inline IdentityId identity() const { return _identity; } 268 QStringList nicks() const; channels()269 inline QStringList channels() const { return _ircChannels.keys(); } 270 /** 271 * Gets the list of available capabilities. 272 * 273 * @returns QStringList of available capabilities 274 */ caps()275 inline const QStringList caps() const { return QStringList(_caps.keys()); } 276 /** 277 * Gets the list of enabled (acknowledged) capabilities. 278 * 279 * @returns QStringList of enabled (acknowledged) capabilities 280 */ capsEnabled()281 inline const QStringList capsEnabled() const { return _capsEnabled; } serverList()282 inline const ServerList& serverList() const { return _serverList; } useRandomServer()283 inline bool useRandomServer() const { return _useRandomServer; } perform()284 inline const QStringList& perform() const { return _perform; } 285 /** 286 * Gets the list of skipped (not auto-negotiated) capabilities. 287 * 288 * @returns QStringList of skippped capabilities 289 */ skipCaps()290 inline const QStringList skipCaps() const { return _skipCaps; } useAutoIdentify()291 inline bool useAutoIdentify() const { return _useAutoIdentify; } autoIdentifyService()292 inline const QString& autoIdentifyService() const { return _autoIdentifyService; } autoIdentifyPassword()293 inline const QString& autoIdentifyPassword() const { return _autoIdentifyPassword; } useSasl()294 inline bool useSasl() const { return _useSasl; } saslAccount()295 inline const QString& saslAccount() const { return _saslAccount; } saslPassword()296 inline const QString& saslPassword() const { return _saslPassword; } useAutoReconnect()297 inline bool useAutoReconnect() const { return _useAutoReconnect; } autoReconnectInterval()298 inline quint32 autoReconnectInterval() const { return _autoReconnectInterval; } autoReconnectRetries()299 inline quint16 autoReconnectRetries() const { return _autoReconnectRetries; } unlimitedReconnectRetries()300 inline bool unlimitedReconnectRetries() const { return _unlimitedReconnectRetries; } rejoinChannels()301 inline bool rejoinChannels() const { return _rejoinChannels; } 302 303 // Custom rate limiting 304 305 /** 306 * Gets whether or not custom rate limiting is used 307 * 308 * @return True if custom rate limiting is enabled, otherwise false. 309 */ useCustomMessageRate()310 inline bool useCustomMessageRate() const { return _useCustomMessageRate; } 311 312 /** 313 * Gets maximum number of messages to send without any delays 314 * 315 * @return 316 * @parblock 317 * Maximum number of messages to send without any delays. A value of 1 disables message 318 * bursting. 319 * @endparblock 320 */ messageRateBurstSize()321 inline quint32 messageRateBurstSize() const { return _messageRateBurstSize; } 322 323 /** 324 * Gets the delay between messages after the maximum number of undelayed messages have been sent 325 * 326 * @return 327 * @parblock 328 * Delay in milliseconds between messages after the maximum number of undelayed messages have 329 * been sent. 330 * @endparblock 331 */ messageRateDelay()332 inline quint32 messageRateDelay() const { return _messageRateDelay; } 333 334 /** 335 * Gets whether or not all rate limiting is disabled, e.g. for IRC bridges 336 * 337 * @return If true, disable rate limiting, otherwise apply configured limits. 338 */ unlimitedMessageRate()339 inline bool unlimitedMessageRate() const { return _unlimitedMessageRate; } 340 341 NetworkInfo networkInfo() const; 342 void setNetworkInfo(const NetworkInfo&); 343 344 QString prefixes() const; 345 QString prefixModes() const; 346 void determinePrefixes() const; 347 supports(const QString & param)348 bool supports(const QString& param) const { return _supports.contains(param); } 349 QString support(const QString& param) const; 350 351 /** 352 * Checks if a given capability is advertised by the server. 353 * 354 * These results aren't valid if the network is disconnected or capability negotiation hasn't 355 * happened, and some servers might not correctly advertise capabilities. Don't treat this as 356 * a guarantee. 357 * 358 * @param[in] capability Name of capability 359 * @returns True if connected and advertised by the server, otherwise false 360 */ capAvailable(const QString & capability)361 inline bool capAvailable(const QString& capability) const { return _caps.contains(capability.toLower()); } 362 // IRCv3 specs all use lowercase capability names 363 364 /** 365 * Checks if a given capability is acknowledged and active. 366 * 367 * @param[in] capability Name of capability 368 * @returns True if acknowledged (active), otherwise false 369 */ capEnabled(const QString & capability)370 inline bool capEnabled(const QString& capability) const { return _capsEnabled.contains(capability.toLower()); } 371 // IRCv3 specs all use lowercase capability names 372 373 /** 374 * Gets the value of an available capability, e.g. for SASL, "EXTERNAL,PLAIN". 375 * 376 * @param[in] capability Name of capability 377 * @returns Value of capability if one was specified, otherwise empty string 378 */ capValue(const QString & capability)379 QString capValue(const QString& capability) const { return _caps.value(capability.toLower()); } 380 // IRCv3 specs all use lowercase capability names 381 // QHash returns the default constructed value if not found, in this case, empty string 382 // See: https://doc.qt.io/qt-4.8/qhash.html#value 383 384 /** 385 * Check if the given authentication mechanism is likely to be supported. 386 * 387 * This depends on the server advertising SASL support and either declaring available mechanisms 388 * (SASL 3.2), or just indicating something is supported (SASL 3.1). 389 * 390 * @param[in] saslMechanism Desired SASL mechanism 391 * @return True if mechanism supported or unknown, otherwise false 392 */ 393 bool saslMaybeSupports(const QString& saslMechanism) const; 394 395 IrcUser* newIrcUser(const QString& hostmask, const QVariantMap& initData = QVariantMap()); newIrcUser(const QByteArray & hostmask)396 inline IrcUser* newIrcUser(const QByteArray& hostmask) { return newIrcUser(decodeServerString(hostmask)); } 397 IrcUser* ircUser(QString nickname) const; ircUser(const QByteArray & nickname)398 inline IrcUser* ircUser(const QByteArray& nickname) const { return ircUser(decodeServerString(nickname)); } ircUsers()399 inline QList<IrcUser*> ircUsers() const { return _ircUsers.values(); } ircUserCount()400 inline quint32 ircUserCount() const { return _ircUsers.count(); } 401 402 IrcChannel* newIrcChannel(const QString& channelname, const QVariantMap& initData = QVariantMap()); newIrcChannel(const QByteArray & channelname)403 inline IrcChannel* newIrcChannel(const QByteArray& channelname) { return newIrcChannel(decodeServerString(channelname)); } 404 IrcChannel* ircChannel(QString channelname) const; ircChannel(const QByteArray & channelname)405 inline IrcChannel* ircChannel(const QByteArray& channelname) const { return ircChannel(decodeServerString(channelname)); } ircChannels()406 inline QList<IrcChannel*> ircChannels() const { return _ircChannels.values(); } ircChannelCount()407 inline quint32 ircChannelCount() const { return _ircChannels.count(); } 408 409 QByteArray codecForServer() const; 410 QByteArray codecForEncoding() const; 411 QByteArray codecForDecoding() const; 412 void setCodecForServer(QTextCodec* codec); 413 void setCodecForEncoding(QTextCodec* codec); 414 void setCodecForDecoding(QTextCodec* codec); 415 416 QString decodeString(const QByteArray& text) const; 417 QByteArray encodeString(const QString& string) const; 418 QString decodeServerString(const QByteArray& text) const; 419 QByteArray encodeServerString(const QString& string) const; 420 421 static QByteArray defaultCodecForServer(); 422 static QByteArray defaultCodecForEncoding(); 423 static QByteArray defaultCodecForDecoding(); 424 static void setDefaultCodecForServer(const QByteArray& name); 425 static void setDefaultCodecForEncoding(const QByteArray& name); 426 static void setDefaultCodecForDecoding(const QByteArray& name); 427 autoAwayActive()428 inline bool autoAwayActive() const { return _autoAwayActive; } setAutoAwayActive(bool active)429 inline void setAutoAwayActive(bool active) { _autoAwayActive = active; } 430 431 public slots: 432 void setNetworkName(const QString& networkName); 433 void setCurrentServer(const QString& currentServer); 434 void setConnected(bool isConnected); 435 void setConnectionState(int state); 436 virtual void setMyNick(const QString& mynick); 437 void setLatency(int latency); 438 void setIdentity(IdentityId); 439 440 void setServerList(const QVariantList& serverList); 441 void setUseRandomServer(bool); 442 void setPerform(const QStringList&); 443 /** 444 * Sets the list of skipped (not auto-negotiated) capabilities 445 * 446 * @param skipCaps QStringList of skipped (not auto-negotiated) capabilities 447 */ 448 void setSkipCaps(const QStringList& skipCaps); 449 void setUseAutoIdentify(bool); 450 void setAutoIdentifyService(const QString&); 451 void setAutoIdentifyPassword(const QString&); 452 void setUseSasl(bool); 453 void setSaslAccount(const QString&); 454 void setSaslPassword(const QString&); 455 virtual void setUseAutoReconnect(bool); 456 virtual void setAutoReconnectInterval(quint32); 457 virtual void setAutoReconnectRetries(quint16); 458 void setUnlimitedReconnectRetries(bool); 459 void setRejoinChannels(bool); 460 461 // Custom rate limiting 462 463 /** 464 * Sets whether or not custom rate limiting is used. 465 * 466 * Setting limits too low may get you disconnected from the server! 467 * 468 * @param[in] useCustomRate If true, use custom rate limits, otherwise use Quassel defaults. 469 */ 470 void setUseCustomMessageRate(bool useCustomRate); 471 472 /** 473 * Sets maximum number of messages to send without any delays 474 * 475 * @param[in] burstSize 476 * @parblock 477 * Maximum number of messages to send without any delays. A value of 1 disables message 478 * bursting. Cannot be less than 1 as sending 0 messages at a time accomplishes nothing. 479 * @endparblock 480 */ 481 void setMessageRateBurstSize(quint32 burstSize); 482 483 /** 484 * Sets the delay between messages after the maximum number of undelayed messages have been sent 485 * 486 * @param[in] messageDelay 487 * @parblock 488 * Delay in milliseconds between messages after the maximum number of undelayed messages have 489 * been sent. 490 * @endparblock 491 */ 492 void setMessageRateDelay(quint32 messageDelay); 493 494 /** 495 * Sets whether or not all rate limiting is disabled, e.g. for IRC bridges 496 * 497 * Don't use with most normal networks. 498 * 499 * @param[in] unlimitedRate If true, disable rate limiting, otherwise apply configured limits. 500 */ 501 void setUnlimitedMessageRate(bool unlimitedRate); 502 503 void setCodecForServer(const QByteArray& codecName); 504 void setCodecForEncoding(const QByteArray& codecName); 505 void setCodecForDecoding(const QByteArray& codecName); 506 507 void addSupport(const QString& param, const QString& value = QString()); 508 void removeSupport(const QString& param); 509 510 // IRCv3 capability negotiation (can be connected to signals) 511 512 /** 513 * Add an available capability, optionally providing a value. 514 * 515 * This may happen during first connect, or at any time later if a new capability becomes 516 * available (e.g. SASL service starting). 517 * 518 * @param[in] capability Name of the capability 519 * @param[in] value 520 * @parblock 521 * Optional value of the capability, e.g. sasl=plain. 522 * @endparblock 523 */ 524 void addCap(const QString& capability, const QString& value = QString()); 525 526 /** 527 * Marks a capability as acknowledged (enabled by the IRC server). 528 * 529 * @param[in] capability Name of the capability 530 */ 531 void acknowledgeCap(const QString& capability); 532 533 /** 534 * Removes a capability from the list of available capabilities. 535 * 536 * This may happen during first connect, or at any time later if an existing capability becomes 537 * unavailable (e.g. SASL service stopping). This also removes the capability from the list 538 * of acknowledged capabilities. 539 * 540 * @param[in] capability Name of the capability 541 */ 542 void removeCap(const QString& capability); 543 544 /** 545 * Clears all capabilities from the list of available capabilities. 546 * 547 * This also removes all capabilities from the list of acknowledged capabilities. 548 */ 549 void clearCaps(); 550 addIrcUser(const QString & hostmask)551 inline void addIrcUser(const QString& hostmask) { newIrcUser(hostmask); } addIrcChannel(const QString & channel)552 inline void addIrcChannel(const QString& channel) { newIrcChannel(channel); } 553 554 // init geters 555 QVariantMap initSupports() const; 556 /** 557 * Get the initial list of available capabilities. 558 * 559 * @return QVariantMap of <QString, QString> indicating available capabilities and values 560 */ 561 QVariantMap initCaps() const; 562 /** 563 * Get the initial list of enabled (acknowledged) capabilities. 564 * 565 * @return QVariantList of QString indicating enabled (acknowledged) capabilities and values 566 */ initCapsEnabled()567 QVariantList initCapsEnabled() const { return toVariantList(capsEnabled()); } initServerList()568 inline QVariantList initServerList() const { return toVariantList(serverList()); } 569 virtual QVariantMap initIrcUsersAndChannels() const; 570 571 // init seters 572 void initSetSupports(const QVariantMap& supports); 573 /** 574 * Initialize the list of available capabilities. 575 * 576 * @param[in] caps QVariantMap of <QString, QString> indicating available capabilities and values 577 */ 578 void initSetCaps(const QVariantMap& caps); 579 /** 580 * Initialize the list of enabled (acknowledged) capabilities. 581 * 582 * @param[in] capsEnabled QVariantList of QString indicating enabled (acknowledged) capabilities 583 */ initSetCapsEnabled(const QVariantList & capsEnabled)584 inline void initSetCapsEnabled(const QVariantList& capsEnabled) { _capsEnabled = fromVariantList<QString>(capsEnabled); } initSetServerList(const QVariantList & serverList)585 inline void initSetServerList(const QVariantList& serverList) { _serverList = fromVariantList<Server>(serverList); } 586 virtual void initSetIrcUsersAndChannels(const QVariantMap& usersAndChannels); 587 588 /** 589 * Update IrcUser hostmask and username from mask, creating an IrcUser if one does not exist. 590 * 591 * @param[in] mask Full nick!user@hostmask string 592 * @return IrcUser of the matching nick if exists, otherwise a new IrcUser 593 */ 594 IrcUser* updateNickFromMask(const QString& mask); 595 596 // these slots are to keep the hashlists of all users and the 597 // channel lists up to date 598 void ircUserNickChanged(QString newnick); 599 requestConnect()600 virtual inline void requestConnect() const { REQUEST(NO_ARG) } requestDisconnect()601 virtual inline void requestDisconnect() const { REQUEST(NO_ARG) } requestSetNetworkInfo(const NetworkInfo & info)602 virtual inline void requestSetNetworkInfo(const NetworkInfo& info) { REQUEST(ARG(info)) } 603 604 void emitConnectionError(const QString&); 605 606 protected slots: 607 virtual void removeIrcUser(IrcUser* ircuser); 608 virtual void removeIrcChannel(IrcChannel* ircChannel); 609 virtual void removeChansAndUsers(); 610 611 signals: 612 void aboutToBeDestroyed(); 613 void networkNameSet(const QString& networkName); 614 void currentServerSet(const QString& currentServer); 615 void connectedSet(bool isConnected); 616 void connectionStateSet(Network::ConnectionState); 617 // void connectionStateSet(int); 618 void connectionError(const QString& errorMsg); 619 void myNickSet(const QString& mynick); 620 // void latencySet(int latency); 621 void identitySet(IdentityId); 622 623 void configChanged(); 624 625 // void serverListSet(QVariantList serverList); 626 // void useRandomServerSet(bool); 627 // void performSet(const QStringList &); 628 // void useAutoIdentifySet(bool); 629 // void autoIdentifyServiceSet(const QString &); 630 // void autoIdentifyPasswordSet(const QString &); 631 // void useAutoReconnectSet(bool); 632 // void autoReconnectIntervalSet(quint32); 633 // void autoReconnectRetriesSet(quint16); 634 // void unlimitedReconnectRetriesSet(bool); 635 // void rejoinChannelsSet(bool); 636 637 // Custom rate limiting (can drive other slots) 638 639 /** 640 * Signals enabling or disabling custom rate limiting 641 * 642 * @see Network::useCustomMessageRate() 643 * 644 * @param[out] useCustomRate 645 */ 646 void useCustomMessageRateSet(const bool useCustomRate); 647 648 /** 649 * Signals a change in maximum number of messages to send without any delays 650 * 651 * @see Network::messageRateBurstSize() 652 * 653 * @param[out] burstSize 654 */ 655 void messageRateBurstSizeSet(const quint32 burstSize); 656 657 /** 658 * Signals a change in delay between messages after the max. undelayed messages have been sent 659 * 660 * @see Network::messageRateDelay() 661 * 662 * @param[out] messageDelay 663 */ 664 void messageRateDelaySet(const quint32 messageDelay); 665 666 /** 667 * Signals enabling or disabling all rate limiting 668 * 669 * @see Network::unlimitedMessageRate() 670 * 671 * @param[out] unlimitedRate 672 */ 673 void unlimitedMessageRateSet(const bool unlimitedRate); 674 675 // void codecForServerSet(const QByteArray &codecName); 676 // void codecForEncodingSet(const QByteArray &codecName); 677 // void codecForDecodingSet(const QByteArray &codecName); 678 679 // void supportAdded(const QString ¶m, const QString &value); 680 // void supportRemoved(const QString ¶m); 681 682 // IRCv3 capability negotiation (can drive other slots) 683 /** 684 * Indicates a capability is now available, with optional value in Network::capValue(). 685 * 686 * @see Network::addCap() 687 * 688 * @param[in] capability Name of the capability 689 */ 690 void capAdded(const QString& capability); 691 692 /** 693 * Indicates a capability was acknowledged (enabled by the IRC server). 694 * 695 * @see Network::acknowledgeCap() 696 * 697 * @param[in] capability Name of the capability 698 */ 699 void capAcknowledged(const QString& capability); 700 701 /** 702 * Indicates a capability was removed from the list of available capabilities. 703 * 704 * @see Network::removeCap() 705 * 706 * @param[in] capability Name of the capability 707 */ 708 void capRemoved(const QString& capability); 709 710 // void ircUserAdded(const QString &hostmask); 711 void ircUserAdded(IrcUser*); 712 // void ircChannelAdded(const QString &channelname); 713 void ircChannelAdded(IrcChannel*); 714 715 // void connectRequested() const; 716 // void disconnectRequested() const; 717 // void setNetworkInfoRequested(const NetworkInfo &) const; 718 719 protected: ircChannelFactory(const QString & channelname)720 inline virtual IrcChannel* ircChannelFactory(const QString& channelname) { return new IrcChannel(channelname, this); } ircUserFactory(const QString & hostmask)721 inline virtual IrcUser* ircUserFactory(const QString& hostmask) { return new IrcUser(hostmask, this); } 722 723 private: 724 QPointer<SignalProxy> _proxy; 725 726 NetworkId _networkId; 727 IdentityId _identity; 728 729 QString _myNick; 730 int _latency; 731 QString _networkName; 732 QString _currentServer; 733 bool _connected; 734 ConnectionState _connectionState; 735 736 mutable QString _prefixes; 737 mutable QString _prefixModes; 738 739 QHash<QString, IrcUser*> _ircUsers; // stores all known nicks for the server 740 QHash<QString, IrcChannel*> _ircChannels; // stores all known channels 741 QHash<QString, QString> _supports; // stores results from RPL_ISUPPORT 742 743 QHash<QString, QString> _caps; /// Capabilities supported by the IRC server 744 // By synchronizing the supported capabilities, the client could suggest certain behaviors, e.g. 745 // in the Network settings dialog, recommending SASL instead of using NickServ, or warning if 746 // SASL EXTERNAL isn't available. 747 QStringList _capsEnabled; /// Enabled capabilities that received 'CAP ACK' 748 // _capsEnabled uses the same values from the <name>=<value> pairs stored in _caps 749 750 751 ServerList _serverList; 752 bool _useRandomServer; 753 QStringList _perform; 754 QStringList _skipCaps; ///< Capabilities to skip during negotiation (keep list sorted!) 755 756 bool _useAutoIdentify; 757 QString _autoIdentifyService; 758 QString _autoIdentifyPassword; 759 760 bool _useSasl; 761 QString _saslAccount; 762 QString _saslPassword; 763 764 bool _useAutoReconnect; 765 quint32 _autoReconnectInterval; 766 quint16 _autoReconnectRetries; 767 bool _unlimitedReconnectRetries; 768 bool _rejoinChannels; 769 770 // Custom rate limiting 771 bool _useCustomMessageRate; /// If true, use custom rate limits, otherwise use defaults 772 quint32 _messageRateBurstSize; /// Maximum number of messages to send without any delays 773 quint32 _messageRateDelay; /// Delay in ms. for messages when max. burst messages sent 774 bool _unlimitedMessageRate; /// If true, disable rate limiting, otherwise apply limits 775 776 QTextCodec* _codecForServer; 777 QTextCodec* _codecForEncoding; 778 QTextCodec* _codecForDecoding; 779 780 static QTextCodec* _defaultCodecForServer; 781 static QTextCodec* _defaultCodecForEncoding; 782 static QTextCodec* _defaultCodecForDecoding; 783 784 bool _autoAwayActive; // when this is active handle305 and handle306 don't trigger any output 785 786 friend class IrcUser; 787 friend class IrcChannel; 788 }; 789 790 //! Stores all editable information about a network (as opposed to runtime state). 791 struct COMMON_EXPORT NetworkInfo 792 { 793 QString networkName; 794 795 Network::ServerList serverList; 796 QStringList perform; 797 QStringList skipCaps; ///< Capabilities to skip during negotiation 798 799 QString autoIdentifyService{"NickServ"}; 800 QString autoIdentifyPassword; 801 802 QString saslAccount; 803 QString saslPassword; 804 805 QByteArray codecForServer; 806 QByteArray codecForEncoding; 807 QByteArray codecForDecoding; 808 809 NetworkId networkId{0}; 810 IdentityId identity{1}; 811 812 quint32 messageRateBurstSize{5}; ///< Maximum number of messages to send without any delays 813 quint32 messageRateDelay{2200}; ///< Delay in ms. for messages when max. burst messages sent 814 815 quint32 autoReconnectInterval{60}; 816 quint16 autoReconnectRetries{20}; 817 818 bool rejoinChannels{true}; 819 bool useRandomServer{false}; 820 bool useAutoIdentify{false}; 821 bool useSasl{false}; 822 bool useAutoReconnect{true}; 823 bool unlimitedReconnectRetries{false}; 824 bool useCustomMessageRate{false}; ///< If true, use custom rate limits, otherwise use defaults 825 bool unlimitedMessageRate{false}; ///< If true, disable rate limiting, otherwise apply limits 826 827 public: 828 bool operator==(const NetworkInfo& other) const; 829 bool operator!=(const NetworkInfo& other) const; 830 831 /** 832 * Gets the list of skipped capabilities in a space-separated string 833 * 834 * @see skipCaps 835 * @return QString representing skipCaps with each cap separated by a space 836 */ 837 QString skipCapsToString() const; 838 /** 839 * Sets the list of skipped capabilities from a space-separated string 840 * 841 * @param flattenedSkipCaps QString representing skipCaps with each cap separated by a space 842 */ 843 void skipCapsFromString(const QString& flattenedSkipCaps); 844 }; 845 846 COMMON_EXPORT QDataStream& operator<<(QDataStream& out, const NetworkInfo& info); 847 COMMON_EXPORT QDataStream& operator>>(QDataStream& in, NetworkInfo& info); 848 COMMON_EXPORT QDebug operator<<(QDebug dbg, const NetworkInfo& i); 849 Q_DECLARE_METATYPE(NetworkInfo) 850 851 COMMON_EXPORT QDataStream& operator<<(QDataStream& out, const Network::Server& server); 852 COMMON_EXPORT QDataStream& operator>>(QDataStream& in, Network::Server& server); 853 COMMON_EXPORT QDebug operator<<(QDebug dbg, const Network::Server& server); 854 Q_DECLARE_METATYPE(Network::Server) 855