| 33 | using util::TrimStringView; |
| 34 | |
| 35 | static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections) |
| 36 | { |
| 37 | std::string str, prefix; |
| 38 | std::string::size_type pos; |
| 39 | int linenr = 1; |
| 40 | while (std::getline(stream, str)) { |
| 41 | bool used_hash = false; |
| 42 | if ((pos = str.find('#')) != std::string::npos) { |
| 43 | str = str.substr(0, pos); |
| 44 | used_hash = true; |
| 45 | } |
| 46 | const static std::string pattern = " \t\r\n"; |
| 47 | str = TrimString(str, pattern); |
| 48 | if (!str.empty()) { |
| 49 | if (*str.begin() == '[' && *str.rbegin() == ']') { |
| 50 | const std::string section = str.substr(1, str.size() - 2); |
| 51 | sections.emplace_back(SectionInfo{section, filepath, linenr}); |
| 52 | prefix = section + '.'; |
| 53 | } else if (*str.begin() == '-') { |
| 54 | error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str); |
| 55 | return false; |
| 56 | } else if ((pos = str.find('=')) != std::string::npos) { |
| 57 | std::string name = prefix + TrimString(std::string_view{str}.substr(0, pos), pattern); |
| 58 | std::string_view value = TrimStringView(std::string_view{str}.substr(pos + 1), pattern); |
| 59 | if (used_hash && name.find("rpcpassword") != std::string::npos) { |
| 60 | error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr); |
| 61 | return false; |
| 62 | } |
| 63 | options.emplace_back(name, value); |
| 64 | if ((pos = name.rfind('.')) != std::string::npos && prefix.length() <= pos) { |
| 65 | sections.emplace_back(SectionInfo{name.substr(0, pos), filepath, linenr}); |
| 66 | } |
| 67 | } else { |
| 68 | error = strprintf("parse error on line %i: %s", linenr, str); |
| 69 | if (str.size() >= 2 && str.starts_with("no")) { |
| 70 | error += strprintf(", if you intended to specify a negated option, use %s=1 instead", str); |
| 71 | } |
| 72 | return false; |
| 73 | } |
| 74 | } |
| 75 | ++linenr; |
| 76 | } |
| 77 | return true; |
| 78 | } |
| 79 | |
| 80 | bool IsConfSupported(KeyInfo& key, std::string& error) { |
| 81 | if (key.name == "conf") { |
no test coverage detected