Coverage Report

Created: 2026-10-23 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/src/proxy/http/remap/UrlMapping.cc
Line
Count
Source
1
/** @file
2
3
  A brief file description
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
23
 */
24
25
#include "tscore/ink_defs.h"
26
#include "proxy/http/remap/UrlMapping.h"
27
#include "records/RecCore.h"
28
#include "tscore/ink_cap.h"
29
30
// Avoid including private header files
31
struct CacheHostRecord;
32
extern void             destroyCacheHostRecord(CacheHostRecord *rec);
33
extern CacheHostRecord *createCacheHostRecord(const char *volume_str, char *errbuf, size_t errbufsize);
34
35
namespace
36
{
37
DbgCtl dbg_ctl_url_rewrite{"url_rewrite"};
38
39
} // end anonymous namespace
40
41
/**
42
 *
43
 **/
44
bool
45
url_mapping::add_plugin_instance(RemapPluginInst *i)
46
0
{
47
0
  _plugin_inst_list.push_back(i);
48
0
  return true;
49
0
}
50
51
/**
52
 *
53
 **/
54
RemapPluginInst *
55
url_mapping::get_plugin_instance(std::size_t index) const
56
0
{
57
0
  Dbg(dbg_ctl_url_rewrite, "get_plugin says we have %zu plugins and asking for plugin %zu", _plugin_inst_list.size(), index);
58
0
  if (index < _plugin_inst_list.size()) {
59
0
    return _plugin_inst_list[index];
60
0
  }
61
0
  return nullptr;
62
0
}
63
64
/**
65
 *
66
 **/
67
url_mapping::~url_mapping()
68
0
{
69
0
  referer_info     *r;
70
0
  redirect_tag_str *rc;
71
0
  acl_filter_rule  *afr;
72
73
0
  tag                 = static_cast<char *>(ats_free_null(tag));
74
0
  filter_redirect_url = static_cast<char *>(ats_free_null(filter_redirect_url));
75
76
0
  while ((r = referer_list) != nullptr) {
77
0
    referer_list = r->next;
78
0
    delete r;
79
0
  }
80
81
0
  while ((rc = redir_chunk_list) != nullptr) {
82
0
    redir_chunk_list = rc->next;
83
0
    delete rc;
84
0
  }
85
86
  // Delete filters
87
0
  while ((afr = filter) != nullptr) {
88
0
    filter = afr->next;
89
0
    delete afr;
90
0
  }
91
92
  // Destroy any volume hosting records
93
0
  destroyCacheHostRecord(volume_host_rec.load(std::memory_order_acquire));
94
95
  // Destroy the URLs
96
0
  fromURL.destroy();
97
0
  toURL.destroy();
98
0
}
99
100
bool
101
url_mapping::initVolumeHostRec(char *errbuf, size_t errbufsize)
102
0
{
103
0
  if (_volume_str.empty() || volume_host_rec.load(std::memory_order_acquire) != nullptr) {
104
0
    return true;
105
0
  }
106
107
0
  CacheHostRecord *new_rec = createCacheHostRecord(_volume_str.c_str(), errbuf, errbufsize);
108
109
0
  if (!new_rec) {
110
0
    return false;
111
0
  }
112
113
0
  CacheHostRecord *expected = nullptr;
114
115
0
  if (volume_host_rec.compare_exchange_strong(expected, new_rec, std::memory_order_acq_rel)) {
116
0
    Dbg(dbg_ctl_url_rewrite, "Initialized volume_host_rec for @volume=%s", _volume_str.c_str());
117
0
    return true;
118
0
  } else {
119
    // Another thread beat us to it, destroy our copy
120
0
    destroyCacheHostRecord(new_rec);
121
0
    return true;
122
0
  }
123
0
}
124
125
void
126
url_mapping::Print() const
127
0
{
128
0
  char from_url_buf[131072], to_url_buf[131072];
129
130
0
  fromURL.string_get_buf(from_url_buf, static_cast<int>(sizeof(from_url_buf)));
131
0
  toURL.string_get_buf(to_url_buf, static_cast<int>(sizeof(to_url_buf)));
132
0
  printf("\t %s %s=> %s %s <%s> [plugins %s enabled; running with %zu plugins]\n", from_url_buf, unique ? "(unique)" : "",
133
0
         to_url_buf, homePageRedirect ? "(R)" : "", tag ? tag : "", _plugin_inst_list.size() > 0 ? "are" : "not",
134
0
         _plugin_inst_list.size());
135
0
}
136
137
std::string
138
url_mapping::PrintRemapHitCount() const
139
0
{
140
0
  std::string result = R"({"fromURL": ")" + remapKey + R"(", "hit_count": )" + std::to_string(_hitCount) + "}";
141
0
  return result;
142
0
}
143
144
/**
145
 *
146
 **/
147
redirect_tag_str *
148
redirect_tag_str::parse_format_redirect_url(char *url)
149
0
{
150
0
  char             *c;
151
0
  redirect_tag_str *r;
152
0
  redirect_tag_str *list = nullptr;
153
154
0
  if (url && *url) {
155
0
    for (redirect_tag_str **rr = &list; *(c = url) != 0;) {
156
0
      char type = 0;
157
0
      for (type = 's'; *c; c++) {
158
0
        if (c[0] == '%') {
159
0
          char tmp_type = static_cast<char>(tolower(static_cast<int>(c[1])));
160
0
          if (tmp_type == 'r' || tmp_type == 'f' || tmp_type == 't' || tmp_type == 'o') {
161
0
            if (url == c) {
162
0
              type = tmp_type;
163
0
            }
164
0
            break;
165
0
          }
166
0
        }
167
0
      }
168
0
      r = new redirect_tag_str();
169
0
      if (likely(r)) {
170
0
        if ((r->type = type) == 's') {
171
0
          char svd     = *c;
172
0
          *c           = 0;
173
0
          r->chunk_str = ats_strdup(url);
174
0
          *c           = svd;
175
0
          url          = c;
176
0
        } else {
177
0
          url += 2;
178
0
        }
179
0
        (*rr = r)->next = nullptr;
180
0
        rr              = &(r->next);
181
0
      } else {
182
0
        break; /* memory allocation error */
183
0
      }
184
0
    }
185
0
  }
186
0
  return list;
187
0
}
188
189
/**
190
 *
191
 **/
192
referer_info::referer_info(const char *_ref, bool *error_flag, char *errmsgbuf, int errmsgbuf_size)
193
0
{
194
0
  std::string error;
195
0
  int         erroffset;
196
197
0
  if (error_flag) {
198
0
    *error_flag = false;
199
0
  }
200
201
0
  if (_ref) {
202
0
    if (*_ref == '~') {
203
0
      negative = true;
204
0
      _ref++;
205
0
    }
206
0
    if ((referer = ats_strdup(_ref)) != nullptr) {
207
0
      referer_size = strlen(referer);
208
0
      if (!strcmp(referer, "*")) {
209
0
        any = true;
210
0
      } else {
211
0
        regex_valid = regex.compile(referer, error, erroffset, RE_CASE_INSENSITIVE, "map_with_referer referer");
212
0
        if (regex_valid == false) {
213
0
          if (errmsgbuf && (errmsgbuf_size - 1) > 0) {
214
0
            ink_strlcpy(errmsgbuf, error.c_str(), errmsgbuf_size);
215
0
          }
216
0
          if (error_flag) {
217
0
            *error_flag = true;
218
0
          }
219
0
        }
220
0
      }
221
0
    }
222
0
  }
223
0
}
224
225
/**
226
 *
227
 **/
228
referer_info::~referer_info()
229
0
{
230
0
  ats_free(referer);
231
0
  referer      = nullptr;
232
0
  referer_size = 0;
233
0
}