かんたん作成【HTML CSS JavaScript PHP CGI Perl Ruby Python .htaccess】

チャット

#! /usr/local/bin/perl

# 設定
$FILE        = './dat/chat.dat';    # 発言保存ファイル
$INFILE        = './dat/chatin.dat';    # 参加者保存ファイル
$MAX        = 100;            # 保存件数
$NAMEMAX    = 10;            # 名前文字数制限(全角)
$TEXTMAX    = 50;            # 発言文字数制限(全角)
$REFRESH    = 50;            # 再読み込み時間(秒)
$DELETE        = 10 * 60;        # 参加者自動削除時間(秒)

$time = time;                # 日時取得
loadForm();                # フォームデータ取り込み
if($FORM{'frame'} eq "input") {
    frameInput();            # 入力用フレームを表示
}
elsif($FORM{'frame'} eq "view") {
    frameView();            # 表示用フレームを表示
}
else {
    frameSet();            # フレームセット
}
exit;

#================================================ フレームセット
sub frameSet
{
    print qq(Content-type: text/html; charset=Shift_JIS\n\n);
    print <<"    END";
        <html>
        <head>
        <title>チャット</title>
        <frameset border="0" rows="85%,*">
            <frame name="view" src="$ENV{SCRIPT_NAME}?frame=view">
            <frame name="input" src="$ENV{SCRIPT_NAME}?frame=input">
        </frameset>
        </head>
        </html>
    END
}

#================================================ 入力用フレームを表示
sub frameInput
{
    my    ($i);
    if($FORM{'mode'}) {
        loadData();                        # 参加者・発言データ読み込み
    }
    print qq(Content-type: text/html; charset=Shift_JIS\n\n);
    print <<"    END";
        <html>
        <head>
        <title>チャット</title>
        <style type="text/css">
        <!--
        body, form    {
            margin:    0px;
        }
        table    {
            width:    100%;
            text-align:    center;
        }
        //-->
        </style>
        <script language="JavaScript">
        <!--
        function namefocus() {        // ページ表示後に名前入力欄にカーソルを自動的に移動
            document.inputname.name.focus()
        }
        function textfocus() {        // ページ表示後に発言入力欄にカーソルを自動的に移動
            document.inputtext.text.focus()
        }
        function textsubmit() {        // 発言後(0.5秒後)に入力欄をリセットしカーソルを移動
            setTimeout('document.inputtext.reset.click(); textfocus()', 500)
        }
        //-->
        </script>
        </head>
    END
    if($FORM{'name'} eq "" or $FORM{'mode'} eq "out" or $error) {        # 名前入力ページ表示
        print <<"        END";
            <body bgcolor="#ffffcc" onLoad="namefocus()">
            <hr color="#ff9933">
            <table>
                <tr>
                    <td>
                    <form name="inputname" action="$ENV{'SCRIPT_NAME'}" method="POST">
                    名前($NAMEMAX文字以内):
                    <input type="text" name="name" size="70" maxlength="$NAMEMAX" value="$FORM{'name'}">
                    <input type="submit" value="参加する(Enter)">
                    <input type="hidden" name="frame" value="input">
                    <input type="hidden" name="mode" value="in">
                    </form>
                    </td>
                </tr>
            </table>
        END
    }
    else {                                # 発言入力ページ表示
        print <<"        END";
            <body bgcolor="#ffffcc" onLoad="textfocus()">
            <hr color="#ff9933">
            <table>
                <tr>
                    <td>
                    <form name="inputtext" action="$ENV{'SCRIPT_NAME'}" method="POST" target="view"
                        onSubmit="textsubmit()">
                    $FORM{'name'}:
                    <input type="text" name="text" size="70" maxlength="$TEXTMAX">
                    <input type="submit" value="発言する(Enter)">
                    <input type="reset" name="reset" value="リセット" onClick="textfocus()">
                    <input type="hidden" name="frame" value="view">
                    <input type="hidden" name="mode" value="write">
                    <input type="hidden" name="name" value="$FORM{'name'}">
                    </form>
                    </td>
                    <td>
                    <a href="$ENV{'SCRIPT_NAME'}?frame=view" target="view" onClick="textfocus()">更新(Enter)</a>
                    </td>
                    <td>
                    <form action="$ENV{'SCRIPT_NAME'}" method="POST">
                    <input type="submit" value="退出する">
                    <input type="hidden" name="frame" value="input">
                    <input type="hidden" name="mode" value="out">
                    <input type="hidden" name="name" value="$FORM{'name'}">
                    </form>
                    </td>
                </tr>
            </table>
        END
    }
    if($error) {    # エラーメッセージを表示
        print qq(<font color="red">※$error</font>\n);
    }
    print <<"    END";
        </body>
        </html>
    END
}

#================================================ 表示用フレームを表示
sub frameView
{
    my    ($i);
    loadData();                            # 参加者・発言データ読み込み
    print qq(Content-type: text/html; charset=Shift_JIS\n\n);
    print <<"    END";
        <html>
        <head>
        <meta http-equiv="refresh" content="$REFRESH;url=$ENV{'SCRIPT_NAME'}?frame=view">
        <title>チャット</title>
        <style type="text/css">
        <!--
        body    {
            margin:    0px;
        }
        table    {
            margin:    0px 20px;
        }
        //-->
        </style>
        </head>
        <body bgcolor="#ffffcc">
        <hr color="#ff9933">
    END
    printf qq(参加者: \n);
    for($i = 0 ; $i < @IN ; $i++) {                    # 参加者データ表示
        my    ($tm, $name) = split(/\t/, $IN[$i]);
        if($tm + $DELETE >= $time) {    # 自動削除時間を経過した参加者以外を表示
            print qq($name );
        }
    }
    print <<"    END";
        <br>
        <hr color="#ff9933">
        <table>
    END
    for($i = 0 ; $i < @DATA ; $i++) {                # 発言データ表示
        my    ($tm, $name, $text) = split(/\t/, $DATA[$i]);
        my    ($sec, $min, $hour, $date, $mon, $year, $day) = localtime($tm);
        print qq(<tr>);
        print qq(<td align="right" valign="top" nowrap><font size="-1">$name≫</font></td>);
        print qq(<td><b>$text</b> );
        printf qq(<font size="-2">[%02d/%02d %02d:%02d]</font></td>), ++$mon, $date, $hour, $min;
        print qq(</tr>);
    }
    print <<"    END";
        </table>
        </body>
        </html>
    END
}

#================================================ 発言データ・参加者データ読み込み
sub loadData
{
    my    ($i);
    open(FILE, "<$FILE");                        # 発言データ読み込み
    eval{ flock(FILE, 1) };
    @DATA = <FILE>;
    close FILE;
    open(FILE, "<$INFILE");                        # 参加者データ読み込み
    eval{ flock(FILE, 1) };
    @IN = <FILE>;
    close FILE;
    if($FORM{'mode'}) {
        if($FORM{'mode'} eq 'in') {                # 参加
            if($FORM{'name'} and length($FORM{'name'}) <= $NAMEMAX * 2) {    # 名前入力がある場合
                if($FORM{'name'} eq "管理人") {    # 使用禁止の名前をチェック
                    $error = "『$FORM{'name'}』では参加できません。"
                        . "別の名前で参加してください。";
                    return;
                }
                for($i = 0 ; $i < @IN ; $i++) {    # 名前の重複チェック
                    my    ($tm, $name) = split(/\t/, $IN[$i]);
                    if($name eq $FORM{'name'}) {
                        $error = "『$FORM{'name'}』さんは現在参加中です。"
                            . "別の名前で参加してください。";
                        return;
                    }
                }
                push @IN, "$time\t$FORM{'name'}\t\n";
                unshift @DATA, "$time\t管理人\t『$FORM{'name'}』さんが参加されます。\t\n";
            }
            else {            # 空欄の場合 戻る
                $error = "名前を入力してください。";
                return;
            }
        }
        elsif($FORM{'mode'} eq 'out') {                # 退出
            for($i = 0 ; $i < @IN ; $i++) {
                my    ($tm, $name) = split(/\t/, $IN[$i]);
                if($name eq $FORM{'name'}) {    # 退出者データを探す
                    splice @IN, $i, 1;    # 参加者データから削除
                    unshift @DATA, "$time\t管理人\t『$FORM{'name'}』さんが退出しました。\t\n";
                    last;
                }
            }
        }
        elsif($FORM{'mode'} eq 'write') {            # 発言
            if($FORM{'text'} and length($FORM{'text'}) <= $TEXTMAX * 2) {    # 発言入力がある場合
                if(@IN > 0) {
                    for($i = 0 ; $i < @IN ; $i++) {
                        my    ($tm, $name) = split(/\t/, $IN[$i]);
                        if($name eq $FORM{'name'}) {    # 参加者データを探す
                            $IN[$i] = "$time\t$FORM{'name'}\t\n";    # 参加者データ更新
                            unshift @DATA, "$time\t$FORM{'name'}\t$FORM{'text'}\t\n";
                            last;
                        }
                    }
                }
            }
            else {            # 空欄の場合 戻る(ページ更新のみ)
                return;
            }
        }
        while(@DATA > $MAX) {                    # 保存件数以上のデータを削除
            pop @DATA;
        }
        open(FILE, ">$FILE");                    # 発言データ書き込み(保存)
        eval{ flock(FILE, 2) };
        print FILE @DATA;
        close FILE;
        for($i = 0 ; $i < @IN ; $i++) {                # 自動削除
            my    ($tm, $name) = split(/\t/, $IN[$i]);
            if($tm + $DELETE < $time) {    # 自動削除時間経過の参加者を削除
                splice @IN, $i, 1;
                $i--;
            }
        }
        open(FILE, ">$INFILE");                    # 参加者データ書き込み(保存)
        eval{ flock(FILE, 2) };
        print FILE @IN;
        close FILE;
    }
}

#================================================ フォームデータ取り込み
sub loadForm
{
    my    ($query, $pair);
    if($ENV{'REQUEST_METHOD'} eq 'POST') {
        read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
    }
    else {
        $query = $ENV{'QUERY_STRING'};
    }
    foreach $pair (split(/&/, $query)) {
        my    ($key, $value) = split(/=/, $pair);
        $value =~ tr/+/ /;
        $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg;
        $value =~ s/&/&amp;/g;
        $value =~ s/</&lt;/g;
        $value =~ s/>/&gt;/g;
        $value =~ s/\s//g;
        $value =~ s/\x81\x40//g;
        $value =~ s/\x0D\x0A//g;
        $value =~ tr/\t//;
        $FORM{$key} = $value;
    }
}
CGI(Perl)
Hello world ! ユーザーエージェント取得・表示($ENV{'HTTP_USER_AGENT'})
IPアドレス取得・表示($ENV{'REMOTE_ADDR'}) リンク元取得・表示($ENV{'HTTP_REFERER'})
URL取得・表示($ENV{'HTTP_HOST'}, $ENV{'REQUEST_URI'}) 環境変数を全て表示(%ENV)
ホスト名取得・表示(gethostbyaddr) 訪問者のプロバイダーを表示
訪問者の都道府県を取得・表示 日付を表示(localtime time)
日付を画像表示(localtime time, substr) アクセス日時を表示(localtime time)
指定の日までの日数を表示 曜日によって背景色を変える
日によって背景色を変える 月によって背景色を変える
見るたびに背景色を変える 見るたびに背景画像を変える
おみくじ(rand, int) カラーチャート
Shift_JIS文字コード表 UTF-8文字コード表
グラフ(横棒グラフ) アクセスカウンター
アクセスカウンター(画像) アクセスカウンター(今日・昨日)
訪問回数(クッキー, $ENV{'HTTP_COOKIE'}, Set-Cookie) アクセスログ保存
アクセスログ集計 パスワード認証
クッションページ($ENV{'QUERY_STRING'}) クッションページ($ENV{'PATH_INFO'})
フォーム入力内容をクッキーに保存 1つのCGIでフレームページを表示
IPアドレスからホスト名を取得(gethostbyaddr) ホスト名からIPアドレスを取得(gethostbyname)
IPアドレスからプロバイダーを取得 IPアドレスから都道府県を取得
文章中の文字列を別の文字列に一括変換 カレンダー
カレンダー(前月・次月へのリンク付) カレンダー(今年1月〜12月)
掲示板 掲示板(URL自動変換/連続改行・スペース削除)
掲示板(年齢・性別・都道府県選択) 画像アップロード掲示板
チャット Web日記
サイトマップ(ディレクトリ内のファイルを調べる) Webデータ取得(HTTPヘッダー, HTMLソース, use Socket)
Webデータ取得(HTTPヘッダー, HTMLソース, use HTTP::Request::Common) トラックバック受信
トラックバック送信 メール送信(メールフォーム, sendmail)
リバーシ(ボードゲーム) .htaccessユーザー認証用ユーザーファイル作成
リダイレクト 条件指定リダイレクト
言語振り分けリダイレクト 条件指定アクセス拒否(ステータスコードを返す)
HTMLファイル読み込み・表示 HTMLファイル読み込み・パスワード認証
HTMLファイル読み込み・条件指定アクセス拒否 HTMLファイル読み込み・条件指定リダイレクト
外部CGIファイル読み込み(require) 画像ファイル読み込み・表示
画像縮小・拡大・サイズ変更(Image::Magick, Resize) 画像切り出し(Image::Magick, Crop)
画像文字埋め込み(Image::Magick, Annotate) 画像合成(Image::Magick, Composite)
画像生成・保存(Image::Magick->new) 画像合成アクセスカウンター
かんたん作成【HTML CSS JavaScript PHP CGI Perl Ruby Python .htaccess】