2012年6月28日木曜日

wgetでPOSTする&POSTデータの+記号が消える

みなさんLinuxのコマンドであるwgetつかってますか?
簡単に出来ることを並べると

・ 再帰的なダウンロードの自動化
・ ログインが必要なサイト監視
・ xmlやJSONの取得
・ データのPOST

など大活躍。
こちらのページはoptionの一覧を詳しく説明してるので一読の価値あり!

ダウンロードコマンドwgetのオプション一覧(linux)

その多彩な機能のひとつ、「データのPOSTする方法」でちょっとハマったのでメモ。
例えば下記のコマンドを実行するとdataと言うnameでhogehogeをPOSTします。
 
wget --post-data 'data=hogehoge' http://hoge.jp

例えばPHPプログラムだけでPOSTするのは結構な手間ですが利用すると実装が楽になります。
また他にもmailのエイリアスを利用した内容の自動転送とかが容易になります。
(両方セキュリティ上の懸念点はあるので仕様と相談してくださいね!!)
ついでにPOSTだけしたい(サイトのhtmlを取得しない)場合は

--spider

を引数でつけてやるとファイルが無限増殖しません。
で実際の使い方はphpなどでsystem関数などに入れて実際のPOSTデータは変数っての多いと思います。
例えばphpだとこんな感じ。

`wget --spider --post-data 'data=" . $data . "&time=" .$time . "' http://hoge.jp`;

(PHPのバッククォートは shell_exec() と等価です)
POSTの数を増やしたい時は&で繋げば増やせます。
でここで大事なのがbase64などの記号の入った内容をPOSTする場合。
wgetのPOSTは中途半端にエスケープまたはURLencodeをしてるようです。
例えばPOSTの際に+を半角スペースに置き換えてしまいます。
つまり

$data = 'hoge+hoge';

をwgetでPOSTすると受け取り側(例はPHP)は

echo $_POST['data']; //←hoge hoge と出力される

となります。
これにより

・ base64変換したバイナリ
・ mail添付ファイルなのどのmimeの内容

などをPOSTした際にちゃんと復元が出来なくなります。
これの対策としては
POSTする対象のデータを事前にURLencodeしてからコマンドの引数にしてやること。
同じくPHPで$dataの中身がbase64encodeされたデータなどで+があるとすると。

$data = 'hoge+hoge';
$data = urlencode($data);

としてから$dataをコマンドに渡せばOKです。
ということで具体的な事例がググっても出てこなこなかったのでメモとして残して置きます。