風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

お名前.comの共用サーバーSDで*.htmlからPHPを実行する方法

2013/12/30 追記

よりシンプルで使い勝手のよい方法は

お名前.comの共用サーバーSDで拡張子htmlをPHPとして実行する方法 - 風柳メモ

を参照。


拡張子htmlのものをCGIとして実行させる方法→NG

とりあえず、お名前.com 拡張子 html php で検索してみたところ、

お名前.com共用サーバーSDで拡張子.htmlをPHPとして実行する : にわタコのblog

という記事がヒットした。


要点は、

  1. .htaccessに「AddHandler cgi-script .html」記述
  2. PHPを実行したい *.html ファイルの先頭行(シバン・shebang)に「#! /usr/local/bin/php-cgi」を記述*1
  3. 当該 *.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

要点は、

  1. .htaccessに「AddOutputFilter INCLUDES .html」記述
  2. *.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>&lt;!--#exec cgi="./check.php" --&gt; の場合</h2>
<!--#exec cgi="./check.php" -->
<h2>&lt;!--#include virtual="./check.php" --&gt; の場合</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」を使う。