File: Variables.h

package info (click to toggle)
trafficserver 9.2.5%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 53,008 kB
  • sloc: cpp: 345,484; ansic: 31,134; python: 24,200; sh: 7,271; makefile: 3,045; perl: 2,261; java: 277; pascal: 119; sql: 94; xml: 2
file content (179 lines) | stat: -rw-r--r-- 5,823 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#pragma once

#include <list>

#include <cstring>
#include "ComponentBase.h"
#include "StringHash.h"
#include "HttpHeader.h"
#include "Utils.h"

namespace EsiLib
{
class Variables : private ComponentBase
{
public:
  Variables(const char *debug_tag, ComponentBase::Debug debug_func, ComponentBase::Error error_func,
            Utils::HeaderValueList allowlistCookies)
    : ComponentBase(debug_tag, debug_func, error_func),
      _headers_parsed(false),
      _query_string(""),
      _query_string_parsed(false),
      _cookie_jar_created(false)
  {
    _allowlistCookies.insert(_allowlistCookies.end(), allowlistCookies.begin(), allowlistCookies.end());
  };

  /** currently 'host', 'referer', 'accept-language', 'cookie' and 'user-agent' headers are parsed */
  void populate(const HttpHeader &header);

  void
  populate(const HttpHeaderList &headers)
  {
    for (const auto &header : headers) {
      populate(header);
    }
  };

  void
  populate(const char *query_string, int query_string_len = -1)
  {
    if (query_string && (query_string_len != 0)) {
      if (query_string_len == -1) {
        query_string_len = strlen(query_string);
      }
      if (_query_string_parsed) {
        _parseQueryString(query_string, query_string_len);
      } else {
        _query_string.assign(query_string, query_string_len);
      }
    }
  }

  /** returns value of specified variable; empty string returned for unknown variable; key
   * has to be prefixed with 'http_' string for all variable names except 'query_string' */
  const std::string &getValue(const std::string &name) const;

  /** convenient alternative for method above */
  const std::string &
  getValue(const char *name, int name_len = -1) const
  {
    if (!name) {
      return EMPTY_STRING;
    }
    std::string var_name;
    if (name_len == -1) {
      var_name.assign(name);
    } else {
      var_name.assign(name, name_len);
    }
    return getValue(var_name);
  }

  void clear();

  ~Variables() override { _releaseCookieJar(); };

  // noncopyable
  Variables(const Variables &) = delete;            // non-copyable
  Variables &operator=(const Variables &) = delete; // non-copyable

private:
  static const std::string EMPTY_STRING;
  static const std::string TRUE_STRING;
  static const std::string VENDOR_STRING;
  static const std::string VERSION_STRING;
  static const std::string PLATFORM_STRING;

  enum SimpleHeader {
    HTTP_HOST    = 0,
    HTTP_REFERER = 1,
  };
  static const std::string SIMPLE_HEADERS[]; // indices should map to enum values above

  enum SpecialHeader {
    HTTP_ACCEPT_LANGUAGE = 0,
    HTTP_COOKIE          = 1,
    HTTP_USER_AGENT      = 2,
    QUERY_STRING         = 3,
    HTTP_HEADER          = 4,
  };
  static const std::string SPECIAL_HEADERS[]; // indices should map to enum values above

  // normalized versions of the headers above; indices should correspond correctly
  static const std::string NORM_SIMPLE_HEADERS[];
  static const std::string NORM_SPECIAL_HEADERS[]; // indices should again map to enum values

  static const int N_SIMPLE_HEADERS  = HTTP_REFERER + 1;
  static const int N_SPECIAL_HEADERS = HTTP_HEADER + 1;

  StringHash _simple_data;
  StringHash _dict_data[N_SPECIAL_HEADERS];

  inline std::string &_toUpperCase(std::string &str) const;
  inline int _searchHeaders(const std::string headers[], const char *name, int name_len) const;
  bool _parseDictVariable(const std::string &variable, const char *&header, int &header_len, const char *&attr,
                          int &attr_len) const;
  void _parseCookieString(const char *str, int str_len);
  void _parseUserAgentString(const char *str, int str_len);
  void _parseAcceptLangString(const char *str, int str_len);
  inline void _parseSimpleHeader(SimpleHeader hdr, const std::string &value);
  inline void _parseSimpleHeader(SimpleHeader hdr, const char *value, int value_len);
  void _parseSpecialHeader(SpecialHeader hdr, const char *value, int value_len);
  void _parseCachedHeaders();

  inline void _insert(StringHash &hash, const std::string &key, const std::string &value);

  Utils::HeaderValueList _cached_simple_headers[N_SIMPLE_HEADERS];
  Utils::HeaderValueList _cached_special_headers[N_SPECIAL_HEADERS];

  Utils::HeaderValueList _allowlistCookies;
  std::string _cookie_str;
  bool _headers_parsed;
  std::string _query_string;
  bool _query_string_parsed;

  void _parseHeader(const char *name, int name_len, const char *value, int value_len);
  void _parseQueryString(const char *query_string, int query_string_len);

  StringKeyHash<StringHash> _sub_cookies;
  bool _cookie_jar_created;

  void _parseSubCookies();

  inline void
  _releaseCookieJar()
  {
    if (_cookie_jar_created) {
      _sub_cookies.clear();
      _cookie_jar_created = false;
    }
  }

  mutable std::string _cached_sub_cookie_value;
  const std::string &_getSubCookieValue(const std::string &cookie_str, size_t cookie_part_divider) const;
};
}; // namespace EsiLib