FrontPage

自作CGI掲示板のログ作成部

実際に作成したソースコードを公開します。
私の掲示板では、分かりやすさのため、機能の観点でソースを2つに分けています。
それぞれ、表(HTML出力部: guestbook.cgi)と裏(ログファイル作成部: write.cgi)といったかたちで。
ここではログの書込みとクッキーの設定に特化したwrite.cgiを、コメント中にて解説しています。

近いうちに簡単なフローなど書いてみようかと。
クエリ、フォーム、URLデコードの仕組みについても少しまとめたい?

ファイル名: write_r4.cgi

#!/usr/bin/perl


use warnings;                                                   # 警告表示                                         #
use strict;                                                     # 構文チェック                                     #
                                                                #                                                  #
require './jcode.pl';                                           # for URLデコード                                  #
require './idroll.pl';                                          # for ID文字列振出し                               #
require './gb_util.pl';                                         # for ログの確定とロールバック                     #
                                                                #                                                  #
# URL Decode **************************************************## URLデコード                                      #
my $tmp0 = my $tmp1 = "";                                       # 作業領域                                         #
my @decopairs = ("");                                           # フォームの内容を各データごとに格納する           #
my $key = "";                                                   # フォームデータのキー                             #
my $value = "";                                                 # フォームデータの値                               #
my %form = ("", "");                                            # 実操作用ハッシュ                                 #
                                                                #                                                  #
if( $ENV{'REQUEST_METHOD'} eq "POST" )                          # POST使用かどうか                                 #
{                                                               # POST使用の場合                                   #
    read( STDIN, $tmp0, $ENV{'CONTENT_LENGTH'} );               # フォームに入力された内容を変数に格納する         #
}                                                               #                                                  #
else                                                            #                                                  #
{                                                               # POST使用以外の場合                               #
    $tmp0 = $ENV{'QUERY_STRING'};                               # クエリの内容を変数に格納する                     #
}                                                               #                                                  #
                                                                #                                                  #
@decopairs = split( /&/, $tmp0 );                               # フォーム入力内容を'&'区切りで配列に格納する      #
                                                                #                                                  #
foreach $tmp1 (@decopairs)                                      # 配列の各要素について                             #
{                                                               #                                                  #
    ($key, $value) = split( /=/, $tmp1 );                       # '='区切りでキーと値に切分ける                    #
    $value =~ tr/+/ /;                                          # URLデコード                                      #
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack ("C", hex($1))/eg; # URLデコード                                    #
#   jcode::convert(*value, 'sjis');                             # URLデコード                                      #
    jcode::h2z_sjis( \$value );                                 # 半角カナ → 全角                                 #
    $form{$key} = $value;                                       # フォームの内容をハッシュ(ログ用)にセット         #
}                                                               #                                                  #
# Resist Ads **************************************************## ログ確定・切戻し処理                             #
if( $form{'confirm'} )                                          # 確定ボタンが押されたかどうか                     #
{                                                               # 確定ボタンが押された場合                         #
    &gb_util::confirm();                                        # ログ確定サブルーチンを呼出す                     #
    print "Location: http://bj006.com/cgi/guestbook.cgi"."\n\n"; # 掲示板に戻る                                    #
}                                                               #                                                  #
elsif( $form{'rollback'} )                                      # ロールバックボタンが押されたかどうか             #
{                                                               # ロールバックボタンが押された場合                 #
    &gb_util::rollback();                                       # ロールバックサブルーチンを呼出す                 #
    print "Location: http://bj006.com/cgi/guestbook.cgi"."\n\n"; # 掲示板に戻る                                    #
}                                                               #                                                  #
elsif( "2109" == $form{'mssid'} )                               # ID入力値が強制切戻し命令番号と一致するか         #
{                                                               # ID入力値が強制切戻し命令番号と一致する場合       #
    &gb_util::rollback2();                                      # 強制ロールバックサブルーチンを呼出す             #
    print "Location: http://bj006.com/cgi/guestbook.cgi"."\n\n"; # 掲示板に戻る                                    #
}                                                               #                                                  #
#/Resist Ads **************************************************##                                                  #
my $name = "";                                                  # 作業用                                           #
my $subject = "";                                               # 作業用                                           #
my $message = "";                                               # 作業&判定用                                     #
my $url = "";                                                   # 作業&判定用                                     #
my $curl = "";                                                  # クッキー設定用                                   #
my $mssid = "";                                                 # 作業&判定用                                     #
                                                                #                                                  #
$name = $form{'name'};                                          # 名前のデータを格納                               #
$subject = $form{'subject'};                                    # タイトルのデータを格納                           #
$message = $form{'message'};                                    # 本文のデータを格納                               #
$url = $form{'url'};                                            # URLのデータを格納                                #
$curl = $url;                                                   # URLのデータを複製                                #
$mssid = $form{'mssid'};                                        # IDのデータを格納                                 #
                                                                #                                                  #
$name =~ s/<br>//g;                                             # 名前からタグを除く(任意)                         #
$subject =~ s/<br>//g;                                          # タイトルからをタグを除く(任意)                   #
$message =~ s/\n/<br>/g;                                        # 本文の改行をタグに変換                           #
                                                                #                                                  #
#/URL Decode **************************************************##                                                  #
# ERR Check ***************************************************## フォームデータに対しエラー判定をする             #
if(                                                             # 入力値が異常かどうか(*性能改善余地)              #
    length( $message ) > 1600 ||                                # 本文が長すぎる                                   #
    length( $message ) == 0 ||                                  # 本文がない                                       #
    (($mssid > 1024 || $mssid < 1) && $mssid ne '****')         # ID値が上限以上下限以下かつ特殊文字列でない       #
  )                                                             #                                                  #
{                                                               # 入力値が異常の場合                               #
    print "Location: http://bj006.com/cgi/error1.htm"."\n\n";   # エラーページ1へジャンプ                         #
}                                                               #                                                  #
else                                                            #                                                  #
{                                                               # 入力値が異常でない場合                           #
#/ERR Check ***************************************************##                                                  #
# Write Log File then Move ************************************## ログ書込みとページ移動                           #
# Get Time ****************************************************## 入力時刻の取得                                   #
    my ($sec, $min, $hour) = (0, 0, 0);                         # 入力時刻(秒, 分, 時)                             #
    my ($day, $mon, $year) = (0, 0, 0);                         # 入力時刻(日, 月, 年)                             #
    my ($weeko, $yday, $isdat) = (0, 0, 0);                     # 入力時刻(曜日, 年初からの日数, サマータイム判定) #
    my $time = "";                                              # 整形済み入力時刻                                 #
    my @weeka = ( 'Sun','Mon','Tue','Wed','Thu','Fri','Sat' );  # 曜日を文字列で表すため                           #
                                                                #                                                  #
    ($sec,$min,$hour,$day,$mon,$year,$weeko,$yday,$isdat) = localtime(); # 入力時刻の取得                          #
    $year += 1900;                                              # 年表示のため                                     #
    $mon++;                                                     # 月表示のため                                     #
    $time = sprintf( "%04d-%02d-%02d (%s) %02d:%02d:%02d",      # 入力時刻のフォーマット整形                       #
                $year,$mon,$day,$weeka[$weeko],$hour,$min,$sec ); #                                                #
#/Get Time ****************************************************##                                                  #
# Get ID ******************************************************## ID文字列の取得                                   #
    my $mystr = "";                                             # ID文字列                                         #
                                                                #                                                  #
    if( $mssid ne '****' )                                      # 入力されたIDが特殊文字列でないかどうか           #
    {                                                           # 入力されたIDが特殊文字列でない場合               #
        $mystr = idroll::roll( $mssid - 1 );                    # ID文字列の振出し                                 #
    }                                                           #                                                  #
    else                                                        #                                                  #
    {                                                           # 入力されたIDが特殊文字列の場合                   #
        $mystr = '<b><font color="#00FF00">Hermit Webmaster</font></b>' # 管理人用文字列                           #
    }                                                           #                                                  #
#/Get ID ******************************************************##                                                  #
# GET IP and Host *********************************************## 入力者のIPアドレスとホストを取得                 #
    my $ipaddr = "";                                            # 環境変数からIPアドレスを格納する                 #
    my $host = "";                                              # ホスト名を格納する                               #
                                                                #                                                  #
    $ipaddr = $ENV{'REMOTE_ADDR'};                              # 環境変数からデータを変数に格納する               #
    $host = gethostbyaddr( pack("C4", $ipaddr), 2 ) || $ipaddr; # IPアドレスからホスト取得、失敗したらIPアドレス   #
#/GET IP and Host *********************************************##                                                  #
    if( index( $url, 'http://' ) < 0 )                          # 入力URLが"http://"以外で始まるかどうか           #
    {                                                           # 入力URLが"http://"以外で始まる場合               #
        $url = $curl = 'http://';                               # デフォルト値設定とする(無視対象文字列となります) #
    }                                                           #                                                  #
                                                                #                                                  #
    if( $url eq 'http://' )                                     # 入力URLがデフォルト値かどうか                    #
    {                                                           # 入力URLがデフォルト値の場合                      #
        $url = 'URL';                                           # ただの文字列                                     #
    }                                                           #                                                  #
    else                                                        # 入力URLがある場合                                #
    {                                                           #                                                  #
        $url = "<a href=\""."$url"."\">URL</a>";                # ハイパーリンクを設定                             #
    }                                                           #                                                  #
                                                                #                                                  #
    open LOGW, ">>./guestlog.txt"                                    # ログファイルオープン                        #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したらエラーページ0へジャンプ          #
    flock( LOGW, 2 )                                                 # 占有ロック                                  #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したらエラーページ0へジャンプ          #
    print LOGW "$name#@#$subject#@#$message#@#$url#@#".         # ログファイルへ追加書込み                         #
                   "$mystr#@#$time#@#$ipaddr#@#$host#@#\n";     #                                                  #
    close( LOGW );                                              # ファイルクローズ                                 #
# Set Cookie **************************************************##                                                  #
    my $target = 0;                                             # クッキーの失効時刻を定める                       #
    my ($gsec, $gmin, $ghour) = (0, 0, 0);                      # GMT時刻(秒, 分, 時)                              #
    my ($gday, $gmon, $gyear) = (0, 0, 0);                      # GMT時刻(日, 月, 年)                              #
    my ($gweeko, $gyday, $gisdat) = (0, 0, 0);                  # GMT時刻(曜日, 年初からの日数, サマータイム判定)  #
    my @gmona = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',      # 月文字列配列                                     #
                  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');    #                                                  #
    my $expire = "";                                            # 整形済クッキー失効時刻                           #
    my $cs = "";                                                # クッキーに保持するデータ文                       #
                                                                #                                                  #
    $target = time() + (60 * 60 * 24 * 90);                     # クッキーの生存期間を設定(この場合は90日間となる) #
    ($gsec,$gmin,$ghour,$gday,$gmon,$gyear,$gweeko,$gyday,$gisdat) = gmtime($target); # 期限切れ時のGMTを取得      #
    $gyear += 1900;                                             # 西暦の正規化                                     #
                                                                #                                                  #
    $expire = sprintf( "%s, %02d-%s-%04d %02d:%02d:%02d GMT",   # クッキー設定用フォーマット整形                   #
                  $weeka[$gweeko], $gday, $gmona[$gmon],        #                                                  #
                  $gyear, $ghour, $gmin, $gsec );               #                                                  #
                                                                #                                                  #
    $cs = "$name#@#$curl#@#$mssid#@#";                          # クッキーに保持するのは名前、URL、ID              #
                                                                #                                                  #
    print "Set-cookie:$cs; expires=$expire\n";                  # クッキーの設定                                   #
#/Set Cookie **************************************************##                                                  #
    print "Location: http://bj006.com/cgi/guestbook.cgi"."\n\n"; # すべてが正常なら、掲示板に戻る                  #
}                                                               #                                                  #
#/Write Log File then Move ************************************##                                                  #
exit;                                                           # 処理終了                                         #

ファイル名: gb_util.pl

# package gb_util *********************************************## 掲示板CGI追加機能                                #
{
package gb_util;
                                                                #                                                  #
use warnings;                                                   # 警告表示                                         #
use strict;                                                     # 構文チェック                                     #
# sub confirm *************************************************## 未確定ログ確定                                   #
sub confirm                                                     # サブルーチン: ログファイルの内容を確定する       #
{                                                               #                                                  #
    my $logNum = 1;                                             # ログ番号 for バックアップ退避                    #
    my $buf = "";                                               # 作業領域                                         #
                                                                #                                                  #
    for( ; ; )                                                  # 無限ループ                                       #
    {                                                           #                                                  #
        if( (-s "./LOG_MAS.txt") == (-s "./guestlog.txt") )     # ログファイルがバックアップファイルと同一かどうか #
        {                                                       # ログファイルがバックアップファイルと同一の場合   #
            last;                                               # その後の処理をせず終了                           #
        }                                                       #                                                  #
                                                                #                                                  #
        while( -e "./LOG_MAS_$logNum.txt" )                     # 対象の番号のバックアップファイルが存在する限り   #
        {                                                       #                                                  #
            $logNum++;                                          # ログ番号を加算していく                           #
        }                                                       # ループを抜けたら最新の番号となる                 #
        rename( "./LOG_MAS.txt", "./LOG_MAS_$logNum.txt" );     # バックアップ退避                                 #
                                                                #                                                  #
        open( INFO, "<./guestlog.txt" )                                  # ファイルオープン(読込み専用)            #
            or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ     #
        flock( INFO, 1 )                                                 # 排他ロック(LOCK_SH == 1)                #
            or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ     #
        read( INFO, $buf, (-s "./guestlog.txt") );              # ファイル内容を変数に読込む                       #
        close( INFO );                                          # ファイルクローズ                                 #
                                                                #                                                  #
        open( OUTFO, ">./LOG_MAS.txt" )                                  # ファイルオープン(書込み専用)            #
            or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ     #
        flock( OUTFO, 2 )                                                # 排他ロック(LOCK_EX == 2)                #
            or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ     #
        print OUTFO $buf;                                       # マスタファイルの内容をログに書き込む             #
        close( OUTFO );                                         # ファイルクローズ                                 #
                                                                #                                                  #
        last;                                                   # ループ終了                                       #
    }                                                           #                                                  #
                                                                #                                                  #
    return 0;                                                   # 処理終了                                         #
}
#/sub confirm *************************************************##                                                  #
# sub rollback ************************************************## ログ状態のロールバック                           #
sub rollback                                                    # サブルーチン: ログファイルの内容を巻戻す         #
{                                                               #                                                  #
    my $buf = "";                                               # 作業領域                                         #
                                                                #                                                  #
    open( INFO, "<./LOG_MAS.txt" )                                   # ファイルオープン(読込み専用)                #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    flock( INFO, 1 )                                                 # 共有ロック(LOCK_SH == 1)                    #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    read( INFO, $buf, (-s "./LOG_MAS.txt") );                   # ファイル内容を変数に読込む                       #
    close( INFO );                                              # ファイルクローズ                                 #
                                                                #                                                  #
    open( OUTFO, ">./guestlog.txt" )                                 # ファイルオープン(書込み専用)                #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    flock( OUTFO, 2 )                                                # 排他ロック(LOCK_EX == 2)                    #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
                                                                #                                                  #
    seek( OUTFO, 0, 0 );                                        # ポインタをファイルの先頭にセット                 #
    truncate( OUTFO, 0 );                                       # ファイル内容を消去                               #
                                                                #                                                  #
    print OUTFO $buf;                                           # マスタファイルの内容をログに書き込む             #
    close( OUTFO );                                             # ファイルクローズ                                 #
                                                                #                                                  #
    return 0;                                                   # 処理終了                                         #
}
#/sub rollback ************************************************##                                                  #
# sub rollback2 ***********************************************## ログ状態のロールバック2                          #
sub rollback2                                                   # サブルーチン: ログファイルの内容を(強引に)巻戻す #
{                                                               #                                                  #
    my $buf = "";                                               # 作業領域                                         #
                                                                #                                                  #
    open( INFO, "<./LOG_MAS_FRC.txt" )                               # ファイルオープン(読込み専用)                #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    flock( INFO, 1 )                                                 # 共有ロック(LOCK_SH == 1)                    #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    read( INFO, $buf, (-s "./LOG_MAS_FRC.txt") );               # ファイル内容を変数に読込む                       #
    close( INFO );                                              # ファイルクローズ                                 #
                                                                #                                                  #
    open( OUTFO, ">./guestlog.txt" )                                 # ファイルオープン(書込み専用)                #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
    flock( OUTFO, 2 )                                                # 排他ロック(LOCK_EX == 2)                    #
        or print "Location: http://bj006.com/cgi/error0.htm"."\n\n"; # 失敗したら、エラーページ0へジャンプ         #
                                                                #                                                  #
    seek( OUTFO, 0, 0 );                                        # ポインタをファイルの先頭にセット                 #
    truncate( OUTFO, 0 );                                       # ファイル内容を消去                               #
                                                                #                                                  #
    print OUTFO $buf;                                           # マスタファイルの内容をログに書き込む             #
    close( OUTFO );                                             # ファイルクローズ                                 #
                                                                #                                                  #
    &gb_util::confirm();                                        # 確定処理も行う(!性能改善余地!)                   #
                                                                #                                                  #
    return 0;                                                   # 処理終了                                         #
}
#/sub rollback ************************************************##                                                  #
1;
}
#/package gb_util *********************************************##                                                  #

関連ページ

Perl・CGI入門/パッケージを使う/ID Roll
Perl・CGI入門/自作掲示板/HTML出力

修正履歴

  • write_r2.cgi
    • strictとwarnings
    • 合わせて変数の初期化を実施。
    • ログファイルに使用する区切り文字を変更
    • 本文が空の場合の処理を追加

  • write_r3.cgi
    • もろもろ改良

  • guestbook_r4.cgi
    • ログ切戻し機能実装
    • クッキー作成部の修正
[添付ファイル一覧] [全ページの添付ファイル一覧]
アップロード可能最大ファイルサイズは 1,024KB です。

管理者パスワード:

参考ページ

http://www.perl-labo.org/
http://perl.misty.ne.jp/


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-02-08 (月) 02:08:16 (5191d)