またまた、apache httpd 2.4.2 の mod_sed ですが、今回は入力時のフィルタ機能について試してみました。ディレクティブで言うと、AddInputFilter と InputSed ですね。
httpd に対して、POST されたときにこの機能が適用されます。そのためには、CGIが動作できるように設定する必要があります。
実は現在の apache httpd では、CGI 用のモジュールとして、mod_cgi ではなくて、mod_cgid が標準でインストールされています。つまり、前回のインストールでは、mod_cgi は作成されず、どうしても mod_cgi が必要なら、configure のオプションで、
--enable-cgi
を追加する必要があります。mod_cgid の通信はソケットで行うので、ScriptSock ディレクティブが用意されています。標準ではソケット名は、
/usr/local/httpd242/logs/cgisock
です。cgi の設定は、httpd.conf で以下を指定します。
LoadModule cgid_module modules/mod_cgid.so
後は以前と同様です。
再起動すると、
# ls -l /usr/local/httpd242/logs/cgisock.*
srwx------ 1 daemon root 0 Jul x xx:xx /usr/local/httpd242/logs/cgisock.1731
#
というソケットが作成されます。ちなみに1731 は、httpd のプロセスIDです。これで CGI の準備はできました。
今回の mod_sed の入力フィルタを試すには、htmlファイルと CGI 用のプログラムが必要です。早速用意してみます。
html ファイルは、/usr/local/httpd242/htdocs/sed/test2-sed.html として、
<html><head></head><body>
<form action="/sed/program/prog1.sh" method="post">
<label>data1: <input type="text" name="data1"></label><br>
<label>data2: <input type="text" name="data2"></label><br>
<input type="submit" value="OK">
<input type="reset" value="Reset"><br>
</form>
</body></html>
とします。
そこで呼び出される CGI プログラム /usr/local/httpd242/htdocs/sed/program/prog1.sh は、bash で作ります。
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "<html><head></head><body><pre>"
read Line
echo $Line
echo "</pre></body></html>"
テストするためにブラウザで、data1 に <b>abc</b> 、data2 に<u>def</u>を入れて prog1.sh を動かすと、
data1=%3Cb%3Eabc%3C%2Fb%3E&data2=%3Cu%3Edef%3C%2Fu%3E
のように POST によって送られてきたデータがそのまま表示されます。
準備が出来たので、mod_sed の入力フィルタのテスト用にはクロスサイトスクリプティング対策で基本のエスケープ処理を実施してみます。
< が %3C 、> が %3E 、& が %26 、" が%22 、' が %27 ですから、
%3C なら、%26lt%3B 、%3E なら %26gt%3B 、
%26 なら %26amp%3B 、 %22なら %26quot%3B
%27 なら、%26%2339%3B に変換してしまいましょう。最初に %26 を処理してしまうのがコツです。
ディレクティブはこうなります。
これは入力フィルタなので、出力フィルタで問題になった 304 を返さないように htmlファイルを更新しておく必要はないのでテストは楽です。
data1 に <b>a&b</b> 、 data2 に <u>"de'</u> を与えてみますと、
data1=%26lt%3Bb%26gt%3Ba%26amp%3Bb%26lt%3B%2Fb%26gt%3B&
data2=%26lt%3Bu%26gt%3B%26quot%3Bde%26%2339%3B%26lt%3B%2Fu%26gt%3B
のようになりました。(適当に改行してあります。)
念のために変換された入力データをデコードして表示してみます。bash で、POSTされたデータをデコードする方法は、
http://betu-masea.cocolog-nifty.com/blog/2006/10/bash3_1cf1.html
が参考になります。そこで定義されている urldecode() という関数をそのまま使って、先ほどのprog1.sh スクリプトの echo $Line の部分を、
urldecode Line
echo $RESULT
とすれば、上述の結果は、
data1=<b>a&b</b>&data2=<u>"de'</u>
となりました。これだと既存のプログラムの & 文字処理を修正する必要があるかもしれませんので、実際に使う場合はデコード前のパラメタの分離とこの辺の工夫が必要です。
POSTで mod_sed に渡されたデータは丸ごとパターンスーペースに入力してしまうので1サイクルで処理が行われるようです。つまり、N コマンドのような次の行を読み込むものは意味がなさそうです。
ざっと調べたところ InputSed の例はほとんど見当たりませんが、今回試してみて以外に役立つような気がしました。
httpd に対して、POST されたときにこの機能が適用されます。そのためには、CGIが動作できるように設定する必要があります。
実は現在の apache httpd では、CGI 用のモジュールとして、mod_cgi ではなくて、mod_cgid が標準でインストールされています。つまり、前回のインストールでは、mod_cgi は作成されず、どうしても mod_cgi が必要なら、configure のオプションで、
--enable-cgi
を追加する必要があります。mod_cgid の通信はソケットで行うので、ScriptSock ディレクティブが用意されています。標準ではソケット名は、
/usr/local/httpd242/logs/cgisock
です。cgi の設定は、httpd.conf で以下を指定します。
LoadModule cgid_module modules/mod_cgid.so
後は以前と同様です。
再起動すると、
# ls -l /usr/local/httpd242/logs/cgisock.*
srwx------ 1 daemon root 0 Jul x xx:xx /usr/local/httpd242/logs/cgisock.1731
#
というソケットが作成されます。ちなみに1731 は、httpd のプロセスIDです。これで CGI の準備はできました。
今回の mod_sed の入力フィルタを試すには、htmlファイルと CGI 用のプログラムが必要です。早速用意してみます。
html ファイルは、/usr/local/httpd242/htdocs/sed/test2-sed.html として、
<html><head></head><body>
<form action="/sed/program/prog1.sh" method="post">
<label>data1: <input type="text" name="data1"></label><br>
<label>data2: <input type="text" name="data2"></label><br>
<input type="submit" value="OK">
<input type="reset" value="Reset"><br>
</form>
</body></html>
とします。
そこで呼び出される CGI プログラム /usr/local/httpd242/htdocs/sed/program/prog1.sh は、bash で作ります。
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "<html><head></head><body><pre>"
read Line
echo $Line
echo "</pre></body></html>"
テストするためにブラウザで、data1 に <b>abc</b> 、data2 に<u>def</u>を入れて prog1.sh を動かすと、
data1=%3Cb%3Eabc%3C%2Fb%3E&data2=%3Cu%3Edef%3C%2Fu%3E
のように POST によって送られてきたデータがそのまま表示されます。
準備が出来たので、mod_sed の入力フィルタのテスト用にはクロスサイトスクリプティング対策で基本のエスケープ処理を実施してみます。
< が %3C 、> が %3E 、& が %26 、" が%22 、' が %27 ですから、
%3C なら、%26lt%3B 、%3E なら %26gt%3B 、
%26 なら %26amp%3B 、 %22なら %26quot%3B
%27 なら、%26%2339%3B に変換してしまいましょう。最初に %26 を処理してしまうのがコツです。
ディレクティブはこうなります。
<Directory "/usr/local/httpd242/htdocs/sed/program"> Options +ExecCGI AddHandler cgi-script .sh AddInputFilter Sed sh InputSed "s/%26/%26amp%3B/g" InputSed "s/%3C/%26lt%3B/g" InputSed "s/%3E/%26gt%3B/g" InputSed "s/%22/%26quot%3B/g" InputSed "s/%27/%26%2339%3B/g" </Directory>
これは入力フィルタなので、出力フィルタで問題になった 304 を返さないように htmlファイルを更新しておく必要はないのでテストは楽です。
data1 に <b>a&b</b> 、 data2 に <u>"de'</u> を与えてみますと、
data1=%26lt%3Bb%26gt%3Ba%26amp%3Bb%26lt%3B%2Fb%26gt%3B&
data2=%26lt%3Bu%26gt%3B%26quot%3Bde%26%2339%3B%26lt%3B%2Fu%26gt%3B
のようになりました。(適当に改行してあります。)
念のために変換された入力データをデコードして表示してみます。bash で、POSTされたデータをデコードする方法は、
http://betu-masea.cocolog-nifty.com/blog/2006/10/bash3_1cf1.html
が参考になります。そこで定義されている urldecode() という関数をそのまま使って、先ほどのprog1.sh スクリプトの echo $Line の部分を、
urldecode Line
echo $RESULT
とすれば、上述の結果は、
data1=<b>a&b</b>&data2=<u>"de'</u>
となりました。これだと既存のプログラムの & 文字処理を修正する必要があるかもしれませんので、実際に使う場合はデコード前のパラメタの分離とこの辺の工夫が必要です。
POSTで mod_sed に渡されたデータは丸ごとパターンスーペースに入力してしまうので1サイクルで処理が行われるようです。つまり、N コマンドのような次の行を読み込むものは意味がなさそうです。
ざっと調べたところ InputSed の例はほとんど見当たりませんが、今回試してみて以外に役立つような気がしました。
※コメント投稿者のブログIDはブログ作成者のみに通知されます