/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2016 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "coreircchannel.h"
#include "coreircuser.h"
+// IRCv3 capabilities
+#include "irccap.h"
+
#include <QTimer>
#ifdef HAVE_SSL
#include "coresession.h"
+#include <functional>
+
class CoreIdentity;
class CoreUserInputHandler;
class CoreIgnoreListManager;
inline QString channelKey(const QString &channel) const { return _channelKeys.value(channel.toLower(), QString()); }
+ inline QByteArray readChannelCipherKey(const QString &channel) const { return _cipherKeys.value(channel.toLower()); }
+ inline void storeChannelCipherKey(const QString &channel, const QByteArray &key) { _cipherKeys[channel.toLower()] = key; }
+
inline bool isAutoWhoInProgress(const QString &channel) const { return _autoWhoPending.value(channel.toLower(), 0); }
inline UserId userId() const { return _coreSession->user(); }
inline quint16 localPort() const { return socket.localPort(); }
inline quint16 peerPort() const { return socket.peerPort(); }
+ QList<QList<QByteArray>> splitMessage(const QString &cmd, const QString &message, std::function<QList<QByteArray>(QString &)> cmdGenerator);
+
+ // IRCv3 capability negotiation
+
+ /**
+ * Checks if capability negotiation is currently ongoing.
+ *
+ * @returns True if in progress, otherwise false
+ */
+ inline bool capNegotiationInProgress() const { return !_capsQueued.empty(); }
+
+ /**
+ * Queues a capability to be requested.
+ *
+ * Adds to the list of capabilities being requested. If non-empty, CAP REQ messages are sent
+ * to the IRC server. This may happen at login or if capabilities are announced via CAP NEW.
+ *
+ * @param[in] capability Name of the capability
+ */
+ void queueCap(const QString &capability);
+
+ /**
+ * Begins capability negotiation if capabilities are queued, otherwise returns.
+ *
+ * If any capabilities are queued, this will begin the cycle of taking each capability and
+ * requesting it. When no capabilities remain, capability negotiation is suitably ended.
+ */
+ void beginCapNegotiation();
+
+ /**
+ * List of capabilities requiring further core<->server messages to configure.
+ *
+ * For example, SASL requires the back-and-forth of AUTHENTICATE, so the next capability cannot
+ * be immediately sent.
+ *
+ * See: http://ircv3.net/specs/extensions/sasl-3.2.html
+ */
+ const QStringList capsRequiringConfiguration = QStringList {
+ IrcCap::SASL
+ };
+
public slots:
virtual void setMyNick(const QString &mynick);
void userInput(BufferInfo bufferInfo, QString msg);
void putRawLine(QByteArray input);
void putCmd(const QString &cmd, const QList<QByteArray> ¶ms, const QByteArray &prefix = QByteArray());
+ void putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, const QByteArray &prefix = QByteArray());
void setChannelJoined(const QString &channel);
void setChannelParted(const QString &channel);
// Blowfish stuff
#ifdef HAVE_QCA2
- Cipher *cipher(const QString &recipient) const;
+ Cipher *cipher(const QString &recipient);
QByteArray cipherKey(const QString &recipient) const;
void setCipherKey(const QString &recipient, const QByteArray &key);
+ bool cipherUsesCBC(const QString &target);
#endif
+ // IRCv3 capability negotiation (can be connected to signals)
+
+ /**
+ * Indicates a capability is now available, with optional value in Network::capValue().
+ *
+ * @see Network::addCap()
+ *
+ * @param[in] capability Name of the capability
+ */
+ void serverCapAdded(const QString &capability);
+
+ /**
+ * Indicates a capability was acknowledged (enabled by the IRC server).
+ *
+ * @see Network::acknowledgeCap()
+ *
+ * @param[in] capability Name of the capability
+ */
+ void serverCapAcknowledged(const QString &capability);
+
+ /**
+ * Indicates a capability was removed from the list of available capabilities.
+ *
+ * @see Network::removeCap()
+ *
+ * @param[in] capability Name of the capability
+ */
+ void serverCapRemoved(const QString &capability);
+
+ /**
+ * Sends the next capability from the queue.
+ *
+ * During nick registration if any capabilities remain queued, this will take the next and
+ * request it. When no capabilities remain, capability negotiation is ended.
+ */
+ void sendNextCap();
+
void setAutoWhoEnabled(bool enabled);
void setAutoWhoInterval(int interval);
void setAutoWhoDelay(int delay);
+ /**
+ * Appends the given channel/nick to the front of the AutoWho queue.
+ *
+ * When 'away-notify' is enabled, this will trigger an immediate AutoWho since regular
+ * who-cycles are disabled as per IRCv3 specifications.
+ *
+ * @param[in] channelOrNick Channel or nickname to WHO
+ */
+ void queueAutoWhoOneshot(const QString &channelOrNick);
+
bool setAutoWhoDone(const QString &channel);
void updateIssuedModes(const QString &requestedModes);
void socketHasData();
void socketError(QAbstractSocket::SocketError);
void socketInitialized();
- inline void socketCloseTimeout() { socket.disconnectFromHost(); }
+ inline void socketCloseTimeout() { socket.abort(); }
void socketDisconnected();
void socketStateChanged(QAbstractSocket::SocketState);
void networkInitialized();
QTimer _pingTimer;
uint _lastPingTime;
uint _pingCount;
+ bool _sendPings;
QStringList _autoWhoQueue;
QHash<QString, int> _autoWhoPending;
QTimer _autoWhoTimer, _autoWhoCycleTimer;
+ // Maintain a list of CAPs that are being checked; if empty, negotiation finished
+ // See http://ircv3.net/specs/core/capability-negotiation-3.2.html
+ QStringList _capsQueued; /// Capabilities to be checked
+ bool _capNegotiationActive; /// Whether or not full capability negotiation was started
+ // Avoid displaying repeat "negotiation finished" messages
+ bool _capInitialNegotiationEnded; /// Whether or not initial capability negotiation finished
+ // Avoid sending repeat "CAP END" replies when registration is already ended
+
+ /**
+ * Gets the next capability to request, removing it from the queue.
+ *
+ * @returns Name of capability to request
+ */
+ QString takeQueuedCap();
+
QTimer _tokenBucketTimer;
int _messageDelay; // token refill speed in ms
int _burstSize; // size of the token bucket
QString _requestedUserModes; // 2 strings separated by a '-' character. first part are requested modes to add, the second to remove
- // Blowfish key map
+ // List of blowfish keys for channels
QHash<QString, QByteArray> _cipherKeys;
};