17#ifndef OPENVPN_OPTIONS_MERGE_H
18#define OPENVPN_OPTIONS_MERGE_H
71 const std::string &
error()
const
100 return "MERGE_UNDEFINED";
102 return "MERGE_SUCCESS";
104 return "MERGE_EXCEPTION";
106 return "MERGE_OVPN_EXT_FAIL";
108 return "MERGE_OVPN_FILE_FAIL";
110 return "MERGE_REF_FAIL";
112 return "MERGE_MULTIPLE_REF_FAIL";
127 const std::string &profile_ext,
128 const std::string &profile_dir_override,
129 const Follow follow_references,
130 const size_t max_line_len,
131 const size_t max_size)
136 size_t total_size = 0;
139 std::string orig_profile_content;
140 std::string profile_dir;
143 profile_dir = !profile_dir_override.empty() ? profile_dir_override :
path::dirname(profile_path);
149 total_size = orig_profile_content.size();
158 catch (
const file_is_binary &e)
161 error_ = std::string(
"ERR_PROFILE_FILE_IS_BINARY: ") + e.what();
164 catch (
const file_too_large &e)
167 error_ = std::string(
"ERR_PROFILE_FILE_TOO_LARGE: ") + e.what();
170 catch (
const std::exception &e)
173 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
178 expand_profile(orig_profile_content, profile_dir, follow_references, max_line_len, max_size, total_size);
180 catch (
const std::exception &e)
183 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
187 static std::string
merge(
const std::string &profile_path,
188 const std::string &profile_ext,
189 const std::string &profile_dir_override,
190 const Follow follow_references,
191 const size_t max_line_len,
192 const size_t max_size)
196 profile_dir_override,
212 const std::string &profile_dir,
213 const Follow follow_references,
214 const size_t max_line_len,
215 const size_t max_size,
218 if (total_size > max_size)
221 error_ =
"ERR_PROFILE_FILE_TOO_LARGE: file too large";
227 SplitLines in(orig_profile_content, max_line_len);
228 bool in_multiline =
false;
229 bool opaque_multiline =
false;
238 error_ =
"ERR_PROFILE_LINE_TOO_LONG: line too long";
241 const std::string &line = in.
line_ref();
248 in_multiline =
false;
249 opaque_multiline =
false;
254 Option opt = Split::by_space<Option, OptionList::LexComment, SpaceMatch, Split::NullLimit>(line);
260 multiline = std::move(opt);
262 unsigned int flags = 0;
267 unsigned int flags = 0;
268 bool is_fileref = (!opaque_multiline
279 const std::string authfile = opt.
get(3, 256);
280 if (authfile !=
"auto" && authfile !=
"auto-nct"
281 && authfile !=
"basic" && authfile !=
"digest"
282 && authfile !=
"ntlm" && authfile !=
"none")
287 opt.
ref(0) =
"http-proxy-user-pass";
288 opt.
ref(1) = authfile;
302 const std::string fn_str = opt.
get(1, 256);
308 error_ =
"ERR_PROFILE_NO_FILENAME: filename not provided";
314 error_ = std::string(
"ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn;
321 std::string file_content;
328 error_ = std::string(
"ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn +
": cannot follow file reference";
333 total_size += file_content.size();
334 if (total_size > max_size)
337 error_ = std::string(
"ERR_PROFILE_FILE_TOO_LARGE: ") + fn +
": file too large";
342 catch (
const std::exception &e)
346 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + fn +
" : " + e.what();
359 std::string key_direction;
361 key_direction = opt.
get(2, 16);
363 key_direction =
"bidirectional";
369 std::ostringstream
os;
370 const std::string &tag = opt.
ref(0);
372 os <<
'<' << tag <<
">\n"
373 << file_content <<
"</" << tag <<
">\n";
398 error_ =
"ERR_PROFILE_GENERIC: ";
415 return d ==
"auth-user-pass";
417 return d ==
"ca" || d ==
"cert" || d ==
"crl-verify";
421 return d ==
"extra-certs";
423 if (d ==
"http-proxy")
441 if (d ==
"relay-extra-ca")
443 if (d ==
"relay-tls-auth")
450 if (d ==
"static-key")
459 if (d ==
"tls-crypt")
461 if (d ==
"tls-crypt-v2")
481 const std::string &ref_dir,
482 const Follow follow_references,
483 const size_t max_line_len,
484 const size_t max_size)
496 catch (
const std::exception &e)
499 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
504 const std::string &ref_dir,
505 const Follow follow_references,
506 const size_t max_line_len,
507 const size_t max_size)
static void detect_multiline_breakout(const std::string &opt, const std::string &tag)
static void untag_open_tag(std::string &str)
static bool is_close_tag(const std::string &str, const std::string &tag)
static bool ignore_line(const std::string &line)
static bool is_open_tag(const std::string &str)
const std::string & get(const size_t index, const size_t max_len) const
void resize(const size_t n)
void reserve(const size_t n)
std::string escape(const bool csv) const
const std::string & ref(const size_t i) const
ProfileMergeFromString(const std::string &profile_content, const std::string &ref_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size)
static std::string merge(const std::string &profile_content, const std::string &ref_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size)
void expand_profile(const std::string &orig_profile_content, const std::string &profile_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size, size_t total_size)
const std::string & basename() const
const std::string & error() const
OPENVPN_EXCEPTION(merge_error)
const char * status_string() const
ProfileMerge(const std::string &profile_path, const std::string &profile_ext, const std::string &profile_dir_override, const Follow follow_references, const size_t max_line_len, const size_t max_size)
static bool is_fileref_directive(const std::string &d, unsigned int &flags)
const std::string & profile_content() const
std::vector< std::string > ref_fail_list_
const std::vector< std::string > & ref_path_list() const
std::vector< std::string > ref_succeed_list_
@ MERGE_MULTIPLE_REF_FAIL
@ F_MAY_INCLUDE_KEY_DIRECTION
std::string profile_content_
static std::string merge(const std::string &profile_path, const std::string &profile_ext, const std::string &profile_dir_override, const Follow follow_references, const size_t max_line_len, const size_t max_size)
bool line_overflow() const
#define OPENVPN_THROW(exc, stuff)
std::string ext(const std::string &basename)
std::string dirname(const std::string &path)
std::string basename(const std::string &path)
std::string join(const std::string &p1, const std::string &p2)
bool is_flat(const std::string &path)
int strcasecmp(const char *s1, const char *s2)
void add_trailing(std::string &str, const char c)
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
void ext(const std::string &path)