Aktualizr
C++ SOTA Client
config_utils.h
1 #ifndef CONFIG_UTILS_H_
2 #define CONFIG_UTILS_H_
3 
4 #include <string>
5 
6 #include <boost/property_tree/ini_parser.hpp>
7 
8 #include "libaktualizr/types.h"
9 #include "logging/logging.h"
10 #include "utils.h"
11 
12 /*
13  The following uses a small amount of template hackery to provide a nice
14  interface to load the sota.toml config file. StripQuotesFromStrings is
15  templated, and passes everything that isn't a string straight through.
16  Strings in toml are always double-quoted, and we remove them by specializing
17  StripQuotesFromStrings for std::string.
18 
19  The end result is that the sequence of calls in Config::updateFromToml are
20  pretty much a direct expression of the required behaviour: load this variable
21  from this config entry, and print a warning at the
22 
23  Note that default values are defined by Config's default constructor.
24  */
25 
26 template <typename T>
27 inline T StripQuotesFromStrings(const T& value);
28 
29 template <>
30 inline std::string StripQuotesFromStrings<std::string>(const std::string& value) {
31  return Utils::stripQuotes(value);
32 }
33 
34 template <typename T>
35 inline T StripQuotesFromStrings(const T& value) {
36  return value;
37 }
38 
39 template <typename T>
40 inline T addQuotesToStrings(const T& value);
41 
42 template <>
43 inline std::string addQuotesToStrings<std::string>(const std::string& value) {
44  return Utils::addQuotes(value);
45 }
46 
47 template <typename T>
48 inline T addQuotesToStrings(const T& value) {
49  return value;
50 }
51 
52 template <typename T>
53 inline void writeOption(std::ostream& sink, const T& data, const std::string& option_name) {
54  sink << option_name << " = " << addQuotesToStrings(data) << "\n";
55 }
56 
57 template <typename T>
58 inline void CopyFromConfig(T& dest, const std::string& option_name, const boost::property_tree::ptree& pt) {
59  boost::optional<T> value = pt.get_optional<T>(option_name);
60  if (value.is_initialized()) {
61  dest = StripQuotesFromStrings(value.get());
62  }
63 }
64 
65 template <>
66 inline void CopyFromConfig(StorageType& dest, const std::string& option_name, const boost::property_tree::ptree& pt) {
67  boost::optional<std::string> value = pt.get_optional<std::string>(option_name);
68  if (value.is_initialized()) {
69  std::string storage_type{StripQuotesFromStrings(value.get())};
70  if (storage_type == "sqlite") {
71  dest = StorageType::kSqlite;
72  } else {
73  dest = StorageType::kFileSystem;
74  }
75  }
76 }
77 
78 template <>
79 inline void CopyFromConfig(KeyType& dest, const std::string& option_name, const boost::property_tree::ptree& pt) {
80  boost::optional<std::string> value = pt.get_optional<std::string>(option_name);
81  if (value.is_initialized()) {
82  std::string key_type{StripQuotesFromStrings(value.get())};
83  if (key_type == "RSA2048") {
84  dest = KeyType::kRSA2048;
85  } else if (key_type == "RSA3072") {
86  dest = KeyType::kRSA3072;
87  } else if (key_type == "RSA4096") {
88  dest = KeyType::kRSA4096;
89  } else if (key_type == "ED25519") {
90  dest = KeyType::kED25519;
91  } else {
92  dest = KeyType::kUnknown;
93  }
94  }
95 }
96 
97 template <>
98 inline void CopyFromConfig(CryptoSource& dest, const std::string& option_name, const boost::property_tree::ptree& pt) {
99  boost::optional<std::string> value = pt.get_optional<std::string>(option_name);
100  if (value.is_initialized()) {
101  std::string crypto_source{StripQuotesFromStrings(value.get())};
102  if (crypto_source == "pkcs11") {
103  dest = CryptoSource::kPkcs11;
104  } else {
105  dest = CryptoSource::kFile;
106  }
107  }
108 }
109 
110 template <>
111 inline void CopyFromConfig(utils::BasedPath& dest, const std::string& option_name,
112  const boost::property_tree::ptree& pt) {
113  boost::optional<std::string> value = pt.get_optional<std::string>(option_name);
114  if (value.is_initialized()) {
115  utils::BasedPath bp{StripQuotesFromStrings(value.get())};
116  dest = bp;
117  }
118 }
119 
120 template <typename T>
121 inline void CopySubtreeFromConfig(T& dest, const std::string& subtree_name, const boost::property_tree::ptree& pt) {
122  auto subtree = pt.get_child_optional(subtree_name);
123  if (subtree.is_initialized()) {
124  dest.updateFromPropertyTree(subtree.get());
125  } else {
126  // call with empty tree so that default value warnings are preserved
127  dest.updateFromPropertyTree(boost::property_tree::ptree());
128  }
129 }
130 
131 template <typename T>
132 inline void WriteSectionToStream(T& sec, const std::string& section_name, std::ostream& os) {
133  os << std::boolalpha;
134  os << "[" << section_name << "]\n";
135  sec.writeToStream(os);
136  os << "\n";
137 }
138 
139 #endif // CONFIG_UTILS_H_
types.h
data
General data structures.
Definition: types.h:217
utils::BasedPath
The BasedPath class Can represent an absolute or relative path, only readable through the BasePath::g...
Definition: types.h:31