Merge pull request #2813 from str4d/2074-uacomment
Implement uacomment config parameter
This commit is contained in:
14
src/init.cpp
14
src/init.cpp
@@ -1250,6 +1250,20 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
|
|
||||||
RegisterNodeSignals(GetNodeSignals());
|
RegisterNodeSignals(GetNodeSignals());
|
||||||
|
|
||||||
|
// sanitize comments per BIP-0014, format user agent and check total size
|
||||||
|
std::vector<string> uacomments;
|
||||||
|
BOOST_FOREACH(string cmt, mapMultiArgs["-uacomment"])
|
||||||
|
{
|
||||||
|
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
|
||||||
|
return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt));
|
||||||
|
uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT));
|
||||||
|
}
|
||||||
|
strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
|
||||||
|
if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
|
||||||
|
return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.",
|
||||||
|
strSubVersion.size(), MAX_SUBVERSION_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
if (mapArgs.count("-onlynet")) {
|
if (mapArgs.count("-onlynet")) {
|
||||||
std::set<enum Network> nets;
|
std::set<enum Network> nets;
|
||||||
BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) {
|
BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) {
|
||||||
|
|||||||
@@ -4820,7 +4820,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (!vRecv.empty())
|
if (!vRecv.empty())
|
||||||
vRecv >> addrFrom >> nNonce;
|
vRecv >> addrFrom >> nNonce;
|
||||||
if (!vRecv.empty()) {
|
if (!vRecv.empty()) {
|
||||||
vRecv >> LIMITED_STRING(pfrom->strSubVer, 256);
|
vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH);
|
||||||
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
|
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
|
||||||
}
|
}
|
||||||
if (!vRecv.empty())
|
if (!vRecv.empty())
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ static std::vector<ListenSocket> vhListenSocket;
|
|||||||
CAddrMan addrman;
|
CAddrMan addrman;
|
||||||
int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
|
int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
|
||||||
bool fAddressesInitialized = false;
|
bool fAddressesInitialized = false;
|
||||||
|
std::string strSubVersion;
|
||||||
|
|
||||||
vector<CNode*> vNodes;
|
vector<CNode*> vNodes;
|
||||||
CCriticalSection cs_vNodes;
|
CCriticalSection cs_vNodes;
|
||||||
@@ -435,7 +436,7 @@ void CNode::PushVersion()
|
|||||||
else
|
else
|
||||||
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
|
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
|
||||||
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
|
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
|
||||||
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
|
nLocalHostNonce, strSubVersion, nBestHeight, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ static const unsigned int MAX_INV_SZ = 50000;
|
|||||||
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
||||||
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
|
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
|
||||||
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
|
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
|
||||||
|
/** Maximum length of strSubVer in `version` message */
|
||||||
|
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
|
||||||
/** -listen default */
|
/** -listen default */
|
||||||
static const bool DEFAULT_LISTEN = true;
|
static const bool DEFAULT_LISTEN = true;
|
||||||
/** The maximum number of entries in mapAskFor */
|
/** The maximum number of entries in mapAskFor */
|
||||||
@@ -156,6 +158,9 @@ extern CCriticalSection cs_vAddedNodes;
|
|||||||
extern NodeId nLastNodeId;
|
extern NodeId nLastNodeId;
|
||||||
extern CCriticalSection cs_nLastNodeId;
|
extern CCriticalSection cs_nLastNodeId;
|
||||||
|
|
||||||
|
/** Subversion as sent to the P2P network in `version` messages */
|
||||||
|
extern std::string strSubVersion;
|
||||||
|
|
||||||
struct LocalServiceInfo {
|
struct LocalServiceInfo {
|
||||||
int nScore;
|
int nScore;
|
||||||
int nPort;
|
int nPort;
|
||||||
|
|||||||
@@ -469,8 +469,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("version", CLIENT_VERSION));
|
obj.push_back(Pair("version", CLIENT_VERSION));
|
||||||
obj.push_back(Pair("subversion",
|
obj.push_back(Pair("subversion", strSubVersion));
|
||||||
FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
|
|
||||||
obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
|
obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
|
||||||
obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
|
obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
|
||||||
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
|
|||||||
comments.push_back(std::string("comment1"));
|
comments.push_back(std::string("comment1"));
|
||||||
std::vector<std::string> comments2;
|
std::vector<std::string> comments2;
|
||||||
comments2.push_back(std::string("comment1"));
|
comments2.push_back(std::string("comment1"));
|
||||||
comments2.push_back(std::string("comment2"));
|
comments2.push_back(SanitizeString(std::string("Comment2; .,_?@; !\"#$%&'()*+-/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()), std::string("/Test:0.9.99-beta1/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()), std::string("/Test:0.9.99-beta1/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99924, std::vector<std::string>()), std::string("/Test:0.9.99-beta25/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99924, std::vector<std::string>()), std::string("/Test:0.9.99-beta25/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99925, std::vector<std::string>()), std::string("/Test:0.9.99-rc1/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99925, std::vector<std::string>()), std::string("/Test:0.9.99-rc1/"));
|
||||||
@@ -423,8 +423,8 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
|
|||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99999, std::vector<std::string>()), std::string("/Test:0.9.99-49/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99999, std::vector<std::string>()), std::string("/Test:0.9.99-49/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments), std::string("/Test:0.9.99-beta1(comment1)/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments), std::string("/Test:0.9.99-beta1(comment1)/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99950, comments), std::string("/Test:0.9.99(comment1)/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99950, comments), std::string("/Test:0.9.99(comment1)/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2), std::string("/Test:0.9.99-beta1(comment1; comment2)/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2), std::string("/Test:0.9.99-beta1(comment1; Comment2; .,_?@; )/"));
|
||||||
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99950, comments2), std::string("/Test:0.9.99(comment1; comment2)/"));
|
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99950, comments2), std::string("/Test:0.9.99(comment1; Comment2; .,_?@; )/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
|
BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
|
||||||
|
|||||||
@@ -15,17 +15,20 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
string SanitizeString(const string& str)
|
static const string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
|
||||||
|
static const string SAFE_CHARS[] =
|
||||||
|
{
|
||||||
|
CHARS_ALPHA_NUM + " .,;_/:?@()", // SAFE_CHARS_DEFAULT
|
||||||
|
CHARS_ALPHA_NUM + " .,;_?@" // SAFE_CHARS_UA_COMMENT
|
||||||
|
};
|
||||||
|
|
||||||
|
string SanitizeString(const string& str, int rule)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
|
|
||||||
* even possibly remotely dangerous like & or >
|
|
||||||
*/
|
|
||||||
static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()");
|
|
||||||
string strResult;
|
string strResult;
|
||||||
for (std::string::size_type i = 0; i < str.size(); i++)
|
for (std::string::size_type i = 0; i < str.size(); i++)
|
||||||
{
|
{
|
||||||
if (safeChars.find(str[i]) != std::string::npos)
|
if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
|
||||||
strResult.push_back(str[i]);
|
strResult.push_back(str[i]);
|
||||||
}
|
}
|
||||||
return strResult;
|
return strResult;
|
||||||
|
|||||||
@@ -22,8 +22,22 @@
|
|||||||
/** This is needed because the foreach macro can't get over the comma in pair<t1, t2> */
|
/** This is needed because the foreach macro can't get over the comma in pair<t1, t2> */
|
||||||
#define PAIRTYPE(t1, t2) std::pair<t1, t2>
|
#define PAIRTYPE(t1, t2) std::pair<t1, t2>
|
||||||
|
|
||||||
|
/** Used by SanitizeString() */
|
||||||
|
enum SafeChars
|
||||||
|
{
|
||||||
|
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
|
||||||
|
SAFE_CHARS_UA_COMMENT //!< BIP-0014 subset
|
||||||
|
};
|
||||||
|
|
||||||
std::string SanitizeFilename(const std::string& str);
|
std::string SanitizeFilename(const std::string& str);
|
||||||
std::string SanitizeString(const std::string& str);
|
/**
|
||||||
|
* Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email
|
||||||
|
* addresses, but avoid anything even possibly remotely dangerous like & or >
|
||||||
|
* @param[in] str The string to sanitize
|
||||||
|
* @param[in] rule The set of safe chars to choose (default: least restrictive)
|
||||||
|
* @return A new string without unsafe chars
|
||||||
|
*/
|
||||||
|
std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT);
|
||||||
std::string HexInt(uint32_t val);
|
std::string HexInt(uint32_t val);
|
||||||
uint32_t ParseHexToUInt32(const std::string& str);
|
uint32_t ParseHexToUInt32(const std::string& str);
|
||||||
std::vector<unsigned char> ParseHex(const char* psz);
|
std::vector<unsigned char> ParseHex(const char* psz);
|
||||||
|
|||||||
Reference in New Issue
Block a user