Merge branch 'master' into unix

This commit is contained in:
Alexey Sokolov
2025-04-18 23:46:16 +01:00
1234 changed files with 149930 additions and 10349 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
#
# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details.
# Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
#
# Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
# Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
+31 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
#include <znc/Nick.h>
#include <znc/ZNCString.h>
#include <znc/Buffer.h>
#include <znc/Translation.h>
#include <map>
// Forward Declarations
@@ -31,7 +32,7 @@ class CConfig;
class CFile;
// !Forward Declarations
class CChan {
class CChan : private CCoreTranslationMixin {
public:
typedef enum {
Voice = '+',
@@ -75,10 +76,24 @@ class CChan {
const CString& sHost);
// Modes
/// @deprecated Use SetModes(CString, VCString)
void SetModes(const CString& s);
/**
* Set the current modes for this channel
* @param sModes The mode characters being changed
* @param vsModeParams The parameters for the modes to be set
*/
void SetModes(const CString& sModes, const VCString& vsModeParams);
/// @deprecated Use ModeChange(CString, VCString, CNick*)
void ModeChange(const CString& sModes, const CNick* OpNick = nullptr);
bool AddMode(unsigned char uMode, const CString& sArg);
bool RemMode(unsigned char uMode);
/**
* Handle changing the modes on a channel
* @param sModes The mode string (eg. +ovbs-pbo)
* @param vsModeParams The parameters for the mode string
*/
void ModeChange(const CString& sModes,const VCString& vsModeParams, const CNick* OpNick = nullptr);
bool AddMode(char cMode, const CString& sArg);
bool RemMode(char cMode);
CString GetModeString() const;
CString GetModeArg(CString& sArgs) const;
CString GetModeForNames() const;
@@ -120,10 +135,14 @@ class CChan {
// !Buffer
// m_Nick wrappers
/// e.g. '@' for chanop.
CString GetPermStr() const { return m_Nick.GetPermStr(); }
bool HasPerm(unsigned char uPerm) const { return m_Nick.HasPerm(uPerm); }
bool AddPerm(unsigned char uPerm) { return m_Nick.AddPerm(uPerm); }
bool RemPerm(unsigned char uPerm) { return m_Nick.RemPerm(uPerm); }
/// e.g. '@' for chanop.
bool HasPerm(char cPerm) const { return m_Nick.HasPerm(cPerm); }
/// e.g. '@' for chanop.
bool AddPerm(char cPerm) { return m_Nick.AddPerm(cPerm); }
/// e.g. '@' for chanop.
bool RemPerm(char cPerm) { return m_Nick.RemPerm(cPerm); }
// !wrappers
// Setters
@@ -154,14 +173,14 @@ class CChan {
// Getters
CIRCNetwork* GetNetwork() const { return m_pNetwork; }
bool IsModeKnown() const { return m_bModeKnown; }
bool HasMode(unsigned char uMode) const;
bool HasMode(char cMode) const;
CString GetOptions() const;
CString GetModeArg(unsigned char uMode) const;
CString GetModeArg(char cMode) const;
std::map<char, unsigned int> GetPermCounts() const;
bool IsOn() const { return m_bIsOn; }
const CString& GetName() const { return m_sName; }
const std::map<unsigned char, CString>& GetModes() const {
return m_musModes;
const std::map<char, CString>& GetModes() const {
return m_mcsModes;
}
const CString& GetKey() const { return m_sKey; }
const CString& GetTopic() const { return m_sTopic; }
@@ -204,7 +223,7 @@ class CChan {
CBuffer m_Buffer;
bool m_bModeKnown;
std::map<unsigned char, CString> m_musModes;
std::map<char, CString> m_mcsModes;
};
#endif // !ZNC_CHAN_H
+79 -84
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ class CMessage;
class CChan;
// !Forward Declarations
class CAuthBase {
class CAuthBase : private CCoreTranslationMixin {
public:
CAuthBase(const CString& sUsername, const CString& sPassword,
CZNCSock* pSock)
@@ -98,71 +98,7 @@ class CClientAuth : public CAuthBase {
class CClient : public CIRCSocket {
public:
CClient()
: CIRCSocket(),
m_bGotPass(false),
m_bGotNick(false),
m_bGotUser(false),
m_bInCap(false),
m_bCapNotify(false),
m_bAwayNotify(false),
m_bAccountNotify(false),
m_bExtendedJoin(false),
m_bNamesx(false),
m_bUHNames(false),
m_bAway(false),
m_bServerTime(false),
m_bBatch(false),
m_bEchoMessage(false),
m_bSelfMessage(false),
m_bPlaybackActive(false),
m_pUser(nullptr),
m_pNetwork(nullptr),
m_sNick("unknown-nick"),
m_sPass(""),
m_sUser(""),
m_sNetwork(""),
m_sIdentifier(""),
m_spAuth(),
m_ssAcceptedCaps(),
m_ssSupportedTags(),
m_mCoreCaps({
{"multi-prefix",
{false, [this](bool bVal) { m_bNamesx = bVal; }}},
{"userhost-in-names",
{false, [this](bool bVal) { m_bUHNames = bVal; }}},
{"echo-message",
{false, [this](bool bVal) { m_bEchoMessage = bVal; }}},
{"server-time",
{false, [this](bool bVal) {
m_bServerTime = bVal;
SetTagSupport("time", bVal);
}}},
{"batch", {false, [this](bool bVal) {
m_bBatch = bVal;
SetTagSupport("batch", bVal);
}}},
{"cap-notify",
{false, [this](bool bVal) { m_bCapNotify = bVal; }}},
{"away-notify",
{true, [this](bool bVal) { m_bAwayNotify = bVal; }}},
{"account-notify",
{true, [this](bool bVal) { m_bAccountNotify = bVal; }}},
{"extended-join",
{true, [this](bool bVal) { m_bExtendedJoin = bVal; }}},
}) {
EnableReadLine();
// RFC says a line can have 512 chars max, but we are
// a little more gentle ;)
SetMaxBufferThreshold(1024);
// For compatibility with older clients
m_mCoreCaps["znc.in/server-time-iso"] = m_mCoreCaps["server-time"];
m_mCoreCaps["znc.in/batch"] = m_mCoreCaps["batch"];
m_mCoreCaps["znc.in/self-message"] = {
false, [this](bool bVal) { m_bSelfMessage = bVal; }};
}
CClient();
virtual ~CClient();
CClient(const CClient&) = delete;
@@ -175,12 +111,15 @@ class CClient : public CIRCSocket {
CString GetNick(bool bAllowIRCNick = true) const;
CString GetNickMask() const;
CString GetIdentifier() const { return m_sIdentifier; }
unsigned short int CapVersion() const { return m_uCapVersion; }
bool HasCap302() const { return CapVersion() >= 302; }
bool HasCapNotify() const { return m_bCapNotify; }
bool HasAwayNotify() const { return m_bAwayNotify; }
bool HasAccountNotify() const { return m_bAccountNotify; }
bool HasExtendedJoin() const { return m_bExtendedJoin; }
bool HasNamesx() const { return m_bNamesx; }
bool HasUHNames() const { return m_bUHNames; }
bool HasChgHost() const { return m_bChgHost; }
bool IsAway() const { return m_bAway; }
bool HasServerTime() const { return m_bServerTime; }
bool HasBatch() const { return m_bBatch; }
@@ -199,14 +138,23 @@ class CClient : public CIRCSocket {
void SetPlaybackActive(bool bActive) { m_bPlaybackActive = bActive; }
void PutIRC(const CString& sLine);
// Strips prefix and potentially tags before sending to server.
void PutIRCStripping(CMessage Message);
/** Sends a raw data line to the client.
* @param sLine The line to be sent.
*
* The line is first passed \e unmodified to the \ref CModule::OnSendToClient()
* module hook. If no module halts the process, the line is then sent to the client.
* The line is first passed \e unmodified to the \ref
* CModule::OnSendToClient() module hook. If no module halts the process,
* the line is then sent to the client.
*
* These lines appear in the debug output in the following syntax:
* \code [time] (user/network) ZNC -> CLI [line] \endcode
*
* Prefer \l PutClient() instead.
*/
bool PutClientRaw(const CString& sLine);
/** Sends a message to the client.
* See \l PutClient(const CMessage&) for details.
*/
void PutClient(const CString& sLine);
/** Sends a message to the client.
@@ -245,14 +193,17 @@ class CClient : public CIRCSocket {
* ----------- | ----------
* \c time | \l CClient::HasServerTime() (<a href="http://ircv3.net/specs/extensions/server-time-3.2.html">server-time</a>)
* \c batch | \l CClient::HasBatch() (<a href="http://ircv3.net/specs/extensions/batch-3.2.html">batch</a>)
*
* Additional tags can be added via \l CClient::SetTagSupport().
*
* @warning Bypassing the filter may cause troubles to some older IRC clients.
* @warning Bypassing the filter may cause troubles to some older IRC
* clients.
*
* It is possible to bypass the filter by converting a message to a string
* using \l CMessage::ToString(), and passing the resulting raw line to the
* \l CClient::PutClient(const CString& sLine) overload:
* \l CClient::PutClientRaw(const CString& sLine):
* \code
* pClient->PutClient(Message.ToString());
* pClient->PutClientRaw(Message.ToString());
* \endcode
*/
bool PutClient(const CMessage& Message);
@@ -269,14 +220,16 @@ class CClient : public CIRCSocket {
bool IsTagEnabled(const CString& sTag) const {
return 1 == m_ssSupportedTags.count(sTag);
}
/** Registers a tag as being supported or unsupported by a client.
/** Registers a tag as being supported or unsupported by the client.
* This doesn't affect tags which the client sends.
* @param sTag The tag to register.
* @param bState Whether the client supports the tag.
*/
void SetTagSupport(const CString& sTag, bool bState);
void NotifyServerDependentCaps(const SCString& ssCaps);
void ClearServerDependentCaps();
/** Notifies client about one specific cap which server has just notified us about.
*/
void NotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue);
void ReadLine(const CString& sData) override;
bool SendMotd();
@@ -299,11 +252,33 @@ class CClient : public CIRCSocket {
CIRCSock* GetIRCSock();
CString GetFullName() const;
/** Sends AUTHENTIATE message to client.
* It encodes it to Base64 and splits to multiple IRC messages if necessary.
*/
void SendSASLChallenge(CString sMessage);
void RefuseSASLLogin(const CString& sReason);
void AcceptSASLLogin(CUser& User);
/** Start potentially asynchronous process of checking the credentials.
* When finished, will send the success/failure SASL numerics to the
* client. This is mostly useful for SASL PLAIN.
* sAuthorizationId is internally passed through ParseUser() to extract
* network and client id.
* Currently sUser should match the username from
* sAuthorizationId: either in full, or just the username part; but in a
* future version we may add an ability to actually login as a different
* user, but with your password.
*/
void StartSASLPasswordCheck(const CString& sUser, const CString& sPassword,
const CString& sAuthorizationId);
/** Gathers username, client id, network name, if present. Returns username
* cleaned from client id and network name.
*/
CString ParseUser(const CString& sAuthLine);
private:
void HandleCap(const CMessage& Message);
void RespondCap(const CString& sResponse);
void ParsePass(const CString& sAuthLine);
void ParseUser(const CString& sAuthLine);
void ParseIdentifier(const CString& sAuthLine);
template <typename T>
@@ -315,6 +290,15 @@ class CClient : public CIRCSocket {
unsigned int DetachChans(const std::set<CChan*>& sChans);
bool OnActionMessage(CActionMessage& Message);
void OnAuthenticateMessage(const CAuthenticateMessage& Message);
void AbortSASL(const CString& sFullIRCLine);
bool IsDuringSASL() const { return !m_sSASLMechanism.empty(); }
/**
* Returns set of all available SASL mechanisms.
*/
SCString EnumerateSASLMechanisms() const;
bool OnCTCPMessage(CCTCPMessage& Message);
bool OnJoinMessage(CJoinMessage& Message);
bool OnModeMessage(CModeMessage& Message);
@@ -323,6 +307,7 @@ class CClient : public CIRCSocket {
bool OnPingMessage(CMessage& Message);
bool OnPongMessage(CMessage& Message);
bool OnQuitMessage(CQuitMessage& Message);
bool OnTagMessage(CTargetMessage& Message);
bool OnTextMessage(CTextMessage& Message);
bool OnTopicMessage(CTopicMessage& Message);
bool OnOtherMessage(CMessage& Message);
@@ -331,6 +316,7 @@ class CClient : public CIRCSocket {
bool m_bGotPass;
bool m_bGotNick;
bool m_bGotUser;
unsigned short int m_uCapVersion;
bool m_bInCap;
bool m_bCapNotify;
bool m_bAwayNotify;
@@ -338,32 +324,41 @@ class CClient : public CIRCSocket {
bool m_bExtendedJoin;
bool m_bNamesx;
bool m_bUHNames;
bool m_bChgHost;
bool m_bAway;
bool m_bServerTime;
bool m_bBatch;
bool m_bEchoMessage;
bool m_bSelfMessage;
bool m_bMessageTagCap;
bool m_bSASLCap;
bool m_bPlaybackActive;
CUser* m_pUser;
CIRCNetwork* m_pNetwork;
CString m_sNick;
CString m_sPass;
// User who didn't necessarily login yet, or might not even exist.
CString m_sUser;
CString m_sNetwork;
CString m_sIdentifier;
CString m_sSASLBuffer;
// Set while the exchange is in progress
CString m_sSASLMechanism;
// Username who successfully logged in using SASL. This is not a CUser*
// because between the 903 and CAP END the user could have been deleted.
CString m_sSASLUser;
std::shared_ptr<CAuthBase> m_spAuth;
SCString m_ssAcceptedCaps;
SCString m_ssSupportedTags;
// The capabilities supported by the ZNC core - capability names mapped
// to a pair which contains a bool describing whether the capability is
// server-dependent, and a capability value change handler.
std::map<CString, std::pair<bool, std::function<void(bool bVal)>>>
m_mCoreCaps;
// A subset of CIRCSock::GetAcceptedCaps(), the caps that can be listed
// in CAP LS and may be notified to the client with CAP NEW (cap-notify).
SCString m_ssServerDependentCaps;
SCString m_ssPreviouslyFailedSASLMechanisms;
// The capabilities supported by the ZNC core - capability names mapped to
// change handler. Note: this lists caps which don't require support on IRC
// server.
static const std::map<CString, std::function<void(CClient*, bool bVal)>>&
CoreCaps();
friend class ClientTest;
friend class CCoreCaps;
};
#endif // !ZNC_CLIENT_H
+16 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,10 +35,11 @@ struct CConfigEntry {
class CConfig {
public:
CConfig() : m_ConfigEntries(), m_SubConfigs() {}
CConfig() : m_ConfigEntries(), m_SubConfigs(), m_SubConfigNameSets() {}
typedef std::map<CString, VCString> EntryMap;
typedef std::map<CString, CConfigEntry> SubConfig;
typedef std::pair<CString, CConfigEntry> SubConfigEntry;
typedef std::vector<SubConfigEntry> SubConfig;
typedef std::map<CString, SubConfig> SubConfigMap;
typedef EntryMap::const_iterator EntryMapIterator;
@@ -62,14 +63,13 @@ class CConfig {
bool AddSubConfig(const CString& sTag, const CString& sName,
CConfig Config) {
SubConfig& conf = m_SubConfigs[sTag];
SubConfig::const_iterator it = conf.find(sName);
auto& nameset = m_SubConfigNameSets[sTag];
if (it != conf.end()) {
return false;
}
if (nameset.find(sName) != nameset.end()) return false;
nameset.insert(sName);
m_SubConfigs[sTag].emplace_back(sName, Config);
conf[sName] = Config;
return true;
}
@@ -142,9 +142,9 @@ class CConfig {
return false;
}
bool FindSubConfig(const CString& sName, SubConfig& Config,
bool FindSubConfig(const CString& sTag, SubConfig& Config,
bool bErase = true) {
SubConfigMap::iterator it = m_SubConfigs.find(sName);
auto it = m_SubConfigs.find(sTag);
if (it == m_SubConfigs.end()) {
Config.clear();
return false;
@@ -153,6 +153,7 @@ class CConfig {
if (bErase) {
m_SubConfigs.erase(it);
m_SubConfigNameSets.erase(sTag);
}
return true;
@@ -166,8 +167,12 @@ class CConfig {
void Write(CFile& file, unsigned int iIndentation = 0);
private:
typedef SCString SubConfigNameSet;
typedef std::map<CString, SubConfigNameSet> SubConfigNameSetMap;
EntryMap m_ConfigEntries;
SubConfigMap m_SubConfigs;
SubConfigNameSetMap m_SubConfigNameSets;
};
#endif // !ZNC_CONFIG_H
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+8 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ class CIRCNetworkPingTimer;
class CIRCNetworkJoinTimer;
class CMessage;
class CIRCNetwork {
class CIRCNetwork : private CCoreTranslationMixin {
public:
static bool IsValidNetwork(const CString& sNetwork);
@@ -93,6 +93,9 @@ class CIRCNetwork {
bool AddChan(CChan* pChan);
bool AddChan(const CString& sName, bool bInConfig);
bool DelChan(const CString& sName);
bool MoveChan(const CString& sChan, unsigned int index, CString& sError);
bool SwapChans(const CString& sChan1, const CString& sChan2,
CString& sError);
void JoinChans();
void JoinChans(std::set<CChan*>& sChans);
@@ -153,8 +156,11 @@ class CIRCNetwork {
void IRCConnected();
void IRCDisconnected();
void CheckIRCConnect();
void NotifyClientsAboutServerDependentCap(const CString& sCap, bool bValue);
bool IsServerCapAccepted(const CString& sCap) const;
bool PutIRC(const CString& sLine);
bool PutIRC(const CMessage& Message);
// Buffers
void AddRawBuffer(const CMessage& Format, const CString& sText = "") {
+73 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,8 +56,49 @@ class CIRCSock : public CIRCSocket {
void SockError(int iErrno, const CString& sDescription) override;
void Timeout() override;
void ReachedMaxBuffer() override;
#ifdef HAVE_LIBSSL
void SSLCertError(X509* pCert) override;
#endif
/** Sends a raw data line to the server.
* @param sLine The line to be sent.
*
* The line is first passed \e unmodified to the \ref
* CModule::OnSendToIRC() module hook. If no module halts the process,
* the line is then sent to the server.
*
* Prefer \l PutIRC() instead.
*/
void PutIRCRaw(const CString& sLine);
/** Sends a message to the server.
* See \l PutIRC(const CMessage&) for details.
*/
void PutIRC(const CString& sLine);
/** Sends a message to the server.
* @param Message The message to be sent.
* @note Only known and compatible messages and tags are sent.
*
* This method can delay the delivery of the message to honor protection
* from flood.
*
* This method ensures that only tags, that were negotiated with CAP REQ
* and CAP ACK, are sent. Not all IRC server are capable of handling all
* messages and tags. Thus, in order to stay compatible with a variety of
* IRC servers, ZNC has to filter out messages and tags that the server
* has not explicitly acknowleged.
*
* Additional tags can be added via \l CIRCSock::SetTagSupport().
*
* @warning Bypassing the filter may cause troubles to some older IRC
* servers.
*
* It is possible to bypass the filter by converting a message to a string
* using \l CMessage::ToString(), and passing the resulting raw line to the
* \l CIRCSock::PutIRCRaw(const CString& sLine):
* \code
* pServer->PutIRCRaw(Message.ToString());
* \endcode
*/
void PutIRC(const CMessage& Message);
void PutIRCQuick(const CString& sLine); //!< Should be used for PONG only
void ResetChans();
void Quit(const CString& sQuitMsg = "");
@@ -71,6 +112,16 @@ class CIRCSock : public CIRCSocket {
* should be resumed again.
*/
void ResumeCap();
bool IsTagEnabled(const CString& sTag) const {
return 1 == m_ssSupportedTags.count(sTag);
}
/** Registers a tag as being supported or unsupported by the server.
* This doesn't affect tags which the server sends.
* @param sTag The tag to register.
* @param bState Whether the client supports the tag.
*/
void SetTagSupport(const CString& sTag, bool bState);
// Setters
void SetPass(const CString& s) { m_sPass = s; }
@@ -78,10 +129,11 @@ class CIRCSock : public CIRCSocket {
// Getters
unsigned int GetMaxNickLen() const { return m_uMaxNickLen; }
EChanModeArgs GetModeType(unsigned char uMode) const;
unsigned char GetPermFromMode(unsigned char uMode) const;
const std::map<unsigned char, EChanModeArgs>& GetChanModes() const {
return m_mueChanModes;
EChanModeArgs GetModeType(char cMode) const;
char GetPermFromMode(char cMode) const;
char GetModeFromPerm(char cPerm) const;
const std::map<char, EChanModeArgs>& GetChanModes() const {
return m_mceChanModes;
}
bool IsPermChar(const char c) const {
return (c != '\0' && GetPerms().find(c) != CString::npos);
@@ -101,15 +153,16 @@ class CIRCSock : public CIRCSocket {
bool HasAccountNotify() const { return m_bAccountNotify; }
bool HasExtendedJoin() const { return m_bExtendedJoin; }
bool HasServerTime() const { return m_bServerTime; }
const std::set<unsigned char>& GetUserModes() const {
return m_scUserModes;
}
bool HasMessageTagCap() const { return m_bMessageTagCap; }
const std::set<char>& GetUserModes() const { return m_scUserModes; }
// This is true if we are past raw 001
bool IsAuthed() const { return m_bAuthed; }
const SCString& GetAcceptedCaps() const { return m_ssAcceptedCaps; }
bool IsCapAccepted(const CString& sCap) {
return 1 == m_ssAcceptedCaps.count(sCap);
}
CString GetCapLsValue(const CString& sKey,
const CString& sDefault = "") const;
const MCString& GetISupport() const { return m_mISupport; }
CString GetISupport(const CString& sKey,
const CString& sDefault = "") const;
@@ -124,6 +177,7 @@ class CIRCSock : public CIRCSocket {
bool OnActionMessage(CActionMessage& Message);
bool OnAwayMessage(CMessage& Message);
bool OnCapabilityMessage(CMessage& Message);
bool OnChgHostMessage(CChgHostMessage& Message);
bool OnCTCPMessage(CCTCPMessage& Message);
bool OnErrorMessage(CMessage& Message);
bool OnInviteMessage(CMessage& Message);
@@ -137,10 +191,11 @@ class CIRCSock : public CIRCSocket {
bool OnPingMessage(CMessage& Message);
bool OnPongMessage(CMessage& Message);
bool OnQuitMessage(CQuitMessage& Message);
bool OnTagMessage(CTargetMessage& Message);
bool OnTextMessage(CTextMessage& Message);
bool OnTopicMessage(CTopicMessage& Message);
bool OnWallopsMessage(CMessage& Message);
bool OnServerCapAvailable(const CString& sCap);
bool OnServerCapAvailable(const CString& sCap, const CString& sValue);
// !Message Handlers
void SetNick(const CString& sNick);
@@ -158,10 +213,11 @@ class CIRCSock : public CIRCSocket {
bool m_bAccountNotify;
bool m_bExtendedJoin;
bool m_bServerTime;
bool m_bMessageTagCap;
CString m_sPerms;
CString m_sPermModes;
std::set<unsigned char> m_scUserModes;
std::map<unsigned char, EChanModeArgs> m_mueChanModes;
std::set<char> m_scUserModes;
std::map<char, EChanModeArgs> m_mceChanModes;
CIRCNetwork* m_pNetwork;
CNick m_Nick;
CString m_sPass;
@@ -170,18 +226,22 @@ class CIRCSock : public CIRCSocket {
unsigned int m_uCapPaused;
SCString m_ssAcceptedCaps;
SCString m_ssPendingCaps;
MCString m_msCapLsValues;
time_t m_lastCTCP;
unsigned int m_uNumCTCP;
static const time_t m_uCTCPFloodTime;
static const unsigned int m_uCTCPFloodCount;
MCString m_mISupport;
std::deque<CString> m_vsSendQueue;
std::deque<CMessage> m_vSendQueue;
short int m_iSendsAllowed;
unsigned short int m_uFloodBurst;
double m_fFloodRate;
bool m_bFloodProtection;
SCString m_ssSupportedTags;
VCString m_vsSSLError;
friend class CIRCFloodTimer;
friend class CCoreCaps;
};
#endif // !ZNC_IRCSOCK_H
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+67 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,17 +17,10 @@
#ifndef ZNC_MESSAGE_H
#define ZNC_MESSAGE_H
// Remove this after Feb 2016 when Debian 7 is EOL
#if __cpp_ref_qualifiers >= 200710
#define ZNC_LVREFQUAL &
#elif defined(__clang__)
#define ZNC_LVREFQUAL &
#elif __GNUC__ > 4 || \
__GNUC__ == 4 && (__GNUC_MINOR__ > 8 || \
__GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 1)
#define ZNC_LVREFQUAL &
#ifdef SWIG
#define ZNC_MSG_DEPRECATED(msg)
#else
#define ZNC_LVREFQUAL
#define ZNC_MSG_DEPRECATED(msg) __attribute__((deprecated(msg)))
#endif
#include <znc/zncconfig.h>
@@ -55,7 +48,8 @@ class CIRCNetwork;
* - `nick` is the sender, which can be obtained with GetNick()
* - `cmd` is command, which is obtained via GetCommand()
* - `0`, `1`, ... are parameters, available via GetParam(n), which removes the
* leading colon (:). If you don't want to remove the colon, use GetParams().
* leading colon (:). If you don't want to remove the colon, use
* GetParamsColon().
*
* For certain events, like a PRIVMSG, convienience commands like GetChan() and
* GetNick() are available, this is not true for all CMessage extensions.
@@ -71,8 +65,10 @@ class CMessage {
Unknown,
Account,
Action,
Authenticate,
Away,
Capability,
ChgHost,
CTCP,
Error,
Invite,
@@ -86,6 +82,7 @@ class CMessage {
Ping,
Pong,
Quit,
TagMsg,
Text,
Topic,
Wallops,
@@ -114,8 +111,27 @@ class CMessage {
void SetCommand(const CString& sCommand);
const VCString& GetParams() const { return m_vsParams; }
CString GetParams(unsigned int uIdx, unsigned int uLen = -1) const;
/**
* Get a subset of the message parameters
*
* This allows accessing a vector of a specific range of parameters,
* allowing easy inline use, such as `pChan->SetModes(Message.GetParam(2), Message.GetParamsSplit(3));`
*
* @param uIdx The index of the first parameter to retrieve
* @param uLen How many parameters to retrieve
* @return A VCString containing the retrieved parameters
*/
VCString GetParamsSplit(unsigned int uIdx, unsigned int uLen = -1) const;
void SetParams(const VCString& vsParams);
void SetParams(VCString&& vsParams);
/// @deprecated use GetParamsColon() instead.
CString GetParams(unsigned int uIdx, unsigned int uLen = -1) const
ZNC_MSG_DEPRECATED("Use GetParamsColon() instead") {
return GetParamsColon(uIdx, uLen);
}
CString GetParamsColon(unsigned int uIdx, unsigned int uLen = -1) const;
CString GetParam(unsigned int uIdx) const;
void SetParam(unsigned int uIdx, const CString& sParam);
@@ -124,6 +140,7 @@ class CMessage {
void SetTime(const timeval& ts) { m_time = ts; }
const MCString& GetTags() const { return m_mssTags; }
MCString& GetTags() { return m_mssTags; }
void SetTags(const MCString& mssTags) { m_mssTags = mssTags; }
CString GetTag(const CString& sKey) const;
@@ -136,12 +153,12 @@ class CMessage {
};
CString ToString(unsigned int uFlags = IncludeAll) const;
void Parse(CString sMessage);
void Parse(const CString& sMessage);
// Implicit and explicit conversion to a subclass reference.
#ifndef SWIG
template <typename M>
M& As() ZNC_LVREFQUAL {
M& As() & {
static_assert(std::is_base_of<CMessage, M>{},
"Must be subclass of CMessage");
static_assert(sizeof(M) == sizeof(CMessage),
@@ -150,7 +167,7 @@ class CMessage {
}
template <typename M>
const M& As() const ZNC_LVREFQUAL {
const M& As() const& {
static_assert(std::is_base_of<CMessage, M>{},
"Must be subclass of CMessage");
static_assert(sizeof(M) == sizeof(CMessage),
@@ -160,12 +177,12 @@ class CMessage {
template <typename M, typename = typename std::enable_if<
std::is_base_of<CMessage, M>{}>::type>
operator M&() ZNC_LVREFQUAL {
operator M&() & {
return As<M>();
}
template <typename M, typename = typename std::enable_if<
std::is_base_of<CMessage, M>{}>::type>
operator const M&() const ZNC_LVREFQUAL {
operator const M&() const& {
return As<M>();
}
// REGISTER_ZNC_MESSAGE allows SWIG to instantiate correct .As<> calls.
@@ -225,6 +242,13 @@ class CActionMessage : public CTargetMessage {
};
REGISTER_ZNC_MESSAGE(CActionMessage);
class CAuthenticateMessage : public CMessage {
public:
CString GetText() const { return GetParam(0); }
void SetText(const CString& sText) { SetParam(0, sText); }
};
REGISTER_ZNC_MESSAGE(CAuthenticateMessage);
class CCTCPMessage : public CTargetMessage {
public:
bool IsReply() const { return GetCommand().Equals("NOTICE"); }
@@ -244,7 +268,14 @@ REGISTER_ZNC_MESSAGE(CJoinMessage);
class CModeMessage : public CTargetMessage {
public:
CString GetModes() const { return GetParams(1).TrimPrefix_n(":"); }
/// @deprecated Use GetModeList() and GetModeParams()
CString GetModes() const { return GetParamsColon(1).TrimPrefix_n(":"); }
CString GetModeList() const { return GetParam(1); };
VCString GetModeParams() const { return GetParamsSplit(2); };
bool HasModes() const { return !GetModeList().empty(); };
};
REGISTER_ZNC_MESSAGE(CModeMessage);
@@ -275,6 +306,8 @@ class CKickMessage : public CTargetMessage {
void SetKickedNick(const CString& sNick) { SetParam(1, sNick); }
CString GetReason() const { return GetParam(2); }
void SetReason(const CString& sReason) { SetParam(2, sReason); }
CString GetText() const { return GetReason(); }
void SetText(const CString& sText) { SetReason(sText); }
};
REGISTER_ZNC_MESSAGE(CKickMessage);
@@ -282,6 +315,8 @@ class CPartMessage : public CTargetMessage {
public:
CString GetReason() const { return GetParam(1); }
void SetReason(const CString& sReason) { SetParam(1, sReason); }
CString GetText() const { return GetReason(); }
void SetText(const CString& sText) { SetReason(sText); }
};
REGISTER_ZNC_MESSAGE(CPartMessage);
@@ -289,6 +324,8 @@ class CQuitMessage : public CMessage {
public:
CString GetReason() const { return GetParam(0); }
void SetReason(const CString& sReason) { SetParam(0, sReason); }
CString GetText() const { return GetReason(); }
void SetText(const CString& sText) { SetReason(sText); }
};
REGISTER_ZNC_MESSAGE(CQuitMessage);
@@ -303,7 +340,18 @@ class CTopicMessage : public CTargetMessage {
public:
CString GetTopic() const { return GetParam(1); }
void SetTopic(const CString& sTopic) { SetParam(1, sTopic); }
CString GetText() const { return GetTopic(); }
void SetText(const CString& sText) { SetTopic(sText); }
};
REGISTER_ZNC_MESSAGE(CTopicMessage);
class CChgHostMessage : public CMessage {
public:
CString GetNewIdent() const { return GetParam(0); }
void SetNewIdent(const CString& sIdent) { SetParam(0, sIdent); }
CString GetNewHost() const { return GetParam(1); }
void SetNewHost(const CString& sHost) { SetParam(1, sHost); }
};
REGISTER_ZNC_MESSAGE(CChgHostMessage);
#endif // !ZNC_MESSAGE_H
+170 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include <znc/main.h>
#include <znc/Translation.h>
#include <functional>
#include <memory>
#include <set>
#include <queue>
#include <sys/time.h>
@@ -166,6 +167,19 @@ class CFPTimer;
class CSockManager;
// !Forward Declarations
class CCapability {
public:
virtual ~CCapability() = default;
virtual void OnServerChangedSupport(CIRCNetwork* pNetwork, bool bState) {}
virtual void OnClientChangedSupport(CClient* pClient, bool bState) {}
CModule* GetModule() { return m_pModule; }
void SetModule(CModule* p) { m_pModule = p; }
protected:
CModule* m_pModule = nullptr;
};
class CTimer : public CCron {
public:
CTimer(CModule* pModule, unsigned int uInterval, unsigned int uCycles,
@@ -335,7 +349,7 @@ CModule* TModLoad(ModHandle p, CUser* pUser, CIRCNetwork* pNetwork,
}
/** A helper class for handling commands in modules. */
class CModCommand {
class CModCommand : private CCoreTranslationMixin {
public:
/// Type for the callback function that handles the actual command.
typedef void (CModule::*ModCmdFunc)(const CString& sLine);
@@ -575,16 +589,21 @@ class CModule {
* @param pOpNick The nick who sent the mode change, or nullptr if set by server.
* @param Nick The nick whose channel mode changes.
* @param Channel The channel on which the user mode is changed.
* @param uMode The mode character that is changed, e.g. '@' for op.
* @param cMode The mode character that is changed, e.g. '@' for op.
* @param bAdded True if the mode is added, else false.
* @param bNoChange true if this mode change doesn't change anything
* because the nick already had this permission.
* @see CIRCSock::GetModeType() for converting uMode into a mode (e.g.
* 'o' for op).
*/
virtual void OnChanPermission3(const CNick* pOpNick, const CNick& Nick,
CChan& Channel, char cMode,
bool bAdded, bool bNoChange);
/// @deprecated. Use OnChanPermission3.
virtual void OnChanPermission2(const CNick* pOpNick, const CNick& Nick,
CChan& Channel, unsigned char uMode,
bool bAdded, bool bNoChange);
/// @deprecated. Use OnChanPermission3.
virtual void OnChanPermission(const CNick& OpNick, const CNick& Nick,
CChan& Channel, unsigned char uMode,
bool bAdded, bool bNoChange);
@@ -800,7 +819,6 @@ class CModule {
/** This module hook is called when a client sends a raw traffic line to ZNC.
* @param sLine The raw traffic line sent.
* @note The line does not include message tags. Use OnUserRawMessage() to access them.
* @return See CModule::EModRet.
*/
virtual EModRet OnUserRaw(CString& sLine);
@@ -994,13 +1012,28 @@ class CModule {
virtual EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sTopic);
/** Called for every CAP received via CAP LS from server.
* If you need to also advertise the cap to clients, use
* AddServerDependentCapability() instead.
* @param sCap capability supported by server.
* @return true if your module supports this CAP and
* needs to turn it on with CAP REQ.
*/
virtual bool OnServerCapAvailable(const CString& sCap);
/** Called for every CAP received via CAP LS from server.
* By default just calls OnServerCapAvailable() without sValue, so
* overriding one of the two is enough.
* If you need to also advertise the cap to clients, use
* AddServerDependentCapability() instead.
* @param sCap capability name supported by server.
* @param sValue value.
* @return true if your module supports this CAP and
* needs to turn it on with CAP REQ.
*/
virtual bool OnServerCap302Available(const CString& sCap, const CString& sValue);
/** Called for every CAP accepted or rejected by server
* (with CAP ACK or CAP NAK after our CAP REQ).
* If you need to also advertise the cap to clients, use
* AddServerDependentCapability() instead.
* @param sCap capability accepted/rejected by server.
* @param bSuccess true if capability was accepted, false if rejected.
*/
@@ -1046,14 +1079,39 @@ class CModule {
/// @deprecated Use OnSendToIRCMessage() instead.
virtual EModRet OnSendToIRC(CString& sLine);
/** This module hook is called when a user sends a TAGMSG message.
* @since 1.10.0
* @param Message The message which was sent.
* @return See CModule::EModRet.
*/
virtual EModRet OnUserTagMessage(CTargetMessage& Message);
/** Called when we receive a channel TAGMSG message <em>from IRC</em>.
* @since 1.10.0
* @param Message The channel message.
* @return See CModule::EModRet.
*/
virtual EModRet OnChanTagMessage(CTargetMessage& Message);
/** Called when we receive a private TAGMSG message <em>from IRC</em>.
* @since 1.10.0
* @param Message The message.
* @return See CModule::EModRet.
*/
virtual EModRet OnPrivTagMessage(CTargetMessage& Message);
ModHandle GetDLL() { return m_pDLL; }
/** This function sends a given raw IRC line to the IRC server, if we
/** This function sends a given IRC line to the IRC server, if we
* are connected to one. Else this line is discarded.
* @param sLine The line which should be sent.
* @return true if the line was queued for sending.
*/
virtual bool PutIRC(const CString& sLine);
/** This function sends a given IRC message to the IRC server, if we
* are connected to one. Else this message is discarded.
* @param Message The message which should be sent.
* @return true if the message was queued for sending.
*/
virtual bool PutIRC(const CMessage& Message);
/** This function sends a given raw IRC line to a client.
* If we are in a module hook which is called for a specific client,
* only that client will get the line, else all connected clients will
@@ -1273,8 +1331,32 @@ class CModule {
virtual EModRet OnUnknownUserRaw(CClient* pClient, CString& sLine);
virtual EModRet OnUnknownUserRawMessage(CMessage& Message);
/** Called after login, and also during JumpNetwork. */
virtual void OnClientAttached();
/** Called upon disconnect, and also during JumpNetwork. */
virtual void OnClientDetached();
#ifndef SWIG
/** Simple API to support client capabilities which depend on server to support that capability.
* It is built on top of other CAP related API, but removes boilerplate,
* and handles some tricky cases related to cap-notify and JumpNetwork. To
* use, create a subclass of CCapability, and pass to this function; it
* will automatically set the module pointer, then call the callbacks to
* notify you when server and client accepted support of the capability, or
* stopped supporting it. Note that it's not a strict toggle: e.g.
* sometimes client will disable the cap even when it was already disabled
* for that client.
* For perl and python modules, this function accepts 3 parameters:
* name, server callback, client callback; signatures of the callbacks are
* the same as of the virtual functions you'd implement in C++.
*/
void AddServerDependentCapability(const CString& sName, std::unique_ptr<CCapability> pCap);
#endif
/** Called when a client told us CAP LS. Use ssCaps.insert("cap-name")
* for announcing capabilities which your module supports.
* If you need to adverite the cap to clients only when it's also supported
* by the server, use AddServerDependentCapability() instead.
* @param pClient The client which requested the list.
* @param ssCaps set of caps which will be sent to client.
*/
@@ -1288,6 +1370,8 @@ class CModule {
virtual bool IsClientCapSupported(CClient* pClient, const CString& sCap,
bool bState);
/** Called when we actually need to turn a capability on or off for a client.
* If you need to adverite the cap to clients only when it's also supported
* by the server, use AddServerDependentCapability() instead.
* If implementing a custom capability, make sure to call
* pClient->SetTagSupport("tag-name", bState) for each tag that the
* capability provides.
@@ -1299,6 +1383,47 @@ class CModule {
virtual void OnClientCapRequest(CClient* pClient, const CString& sCap,
bool bState);
/** Called when a client requests SASL authentication. Use ssMechanisms.insert("MECHANISM")
* for announcing SASL mechanisms which your module supports.
* @param ssMechanisms The set of supported SASL mechanisms to append to.
* @since 1.10.0
*/
virtual void OnClientGetSASLMechanisms(SCString& ssMechanisms);
/** Called when a client has selected a SASL mechanism for SASL authentication.
* If implementing a SASL authentication mechanism, set sResponse to
* specify an initial challenge message to send to the client. Otherwise, an
* empty response will be sent. To avoid sending any immediate response,
* return HALT; in that case the module should schedule calling
* GetClient()->SendSASLChallenge() with the initial response: in IRC SASL,
* server always responds first.
* @param sMechanism The SASL mechanism selected by the client.
* @param sResponse The optional value of an initial SASL challenge message
* to send to the client.
* @since 1.10.0
*/
virtual EModRet OnClientSASLServerInitialChallenge(
const CString& sMechanism, CString& sResponse);
/** Called when a client is sending us a SASL message after the mechanism was selected.
* If implementing a SASL authentication mechanism, check the passed
* credentials, then either request more data by sending a challenge in
* GetClient()->SendSASLChallenge(), or reject authentication by calling
* GetClient()->RefuseSASLLogin(), or accept it by calling
* GetClient()->AcceptSASLLogin().
* At some point before accepting the login, you should call
* GetClient()->ParseUser(authz-id) to let it know the network name to
* attach to and the client id.
* @param sMechanism The SASL mechanism selected by the client.
* @param sMessage The SASL opaque value/credentials sent by the client,
* after debase64ing and concatenating if it was split.
* @since 1.10.0
*/
virtual EModRet OnClientSASLAuthenticate(const CString& sMechanism,
const CString& sMessage);
/** Called when a client sent '*' to abort SASL, or aborted it for another reason.
* @since 1.10.0
*/
virtual void OnClientSASLAborted();
/** Called when a module is going to be loaded.
* @param sModName name of the module.
* @param eType wanted type of the module (user/global).
@@ -1349,6 +1474,26 @@ class CModule {
const CString& sContext = "") const;
#endif
// Default implementations of several callbacks to make
// AddServerDependentCapability work in modpython/modperl.
// Don't worry about existence of these functions.
bool InternalServerDependentCapsOnServerCap302Available(
const CString& sCap, const CString& sValue);
void InternalServerDependentCapsOnServerCapResult(const CString& sCap,
bool bSuccess);
void InternalServerDependentCapsOnClientCapLs(CClient* pClient,
SCString& ssCaps);
bool InternalServerDependentCapsIsClientCapSupported(CClient* pClient,
const CString& sCap,
bool bState);
void InternalServerDependentCapsOnClientCapRequest(CClient* pClient,
const CString& sCap,
bool bState);
void InternalServerDependentCapsOnClientAttached();
void InternalServerDependentCapsOnClientDetached();
void InternalServerDependentCapsOnIRCConnected();
void InternalServerDependentCapsOnIRCDisconnected();
protected:
CModInfo::EModuleType m_eType;
CString m_sDescription;
@@ -1368,6 +1513,7 @@ class CModule {
CString m_sArgs;
CString m_sModPath;
CTranslationDomainRefHolder m_Translation;
std::map<CString, std::unique_ptr<CCapability>> m_mServerDependentCaps;
private:
MCString
@@ -1376,7 +1522,7 @@ class CModule {
std::map<CString, CModCommand> m_mCommands;
};
class CModules : public std::vector<CModule*> {
class CModules : public std::vector<CModule*>, private CCoreTranslationMixin {
public:
CModules();
~CModules();
@@ -1404,6 +1550,9 @@ class CModules : public std::vector<CModule*> {
CString& sRealName);
bool OnBroadcast(CString& sMessage);
bool OnChanPermission3(const CNick* pOpNick, const CNick& Nick,
CChan& Channel, char cMode, bool bAdded,
bool bNoChange);
bool OnChanPermission2(const CNick* pOpNick, const CNick& Nick,
CChan& Channel, unsigned char uMode, bool bAdded,
bool bNoChange);
@@ -1498,6 +1647,9 @@ class CModules : public std::vector<CModule*> {
bool OnUserTopicRequest(CString& sChannel);
bool OnUserQuit(CString& sMessage);
bool OnUserQuitMessage(CQuitMessage& Message);
bool OnUserTagMessage(CTargetMessage& Message);
bool OnChanTagMessage(CTargetMessage& Message);
bool OnPrivTagMessage(CTargetMessage& Message);
bool OnCTCPReply(CNick& Nick, CString& sMessage);
bool OnCTCPReplyMessage(CCTCPMessage& Message);
@@ -1528,8 +1680,10 @@ class CModules : public std::vector<CModule*> {
bool OnSendToClientMessage(CMessage& Message);
bool OnSendToIRC(CString& sLine);
bool OnSendToIRCMessage(CMessage& Message);
bool OnClientAttached();
bool OnClientDetached();
bool OnServerCapAvailable(const CString& sCap);
bool OnServerCapAvailable(const CString& sCap, const CString& sValue);
bool OnServerCapResult(const CString& sCap, bool bSuccess);
CModule* FindModule(const CString& sModule) const;
@@ -1574,6 +1728,14 @@ class CModules : public std::vector<CModule*> {
bool IsClientCapSupported(CClient* pClient, const CString& sCap,
bool bState);
bool OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState);
bool OnClientGetSASLMechanisms(SCString& ssMechanisms);
bool OnClientSASLAborted();
bool OnClientSASLServerInitialChallenge(const CString& sMechanism,
CString& sResponse);
bool OnClientSASLAuthenticate(const CString& sMechanism,
const CString& sBuffer);
bool OnModuleLoading(const CString& sModName, const CString& sArgs,
CModInfo::EModuleType eType, bool& bSuccess,
CString& sRetMsg);
@@ -1587,6 +1749,7 @@ class CModules : public std::vector<CModule*> {
private:
static ModHandle OpenModule(const CString& sModule, const CString& sModPath,
CModInfo& Info, CString& sRetMsg);
static bool ValidateModuleName(const CString& sModule, CString& sRetMsg);
protected:
CUser* m_pUser;
+10 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,14 +47,19 @@ class CNick {
void SetNick(const CString& s);
void SetIdent(const CString& s);
void SetHost(const CString& s);
bool AddPerm(unsigned char uPerm);
bool RemPerm(unsigned char uPerm);
/// e.g. '@' for chanop.
bool AddPerm(char cPerm);
/// e.g. '@' for chanop.
bool RemPerm(char cPerm);
// !Setters
// Getters
/// e.g. '@' for chanop.
CString GetPermStr() const;
unsigned char GetPermChar() const;
bool HasPerm(unsigned char uPerm) const;
/// e.g. '@' for chanop.
char GetPermChar() const;
/// e.g. '@' for chanop.
bool HasPerm(char cPerm) const;
const CString& GetNick() const;
const CString& GetIdent() const;
const CString& GetHost() const;
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+9 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
class CModule;
class CZNCSock : public Csock, public CCoreTranslationMixin {
class CZNCSock : public Csock, protected CCoreTranslationMixin {
public:
CZNCSock(int timeout = 60);
CZNCSock(const CString& sHost, u_short port, int timeout = 60);
@@ -36,12 +36,16 @@ class CZNCSock : public Csock, public CCoreTranslationMixin {
int VerifyPeerCertificate(int iPreVerify,
X509_STORE_CTX* pStoreCTX) override;
void SSLHandShakeFinished() override;
bool CheckSSLCert(X509* pCert);
virtual void SSLCertError(X509* pCert) {}
bool SNIConfigureClient(CString& sHostname) override;
CString GetSSLPeerFingerprint(X509* pCert = nullptr) const;
#else
CString GetSSLPeerFingerprint() const { return ""; }
#endif
void SetHostToVerifySSL(const CString& sHost) {
m_sHostToVerifySSL = sHost;
}
CString GetSSLPeerFingerprint() const;
void SetSSLTrustedPeerFingerprints(const SCString& ssFPs) {
m_ssTrustedFingerprints = ssFPs;
}
@@ -72,7 +76,8 @@ class CZNCSock : public Csock, public CCoreTranslationMixin {
enum EAddrType { ADDR_IPV4ONLY, ADDR_IPV6ONLY, ADDR_ALL };
class CSockManager : public TSocketManager<CZNCSock> {
class CSockManager : public TSocketManager<CZNCSock>,
private CCoreTranslationMixin {
public:
CSockManager();
virtual ~CSockManager();
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+9 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <znc/ZNCString.h>
#include <unordered_map>
#include <variant>
struct CTranslationInfo {
static std::map<CString, CTranslationInfo> GetTranslations();
@@ -83,20 +84,18 @@ class CDelayedTranslation {
class COptionalTranslation {
public:
COptionalTranslation(const CString& sText)
: m_bTranslating(false), m_sText(sText) {}
COptionalTranslation(const CString& sText) : m_text(sText) {}
COptionalTranslation(const char* s) : COptionalTranslation(CString(s)) {}
COptionalTranslation(const CDelayedTranslation& dTranslation)
: m_bTranslating(true), m_dTranslation(dTranslation) {}
COptionalTranslation(const CDelayedTranslation& dTranslation) : m_text(dTranslation) {}
CString Resolve() const {
return m_bTranslating ? m_dTranslation.Resolve() : m_sText;
if (m_text.index() == 0) {
return std::get<0>(m_text);
}
return std::get<1>(m_text).Resolve();
}
private:
bool m_bTranslating;
// TODO switch to std::variant<CString, CDelayedTranslation> after C++17
CString m_sText;
CDelayedTranslation m_dTranslation;
std::variant<CString, CDelayedTranslation> m_text;
};
// Used by everything except modules.
+47 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
#include <znc/Utils.h>
#include <znc/Buffer.h>
#include <znc/Nick.h>
#include <znc/Translation.h>
#include <set>
#include <vector>
@@ -34,9 +35,9 @@ class CIRCSock;
class CUserTimer;
class CServer;
class CUser {
class CUser : private CCoreTranslationMixin {
public:
CUser(const CString& sUserName);
CUser(const CString& sUsername);
~CUser();
CUser(const CUser&) = delete;
@@ -44,31 +45,38 @@ class CUser {
bool ParseConfig(CConfig* Config, CString& sError);
// TODO refactor this
enum eHashType {
HASH_NONE,
HASH_MD5,
HASH_SHA256,
HASH_ARGON2ID,
HASH_DEFAULT = HASH_SHA256
// This should be kept in sync with CUtils::SaltedHash
#if ZNC_HAVE_ARGON
HASH_DEFAULT = HASH_ARGON2ID,
#else
HASH_DEFAULT = HASH_SHA256,
#endif
};
// If you change the default hash here and in HASH_DEFAULT,
// don't forget CUtils::sDefaultHash!
// TODO refactor this
static CString SaltedHash(const CString& sPass, const CString& sSalt) {
return CUtils::SaltedSHA256Hash(sPass, sSalt);
return CUtils::SaltedHash(sPass, sSalt);
}
CConfig ToConfig() const;
bool CheckPass(const CString& sPass) const;
/** Checks password, may upgrade the hash method. */
bool CheckPass(const CString& sPass);
bool AddAllowedHost(const CString& sHostMask);
bool RemAllowedHost(const CString& sHostMask);
void ClearAllowedHosts();
bool IsHostAllowed(const CString& sHost) const;
bool IsValid(CString& sErrMsg, bool bSkipPass = false) const;
static bool IsValidUserName(const CString& sUserName);
static CString MakeCleanUserName(const CString& sUserName);
static bool IsValidUsername(const CString& sUsername);
/** @deprecated Use IsValidUsername() instead. */
static bool IsValidUserName(const CString& sUsername);
static CString MakeCleanUsername(const CString& sUsername);
/** @deprecated Use MakeCleanUsername() instead. */
static CString MakeCleanUserName(const CString& sUsername);
// Modules
CModules& GetModules() { return *m_pModules; }
@@ -88,7 +96,10 @@ class CUser {
bool PutUser(const CString& sLine, CClient* pClient = nullptr,
CClient* pSkipClient = nullptr);
bool PutAllUser(const CString& sLine, CClient* pClient = nullptr,
CClient* pSkipClient = nullptr);
CClient* pSkipClient = nullptr)
ZNC_MSG_DEPRECATED("Use PutUser() instead") {
return PutUser(sLine, pClient, pSkipClient);
}
bool PutStatus(const CString& sLine, CClient* pClient = nullptr,
CClient* pSkipClient = nullptr);
bool PutStatusNotice(const CString& sLine, CClient* pClient = nullptr,
@@ -110,6 +121,7 @@ class CUser {
CString AddTimestamp(const CString& sStr) const;
CString AddTimestamp(time_t tm, const CString& sStr) const;
CString AddTimestamp(timeval tv, const CString& sStr) const;
void CloneNetworks(const CUser& User);
bool Clone(const CUser& User, CString& sErrorRet,
@@ -131,6 +143,11 @@ class CUser {
void SetDenyLoadMod(bool b);
void SetAdmin(bool b);
void SetDenySetBindHost(bool b);
void SetDenySetIdent(bool b);
void SetDenySetNetwork(bool b);
void SetDenySetRealName(bool b);
void SetDenySetQuitMsg(bool b);
void SetDenySetCTCPReplies(bool b);
bool SetStatusPrefix(const CString& s);
void SetDefaultChanModes(const CString& s);
void SetClientEncoding(const CString& s);
@@ -149,6 +166,7 @@ class CUser {
void SetTimestampFormat(const CString& s) { m_sTimestampFormat = s; }
void SetTimestampAppend(bool b) { m_bAppendTimestamp = b; }
void SetTimestampPrepend(bool b) { m_bPrependTimestamp = b; }
void SetAuthOnlyViaModule(bool b) { m_bAuthOnlyViaModule = b; }
void SetTimezone(const CString& s) { m_sTimezone = s; }
void SetJoinTries(unsigned int i) { m_uMaxJoinTries = i; }
void SetMaxJoins(unsigned int i) { m_uMaxJoins = i; }
@@ -161,7 +179,9 @@ class CUser {
// Getters
const std::vector<CClient*>& GetUserClients() const { return m_vClients; }
std::vector<CClient*> GetAllClients() const;
/** @deprecated Use GetUsername() instead. */
const CString& GetUserName() const;
const CString& GetUsername() const;
const CString& GetCleanUserName() const;
const CString& GetNick(bool bAllowDefault = true) const;
const CString& GetAltNick(bool bAllowDefault = true) const;
@@ -183,7 +203,13 @@ class CUser {
bool DenyLoadMod() const;
bool IsAdmin() const;
bool DenySetBindHost() const;
bool DenySetIdent() const;
bool DenySetNetwork() const;
bool DenySetRealName() const;
bool DenySetQuitMsg() const;
bool DenySetCTCPReplies() const;
bool MultiClients() const;
bool AuthOnlyViaModule() const;
const CString& GetStatusPrefix() const;
const CString& GetDefaultChanModes() const;
/** How long must an IRC connection be idle before ZNC sends a ping */
@@ -216,8 +242,8 @@ class CUser {
// !Getters
protected:
const CString m_sUserName;
const CString m_sCleanUserName;
const CString m_sUsername;
const CString m_sCleanUsername;
CString m_sNick;
CString m_sAltNick;
CString m_sIdent;
@@ -244,11 +270,17 @@ class CUser {
bool m_bDenyLoadMod;
bool m_bAdmin;
bool m_bDenySetBindHost;
bool m_bDenySetIdent;
bool m_bDenySetNetwork;
bool m_bDenySetRealName;
bool m_bDenySetQuitMsg;
bool m_bDenySetCTCPReplies;
bool m_bAutoClearChanBuffer;
bool m_bAutoClearQueryBuffer;
bool m_bBeingDeleted;
bool m_bAppendTimestamp;
bool m_bPrependTimestamp;
bool m_bAuthOnlyViaModule;
CUserTimer* m_pUserTimer;
+51 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ class CUtils {
static CString GetIP(unsigned long addr);
static unsigned long GetLongIP(const CString& sIP);
static CString GetHostName();
static void PrintError(const CString& sMessage);
static void PrintMessage(const CString& sMessage, bool bStrong = false);
@@ -51,15 +52,16 @@ class CUtils {
static void PrintAction(const CString& sMessage);
static void PrintStatus(bool bSuccess, const CString& sMessage = "");
#ifndef SWIGPERL
// TODO refactor this
static const CString sDefaultHash;
#endif
/** Asks password from stdin, with confirmation.
*
* @returns Piece of znc.conf with <Pass> block
* */
static CString AskSaltedHashPassForConfig();
static CString GetSaltedHashPass(CString& sSalt);
static CString GetSalt();
static CString SaltedMD5Hash(const CString& sPass, const CString& sSalt);
static CString SaltedSHA256Hash(const CString& sPass, const CString& sSalt);
static CString SaltedHash(const CString& sPass, const CString& sSalt);
static CString GetPass(const CString& sPrompt);
static bool GetInput(const CString& sPrompt, CString& sRet,
const CString& sDefault = "",
@@ -73,12 +75,27 @@ class CUtils {
static timeval GetTime();
static unsigned long long GetMillTime();
#ifdef HAVE_LIBSSL
static void GenerateCert(FILE* pOut, const CString& sHost = "");
static void GenerateCert(FILE* pOut);
#endif /* HAVE_LIBSSL */
static CString CTime(time_t t, const CString& sTZ);
static CString FormatTime(time_t t, const CString& sFormat,
const CString& sTZ);
/** Supports an additional format specifier for formatting sub-second values:
*
* - %f - sub-second fraction
* - %3f - millisecond (default, if no width is specified)
* - %6f - microsecond
*
* However, note that timeval only supports microsecond precision
* (thus, formatting with higher-than-microsecond precision will
* always result in trailing zeroes), and IRC server-time is specified
* in millisecond precision (thus formatting received timestamps with
* higher-than-millisecond precision will always result in trailing
* zeroes).
*/
static CString FormatTime(const timeval& tv, const CString& sFormat,
const CString& sTZ);
static CString FormatServerTime(const timeval& tv);
static timeval ParseServerTime(const CString& sTime);
static SCString GetTimezones();
@@ -113,7 +130,7 @@ class CException {
};
/** Generate a grid-like output from a given input.
/** Generate a grid-like or list-like output from a given input.
*
* @code
* CTable table;
@@ -137,9 +154,25 @@ class CException {
+-------+-------+
| hello | world |
+-------+-------+@endverbatim
*
* If the table has at most two columns, one can switch to ListStyle output
* like so:
* @code
* CTable table;
* table.AddColumn("a");
* table.AddColumn("b");
* table.SetStyle(CTable::ListStyle);
* // ...
* @endcode
*
* This will yield the following (Note that the header is omitted; asterisks
* denote bold text):
* @verbatim
*hello*: world@endverbatim
*/
class CTable : protected std::vector<std::vector<CString>> {
public:
enum EStyle { GridStyle, ListStyle };
CTable() {}
virtual ~CTable() {}
@@ -147,10 +180,18 @@ class CTable : protected std::vector<std::vector<CString>> {
* Please note that you should add all columns before starting to fill
* the table!
* @param sName The name of the column.
* @return false if a column by that name already existed.
* @return false if a column by that name already existed or the current
* style does not allow this many columns.
*/
bool AddColumn(const CString& sName);
/** Selects the output style of the table.
* Select between different styles for printing. Default is GridStyle.
* @param eNewStyle Table style type.
* @return false if the style cannot be applied (usually too many columns).
*/
bool SetStyle(EStyle eNewStyle);
/** Adds a new row to the table.
* After calling this you can fill the row with content.
* @return The index of this row
@@ -198,6 +239,7 @@ class CTable : protected std::vector<std::vector<CString>> {
std::vector<CString> m_vsHeaders;
// Used to cache the width of a column
std::map<CString, CString::size_type> m_msuWidths;
EStyle eStyle = GridStyle;
};
#ifdef HAVE_LIBSSL
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -697,4 +697,11 @@ class CInlineFormatMessage {
CString m_sFormat;
};
// For gtest
#ifdef GTEST_FAIL
inline void PrintTo(const CString& s, std::ostream* os) {
*os << '"' << s.Escape_n(CString::EDEBUG) << '"';
}
#endif
#endif // !ZNCSTRING_H
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+9 -12
View File
@@ -1,5 +1,5 @@
/*
Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,19 +16,9 @@ limitations under the License.
#ifndef ZNC_VERSION_H
#define ZNC_VERSION_H
#ifndef BUILD_WITH_CMAKE
// The following defines are for #if comparison (preprocessor only likes ints)
#define VERSION_MAJOR 1
#define VERSION_MINOR 7
#define VERSION_PATCH -1
// This one is for display purpose and to check ABI compatibility of modules
#define VERSION_STR "1.7.x"
#endif
// Don't use this one
#define VERSION (VERSION_MAJOR + VERSION_MINOR / 10.0)
// autoconf: You can add -DVERSION_EXTRA="stuff" to your CXXFLAGS!
// CMake: You can add -DVERSION_EXTRA=stuff to cmake!
#ifndef VERSION_EXTRA
#define VERSION_EXTRA ""
@@ -67,9 +57,16 @@ extern const char* ZNC_VERSION_EXTRA;
#define ZNC_VERSION_TEXT_I18N "no"
#endif
// This is only here because HASH_DEFAULT has different value
#ifdef ZNC_HAVE_ARGON
#define ZNC_VERSION_TEXT_ARGON "yes"
#else
#define ZNC_VERSION_TEXT_ARGON "no"
#endif
#define ZNC_COMPILE_OPTIONS_STRING \
"IPv6: " ZNC_VERSION_TEXT_IPV6 ", SSL: " ZNC_VERSION_TEXT_SSL \
", DNS: " ZNC_VERSION_TEXT_DNS ", charset: " ZNC_VERSION_TEXT_ICU \
", i18n: " ZNC_VERSION_TEXT_I18N
", i18n: " ZNC_VERSION_TEXT_I18N ", Argon2: " ZNC_VERSION_TEXT_ARGON
#endif // !ZNC_VERSION_H
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ class CConfigWriteTimer;
class CConfig;
class CFile;
class CZNC {
class CZNC : private CCoreTranslationMixin {
public:
CZNC();
~CZNC();
@@ -123,6 +123,7 @@ class CZNC {
}
void SetProtectWebSessions(bool b) { m_bProtectWebSessions = b; }
void SetHideVersion(bool b) { m_bHideVersion = b; }
void SetAuthOnlyViaModule(bool b) { m_bAuthOnlyViaModule = b; }
void SetConnectDelay(unsigned int i);
void SetSSLCiphers(const CString& sCiphers) { m_sSSLCiphers = sCiphers; }
bool SetSSLProtocols(const CString& sProtocols);
@@ -166,6 +167,7 @@ class CZNC {
unsigned int GetConnectDelay() const { return m_uiConnectDelay; }
bool GetProtectWebSessions() const { return m_bProtectWebSessions; }
bool GetHideVersion() const { return m_bHideVersion; }
bool GetAuthOnlyViaModule() const { return m_bAuthOnlyViaModule; }
CString GetSSLCiphers() const { return m_sSSLCiphers; }
CString GetSSLProtocols() const { return m_sSSLProtocols; }
Csock::EDisableProtocol GetDisabledSSLProtocols() const {
@@ -261,6 +263,8 @@ class CZNC {
static void DumpConfig(const CConfig* Config);
private:
static CString FormatBindError();
CFile* InitPidFile();
bool ReadConfig(CConfig& config, CString& sError);
@@ -315,6 +319,7 @@ class CZNC {
TCacheMap<CString> m_sConnectThrottle;
bool m_bProtectWebSessions;
bool m_bHideVersion;
bool m_bAuthOnlyViaModule;
CTranslationDomainRefHolder m_Translation;
unsigned int m_uiConfigWriteDelay;
CConfigWriteTimer* m_pConfigTimer;
+5 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 ZNC, see the NOTICE file for details.
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,9 +31,11 @@
#define HAVE_PTHREAD 1
#cmakedefine HAVE_THREADED_DNS 1
#cmakedefine HAVE_LIBSSL 1
#cmakedefine HAVE_SSL_SESSION_get0_cipher 1
#cmakedefine HAVE_IPV6 1
#cmakedefine HAVE_ZLIB 1
#cmakedefine HAVE_I18N 1
#cmakedefine ZNC_HAVE_ARGON 1
#cmakedefine CSOCK_USE_POLL 1
#cmakedefine HAVE_GETOPT_LONG 1
@@ -41,6 +43,8 @@
#cmakedefine HAVE_TCSETATTR 1
#cmakedefine HAVE_GETPASSPHRASE 1
#cmakedefine HAVE_CLOCK_GETTIME 1
#cmakedefine ZNC_HAVE_GETHOSTNAME 1
#cmakedefine ZNC_HAVE_UNAME 1
#cmakedefine HAVE_ICU 1
#define U_USING_ICU_NAMESPACE 1