postmail.cgiを改造してSSI/PHPのinclude的な機能に対応

postmail.cgi を使ったメールフォームの入力・確認・完了・エラーページで、共通のHTML部品(ヘッダー・フッター等)を差し込み置換できるように改造する。SSIやPHPのinclude的な機能。


SSI include:

<!-- #include "xxxxx" -->

PHP include:

<?php include "xxxxx" ?>

書式を決める

SSI/PHPと似てるけど違う(SSI/PHPコードではない)ものにしておく。
独自実装するオリジナル書式:

<!-- &include "xxxxx" -->

とりあえずローカルファイルのみ、パスはドキュメントルート以降の絶対パスのみ対応する。例:

<!-- &include "/include/header.html" -->
<!-- &include "/include/footer.html" -->

入力・確認・完了・エラーページのテンプレートファイルで、この書式を使えるようにする。

差し込み置換処理ライブラリ新規作成

ファイル
lib/CGI/Include.pm
#
# 独自インクルード対応
#
# 書式:<!-- &include "xxxxx" -->
#
# ローカルファイルのみ、パスはドキュメントルート以降の絶対パスのみ対応
#
package CGI::Include;

use strict;

sub get_contents {

    my ($target) = @_;

    open(IN, "$ENV{DOCUMENT_ROOT}$target") or return '';
    my $data = join('', <IN>);
    close(IN);

    return $data;
}

sub data {

    my ($data) = @_;

    $data =~ s/<!--\s*&include\s+"([^"]+)"\s*-->/&get_contents($1)/eg;

    return $data;
}

1;

入力ページ用CGIファイル新規作成

ファイル
index.cgi
#!/usr/bin/perl -w
use strict;
use lib './lib';
use CGI::Include;

open(IN, "./index.html") or return;
my $data = CGI::Include::data(join('', <IN>));
close(IN);

print "Content-type: text/html; charset=utf-8\n\n";
print $data;

※1行目は環境にあわせて書き換える

Webサーバー設定

入力ページがCGI経由で表示されるよう、Webサーバー側で設定。
Apache なら .htaccess や httpd.conf で mod_rewrite を利用。
例えばフォームURLが /xxxxx/ で、ドキュメントルート直下 .htaccess に書く場合の例:

RewriteEngine on
RewriteRule ^/?xxxxx/?$ /xxxxx/index.cgi [L]
RewriteRule ^/?xxxxx/index\.html /xxxxx/index.cgi [L]

入力ページ以外も対応

postmail.cgi 本体を改造して、確認・完了・エラーページにも対応。

ファイル
postmail.cgi
13: use CGI::Minimal;
14: use CGI::Include;
15: use Jcode;
125: 	open(IN,"$cf{tmpldir}/conf.html") or error("open err: conf.html");
126: 	my $tmpl = CGI::Include::data(join('', <IN>));
127: 	close(IN);
391: 		open(IN,"$cf{tmpldir}/thanks.html") or error("open err: thanks.html");
392: 		my $tmpl = CGI::Include::data(join('', <IN>));
393: 		close(IN);
422: 	open(IN,"$cf{tmpldir}/error.html") or die;
423: 	my $tmpl = CGI::Include::data(join('', <IN>));
424: 	close(IN);
558: 	open(IN,"$cf{tmpldir}/error.html") or die;
559: 	my $tmpl = CGI::Include::data(join('', <IN>));
560: 	close(IN);