C / C ++ URL解码库

我正在开发Linux上的ac / c + +程序。 你能告诉我,如果有任何解码url的c / c ++库吗?

我正在寻找将“http%3A%2F%2F”转换为“http://”的库

或“a + t +%26 + t”到“at&t”

谢谢。

Solutions Collecting From Web of "C / C ++ URL解码库"

实际上,在我编写的一个分析程序(分析数百万个URL编码的字符串)中使用了Saul的函数,并且在这个规模下,这个程序让我的程序变得非常慢,所以我决定写一个更快的版本。 使用GCC和-O2选项编译时,这个速度要快上千倍。 它也可以使用与输入相同的输出缓冲区(例如,如果原始字符串在buf中并且将由其解码对象覆盖,则urldecode2(buf,buf)将起作用)。

编辑:它不会将缓冲区大小作为输入,因为假定缓冲区将足够大,这是安全的,因为已知输出的长度总是小于输入的长度,所以为输出使用相同的缓冲区,或者创建一个至少为输入+ 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'; } 

优秀的glib具有一些URI功能 ,包括方案提取,转义和解脱。

这里是一个百分比编码字符串的C解码器。 如果编码无效,则返回-1,否则返回0。 解码的字符串被存储在外面。 我很肯定这是迄今为止所给答案中最快的代码。

 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; } 

这个功能我刚刚鞭打是非常轻量级的,应该如你所愿,注意我没有编程这严格的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 (ie 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; } } } 

uriparser库体积小巧,重量轻。

尝试urlcpp https://github.com/larroy/urlcpp这是一个C ++模块,你可以很容易地集成在你的项目,取决于boost :: regex

我建议卷曲和libcurl 。 它被广泛使用,应该为你做的伎俩。 只要检查他们的网站。

 /** * 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 

感谢@ThomasH的回答。 我想在这里提出一个更好的格式

而且…由于解码后的URI组件总是比相同的编码后的URI组件长,所以总是有可能在相同的字符数组(也就是“string”)内爆碎。 所以,我会在这里提出两个可能性

 #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; } 

STE *