// No `ini` binding yet. Hdf still takes precedence but will be removed // once we have made all options ini-aware. All new settings should // use the ini path of this method (i.e., pass a bogus Hdf or keep it null) void Config::Iterate(std::function<void (const IniSettingMap&, const Hdf&, const std::string&)> cb, const IniSettingMap &ini, const Hdf& config, const std::string &name, const bool prepend_hhvm /* = true */) { // We shouldn't be passing a leaf here. That's why name is not // optional. assert(!name.empty()); Hdf hdf = config[name]; if (hdf.exists() && !hdf.isEmpty()) { for (Hdf c = hdf.firstChild(); c.exists(); c = c.next()) { cb(IniSetting::Map::object, c, ""); } } else { Hdf empty; auto ini_name = IniName(name, prepend_hhvm); auto* ini_value = ini_iterate(ini, ini_name); if (ini_value && ini_value->isObject()) { for (auto& pair : ini_value->items()) { cb(pair.second, empty, pair.first.data()); } } } }
TEST(IniSetting, ini_iterate) { std::string inistr = "hhvm.ip_block_map[0][location] = /test\n" "hhvm.ip_block_map[0][allow_first] = true\n" "hhvm.ip_block_map[0][ip][allow][0] = 127.0.0.1\n" "hhvm.ip_block_map[0][ip][deny][0] = 8.32.0.0/24\n" "hhvm.ip_block_map[0][ip][deny][1] = " "aaaa:bbbb:cccc:dddd:eeee:ffff:1111::/80\n" "hhvm.ip_block_map[1][location] = /blah\n" "hhvm.ip_block_map[1][allow_first] = true\n" "hhvm.ip_block_map[1][ip][allow][0] = 127.10.10.10\n" "hhvm.ip_block_map[1][ip][deny][0] = 255.255.255.255\n" "hhvm.server.apc.ttl_limit = 1000\n" "hhvm.server.allowed_exec_cmds[]= ls\n" "hhvm.server.allowed_exec_cmds[]= cp\n" "hhvm.jit_a_cold_size = 22222222\n"; IniSettingMap ini; Config::ParseIniString(inistr, ini); auto value = ini_iterate(ini, "hhvm.ip_block_map.0.location"); EXPECT_EQ("/test", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.ip_block_map.1.ip.allow.0"); EXPECT_EQ("127.10.10.10", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.server.apc.ttl_limit"); EXPECT_EQ("1000", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.server.bogus.ttl_limit"); EXPECT_EQ(true, value.isNull()); value = ini_iterate(ini, "hhvm.server.allowed_exec_cmds.1"); EXPECT_EQ("cp", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.ip_block_map.0.ip.deny.0"); EXPECT_EQ("8.32.0.0/24", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.ip_block_map.0.ip.deny.1"); EXPECT_EQ("aaaa:bbbb:cccc:dddd:eeee:ffff:1111::/80", value.toString().toCppString()); value = ini_iterate(ini, "hhvm.ip_block_map.1.ip.allow.2"); EXPECT_EQ(true, value.isNull()); value = ini_iterate(init_null(), "hhvm.ip_block_map"); EXPECT_EQ(true, value.isNull()); value = ini_iterate(ini, "hhvm.ip_block_map"); EXPECT_EQ(true, value.isArray()); EXPECT_EQ(2, value.toArray().size()); // Check some runtime options EXPECT_EQ(22222222, jit::CodeCache::AColdSize); EXPECT_EQ("", RuntimeOption::ExtensionDir); }
const char* Config::Get(const IniSetting::Map &ini, const Hdf& config, const std::string& name /* = "" */, const char *defValue /* = nullptr */, const bool prepend_hhvm /* = true */) { auto ini_name = IniName(name, prepend_hhvm); Hdf hdf = name != "" ? config[name] : config; auto* value = ini_iterate(ini, ini_name); if (value && value->isString()) { // See generic Get##METHOD below for why we are doing this const char* ini_ret = value->data(); const char* hdf_ret = hdf.configGet(value->data()); if (hdf_ret != ini_ret) { ini_ret = hdf_ret; IniSetting::Set(ini_name, ini_ret); } return ini_ret; } return hdf.configGet(defValue); }
// This method must return a char* which is owned by the IniSettingMap // to avoid issues with the lifetime of the char* const char* Config::Get(const IniSettingMap &ini, const Hdf& config, const std::string& name /* = "" */, const char *defValue /* = nullptr */, const bool prepend_hhvm /* = true */) { auto ini_name = IniName(name, prepend_hhvm); Hdf hdf = name != "" ? config[name] : config; auto value = ini_iterate(ini, ini_name); if (value.isString()) { // See generic Get##METHOD below for why we are doing this // Note that value is a string, so value.toString() is not // a temporary. const char* ini_ret = value.toString().data(); const char* hdf_ret = hdf.configGet(ini_ret); if (hdf_ret != ini_ret) { ini_ret = hdf_ret; IniSetting::SetSystem(ini_name, ini_ret); } return ini_ret; } return hdf.configGet(defValue); }
// No `ini` binding yet. Hdf still takes precedence but will be removed // once we have made all options ini-aware. All new settings should // use the ini path of this method (i.e., pass a bogus Hdf or keep it null) void Config::Iterate(std::function<void (const IniSettingMap&, const Hdf&, const std::string&)> cb, const IniSettingMap &ini, const Hdf& config, const std::string &name, const bool prepend_hhvm /* = true */) { Hdf hdf = name.empty() ? config : config[name]; if (hdf.exists() && !hdf.isEmpty()) { for (Hdf c = hdf.firstChild(); c.exists(); c = c.next()) { cb(IniSetting::Map::object, c, ""); } } else { Hdf empty; auto ini_value = name.empty() ? ini : ini_iterate(ini, IniName(name, prepend_hhvm)); if (ini_value.isArray()) { for (ArrayIter iter(ini_value.toArray()); iter; ++iter) { cb(iter.second(), empty, iter.first().toString().toCppString()); } } } }