2013年8月28日水曜日

【C】URLデコードする(UTF-8)

独自鯖を作ってる最中,
クライアントからのpostリクエストボディに「\r\n」も「\0」も何も終端記号が含まれず
feof()とかで終了条件設定しててもむだで
そのままだとfgetc()なりfgets()なりのところで固まってしまうため
Content-Lengthの分だけ監視する必要があった
…のにもまず驚かされたが,
マルチバイト文字がURLエンコード(パーセントエンコード)されることを忘れていて
デコーダを実装するのに軽く絶望していた.

が,こんな簡単に実装できるとは.

まずはUTF-8のおさらい.
Wikipedia[UTF-8]の表を見る.
ん,そういえばこれどこかでやったな…
と,思ったが,残念ながら以前やったのはUTF-16toUTF-8だった.
しかし,土台部分や考えは流用できそうだ.

%XX%XX%XX%XX…と続くエンコード文字列のまず先頭を取得する.
先頭の%XXこいつのXX部分を見て,Wikipediaの表と対応させて
それが0x80未満なら1byte.
0xC2-0xDFなら2bytes.
0xE0-0xEFであれば3bytes…
まぁ4bytes以上の文字は置いといてそんな感じか.
1byteということは%XXこれが1文字.
2bytesということは%XX%XXこれで1文字,
3bytesも同様に%XX%XX%XXこれで1文字.
UTF-8というのは1文字のバイト長が1byte~6bytesという可変長で表現される.

URLエンコードではそのバイト列をバイトずつ区切って,
頭に%をつけてASCII文字のみで送れるようにしたものである.
また,半角スペースが「+」に変換される.

URLデコードではその逆をやる.
まず「+」を全て半角スペースに置き換える.
次に1つ目の%を探して次の2文字を取得する.
こいつの値を見て,その文字が何バイト続くかを判定,
そのバイト分取得したら文字に直す.

…と言葉で書くよりプログラムで書いたほうがわかりやすいな.
今回のプログラムではURLデコードを行うurlDecode関数と,
文字列を置換するreplace関数がある(「+」を半角スペースに直すため用いる).


0 件のコメント:

コメントを投稿