summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/modules/cap.h25
-rw-r--r--src/modules/m_cap.cpp12
2 files changed, 36 insertions, 1 deletions
diff --git a/include/modules/cap.h b/include/modules/cap.h
index a00089260..1ad2ff2f1 100644
--- a/include/modules/cap.h
+++ b/include/modules/cap.h
@@ -23,11 +23,24 @@
namespace Cap
{
- static const unsigned int MAX_CAPS = sizeof(intptr_t) * 8;
+ static const unsigned int MAX_CAPS = (sizeof(intptr_t) * 8) - 1;
+ static const intptr_t CAP_302_BIT = (intptr_t)1 << MAX_CAPS;
+
typedef intptr_t Ext;
typedef LocalIntExt ExtItem;
class Capability;
+ enum Protocol
+ {
+ /** Supports capability negotiation protocol v3.1, or none
+ */
+ CAP_LEGACY,
+
+ /** Supports capability negotiation v3.2
+ */
+ CAP_302
+ };
+
class Manager : public DataProvider
{
public:
@@ -190,6 +203,16 @@ namespace Cap
*/
bool IsRegistered() const { return (extitem != NULL); }
+ /** Get the CAP negotiation protocol version of a user.
+ * The cap must be registered for this to return anything other than CAP_LEGACY.
+ * @param user User whose negotiation protocol version to query
+ * @return One of the Capability::Protocol enum indicating the highest supported capability negotiation protocol version
+ */
+ Protocol GetProtocol(LocalUser* user) const
+ {
+ return ((IsRegistered() && (extitem->get(user) & CAP_302_BIT)) ? CAP_302 : CAP_LEGACY);
+ }
+
/** Called when a user requests to turn this capability on or off.
* @param user User requesting to change the state of the cap
* @param add True if requesting to turn the cap on, false if requesting to turn it off
diff --git a/src/modules/m_cap.cpp b/src/modules/m_cap.cpp
index 2b4055e3c..4411306ed 100644
--- a/src/modules/m_cap.cpp
+++ b/src/modules/m_cap.cpp
@@ -115,6 +115,16 @@ class Cap::ManagerImpl : public Cap::Manager
return NULL;
}
+ Protocol GetProtocol(LocalUser* user) const
+ {
+ return ((capext.get(user) & CAP_302_BIT) ? CAP_302 : CAP_LEGACY);
+ }
+
+ void Set302Protocol(LocalUser* user)
+ {
+ capext.set(user, capext.get(user) | CAP_302_BIT);
+ }
+
bool HandleReq(LocalUser* user, const std::string& reqlist)
{
Ext usercaps = capext.get(user);
@@ -211,6 +221,8 @@ class CommandCap : public SplitCommand
else if ((subcommand == "LS") || (subcommand == "LIST"))
{
const bool is_ls = (subcommand.length() == 2);
+ if ((is_ls) && (parameters.size() > 1) && (parameters[1] == "302"))
+ manager.Set302Protocol(user);
std::string result = subcommand + " :";
manager.HandleList(result, user, is_ls);