2011年5月13日金曜日

C++: Base64エンコード・デコードとURLエンコード

このブログ記事をはてなブックマークに追加

覚書。Base64エンコード・デコードを行う関数とURLエンコードを行う関数をどんな環境でもすぐに参照できるように書いておく。ただし、短いコードのままにしておきたかったので、まったくもって安全ではない。入力前にチェックを入れるとか、関数内で制限を掛けるとか、引数に最大文字数を渡すとか、適当な処理を入れること。よく分からない場合は使わないのが吉。

#include <iostream> #include <iomanip> #include <sstream> #include <algorithm> #include <cstring> using namespace std; int base64encode(const char* p, char* buf) { const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; const int in_size = strlen(p); if (in_size == 0 || p == buf) return 0; int cnt = 0; for (int i = 0; i < (in_size - 1) / 3 + 1; i++) { const unsigned char* c = reinterpret_cast<const unsigned char*>(&p[i*3]); for (int j = 0; j < 4; j++) if (in_size >= i * 3 + j) buf[cnt++] = b64[(c[j-1]<<(6-j*2) | c[j]>>(j*2+2)) & 0x3f]; else buf[cnt++] = '='; } buf[cnt] = '\0'; return cnt; } int base64decode(const char* p, char* buf) { char b64[128] = {}; for (char n = 0, *w = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; *w; b64[*w++] = n++ & 0x3f); char c[4]; int i = 0, j, k; while (*p && *p != '=') { for (j = 0; j < 4 && *p != '='; j++) c[j] = b64[*p++]; for (k = 0; k < j - 1; k++) buf[i++] = c[k]<<(k<<1)+2 | c[k+1]>>(2-k<<1); } buf[i] = '\0'; return i; } string urlencode(const string& text) { const string url_letters("-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"); stringstream ss; for (string::const_iterator p = text.begin(); p != text.end(); ++p) { if (binary_search(url_letters.begin(), url_letters.end(), *p)) ss << *p; else ss << "%" << setw(2) << setfill('0') << hex << static_cast<int>(*p); } return ss.str(); } int main() { // Base64エンコードでは入力文字数の4/3倍ほどの領域が必要. // 文字数が少なかったり改行を入れるともっと必要. char buf[256]; // 256は安全ではない. base64encode("test", buf); // (buf, buf)はダメ. cout << buf << endl; // dGVzdA== base64decode(buf, buf); // 邪悪. cout << buf << endl; // test cout << urlencode("user@test.com") << endl; // user%40test.com return 0; }

0 コメント: