Fix http url path and component's coding (#3237 #3181)

This commit is contained in:
sandro-qiang 2024-01-28 19:18:36 +08:00 committed by GitHub
parent cfe9a31ca6
commit ceae040a7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 130 additions and 10 deletions

View File

@ -204,7 +204,7 @@ static ApiArgsType getAllArgs(const Parser &parser) {
if (parser["Content-Type"].find("application/x-www-form-urlencoded") == 0) {
auto contentArgs = parser.parseArgs(parser.content());
for (auto &pr : contentArgs) {
allArgs[pr.first] = HttpSession::urlDecode(pr.second);
allArgs[pr.first] = HttpSession::urlDecodeComponent(pr.second);
}
} else if (parser["Content-Type"].find("application/json") == 0) {
try {

View File

@ -294,8 +294,8 @@ void RtspUrl::setup(bool is_ssl, const string &url, const string &user, const st
splitUrl(ip, ip, port);
_url = std::move(url);
_user = strCoding::UrlDecode(std::move(user));
_passwd = strCoding::UrlDecode(std::move(passwd));
_user = strCoding::UrlDecodeComponent(std::move(user));
_passwd = strCoding::UrlDecodeComponent(std::move(passwd));
_host = std::move(ip);
_port = port;
_is_ssl = is_ssl;

View File

@ -69,6 +69,40 @@ string strCoding::UrlEncode(const string &str) {
return out;
}
string strCoding::UrlEncodePath(const string &str) {
const char *dont_escape = "!#&'*+:=?@/._-$,;~()";
string out;
size_t len = str.size();
for (size_t i = 0; i < len; ++i) {
char ch = str[i];
if (isalnum((uint8_t) ch) || strchr(dont_escape, (uint8_t) ch) != NULL) {
out.push_back(ch);
} else {
char buf[4];
sprintf(buf, "%%%X%X", (uint8_t) ch >> 4, (uint8_t) ch & 0x0F);
out.append(buf);
}
}
return out;
}
string strCoding::UrlEncodeComponent(const string &str) {
const char *dont_escape = "!'()*-._~";
string out;
size_t len = str.size();
for (size_t i = 0; i < len; ++i) {
char ch = str[i];
if (isalnum((uint8_t) ch) || strchr(dont_escape, (uint8_t) ch) != NULL) {
out.push_back(ch);
} else {
char buf[4];
sprintf(buf, "%%%X%X", (uint8_t) ch >> 4, (uint8_t) ch & 0x0F);
out.append(buf);
}
}
return out;
}
string strCoding::UrlDecode(const string &str) {
string output;
size_t i = 0, len = str.length();
@ -95,6 +129,62 @@ string strCoding::UrlDecode(const string &str) {
return output;
}
string strCoding::UrlDecodePath(const string &str) {
const char *dont_unescape = "#$&+,/:;=?@";
string output;
size_t i = 0, len = str.length();
while (i < len) {
if (str[i] == '%') {
if (i + 3 > len) {
// %后面必须还有两个字节才会反转义
output.append(str, i, len - i);
break;
}
char ch = HexStrToBin(&(str[i + 1]));
if (ch == -1 || strchr(dont_unescape, (unsigned char)ch) != NULL) {
// %后面两个字节不是16进制字符串转义失败或者转义出来可能会造成url包含非path部分比如#?说明提交的是非法拼接的url直接拼接3个原始字符
output.append(str, i, 3);
} else {
output += ch;
}
i += 3;
} else {
output += str[i];
++i;
}
}
return output;
}
std::string strCoding::UrlDecodeComponent(const std::string &str) {
string output;
size_t i = 0, len = str.length();
while (i < len) {
if (str[i] == '%') {
if (i + 3 > len) {
// %后面必须还有两个字节才会反转义
output.append(str, i, len - i);
break;
}
char ch = HexStrToBin(&(str[i + 1]));
if (ch == -1) {
// %后面两个字节不是16进制字符串转义失败直接拼接3个原始字符
output.append(str, i, 3);
} else {
output += ch;
}
i += 3;
} else if (str[i] == '+') {
output += ' ';
++i;
} else {
output += str[i];
++i;
}
}
return output;
}
#if 0
#include "Util/onceToken.h"
static toolkit::onceToken token([]() {

View File

@ -18,8 +18,12 @@ namespace mediakit {
class strCoding {
public:
static std::string UrlEncode(const std::string &str); //urlutf8 编码
static std::string UrlDecode(const std::string &str); //urlutf8解码
[[deprecated]] static std::string UrlEncode(const std::string &str); //url utf8编码, deprecated
static std::string UrlEncodePath(const std::string &str); //url路径 utf8编码
static std::string UrlEncodeComponent(const std::string &str); // url参数 utf8编码
[[deprecated]] static std::string UrlDecode(const std::string &str); //url utf8解码, deprecated
static std::string UrlDecodePath(const std::string &str); //url路径 utf8解码
static std::string UrlDecodeComponent(const std::string &str); // url参数 utf8解码
#if defined(_WIN32)
static std::string UTF8ToGB2312(const std::string &str);//utf_8转为gb2312
static std::string GB2312ToUTF8(const std::string &str); //gb2312 转utf_8

View File

@ -34,7 +34,7 @@ public:
for (auto &pr : *this) {
ret.append(pr.first);
ret.append("=");
ret.append(strCoding::UrlEncode(pr.second));
ret.append(strCoding::UrlEncodeComponent(pr.second));
ret.append("&");
}
if (ret.size()) {

View File

@ -228,7 +228,7 @@ static bool makeFolderMenu(const string &httpPath, const string &strFullPath, st
multimap<string/*url name*/, std::pair<string/*note name*/, string/*file path*/> > file_map;
File::scanDir(strPathPrefix, [&](const std::string &path, bool isDir) {
auto name = fileName(strPathPrefix, path);
file_map.emplace(strCoding::UrlEncode(name), std::make_pair(name, path));
file_map.emplace(strCoding::UrlEncodePath(name), std::make_pair(name, path));
return true;
});
//如果是root目录添加虚拟目录

View File

@ -695,10 +695,34 @@ string HttpSession::urlDecode(const string &str) {
return ret;
}
string HttpSession::urlDecodePath(const string &str) {
auto ret = strCoding::UrlDecodePath(str);
#ifdef _WIN32
GET_CONFIG(string, charSet, Http::kCharSet);
bool isGb2312 = !strcasecmp(charSet.data(), "gb2312");
if (isGb2312) {
ret = strCoding::UTF8ToGB2312(ret);
}
#endif // _WIN32
return ret;
}
string HttpSession::urlDecodeComponent(const string &str) {
auto ret = strCoding::UrlDecodeComponent(str);
#ifdef _WIN32
GET_CONFIG(string, charSet, Http::kCharSet);
bool isGb2312 = !strcasecmp(charSet.data(), "gb2312");
if (isGb2312) {
ret = strCoding::UTF8ToGB2312(ret);
}
#endif // _WIN32
return ret;
}
void HttpSession::urlDecode(Parser &parser) {
parser.setUrl(urlDecode(parser.url()));
parser.setUrl(urlDecodePath(parser.url()));
for (auto &pr : _parser.getUrlArgs()) {
const_cast<string &>(pr.second) = urlDecode(pr.second);
const_cast<string &>(pr.second) = urlDecodeComponent(pr.second);
}
}

View File

@ -44,7 +44,9 @@ public:
void onRecv(const toolkit::Buffer::Ptr &) override;
void onError(const toolkit::SockException &err) override;
void onManager() override;
static std::string urlDecode(const std::string &str);
[[deprecated]] static std::string urlDecode(const std::string &str);
static std::string urlDecodePath(const std::string &str);
static std::string urlDecodeComponent(const std::string &str);
void setTimeoutSec(size_t second);
void setMaxReqSize(size_t max_req_size);