Add support for multi-prefix
[quassel.git] / src / core / corenetwork.h
index e58945a..ae1ebd8 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2012 by the Quassel Project                        *
+ *   Copyright (C) 2005-2015 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -40,6 +40,8 @@
 
 #include "coresession.h"
 
+#include <functional>
+
 class CoreIdentity;
 class CoreUserInputHandler;
 class CoreIgnoreListManager;
@@ -82,6 +84,9 @@ public:
 
     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(); }
@@ -93,6 +98,94 @@ public:
     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 a given capability is enabled.
+     *
+     * @returns True if enabled, otherwise false
+     */
+    inline bool capEnabled(const QString &capability) const { return _capsSupported.contains(capability); }
+
+    /**
+     * Checks if capability negotiation is currently ongoing.
+     *
+     * @returns True if in progress, otherwise false
+     */
+    inline bool capNegotiationInProgress() const { return !_capsQueued.empty(); }
+
+    /**
+     * Gets the value of an enabled or pending capability, e.g. sasl=plain.
+     *
+     * @returns Value of capability if one was specified, otherwise empty string
+     */
+    QString capValue(const QString &capability) const;
+
+    /**
+     * Gets the next capability to request, removing it from the queue.
+     *
+     * @returns Name of capability to request
+     */
+    QString takeQueuedCap();
+
+    // Specific capabilities for easy reference
+
+    /**
+     * Gets the status of the sasl authentication capability.
+     *
+     * http://ircv3.net/specs/extensions/sasl-3.2.html
+     *
+     * @returns True if SASL authentication is enabled, otherwise false
+     */
+    inline bool useCapSASL() const { return capEnabled("sasl"); }
+
+    /**
+     * Gets the status of the away-notify capability.
+     *
+     * http://ircv3.net/specs/extensions/away-notify-3.1.html
+     *
+     * @returns True if away-notify is enabled, otherwise false
+     */
+    inline bool useCapAwayNotify() const { return capEnabled("away-notify"); }
+
+    /**
+     * Gets the status of the account-notify capability.
+     *
+     * http://ircv3.net/specs/extensions/account-notify-3.1.html
+     *
+     * @returns True if account-notify is enabled, otherwise false
+     */
+    inline bool useCapAccountNotify() const { return capEnabled("account-notify"); }
+
+    /**
+     * Gets the status of the extended-join capability.
+     *
+     * http://ircv3.net/specs/extensions/extended-join-3.1.html
+     *
+     * @returns True if extended-join is enabled, otherwise false
+     */
+    inline bool useCapExtendedJoin() const { return capEnabled("extended-join"); }
+
+    /**
+     * Gets the status of the userhost-in-names capability.
+     *
+     * http://ircv3.net/specs/extensions/userhost-in-names-3.2.html
+     *
+     * @returns True if userhost-in-names is enabled, otherwise false
+     */
+    inline bool useCapUserhostInNames() const { return capEnabled("userhost-in-names"); }
+
+    /**
+     * Gets the status of the multi-prefix capability.
+     *
+     * http://ircv3.net/specs/extensions/multi-prefix-3.1.html
+     *
+     * @returns True if multi-prefix is enabled, otherwise false
+     */
+    inline bool useCapMultiPrefix() const { return capEnabled("multi-prefix"); }
+
 public slots:
     virtual void setMyNick(const QString &mynick);
 
@@ -112,6 +205,7 @@ public slots:
     void userInput(BufferInfo bufferInfo, QString msg);
     void putRawLine(QByteArray input);
     void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
+    void putCmd(const QString &cmd, const QList<QList<QByteArray>> &params, const QByteArray &prefix = QByteArray());
 
     void setChannelJoined(const QString &channel);
     void setChannelParted(const QString &channel);
@@ -120,15 +214,64 @@ public slots:
 
     // 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)
+
+    /**
+     * Marks a capability as accepted, providing an optional value.
+     *
+     * Removes it from queue of pending capabilities and triggers any capability-specific
+     * activation.
+     *
+     * @param[in] capability Name of the capability
+     * @param[in] value
+     * @parblock
+     * Optional value of the capability, e.g. sasl=plain.  If left empty, will be copied from the
+     * pending capability.
+     * @endparblock
+     */
+    void addCap(const QString &capability, const QString &value = QString());
+
+    /**
+     * Marks a capability as denied.
+     *
+     * Removes it from the queue of pending capabilities and triggers any capability-specific
+     * deactivation.
+     *
+     * @param[in] capability Name of the capability
+     */
+    void removeCap(const QString &capability);
+
+    /**
+     * Queues a capability as available but not yet accepted or denied.
+     *
+     * Capabilities should be queued when registration pauses for CAP LS for capabilities are only
+     * requested during login.
+     *
+     * @param[in] capability Name of the capability
+     * @param[in] value      Optional value of the capability, e.g. sasl=plain
+     */
+    void queuePendingCap(const QString &capability, const QString &value = QString());
+
     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);
@@ -173,7 +316,7 @@ private slots:
     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();
@@ -225,11 +368,18 @@ private:
     QTimer _pingTimer;
     uint _lastPingTime;
     uint _pingCount;
+    bool _sendPings;
 
     QStringList _autoWhoQueue;
     QHash<QString, int> _autoWhoPending;
     QTimer _autoWhoTimer, _autoWhoCycleTimer;
 
+    // CAPs may have parameter values
+    // See http://ircv3.net/specs/core/capability-negotiation-3.2.html
+    QStringList _capsQueued;                /// Capabilities to be checked
+    QHash<QString, QString> _capsPending;   /// Capabilities pending 'CAP ACK' from server
+    QHash<QString, QString> _capsSupported; /// Enabled capabilities that received 'CAP ACK'
+
     QTimer _tokenBucketTimer;
     int _messageDelay;      // token refill speed in ms
     int _burstSize;         // size of the token bucket
@@ -238,7 +388,7 @@ private:
 
     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;
 };