Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
utils.h
1 #ifndef UTILS_H_
2 #define UTILS_H_
3 
4 #include <boost/filesystem.hpp>
5 #include <memory>
6 #include <string>
7 
8 #include <curl/curl.h>
9 #include <netinet/in.h>
10 
11 #include "json/json.h"
12 
13 struct Utils {
14  static std::string fromBase64(std::string base64_string);
15  static std::string toBase64(const std::string &tob64);
16  static std::string stripQuotes(const std::string &value);
17  static std::string addQuotes(const std::string &value);
18  static std::string extractField(const std::string &in, unsigned int field_id);
19  static Json::Value parseJSON(const std::string &json_str);
20  static Json::Value parseJSONFile(const boost::filesystem::path &filename);
21  static std::string jsonToStr(const Json::Value &json);
22  static std::string jsonToCanonicalStr(const Json::Value &json);
23  static std::string genPrettyName();
24  static std::string readFile(const boost::filesystem::path &filename, bool trim = false);
25 
26  static void writeFile(const boost::filesystem::path &filename, const char *content, size_t size);
27  static void writeFile(const boost::filesystem::path &filename, const std::string &content,
28  bool create_directories = true);
29  static void writeFile(const boost::filesystem::path &filename, const Json::Value &content,
30  bool create_directories = true);
31  static void copyDir(const boost::filesystem::path &from, const boost::filesystem::path &to);
32  static std::string readFileFromArchive(std::istream &as, const std::string &filename, bool trim = false);
33  static void writeArchive(const std::map<std::string, std::string> &entries, std::ostream &as);
34  static Json::Value getHardwareInfo();
35  static Json::Value getNetworkInfo();
36  static std::string getHostname();
37  static std::string randomUuid();
38  static sockaddr_storage ipGetSockaddr(int fd);
39  static std::string ipDisplayName(const sockaddr_storage &saddr);
40  static int ipPort(const sockaddr_storage &saddr);
41  static int shell(const std::string &command, std::string *output, bool include_stderr = false);
42  static boost::filesystem::path absolutePath(const boost::filesystem::path &root, const boost::filesystem::path &file);
43  static void setSocketPort(sockaddr_storage *addr, in_port_t port);
44  static void createDirectories(const boost::filesystem::path &path, mode_t mode);
45  static bool createSecureDirectory(const boost::filesystem::path &path);
46  static std::string urlEncode(const std::string &input);
47  static CURL *curlDupHandleWrapper(CURL *curl_in, bool using_pkcs11);
48  static std::vector<boost::filesystem::path> getDirEntriesByExt(const boost::filesystem::path &dir_path,
49  const std::string &ext);
50  static void setStorageRootPath(const std::string &storage_root_path);
51  static boost::filesystem::path getStorageRootPath();
52 
53  static void setUserAgent(std::string user_agent);
54  static const char *getUserAgent();
55 
56  static void setCaPath(boost::filesystem::path path);
57  static const char *getCaPath();
58 
59  private:
60  static std::string storage_root_path_;
61  static std::string user_agent_;
62  static boost::filesystem::path ca_path_;
63 };
64 
65 /**
66  * RAII Temporary file creation
67  */
69  public:
70  explicit TemporaryFile(const std::string &hint = "file");
71  TemporaryFile(const TemporaryFile &) = delete;
72  TemporaryFile operator=(const TemporaryFile &) = delete;
73  ~TemporaryFile();
74  void PutContents(const std::string &contents);
75  boost::filesystem::path Path() const;
76  std::string PathString() const;
77 
78  private:
79  boost::filesystem::path tmp_name_;
80 };
81 
83  public:
84  explicit TemporaryDirectory(const std::string &hint = "dir");
85  TemporaryDirectory(const TemporaryDirectory &) = delete;
86  TemporaryDirectory operator=(TemporaryDirectory &) = delete;
88  boost::filesystem::path Path() const;
89  std::string PathString() const;
90  boost::filesystem::path operator/(const boost::filesystem::path &subdir) const;
91 
92  private:
93  boost::filesystem::path tmp_name_;
94 };
95 
96 // Can represent an absolute or relative path, only readable through the
97 // `.get()` method
98 //
99 // The intent is to avoid unintentional use of the "naked" relative path by
100 // mandating a base directory for each instantiation
101 class BasedPath {
102  public:
103  BasedPath(boost::filesystem::path p) : p_(std::move(p)) {}
104 
105  boost::filesystem::path get(const boost::filesystem::path &base) const {
106  // note: BasedPath(bp.get()) == bp
107  return Utils::absolutePath(base, p_);
108  }
109 
110  bool empty() const { return p_.empty(); }
111  bool operator==(const BasedPath &b) const { return p_ == b.p_; }
112  bool operator!=(const BasedPath &b) const { return !(*this == b); }
113 
114  private:
115  boost::filesystem::path p_;
116 };
117 
118 // helper template for C (mostly openssl) data structured
119 // user should still take care about the order of destruction
120 // by instantiating StructGuard<> in a right order.
121 // BTW local variables are destructed in reverse order of instantiation
122 template <typename T>
123 using StructGuard = std::unique_ptr<T, void (*)(T *)>;
124 
125 bool operator<(const sockaddr_storage &left, const sockaddr_storage &right); // required by std::map
126 
127 class Socket {
128  public:
129  Socket();
130  virtual ~Socket() = 0;
131 
132  Socket(const Socket &) = delete;
133  Socket &operator=(const Socket &) = delete;
134 
135  int &operator*() { return socket_fd_; }
136  std::string toString();
137 
138  protected:
139  void bind(in_port_t port, bool reuse = true);
140 
141  protected:
142  int socket_fd_;
143 };
144 
145 class ConnectionSocket : public Socket {
146  public:
147  ConnectionSocket(const std::string &ip, in_port_t port, in_port_t bind_port = 0);
148  ~ConnectionSocket() override;
149 
150  public:
151  int connect();
152 
153  private:
154  struct sockaddr_in remote_sock_address_;
155 };
156 
157 class ListenSocket : public Socket {
158  public:
159  ListenSocket(in_port_t port);
160  in_port_t port() const { return _port; }
161 
162  private:
163  in_port_t _port;
164 };
165 
166 // wrapper for curl handles
168  public:
169  CurlEasyWrapper();
170  ~CurlEasyWrapper();
171  CURL *get() { return handle; }
172 
173  private:
174  CURL *handle;
175 };
176 
177 template <typename... T>
178 static void curlEasySetoptWrapper(CURL *curl_handle, CURLoption option, T &&... args) {
179  const CURLcode retval = curl_easy_setopt(curl_handle, option, std::forward<T>(args)...);
180  if (retval != 0u) {
181  throw std::runtime_error(std::string("curl_easy_setopt error: ") + curl_easy_strerror(retval));
182  }
183 }
184 
185 // this is reference implementation of make_unique which is not yet included to C++11
186 namespace std_ {
187 template <class T>
188 struct _Unique_if {
189  using _Single_object = std::unique_ptr<T>;
190 };
191 
192 template <class T>
193 struct _Unique_if<T[]> {
194  using _Unknown_bound = std::unique_ptr<T[]>;
195 };
196 
197 template <class T, size_t N>
198 struct _Unique_if<T[N]> {
199  using _Known_bound = void;
200 };
201 
202 template <class T, class... Args>
203 typename _Unique_if<T>::_Single_object make_unique(Args &&... args) {
204  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
205 }
206 
207 template <class T>
208 typename _Unique_if<T>::_Unknown_bound make_unique(size_t n) {
209  using U = typename std::remove_extent<T>::type;
210  return std::unique_ptr<T>(new U[n]());
211 }
212 
213 template <class T, class... Args>
214 typename _Unique_if<T>::_Known_bound make_unique(Args &&...) = delete;
215 } // namespace std_
216 
217 #endif // UTILS_H_
CurlEasyWrapper
Definition: utils.h:167
BasedPath
Definition: utils.h:101
ConnectionSocket
Definition: utils.h:145
Utils
Definition: utils.h:13
std_::_Unique_if
Definition: utils.h:188
TemporaryDirectory
Definition: utils.h:82
Socket
Definition: utils.h:127
ListenSocket
Definition: utils.h:157
TemporaryFile
RAII Temporary file creation.
Definition: utils.h:68