1
#include "source/common/formatter/substitution_format_utility.h"
2

            
3
#include "envoy/api/os_sys_calls.h"
4

            
5
#include "source/common/api/os_sys_calls_impl.h"
6
#include "source/common/http/header_utility.h"
7
#include "source/common/http/utility.h"
8
#include "source/common/protobuf/utility.h"
9
#include "source/common/runtime/runtime_features.h"
10
#include "source/common/stream_info/utility.h"
11

            
12
namespace Envoy {
13
namespace Formatter {
14

            
15
static const std::string DefaultUnspecifiedValueString = "-";
16

            
17
absl::Status CommandSyntaxChecker::verifySyntax(CommandSyntaxChecker::CommandSyntaxFlags flags,
18
                                                absl::string_view command,
19
                                                absl::string_view subcommand,
20
291834
                                                absl::optional<size_t> length) {
21
291834
  if ((flags == COMMAND_ONLY) && ((subcommand.length() != 0) || length.has_value())) {
22
6
    return absl::InvalidArgumentError(
23
6
        fmt::format("{} does not take any parameters or length", command));
24
6
  }
25

            
26
291828
  if ((flags & PARAMS_REQUIRED).any() && (subcommand.length() == 0)) {
27
9
    return absl::InvalidArgumentError(fmt::format("{} requires parameters", command));
28
9
  }
29

            
30
291819
  if ((flags & LENGTH_ALLOWED).none() && length.has_value()) {
31
1
    return absl::InvalidArgumentError(
32
1
        fmt::format("{} does not allow length to be specified.", command));
33
1
  }
34
291818
  return absl::OkStatus();
35
291819
}
36

            
37
const absl::optional<std::reference_wrapper<const std::string>>
38
72299
SubstitutionFormatUtils::protocolToString(const absl::optional<Http::Protocol>& protocol) {
39
72299
  if (protocol) {
40
72254
    return Http::Utility::getProtocolString(protocol.value());
41
72254
  }
42
45
  return absl::nullopt;
43
72299
}
44

            
45
const std::string&
46
495
SubstitutionFormatUtils::protocolToStringOrDefault(const absl::optional<Http::Protocol>& protocol) {
47
495
  if (protocol) {
48
491
    return Http::Utility::getProtocolString(protocol.value());
49
491
  }
50
4
  return DefaultUnspecifiedValueString;
51
495
}
52

            
53
4
const absl::optional<std::string> SubstitutionFormatUtils::getHostname() {
54
4
#ifdef HOST_NAME_MAX
55
4
  const size_t len = HOST_NAME_MAX;
56
#else
57
  // This is notably the case in OSX.
58
  const size_t len = 255;
59
#endif
60
4
  char name[len];
61
4
  Api::OsSysCalls& os_sys_calls = Api::OsSysCallsSingleton::get();
62
4
  const Api::SysCallIntResult result = os_sys_calls.gethostname(name, len);
63

            
64
4
  absl::optional<std::string> hostname;
65
4
  if (result.return_value_ == 0) {
66
3
    hostname = name;
67
3
  }
68

            
69
4
  return hostname;
70
4
}
71

            
72
1209
const Protobuf::Value& SubstitutionFormatUtils::unspecifiedValue() {
73
1209
  return ValueUtil::nullValue();
74
1209
}
75

            
76
2643
bool SubstitutionFormatUtils::truncate(std::string& str, absl::optional<size_t> max_length) {
77
2643
  if (!max_length) {
78
2610
    return false;
79
2610
  }
80

            
81
33
  if (str.length() > max_length.value()) {
82
26
    str.resize(max_length.value());
83
26
    return true;
84
26
  }
85

            
86
7
  return false;
87
33
}
88

            
89
absl::string_view SubstitutionFormatUtils::truncateStringView(absl::string_view str,
90
293693
                                                              absl::optional<size_t> max_length) {
91
293693
  if (!max_length) {
92
293675
    return str;
93
293675
  }
94

            
95
18
  return str.substr(0, max_length.value());
96
293693
}
97

            
98
absl::StatusOr<SubstitutionFormatUtils::HeaderPair>
99
133496
SubstitutionFormatUtils::parseSubcommandHeaders(absl::string_view subcommand) {
100
133496
  absl::string_view main_header, alternative_header;
101
  // subs is used only to check if there are more than 2 headers separated by '?'.
102
133496
  std::vector<absl::string_view> subs;
103
133496
  parseSubcommand(subcommand, '?', main_header, alternative_header, subs);
104
133496
  if (!subs.empty()) {
105
2
    return absl::InvalidArgumentError(
106
        // Header format rules support only one alternative header.
107
        // docs/root/configuration/observability/access_log/access_log.rst#format-rules
108
2
        absl::StrCat("More than 1 alternative header specified in token: ", subcommand));
109
2
  }
110

            
111
133494
  if (!Http::HeaderUtility::headerNameIsValid(absl::AsciiStrToLower(main_header)) ||
112
133494
      !Http::HeaderUtility::headerNameIsValid(absl::AsciiStrToLower(alternative_header))) {
113
2
    return absl::InvalidArgumentError(
114
2
        "Invalid header configuration. Format string contains invalid characters.");
115
2
  }
116
133492
  return {std::make_pair(main_header, alternative_header)};
117
133494
}
118

            
119
} // namespace Formatter
120
} // namespace Envoy