mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 09:58:54 +00:00
Implement generic tryTo
for string to boolean converions (#4689)
Implement generic `tryTo` for string to boolean converions Also use it in some obvious placed in codebase
This commit is contained in:
parent
ed4354c9ef
commit
d31e1bc2e7
@ -10,10 +10,12 @@
|
||||
|
||||
#include <iomanip>
|
||||
#include <locale>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||
#include <boost/archive/iterators/transform_width.hpp>
|
||||
#include <boost/io/detail/quoted_manip.hpp>
|
||||
#if (BOOST_VERSION >= 106600)
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#else
|
||||
@ -418,4 +420,42 @@ std::string getBufferSHA1(const char* buffer, size_t size) {
|
||||
size_t operator"" _sz(unsigned long long int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
Expected<bool, ConversionError> stringToBool(std::string from) {
|
||||
static const auto table = std::unordered_map<std::string, bool>{
|
||||
{"1", true},
|
||||
{"0", false},
|
||||
{"y", true},
|
||||
{"yes", true},
|
||||
{"n", false},
|
||||
{"no", false},
|
||||
{"t", true},
|
||||
{"true", true},
|
||||
{"f", false},
|
||||
{"false", false},
|
||||
{"ok", true},
|
||||
{"disable", false},
|
||||
{"enable", true},
|
||||
};
|
||||
using CharType = std::string::value_type;
|
||||
// Classic locale could be used here because all available string
|
||||
// representations of boolean have ascii encoding. It must be a bit faster.
|
||||
static const auto& ctype =
|
||||
std::use_facet<std::ctype<CharType>>(std::locale::classic());
|
||||
for (auto& ch : from) {
|
||||
ch = ctype.tolower(ch);
|
||||
}
|
||||
const auto it = table.find(from);
|
||||
if (it == table.end()) {
|
||||
return createError(ConversionError::InvalidArgument,
|
||||
"Wrong string representation of boolean ")
|
||||
<< boost::io::quoted(from);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
} // namespace osquery
|
||||
|
@ -322,4 +322,28 @@ inline typename std::enable_if<
|
||||
tryTo(FromType&& from) {
|
||||
return std::forward<FromType>(from);
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
Expected<bool, ConversionError> stringToBool(std::string from);
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/**
|
||||
* Parsing general representation of boolean value in string.
|
||||
* "1" : true
|
||||
* "0" : false
|
||||
* "y" : true
|
||||
* "yes" : true
|
||||
* "n" : false
|
||||
* "no" : false
|
||||
* ... and so on
|
||||
* For the full list of possible valid values @see stringToBool definition
|
||||
*/
|
||||
template <typename ToType>
|
||||
inline typename std::enable_if<std::is_same<ToType, bool>::value,
|
||||
Expected<ToType, ConversionError>>::type
|
||||
tryTo(std::string from) {
|
||||
return impl::stringToBool(std::move(from));
|
||||
}
|
||||
}
|
||||
|
@ -324,4 +324,45 @@ TEST_F(ConversionsTests, tryTo_same_type) {
|
||||
auto ret2 = tryTo<First>(const_test_lvalue);
|
||||
ASSERT_FALSE(ret2.isError());
|
||||
}
|
||||
|
||||
TEST_F(ConversionsTests, tryTo_string_to_boolean_valid_args) {
|
||||
const auto test_table = std::unordered_map<std::string, bool>{
|
||||
{"1", true}, {"0", false}, {"y", true},
|
||||
{"n", false}, {"yes", true}, {"yEs", true},
|
||||
{"Yes", true}, {"no", false}, {"No", false},
|
||||
{"t", true}, {"T", true}, {"f", false},
|
||||
{"F", false}, {"true", true}, {"True", true},
|
||||
{"tRUE", true}, {"false", false}, {"fALse", false},
|
||||
{"ok", true}, {"OK", true}, {"Ok", true},
|
||||
{"enable", true}, {"Enable", true}, {"ENABLE", true},
|
||||
{"disable", false}, {"Disable", false}, {"DISABLE", false},
|
||||
};
|
||||
for (const auto& argAndAnswer : test_table) {
|
||||
auto exp = tryTo<bool>(argAndAnswer.first);
|
||||
ASSERT_FALSE(exp.isError());
|
||||
EXPECT_EQ(argAndAnswer.second, exp.get());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ConversionsTests, tryTo_string_to_boolean_invalid_args) {
|
||||
const auto test_table = std::vector<std::string>{
|
||||
"", "\0", "\n", "\x06", "\x15", "\x27", "ADS",
|
||||
"7251", "20.09", "M0V+K7V", "+", "-", ".", "@",
|
||||
"1.0", "11", "00", " 0", "1 ", "2", "10",
|
||||
"100%", "_0", "1_", "1.", "2.", "E", "a",
|
||||
"b", "d", "e", "o", "p", "uh", "nix",
|
||||
"nixie", "nixy", "nixey", "nay", "nah", "no way", "veto",
|
||||
"yea", "yeah", "yep", "okey", "aye", "roger", "uh-huh",
|
||||
"righto", "yup", "yuppers", "ja", "surely", "amen", "totally",
|
||||
"sure", "yessir", "true.", "tru", "tr", "tr.", "ff",
|
||||
"yy", "nn", "nope", "null", "nil", "dis", "able",
|
||||
"pos", "neg", "ack", "ACK", "NAK", "enabled", "disabled",
|
||||
"valid", "invalid", "void", "allow", "permit", "positive", "negative",
|
||||
};
|
||||
for (const auto& wrong : test_table) {
|
||||
auto exp = tryTo<bool>(wrong);
|
||||
ASSERT_TRUE(exp.isError());
|
||||
EXPECT_EQ(ConversionError::InvalidArgument, exp.getErrorCode());
|
||||
}
|
||||
}
|
||||
} // namespace osquery
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <osquery/packs.h>
|
||||
#include <osquery/registry_factory.h>
|
||||
|
||||
#include "osquery/core/conversions.h"
|
||||
#include "osquery/core/process.h"
|
||||
#include "osquery/devtools/devtools.h"
|
||||
#include "osquery/filesystem/fileops.h"
|
||||
@ -1049,15 +1050,12 @@ static int booleanValue(char* zArg) {
|
||||
if (i > 0 && zArg[i] == 0) {
|
||||
return static_cast<int>(integerValue(zArg) & 0xffffffff);
|
||||
}
|
||||
if (sqlite3_stricmp(zArg, "on") == 0 || sqlite3_stricmp(zArg, "yes") == 0) {
|
||||
return 1;
|
||||
auto expected = osquery::tryTo<bool>(std::string{zArg});
|
||||
if (expected.isError()) {
|
||||
fprintf(
|
||||
stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
|
||||
}
|
||||
if (sqlite3_stricmp(zArg, "off") == 0 || sqlite3_stricmp(zArg, "no") == 0) {
|
||||
return 0;
|
||||
}
|
||||
fprintf(
|
||||
stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
|
||||
return 0;
|
||||
return expected.get_or(false) ? 1 : 0;
|
||||
}
|
||||
|
||||
inline void meta_tables(int nArg, char** azArg) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <osquery/core/conversions.h>
|
||||
#include <osquery/filesystem.h>
|
||||
#include <osquery/tables.h>
|
||||
|
||||
@ -33,10 +34,9 @@ QueryData genChromeBasedExtensions(QueryContext& context,
|
||||
|
||||
/// A helper check to rename bool-type values as 1 or 0.
|
||||
inline void jsonBoolAsInt(std::string& s) {
|
||||
if (s == "true" || s == "YES" || s == "Yes") {
|
||||
s = "1";
|
||||
} else if (s == "false" || s == "NO" || s == "No") {
|
||||
s = "0";
|
||||
auto expected = tryTo<bool>(s);
|
||||
if (!expected.isError()) {
|
||||
s = expected.get() ? "1" : "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user