我正在linux上开发一个c / c ++程序。如果有任何c / c ++库解码url,你能告诉我吗?
我正在寻找哪些图书馆 兑换 的 “http%3A%2F%2F” 至: 的 “http://”
或 “a + t +%26 + t”到“t& t”
谢谢。
答案 0 :(得分:23)
我实际上在我正在编写的分析程序中使用了Saul的功能(分析了数百万个URL编码的字符串),虽然它有效,但是在这个规模上它使我的程序放慢了速度,所以我决定写一个更快的版本。使用GCC和-O2选项编译时,这个速度要快几千倍。它也可以使用与输入相同的输出缓冲区(例如,如果原始字符串在buf中并且要被其解码的副本覆盖,则urldecode2(buf,buf)将起作用。)
编辑:它没有将缓冲区大小作为输入,因为假设缓冲区足够大,这是安全的,因为已知输出的长度总是be< =输入的那个,所以要么为输出使用相同的缓冲区,要么创建一个至少为null终止符的输入+ 1的大小,例如:
char *output = malloc(strlen(input)+1);
urldecode2(output, input);
printf("Decoded string: %s\n", output);
编辑2:一位匿名用户试图编辑此答案以处理'+'字符对''的翻译,我认为应该这样做,这不是我需要的东西对于我的申请,但我在下面添加了它。
这是例程:
#include <stdlib.h>
#include <ctype.h>
void urldecode2(char *dst, const char *src)
{
char a, b;
while (*src) {
if ((*src == '%') &&
((a = src[1]) && (b = src[2])) &&
(isxdigit(a) && isxdigit(b))) {
if (a >= 'a')
a -= 'a'-'A';
if (a >= 'A')
a -= ('A' - 10);
else
a -= '0';
if (b >= 'a')
b -= 'a'-'A';
if (b >= 'A')
b -= ('A' - 10);
else
b -= '0';
*dst++ = 16*a+b;
src+=3;
} else if (*src == '+') {
*dst++ = ' ';
src++;
} else {
*dst++ = *src++;
}
}
*dst++ = '\0';
}
答案 1 :(得分:4)
这是一个百分比编码字符串的C解码器。如果编码无效则返回-1,否则返回0。解码后的字符串存储在out中。我非常确定这是迄今为止给出的答案中最快的代码。
int percent_decode(char* out, const char* in) {
{
static const char tbl[256] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1
};
char c, v1, v2, beg=out;
if(in != NULL) {
while((c=*in++) != '\0') {
if(c == '%') {
if(!(v1=*in++) || (v1=tbl[(unsigned char)v1])<0 ||
!(v2=*in++) || (v2=tbl[(unsigned char)v2])<0) {
*beg = '\0';
return -1;
}
c = (v1<<4)|v2;
}
*out++ = c;
}
}
*out = '\0';
return 0;
}
答案 2 :(得分:3)
卓越的glib有一些URI functions,包括计划提取,转义和取消转义。
答案 3 :(得分:3)
这个我刚刚掀起的功能非常轻巧,应该按照您的意愿行事,请注意我没有将其编程为严格的URI标准(使用我所知道的顶部)。这是缓冲安全的,并且我没有看到溢出;适应你认为适合:
#include <assert.h>
void urldecode(char *pszDecodedOut, size_t nBufferSize, const char *pszEncodedIn)
{
memset(pszDecodedOut, 0, nBufferSize);
enum DecodeState_e
{
STATE_SEARCH = 0, ///< searching for an ampersand to convert
STATE_CONVERTING, ///< convert the two proceeding characters from hex
};
DecodeState_e state = STATE_SEARCH;
for(unsigned int i = 0; i < strlen(pszEncodedIn)-1; ++i)
{
switch(state)
{
case STATE_SEARCH:
{
if(pszEncodedIn[i] != '%')
{
strncat(pszDecodedOut, &pszEncodedIn[i], 1);
assert(strlen(pszDecodedOut) < nBufferSize);
break;
}
// We are now converting
state = STATE_CONVERTING;
}
break;
case STATE_CONVERTING:
{
// Conversion complete (i.e. don't convert again next iter)
state = STATE_SEARCH;
// Create a buffer to hold the hex. For example, if %20, this
// buffer would hold 20 (in ASCII)
char pszTempNumBuf[3] = {0};
strncpy(pszTempNumBuf, &pszEncodedIn[i], 2);
// Ensure both characters are hexadecimal
bool bBothDigits = true;
for(int j = 0; j < 2; ++j)
{
if(!isxdigit(pszTempNumBuf[j]))
bBothDigits = false;
}
if(!bBothDigits)
break;
// Convert two hexadecimal characters into one character
int nAsciiCharacter;
sscanf(pszTempNumBuf, "%x", &nAsciiCharacter);
// Ensure we aren't going to overflow
assert(strlen(pszDecodedOut) < nBufferSize);
// Concatenate this character onto the output
strncat(pszDecodedOut, (char*)&nAsciiCharacter, 1);
// Skip the next character
i++;
}
break;
}
}
}
答案 4 :(得分:2)
uriparser库小巧轻便。
答案 5 :(得分:1)
尝试urlcpp https://github.com/larroy/urlcpp 这是一个可以轻松集成到项目中的C ++模块,取决于boost :: regex
答案 6 :(得分:1)
我建议curl and libcurl。它被广泛使用,应该为你做的伎俩。只需查看他们的网站。
答案 7 :(得分:0)
/**
* Locale-independent conversion of ASCII characters to lowercase.
*/
int av_tolower(int c)
{
if (c >= 'A' && c <= 'Z')
c ^= 0x20;
return c;
}
/**
* Decodes an URL from its percent-encoded form back into normal
* representation. This function returns the decoded URL in a string.
* The URL to be decoded does not necessarily have to be encoded but
* in that case the original string is duplicated.
*
* @param url a string to be decoded.
* @return new string with the URL decoded or NULL if decoding failed.
* Note that the returned string should be explicitly freed when not
* used anymore.
*/
char *urldecode(const char *url)
{
int s = 0, d = 0, url_len = 0;
char c;
char *dest = NULL;
if (!url)
return NULL;
url_len = strlen(url) + 1;
dest = av_malloc(url_len);
if (!dest)
return NULL;
while (s < url_len) {
c = url[s++];
if (c == '%' && s + 2 < url_len) {
char c2 = url[s++];
char c3 = url[s++];
if (isxdigit(c2) && isxdigit(c3)) {
c2 = av_tolower(c2);
c3 = av_tolower(c3);
if (c2 <= '9')
c2 = c2 - '0';
else
c2 = c2 - 'a' + 10;
if (c3 <= '9')
c3 = c3 - '0';
else
c3 = c3 - 'a' + 10;
dest[d++] = 16 * c2 + c3;
} else { /* %zz or something other invalid */
dest[d++] = c;
dest[d++] = c2;
dest[d++] = c3;
}
} else if (c == '+') {
dest[d++] = ' ';
} else {
dest[d++] = c;
}
}
return dest;
}
by
www.elesos.com
答案 8 :(得分:0)
感谢@ThomasH的回答。我想在这里提出一个更好的格式化......
并且......由于解码的URI组件始终长于相同的编码URI组件,因此始终可以在相同的字符数组中内爆它(也就是: “串”)。所以,我会在这里建议两种可能性:
#include <stdio.h>
int decodeURIComponent (char *sSource, char *sDest) {
int nLength;
for (nLength = 0; *sSource; nLength++) {
if (*sSource == '%' && sSource[1] && sSource[2] && isxdigit(sSource[1]) && isxdigit(sSource[2])) {
sSource[1] -= sSource[1] <= '9' ? '0' : (sSource[1] <= 'F' ? 'A' : 'a')-10;
sSource[2] -= sSource[2] <= '9' ? '0' : (sSource[2] <= 'F' ? 'A' : 'a')-10;
sDest[nLength] = 16 * sSource[1] + sSource[2];
sSource += 3;
continue;
}
sDest[nLength] = *sSource++;
}
sDest[nLength] = '\0';
return nLength;
}
#define implodeURIComponent(url) decodeURIComponent(url, url)
最后......:
int main () {
char sMyUrl[] = "http%3a%2F%2ffoo+bar%2fabcd";
int nNewLength = implodeURIComponent(sMyUrl);
/* Let's print: "http://foo+bar/abcd\nLength: 19" */
printf("%s\nLength: %d\n", sMyUrl, nNewLength);
return 0;
}
步骤*
答案 9 :(得分:0)
这个与我寻找相同问题的问题已经有8年了。根据先前的答案,我还编写了自己的版本,该版本独立于libs,易于理解,而且速度可能很快(无基准)。使用gcc测试过的代码,应该解码直到结尾或无效字符(未经测试)。只记得释放分配的空间。
const char ascii_hex_4bit[23] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
static inline char to_upper(char c)
{
if ((c >= 'a') && (c <= 'z')) return c ^ 0x20;
return c;
}
char *url_decode(const char *str)
{
size_t i, j, len = strlen(str);
char c, d, url_hex;
char *decoded = malloc(len + 1);
if (decoded == NULL) return NULL;
i = 0;
j = 0;
do
{
c = str[i];
d = 0;
if (c == '%')
{
url_hex = to_upper(str[++i]);
if (((url_hex >= '0') && (url_hex <= '9')) || ((url_hex >= 'A') && (url_hex <= 'F')))
{
d = ascii_hex_4bit[url_hex - 48] << 4;
url_hex = to_upper(str[++i]);
if (((url_hex >= '0') && (url_hex <= '9')) || ((url_hex >= 'A') && (url_hex <= 'F')))
{
d |= ascii_hex_4bit[url_hex - 48];
}
else
{
d = 0;
}
}
}
else if (c == '+')
{
d = ' ';
}
else if ((c == '*') || (c == '-') || (c == '.') || ((c >= '0') && (c <= '9')) ||
((c >= 'A') && (c <= 'Z')) || (c == '_') || ((c >= 'a') && (c <= 'z')))
{
d = c;
}
decoded[j++] = d;
++i;
} while ((i < len) && (d != 0));
decoded[j] = 0;
return decoded;
}