原理
-
编码后的字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。
-
这是在 RFC 3986中描述的编码,是为了保护原义字符以免其被解释为特殊的 URL 定界符,同时保护 URL 格式以免其被传输媒体(像一些邮件系统)使用字符转换时弄乱。
编码代码
std::string RawUrlEncode(const std::string &szToEncode) {
std::string src = szToEncode;
char hex[] = "0123456789ABCDEF";
std::string dst;
for (size_t i = 0; i < src.size(); ++i)
{
unsigned char cc = src[i];
if ( cc >= 'A' && cc <= 'Z'
|| cc >='a' && cc <= 'z'
|| cc >='0' && cc <= '9'
|| cc == '.'
|| cc == '_'
|| cc == '-'
)
{
dst += cc;
}
else
{
unsigned char c = static_cast<unsigned char>(src[i]);
dst += '%';
dst += hex[c / 16];
dst += hex[c % 16];
}
}
return dst;
}
解码代码
std::string RawUrlDecode(const std::string &szToDecode) {
std::string result;
int hex = 0;
for (size_t i = 0; i < szToDecode.length(); ++i)
{
switch (szToDecode[i])
{
case '%':
if (isxdigit(szToDecode[i + 1]) && isxdigit(szToDecode[i + 2]))
{
std::string hexStr = szToDecode.substr(i + 1, 2);
hex = strtol(hexStr.c_str(), 0, 16);
if (!((hex >= 48 && hex <= 57) || //0-9
(hex >=97 && hex <= 122) || //a-z
(hex >=65 && hex <= 90) || //A-Z
hex == 0x2e || //.
hex == 0x5f || //_
hex == 0x2d //_
))
{
result += char(hex);
i += 2;
}
else result += '%';
}else {
result += '%';
}
break;
default:
result += szToDecode[i];
break;
}
}
return result;
}