SSI は Server Side Includes の略です。HTML文書中に以下のようなコメントを挿入することにより、サーバー側がコメントの場所に外部ファイルやコマンドの実行結果を置き換えてくれたりする機能です。
<!--#exec cmd="/usr/bin/ls -l" -->
SSI により、例えば次のようなことが可能になります。
SSI を使用するには、WWW サーバーが SSI をサポートしており、SSI を許可する設定が行われている必要があります。サーバーが Apache の場合は httpd.conf に下記を追記してサーバーを再起動してください。
<Directory "/var/www/html"> (略) # # SSI # Options +Includes AddType text/html .shtml AddOutputFilter INCLUDES .shtml </Directory>
SSI を埋め込むファイルの拡張子は .shtml にする必要があります。
example.shtml
下記の例はファイルの最終更新時刻を表示します。
このファイルは <!--#config timefmt="%Y/%m/%d %X" --> <!--#echo var="LAST_MODIFIED" --> に更新されました。
下記はダウンロードファイルの最終更新日とサイズを表示します。
<a href="xxx.zip">xxx.zip</a> (<!--#config timefmt="%Y/%m/%d" --> <!--#flastmod file="xxx.zip" --> 更新, <!--#config sizefmt="abbrev" --> Size:<!--#fsize file="xxx.zip" -->) をダウンロードしてください。
ヘッダ/フッタを指定します。
<doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Sample Page</title> </head> <body> <!--#include file="header.html" --> 本文 <!--#include file="footer.html" --> </body> </html>
<!--#include file="~" -->
<!--#include virtual="~" -->
指定したファイルの中身を読込んで表示します。file="~"
の ~ にはファイル名を指定します。../
や絶対パス名は使用できない場合があります。virtual="~"
の ~ には指定するファイルの仮想パス名(「http://サーバー名/パス名」の「/パス名」の部分)を指定します。
<!--#include file="header.html" --> : <!--#include file="footer.html" -->
onerror
属性でファイルが見つからなかった場合に表示するエラーファイルを指定することができます。
<!--#include file="header.html" onerror="error.html" -->
<!--#fsize file="~" -->
<!--#fsize virtual="~" -->
指定したファイルのサイズを表示します。表示のフォーマットは <!--#config sizefmt="..." -->
で指定したものに従います。file="~"
と virtual="~"
の説明は #include と同様です。
<!--#config sizefmt="abbrev" --> <a href="xxx.zip">ダウンロード</a> (サイズ:<!--#fsize file="xxx.zip" -->)
<!--#flastmod file="~" -->
<!--#flastmod virtual="~" -->
指定したファイルの最終更新時刻を表示します。表示のフォーマットは <!--#config timefmt="..." -->
で指定したものに従います。file="~"
と virtual="~"
の説明は #include と同様です。
最終更新日:<!--#flastmod file="this.html" -->
<!--#echo var="~" -->
指定した環境変数の値を表示します。~ には LAST_MODIFIED などの環境変数名を指定します。
最終更新日:<!--#echo var="LAST_MODIFIED" -->
環境変数名には次のようようなものがあります。
環境変数 | 意味 |
---|---|
DOCUMENT_NAME | この文書のファイル名(ssi.html) |
DOCUMENT_URI | 文書の仮想パス名(/ex/ssi.html) |
QUERY_STRING_UNESCAPED | WWWクライアントから検索用に送信された文字列。いくつかの記号文字(UNIXのシェルのメタ文字)はパックスラッシュ( \ )でエスケープされているので注意。 |
DATE_LOCAL | 現在の時刻(ローカル時刻) |
DATE_GMT | 現在の時刻(グリニッジ標準時) |
LAST_MODIFIED | この文書の最終更新時刻 |
サーバーによっては、「CGIスクリプトが参照可能な環境変数」も表示できます。時間の表示は <!--#config timefmt="..." -->
で指定したフォーマットに従います。
encoding
属性を指定することもできます。規定値は entity
です。
A=<A>
を A=<A>
にエンコードします。
A=<A>
を A=%3cA%3e
にエンコードします。
A=<A>
を A%3d%3cA%3e
にエンコードします。
A=<A>
を QT08QT4=
にエンコードします。
A=<A>
を A=<A>
のまま出力します。
decoding
属性を指定することもできます。規定値は none
です。
A=<A>
を A=<A>
にデコードします。
A=%3cA%3e
を A=<A>
にデコードします。
A%3d%3cA%3e
を A=<A>
にデコードします。
QT08QT4=
を A=<A>
にデコードします。
A=<A>
を A=<A>
のまま読み取ります。
decoding
や encoding
属性は var
属性よりも先に記述してください。
<!--#echo decoding="base64" encoding="url" var="QUERY_STRING" -->
<!--#printenv -->
使用可能な環境変数の一覧を表示します。Apache 1.2 以上のバージョンで使用できます。printenv
と -->
の間にスペースを忘れないでください。
<pre> <!--#printenv --> </pre>
<!--#set var="~" value="~" -->
変数 ~ に、値 ~ を代入します。Apache 1.2 以上のバージョンで使用可能です。
<!--#set var="msg" value="Hello!!" --> <!--#echo var="msg" -->
#echo
と同様に encoding
, decoding
属性を指定することができます。
<!--#config errmsg="~" -->
文書処理中にエラーが発生した場合のエラーメッセージを指定します。これはWWWサーバーのエラーログにも記録されます。
<!--#config errmsg="ERROR!!!!!!" -->
<!--#include file="no-file.html" --> # ファイルが存在しないエラー
<!--#config sizefmt="~" -->
#fsize
コマンドなどで表示されるファイルサイズのフォーマットを指定します。~ に bytes を指定するとバイト単位で、abbrev を指定すると Bytes, KBytes, MBytes などの適切な単位で表示されるようになります。
<!--#config timefmt="~" -->
#echo
コマンドなどで時刻を表示する際のフォーマットを指定します。~ には %Y/%m/%d %H:%M:%s
などの文字列を指定します。 %Y
や %m
は次のような意味を持ちます。
置換文字 | 表示例 | 意味 |
---|---|---|
%c | 10/30/97 11:22:33 | 月/日/年 時:分:秒 |
%x | 10/30/97 | 月/日/年 |
%X | 11:22:33 | 時:分:秒 |
%y | 97 | 年(2桁) |
%Y | 1997 | 年(4桁) |
%b | Oct | 月(3文字) |
%B | October | 月(フルスペル) |
%m | 08 | 月(2桁) |
%a | Sat | 曜日(3文字) |
%A | Saturday | 曜日(フルスペル) |
%d | 30 | 日(2桁) |
%j | 223 | 1月1日からの日数 |
%w | 6 | 日曜日からの日数 |
%p | PM | AMもしくはPM |
%H | 23 | 時(24時間制) |
%I | 11 | 時(12時間制) |
%M | 44 | 分 |
%S | 56 | 秒 |
%Z | JST | タイムゾーン |
<!--#config echomsg="~" -->
#echo
で未定義の変数を出力しようとした際のエラーメッセージを設定します。
<!--#config echomsg="ERROR: Unknown parameter." -->
<!--#echo var="UNDEFINED_PARAMETER" --> # 変数が存在しないエラー
<!--#exec cmd="~" -->
<!--#exec cgi="~" -->
~ で指定したコマンドやCGIを実行し、その結果を表示します。cgi="..."
で呼び出す際は、CGI側で Content-type: text/html
などのヘッダを出力してやる必要があります。
<!--#exec cmd="/bin/ls -l" --> <!--#exec cgi="/cgi-bin/count.cgi" -->
cmd="~"
に引数(arg1, arg2, ...)を引数を渡す場合は次の様に指定します。
<!--#exec cmd="command.pl arg1 arg2" -->
cgi="~"
にも引数を渡してみたかったのですが、下記の様に指定したり、@ARGV
を参照したり $ENV{"QUERY_STRING"}
を参照したりなどいろいろ試してみたのですがうまく渡せませんでした。
× <!--#exec cgi="/cgi-bin/test.cgi arg1 arg2" --> × <!--#exec cgi="/cgi-bin/test.cgi?arg1+arg2" -->
<!--#if expr="~" -->
<!--#elif expr="~" -->
<!--#else -->
<!--#endif -->
条件によって表示する内容を制御します。if
, elseif
, else
は、もし、さもなくばもし、さもなくばを、 endif
は条件式の終わりを意味します。以前は下記のような書式で記述していました。(参考↗)
<!--#if expr="$HTTP_USER_AGENT = /(iPhone|iPod|Android|Windows Phone)/" --> スマホですね <!--#else --> パソコンですね <!--#endif -->
最近は下記のような記述に代わっているようです。(参考↗)
<!--#if expr="%{HTTP_USER_AGENT} =~ /(iPhone|iPod|Android|Windows Phone)/" --> スマホですね <!--#else --> パソコンですね <!--#endif -->
使えると便利な SSI ですが、いくつか注意点があります。
下記の様に .html
を追記すると .html
に対しても SSI を埋め込むことができるようになりますが、SSI 対象となるファイルは Web サーバーがファイルの終端までを読み込み、SSI 処理の有無を確認する必要があるため、パフォーマンスに影響を与えてしまいます。
<Directory "/var/www/html"> : Options +Includes AddType text/html .shtml .html AddOutputFilter INCLUDES .shtml .html </Directory>
必要なファイルのみ拡張子を .shtml
として SSI 対象とするようにしてください。XBitHack
ディレクティブ(↗) を指定すると +w ビットを立てた .html
ファイルのみを SSI 対象とするとありますが、AlmaLinux 9 + Apache 2.4.62 環境ではうまく動作させることができませんでした。(誰かうまく設定できたら教えてください)
SSI を使用可能にしたファイルが クロスサイトスクリプティング(XSS) 攻撃を受けてしまうと、サーバー側に任意の悪意のあるコマンドが実行されてしまい、非常に危険な状態になります。
<article> <h3>このサーバーは乗っ取ったぞ</h3> <p>このサーバーは XSS 問題を含んでいるので、 <!--#exec cmd="/usr/bin/cat /etc/passwd" --> こんなコマンドも実行できちゃうね。</p> </article>
SSI を使用する際はセキュリティに十分な注意を払ってください。