拡張子htmlのものをCGIとして実行させる方法→NG
とりあえず、お名前.com 拡張子 html php で検索してみたところ、
という記事がヒットした。
要点は、
- .htaccessに「AddHandler cgi-script .html」記述
- PHPを実行したい *.html ファイルの先頭行(シバン・shebang)に「#! /usr/local/bin/php-cgi」を記述*1
- 当該 *.html ファイルに実行権を付与(パーミッション:700, 705等)
ということ。
確かに、お名前.comのよくある質問でも、
※.phpファイルを別の拡張子で動作させるためには、該当ファイルをcgiとして実行する
【共用サーバーSD】自分で用意した.htaccessファイルは使用できますか? | よくある質問 | お名前.comヘルプセンター
記述を追記ください。
とあるので、妥当な方法のように思われたのだが…。
なぜか、当方が試した共用サーバSDではうまくいかず、500(Internal Server Error)になってしまう。
しかも、共用サーバSDではエラーログが参照できないので、詳細はわからないという…。
ちなみに、Pythonスクリプトの拡張子を「html」にして同様にやってみると、きちんと実行されたので、.htaccess やパーミッションの指定が誤っているとも考えにくい。
追記
上記で、2. の *.html の shebang を
#! /usr/local/bin/php.cli
にすれば、一応、動作することがわかった。
ただし、CLI SAPI(Command Line Interface Server Application Programming Interface)版であるため、
- HTTPヘッダが出力されない(header()関数等が無効)
- $_GET, $_POST, $_REQUEST などが設定されない。
等の制限があり、あまり使い勝手はよくない。
追記2
CGI SAPI版 PHP が動作しないのは、おそらく、cgi.force_redirect が 1 になっているから、かな?
0 にするのはセキュリティ的にも危険*2ということで、設定的に正しいのだけれども。
ちなみに .htaccess や(ローカルの)php.ini などでは、cgi.force_redirect は 0 に変更できなかった。また、PHPスクリプト内で ini_set() しても、FALSE が返ってくる。
拡張子htmlでSSIを有効にして、外部PHPの実行結果を埋めこむ方法→OK
要点は、
- .htaccessに「AddOutputFilter INCLUDES .html」記述
- *.html ファイルの PHP を埋めこみたいところに「<!--#exec cgi="PHPファイル名" -->」を記述*3
ということ。
この方法の場合、PHPファイルへのshebang追記やパーミッション変更は必要ない模様(パーミッションは644とかで動作する)。
最初の方法がうまくいかないのはちょっともやもやとするけれど、ひとまずこれでしのごう。
複数個所で呼び出したときに変数や関数、クラス等を引き継げないとか、いろいろと問題はあるけれども。
↓は、とりあえず動作した例。
.htaccess
#AddOutputFilter INCLUDES .htm .html # 拡張子がhtmまたはhtmlの全ファイルをSSIの対象にするとサーバに負荷がかかるため、 # ファイル名でフィルタして最小限に絞る(例はindex.htmとindex.htmlのみ対象) <Files ~ "^index\.html?$"> AddOutputFilter INCLUDES .htm .html </Files>
HTMLファイル(index.html)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>[SSI+PHP]テストページ</title> </head> <body> <h1>SSIでPHPの実行結果を読み込むテスト</h1> <h2><!--#exec cgi="./check.php" --> の場合</h2> <!--#exec cgi="./check.php" --> <h2><!--#include virtual="./check.php" --> の場合</h2> <!--#include virtual="./check.php" --> </body> </html>
SSIで読み込むPHPファイル(check.php)
<?php $param_list = array(); foreach ($_GET as $key => $val) { $val = is_array($val) ? ('array(' . implode(", ", $val) . ')') : $val; $param_list[] = htmlspecialchars($key . '=' . $val, ENT_QUOTES); } $param_str = implode("<br />\n", $param_list); $out_str = <<< _EOT_ <p>PHPを実行しました!</p> <h4>URL パラメータ(\$_GET) 一覧</h4> <p>{$param_str}</p> <hr /> _EOT_; echo($out_str);
*1:ちなみに、当方が試した共用サーバSDでは、 /usr/local/bin/php は /usr/local/bin/php-cgiへのエイリアスになっていた。
*2:参考:PHP: 受ける可能性がある攻撃 - Manual
*3:実行するだけなら「#include virtual」等でも可、ただし、$_GETや$_POSTを渡したい場合には、「#exec cgi」を使う。