216 строки
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			216 строки
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (c) 2018-2020 Albert S.
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in all
 | |
| copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
| SOFTWARE.
 | |
| */
 | |
| #include <sstream>
 | |
| #include <string>
 | |
| #include <regex>
 | |
| #include <map>
 | |
| #include <cstdlib>
 | |
| #include <fstream>
 | |
| #include "logger.h"
 | |
| #include "utils.h"
 | |
| 
 | |
| std::string utils::html_xss(std::string_view str)
 | |
| {
 | |
| 	std::string result;
 | |
| 	for(char c : str)
 | |
| 	{
 | |
| 		switch(c)
 | |
| 		{
 | |
| 		case '<':
 | |
| 			result += "<";
 | |
| 			break;
 | |
| 		case '>':
 | |
| 			result += ">";
 | |
| 			break;
 | |
| 		case '\"':
 | |
| 			result += """;
 | |
| 			break;
 | |
| 		case '%':
 | |
| 			result += "%";
 | |
| 			break;
 | |
| 		case '\'':
 | |
| 			result += "'";
 | |
| 			break;
 | |
| 		case '&':
 | |
| 			result += "&";
 | |
| 			break;
 | |
| 		default:
 | |
| 			result += c;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| std::string utils::urldecode(std::string_view str)
 | |
| {
 | |
| 	std::string result;
 | |
| 	int size = str.length();
 | |
| 	for(int i = 0; i < size; i++)
 | |
| 	{
 | |
| 		char c = str[i];
 | |
| 		if(c == '%' && (size - i > 1))
 | |
| 		{
 | |
| 			char h[3];
 | |
| 			h[0] = str[i + 1];
 | |
| 			h[1] = str[i + 2];
 | |
| 			h[2] = 0;
 | |
| 			if(std::isxdigit(h[0]) && std::isxdigit(h[1]))
 | |
| 			{
 | |
| 				c = std::stoi(h, 0, 16);
 | |
| 				i += 2;
 | |
| 			}
 | |
| 		}
 | |
| 		result += c;
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| std::vector<std::string> utils::split(std::string str, char delim)
 | |
| {
 | |
| 	std::vector<std::string> result;
 | |
| 	std::stringstream stream(str);
 | |
| 	std::string item;
 | |
| 	while(std::getline(stream, item, delim))
 | |
| 	{
 | |
| 		result.push_back(item);
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| // TODO: can easily break if we pass a regex here
 | |
| std::vector<std::string> utils::split(std::string str, const std::string &delim)
 | |
| {
 | |
| 	std::regex regex{delim + "+"};
 | |
| 	return split(str, regex);
 | |
| }
 | |
| 
 | |
| std::vector<std::string> utils::split(const std::string &str, std::regex ®ex)
 | |
| {
 | |
| 	std::vector<std::string> result;
 | |
| 	std::regex reg(regex);
 | |
| 	std::copy(std::sregex_token_iterator(str.begin(), str.end(), reg, -1), std::sregex_token_iterator(),
 | |
| 			  std::back_inserter(result));
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| std::string utils::strreplace(std::string str, const std::string &search, const std::string &replace)
 | |
| {
 | |
| 	std::string result = str;
 | |
| 	auto searchlength = search.length();
 | |
| 	auto replacelength = replace.length();
 | |
| 	size_t pos = 0;
 | |
| 	while((pos = result.find(search, pos)) != std::string::npos)
 | |
| 	{
 | |
| 		result = result.replace(pos, searchlength, replace);
 | |
| 		pos += replacelength;
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| std::string utils::getenv(const std::string &key)
 | |
| {
 | |
| 	const char *result = ::getenv(key.c_str());
 | |
| 	if(result == nullptr)
 | |
| 		return std::string();
 | |
| 	return std::string{result};
 | |
| }
 | |
| 
 | |
| std::string utils::readCompleteFile(std::string_view filepath)
 | |
| {
 | |
| 	std::fstream stream(std::string{filepath});
 | |
| 	if(!stream.is_open())
 | |
| 	{
 | |
| 		throw std::runtime_error("utils::readCompleteFile(): stream is not open");
 | |
| 	}
 | |
| 	std::stringstream ss;
 | |
| 	ss << stream.rdbuf();
 | |
| 	std::string content = ss.str();
 | |
| 	return content;
 | |
| }
 | |
| 
 | |
| std::string utils::regex_callback_replacer(std::regex regex, const std::string &input,
 | |
| 										   std::function<std::string(std::smatch &)> callback)
 | |
| {
 | |
| 	std::string result;
 | |
| 	auto tagsbegin = std::sregex_iterator(input.begin(), input.end(), regex);
 | |
| 	auto tagsend = std::sregex_iterator();
 | |
| 	auto matchbegin = 0;
 | |
| 	for(std::sregex_iterator i = tagsbegin; i != tagsend; ++i)
 | |
| 	{
 | |
| 		std::smatch match = *i;
 | |
| 
 | |
| 		auto matchlength = match.length(0);
 | |
| 		auto matchpos = match.position();
 | |
| 
 | |
| 		result += input.substr(matchbegin, matchpos - matchbegin);
 | |
| 		result += callback(match);
 | |
| 		matchbegin = matchpos + matchlength;
 | |
| 	}
 | |
| 	result += input.substr(matchbegin);
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| /* TODO: Convert to C++20, but currently the state is rather poor and would
 | |
|  * require workarounds, so keep it this way for now, and do it properly
 | |
|  * once compiler support gets there */
 | |
| std::string utils::formatLocalDate(time_t t, std::string format)
 | |
| {
 | |
| 	struct tm lt;
 | |
| 	if(localtime_r(&t, <) == nullptr)
 | |
| 	{
 | |
| 		return {};
 | |
| 	}
 | |
| 	char result[20];
 | |
| 	size_t x = strftime(result, sizeof(result), format.c_str(), <);
 | |
| 	if(x == 0)
 | |
| 	{
 | |
| 		return {};
 | |
| 	}
 | |
| 	return std::string{result};
 | |
| }
 | |
| 
 | |
| std::string utils::toISODateTime(time_t t)
 | |
| {
 | |
| 	return utils::formatLocalDate(t, "%Y-%m-%d %H:%M:%S");
 | |
| }
 | |
| 
 | |
| std::string utils::toISODate(time_t t)
 | |
| {
 | |
| 	return utils::formatLocalDate(t, "%Y-%m-%d");
 | |
| }
 | |
| 
 | |
| std::string utils::trim(std::string_view view)
 | |
| {
 | |
| 	std::string_view chars = " \t\n\r";
 | |
| 	auto n = view.find_first_not_of(chars);
 | |
| 	if(n != std::string_view::npos)
 | |
| 	{
 | |
| 		view.remove_prefix(n);
 | |
| 	}
 | |
| 	n = view.find_last_not_of(chars);
 | |
| 	if(n != std::string_view::npos)
 | |
| 	{
 | |
| 		view.remove_suffix(view.size() - n - 1);
 | |
| 	}
 | |
| 	return std::string{view};
 | |
| }
 |