ぱるも日記

ぱるも日記は id:palmo がプログラミング言語 Perl を1から勉強していく日記です。

2006-07-09 Hello, CGI!

配列ハッシュHTML で出力する

先ほどのエントリでは HTML 文によりページを表示しましたが、ただ単に HTML 文を print しているだけだったので、これでは HTML ファイルを表示してるのと、なんら変わりません。

そこで、今度は変数を埋め込んでページを表示してみます。スカラーは p 要素として、配列は ol 要素として、ハッシュは dl 要素として表示してみたいと思います。

関数に切り分けたら、ちょっと長くなりましたが、こんな感じになりました。

#!/usr/local/bin/perl

use strict;

sub print_array(\@) {
    print "<ol>\n";
    print "<li>$_</li>\n" for (@{ $_[0] });
    print "</ol>\n";
}
sub print_hash(\%) {
    my $h = shift;
    print "<dl>\n";
    print "<dt>$_</dt><dd>$h->{$_}</dd>\n" for (keys %$h);
    print "</dl>\n";
}
sub print_var {
  while (my $v = shift) {
    my $type = ref($v);
    if    ($type eq '')       { print "<p>$v</p>\n"; }
    elsif ($type eq 'SCALAR') { print "<p>$$v</p>\n"; }
    elsif ($type eq 'ARRAY')  { print_array(@$v); }
    elsif ($type eq 'HASH')   { print_hash(%$v); }
    elsif ($type eq 'REF')    { print_var($$v); }
    else                      { print "<p>$type</p>\n"; }
  }
}

# メイン処理
{
    print "Content-Type: text/html\n\n";
    print <<HEADER;
<html>
<head><title>Printing Variables</title></head>
<body>
HEADER

    my $sc = "Hello, my name is Palmo!";
    my $ar = ["First", "Second", "Third"];
    my $ha = {Apple => "Red", Banana => "Yellow", Peach => "Pink"};

    print_var($sc, $ar, $ha);

    print <<FOOTER;
</body>
</html>
FOOTER
}

print_array 関数は、渡された配列を ol 要素として出力します。同じく print_hash 関数は渡されたハッシュを dl 要素として出力します。これらの関数プロトタイプによってリファレンスを受け取るようになっています。リファレンスをやりとりする事で、無駄なコピーを抑える事ができます。

print_var 関数は、渡された値のリストをそれぞれ HTML で出力します。ref 関数スカラー変数の中身がリファレンスじゃないなら空文字を、リファレンスなら「何」を参照しているのかを表した文字列を返してくれるのでしたね。これを利用して、リファレンスが渡された時も、中身を適切に表示できるようにしました。if 文が羅列していて、ちょっと汚いですね……。(^_^;)

メイン処理でページを表示しています。$sc はスカラー値、$ar は無名配列へのリファレンス、$ha は無名ハッシュへのリファレンスがそれぞれ入りますね。これを print_var 関数に渡すと、ちゃんと表示してくれるはずです。

var2html.cgi 実行結果

上手く表示できました。(^_^)


ところで if 文の羅列が嫌な時は「Switchモジュールを使えば良いそうです。このモジュールを use すると、C言語などでお馴染みの switch 構文が使えるようになります。

Switch モジュールを使って上のスクリプトの print_var 関数を書き換えると、以下のようになります。

use Switch;

sub print_var {
  while (my $v = shift) {
    switch (my $type = ref($v)) {
        case ''        { print "<p>$v</p>\n"; }
        case 'SCALAR'  { print "<p>$$v</p>\n"; }
        case 'ARRAY'   { print_array(@$v); }
        case 'HASH'    { print_hash(%$v); }
        case 'REF'     { print_var($$v); }
        else           { print "<p>$type</p>\n"; }
    }
  }
}

if 文を羅列するよりは、断然読みやすいですね。

Switch モジュールによる switch は、C言語switch よりも優れていて case 文には数値に限らず色々な条件を書く事ができます。上のように文字列による case も可能ですし、リストやハッシュなどを書けばその中に switch 対象が存在するかどうか調べられ、正規表現を書けばマッチングが行なわれ、コードブロックを渡せば対象を引数として実行されてその返り値が調べられます。

何でもありですね。(^_^;)

簡単なページを出力してみる

まずは、簡単な HTML によるページを表示する CGI プログラムを作ってみます。

lighttpd を導入した時に、以下のような簡単なテスト用 CGI プログラムを作りました。

#!/usr/local/bin/perl

print "Content-Type: text/html\n\n";
print "Hello, world!\n";

この CGI プログラムブラウザで開くと、ただ単に「Hello, world!」と表示されるだけですが、このメッセージの代わりに HTML 文を出力する事で、ページを表示する事ができます。

#!/usr/local/bin/perl

print "Content-Type: text/html\n\n";
print <<HTML;
<html>
  <head>
    <title>Hello, CGI world!</title>
  </head>
  <body>
    <h1>Hello, CGI world!</h1>
    <p>Welcome to CGI world! This is a test page.</p>
  </body>
</html>
HTML
# "HTML" の後ろに改行が必要です

この CGI プログラムは、簡単なページを出力します。HTML については詳しい説明を省略しますが、わからない部分はお気軽にコメントなどでお尋ねください。

hellocgi.cgi 実行結果

上のリンクは、ぱるも砂場内のページへ移動します。広告はサーバーによって自動的に挿入されたものです。以降 CGI の実行結果は、ぱるも砂場内のページにて行なう予定です。

Hello, CGI world! というページが表示されました。簡単ですね。(^_^)


ところで、CGI プログラムUNIX 系のウェブサーバー上で実行させる場合、パーミッションの設定が必要です。パーミッションとは「許可」という意味で、「ファイルのオーナー」「グループ内のユーザー」「その他のユーザー」それぞれに対して、「読み込み」「書き込み」「実行」の許可/不許可を、ファイルごとに行なう事ができます。

「実行」に対する許可は通常はオフになっているはずですので、CGI を実行する為には「実行」に対する許可が必要です。どのようなパーミッションにすれば実行できるようになるかは、サーバーによって異なるので一概には言えませんが、「755」(rwxr-xr-x)や「705」(rwx---r-x)などが多いように思います。

パーミッションの設定は FFFTP などの FTP クライアントソフトを使えば簡単にできます。(^_^)