blob: cfd0f846408db00ca94d0e310a3d430f26e02ee1 [file] [log] [blame]
/** @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.
*/
#include "Utils.h"
#include <sstream>
using namespace EsiLib;
ComponentBase::Debug Utils::DEBUG_LOG(nullptr);
ComponentBase::Error Utils::ERROR_LOG(nullptr);
#define DEBUG_TAG "EsiUtils"
using std::string;
void
Utils::init(ComponentBase::Debug debug_func, ComponentBase::Error error_func)
{
DEBUG_LOG = debug_func;
ERROR_LOG = error_func;
}
bool
Utils::getAttribute(const string &data, const string &attr, size_t curr_pos, size_t end_pos, Attribute &attr_info,
size_t *term_pos /* = 0 */, char terminator /* = 0 */)
{
size_t attr_start = data.find(attr, curr_pos);
if (attr_start >= end_pos) {
ERROR_LOG("[%s] Tag has no [%.*s] attribute", __FUNCTION__, attr.size(), attr.data());
return false;
}
curr_pos = attr_start + attr.size();
bool equals_found = false;
for (; curr_pos < end_pos; ++curr_pos) {
if (data[curr_pos] == ' ') {
continue;
} else {
if (data[curr_pos] == '=') {
equals_found = true;
}
break;
}
}
if (!equals_found) {
ERROR_LOG("[%s] Attribute [%.*s] has no value", __FUNCTION__, attr.size(), attr.data());
return false;
}
++curr_pos;
if (curr_pos == end_pos) {
ERROR_LOG("[%s] No space for value after [%.*s] attribute", __FUNCTION__, attr.size(), attr.data());
return false;
}
bool in_quoted_part = false;
bool quoted = false;
size_t i;
for (i = curr_pos; i < end_pos; ++i) {
if (data[i] == '"') {
quoted = true;
in_quoted_part = !in_quoted_part;
} else if (data[i] == ' ') {
if (!in_quoted_part) {
break;
}
} else if (terminator && !in_quoted_part && (data[i] == terminator)) {
break;
}
}
const char *data_start_ptr = data.data();
if (in_quoted_part) {
ERROR_LOG("[%s] Unterminated quote in value for attribute [%.*s] starting at [%.10s]", __FUNCTION__, attr.size(), attr.data(),
data_start_ptr + curr_pos);
return false;
}
if (terminator && term_pos) {
*term_pos = data.find(terminator, i);
if (*term_pos >= end_pos) {
ERROR_LOG("[%s] Unterminated attribute [%.*s]", __FUNCTION__, attr.size(), attr.data());
return false;
}
}
attr_info.name = data_start_ptr + attr_start;
attr_info.name_len = attr.size();
attr_info.value = data_start_ptr + curr_pos;
attr_info.value_len = i - curr_pos;
if (quoted) {
++attr_info.value;
attr_info.value_len -= 2;
}
return true;
}
void
Utils::parseKeyValueConfig(const std::list<string> &lines, KeyValueMap &kvMap, HeaderValueList &allowlistCookies)
{
string key, value;
std::istringstream iss;
for (const auto &conf_line : lines) {
// handy reference
if (!conf_line.size() || (conf_line[0] == '#')) {
continue;
}
iss.clear();
iss.str(conf_line);
if (iss.good()) {
iss >> key;
iss >> value;
if (key == "allowlistCookie") {
allowlistCookies.push_back(value);
continue;
}
if (key.size() && value.size()) {
kvMap.insert(KeyValueMap::value_type(key, value));
DEBUG_LOG(DEBUG_TAG, "[%s] Read value [%s] for key [%s]", __FUNCTION__, value.c_str(), key.c_str());
}
}
key.clear();
value.clear();
}
}
void
Utils::parseAttributes(const char *data, int data_len, AttributeList &attr_list, const char *pair_separators /* = " " */)
{
attr_list.clear();
if (!data || (data_len <= 0)) {
return;
}
char separator_lookup[256] = {0};
int i;
for (i = 0; pair_separators[i]; ++i) {
separator_lookup[static_cast<uint8_t>(pair_separators[i])] = 1;
}
Attribute attr;
bool inside_quotes = false, end_of_attribute;
bool escape_on = false;
for (i = 0; (i < data_len) && ((isspace(data[i]) || separator_lookup[static_cast<uint8_t>(data[i])])); ++i) {
;
}
attr.name = data + i;
attr.value = nullptr;
for (; i <= data_len; ++i) {
end_of_attribute = false;
if (i == data_len) {
end_of_attribute = true;
} else if (separator_lookup[static_cast<uint8_t>(data[i])] && !inside_quotes) {
end_of_attribute = true;
} // else ignore separator when in quotes
if (end_of_attribute) {
if (!inside_quotes) {
if (attr.value > attr.name) {
attr.value_len = data + i - attr.value;
trimWhiteSpace(attr.name, attr.name_len);
trimWhiteSpace(attr.value, attr.value_len);
if (attr.value[0] == '"') {
++attr.value;
attr.value_len -= 2;
}
if (attr.name_len && attr.value_len) {
DEBUG_LOG(DEBUG_TAG, "[%s] Added attribute with name [%.*s] and value [%.*s]", __FUNCTION__, attr.name_len, attr.name,
attr.value_len, attr.value);
attr_list.push_back(attr);
} // else ignore empty name/value
} // else ignore attribute with no value
} // else ignore variable with unterminated quotes
for (; (i < data_len) && ((isspace(data[i]) || separator_lookup[static_cast<uint8_t>(data[i])])); ++i) {
;
}
attr.name = data + i;
attr.value = nullptr;
inside_quotes = false;
} else if (data[i] == '"') {
if (!escape_on) {
inside_quotes = !inside_quotes;
}
} else if ((data[i] == '=') && !attr.value && !inside_quotes) {
attr.value = data + i + 1;
attr.name_len = data + i - attr.name;
}
escape_on = (data[i] == '\\') ? true : false;
}
}