誰かがこれを行う良いC++コードを知っていますか?
19 に答える
先日、この問題の半分のエンコーディングに直面しました。利用可能なオプションに不満があり、この C サンプル コードを見てから、独自の C++ url-encode 関数を展開することにしました。
#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;
string url_encode(const string &value) {
ostringstream escaped;
escaped.fill('0');
escaped << hex;
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
string::value_type c = (*i);
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << uppercase;
escaped << '%' << setw(2) << int((unsigned char) c);
escaped << nouppercase;
}
return escaped.str();
}
デコード関数の実装は、読者の課題として残されています。:P
string urlDecode(string &SRC) {
string ret;
char ch;
int i, ii;
for (i=0; i<SRC.length(); i++) {
if (int(SRC[i])==37) {
sscanf(SRC.substr(i+1,2).c_str(), "%x", &ii);
ch=static_cast<char>(ii);
ret+=ch;
i=i+2;
} else {
ret+=SRC[i];
}
}
return (ret);
}
最高ではありませんが、正常に動作しています;-)
cpp-netlibには機能があります
namespace boost {
namespace network {
namespace uri {
inline std::string decoded(const std::string &input);
inline std::string encoded(const std::string &input);
}
}
}
URL 文字列を非常に簡単にエンコードおよびデコードできます。
通常、char の int 値に '%' を追加しても、エンコード時に機能しません。値は 16 進数に相当するものと見なされます。たとえば、'/' は '%47' ではなく '%2F' です。
これは、URL のエンコードとデコードの両方に最適で簡潔なソリューションだと思います (ヘッダーの依存関係はあまりありません)。
string urlEncode(string str){
string new_str = "";
char c;
int ic;
const char* chars = str.c_str();
char bufHex[10];
int len = strlen(chars);
for(int i=0;i<len;i++){
c = chars[i];
ic = c;
// uncomment this if you want to encode spaces with +
/*if (c==' ') new_str += '+';
else */if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') new_str += c;
else {
sprintf(bufHex,"%X",c);
if(ic < 16)
new_str += "%0";
else
new_str += "%";
new_str += bufHex;
}
}
return new_str;
}
string urlDecode(string str){
string ret;
char ch;
int i, ii, len = str.length();
for (i=0; i < len; i++){
if(str[i] != '%'){
if(str[i] == '+')
ret += ' ';
else
ret += str[i];
}else{
sscanf(str.substr(i + 1, 2).c_str(), "%x", &ii);
ch = static_cast<char>(ii);
ret += ch;
i = i + 2;
}
}
return ret;
}
win32 C++ アプリで URL をデコードするための API を検索しているときに、この質問にたどり着きました。Windowsが悪いことではないと仮定して、質問はプラットフォームを完全に指定していないためです。
InternetCanonicalizeUrl は、Windows プログラムの API です。詳細はこちら
LPTSTR lpOutputBuffer = new TCHAR[1];
DWORD dwSize = 1;
BOOL fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
DWORD dwError = ::GetLastError();
if (!fRes && dwError == ERROR_INSUFFICIENT_BUFFER)
{
delete lpOutputBuffer;
lpOutputBuffer = new TCHAR[dwSize];
fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
if (fRes)
{
//lpOutputBuffer has decoded url
}
else
{
//failed to decode
}
if (lpOutputBuffer !=NULL)
{
delete [] lpOutputBuffer;
lpOutputBuffer = NULL;
}
}
else
{
//some other error OR the input string url is just 1 char and was successfully decoded
}
InternetCrackUrl (ここ) にも URL をデコードするかどうかを指定するフラグがあるようです
CGICCには、URL のエンコードとデコードを行うメソッドが含まれています。form_urlencode と form_urldecode
libcurl の使用に関する Bill の推奨事項にフォローアップを追加: 素晴らしい提案であり、更新予定:
3 年後、curl_escape関数は廃止されるため、今後使用する場合はcurl_easy_escapeを使用することをお勧めします。
ここでは、2 および 3 バイト シーケンスもデコードする URI デコード/unescape を見つけることができませんでした。オンザフライで c 文字列入力を wstring に変換する自分のバージョンを提供します。
#include <string>
const char HEX2DEC[55] =
{
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
};
#define __x2d__(s) HEX2DEC[*(s)-48]
#define __x2d2__(s) __x2d__(s) << 4 | __x2d__(s+1)
std::wstring decodeURI(const char * s) {
unsigned char b;
std::wstring ws;
while (*s) {
if (*s == '%')
if ((b = __x2d2__(s + 1)) >= 0x80) {
if (b >= 0xE0) { // three byte codepoint
ws += ((b & 0b00001111) << 12) | ((__x2d2__(s + 4) & 0b00111111) << 6) | (__x2d2__(s + 7) & 0b00111111);
s += 9;
}
else { // two byte codepoint
ws += (__x2d2__(s + 4) & 0b00111111) | (b & 0b00000011) << 6;
s += 6;
}
}
else { // one byte codepoints
ws += b;
s += 3;
}
else { // no %
ws += *s;
s++;
}
}
return ws;
}
ジューシービット
#include <ctype.h> // isdigit, tolower
from_hex(char ch) {
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
char to_hex(char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}
注意して
char d = from_hex(hex[0]) << 4 | from_hex(hex[1]);
のように
// %7B = '{'
char d = from_hex('7') << 4 | from_hex('B');
別の解決策として、 Facebook の愚かなライブラリ:folly::uriEscape
とを使用できますfolly::uriUnescape
。
Boostなしのプロジェクトでそれをしなければなりませんでした。それで、自分で書くことになりました。GitHub に置くだけです: https://github.com/corporateshark/LUrlParser
clParseURL URL = clParseURL::ParseURL( "https://name:pwd@github.com:80/path/res" );
if ( URL.IsValid() )
{
cout << "Scheme : " << URL.m_Scheme << endl;
cout << "Host : " << URL.m_Host << endl;
cout << "Port : " << URL.m_Port << endl;
cout << "Path : " << URL.m_Path << endl;
cout << "Query : " << URL.m_Query << endl;
cout << "Fragment : " << URL.m_Fragment << endl;
cout << "User name : " << URL.m_UserName << endl;
cout << "Password : " << URL.m_Password << endl;
}