#!/usr/bin/perl #┌───────────────────────────────── #│ COMCHAT v4.2 (2002/01/20) #│ Copyright(C) Kent Web 1997-2002 #│ webmaster@kent-web.com #│ http://www.kent-web.com/ #└───────────────────────────────── $ver = 'COMCHAT v4.2'; #┌───────────────────────────────── #│ [注意事項] #│ 1. このスクリプトはフリーソフトです。このスクリプトを使用した #│ いかなる損害に対して作者は一切の責任を負いません。 #│ 2. 設置に関する質問はサポート掲示板にお願いいたします。 #│ 直接メールによる質問は一切お受けいたしておりません。 #└───────────────────────────────── # #【ディレクトリ構成例】 # # public_html / index.html (トップページ等) # | # +-- comchat / comchat.cgi [755] # | chatmgr.cgi [755] # | jcode.pl [644] # | comchat.log [666] # | member.dat [666] # | deny.dat [666] # | rank.dat [666] # | # +-- lock [777] / #============# # 設定項目 # #============# # 文字コード変換ライブラリ取込み require './jcode.pl'; # 戻り先のURL(index.htmlなど) $homepage = 'http://homepage3.nifty.com/gamers_park/ff/index.html'; # 最大記事数 $max = 30; # リロード時間の選択秒数 @reload = (0,30,40,50,60); # リロード時間の初期値 $re_sec = 30; # 表示行数 @line = (10,20,30,40,50); # 本文文字サイズ $b_size = '13px'; # 文字色を指定(必ず偶数で。上下の配列はペアで) @COLORS = ('#0000FF','#DF0000','#008040','#800000','#C100C1','#FF80C0','#FF8040','#000080'); @IROIRO = ('青','赤','みどり','茶','紫','ピンク','オレンジ','あい色'); # タイトル名 $title = "FF CHAT ROOM"; # タイトルの大きさ $t_size = '18px'; # タグの許可 (0=no 1=yes) $tagkey = 0; # methodの形式 (POST/GET) $method = 'POST'; # ポインタの形状(ログ表示部で「名前」の前につく) $pointer = "★"; # スクリプトファイル名 $script = './comchat.cgi'; # ログファイル名 $logfile = './comchat.log'; # 参加者表示ファイル名 $memfile = './member.dat'; # ファイルロック形式 # → 0=no 1=symlink関数 2=mkdir関数 $lockkey = 1; # ロックファイル名 $lockfile = './lock/comchat.lock'; # 入退室案内名 $master = "MASTER"; # 入退室メッセージ $in_msg = "さん、いらっしゃい。"; # 入室時 $out_msg = "さん、さようなら〜。"; # 退室時 # 入退室メッセージの色 $rep_color = "#000000"; # 入室時にIPアドレスを表示 (0=no 1=yes) $host_view = 1; # bodyタグ(背景色・文字色などを定義) $body = ''; # Chat Managerを指定 $chatmgr = './chatmgr.cgi'; # IP拒否アドレスのログ $denyfile = './deny.dat'; # 顔文字 @faces = ('(^_^)', '(^_^;)', '(*^^*)', '(;_;)', '(ーー;', ' m(_ _)m', '(・_・)', '(^^)/~~', '(@_@)', '\(^O^)/', '(?_?)'); # 発言ランキング (0=no 1=yes) $rankkey = 0; # 発言ランクファイル $rankfile = './rank.dat'; # 発言ランクログ保存日数 $limit = 7; #============# # 設定完了 # #============# &decode; &deny; if (!$buffer) { &frame; } if ($mode eq 'form') { &form1; } if ($mode eq 'into') { &form2; } if ($in{'comment'} && $mode eq 'regist') { ®ist; } if ($mode eq 'bye') { &byebye; } &log_view; #------------------# # フレームを生成 # #------------------# sub frame { # クッキーを取得 &get_cookie; # クッキーにリロード時間/行数のない場合は初期値を代入 if ($ck{'retime'} eq "") { $ck{'retime'} = $re_sec; } if ($ck{'line'} eq "") { $ck{'line'} = $line[1]; } &header; print <<"EOM"; <body>フレーム非対応のブラウザの方は利用できません</body> EOM exit; } #------------------# # HTMLのヘッダー # #------------------# sub header { print "Content-type: text/html\n\n"; print <<"EOM"; $title EOM } #-----------------------# # フォーム1 : 入室画面 # #-----------------------# sub form1 { # クッキーを取得 &get_cookie; # HTMLを出力 &header; print <<"EOM"; $body
[BACK]
$title

\n"; print "\n"; print "
おなまえ
Eメール
リロード 行数

文字色を選んでください
\n"; if ($ck{'color'} eq "") { $ck{'color'} = $COLORS[0]; } $key = int (@COLORS / 2); $i=0; foreach (@COLORS) { $i++; if ($ck{'color'} eq $_) { print ""; print "\n"; } else { print ""; print "\n"; } if ($i == $key) { print "
\n"; } } print "
\n"; print "\n\n\n"; exit; } #----------------------------# # フォーム2 : 発言フォーム # #----------------------------# sub form2 { ®ist('into'); # クッキーを提供 &set_cookie; # 以下のJavaScript(発言コメントの自動消去機能)は # ゆいちゃっと (http://www.cup.com/yui/) から移植しました。 &header; print <<"EOM"; $body
\n"; print "
名前$in{'name'}
発言
かお文字 \n 文字色 \n リロード \n 行数 \n"; print "
\n"; print "\n"; print "\n"; print "
\n"; print "発言自動消去

\n"; print "[管理用]\n"; if ($rankkey) { print "[発言ランキング]\n"; } print "\n"; exit; } #--------------# # 記事表示部 # #--------------# sub log_view { &header; if ($in{'retime'} != 0) { local($ename) = &url_enc($in{'name'}); print "\n"; } ## 参加者表示 &member; print "\n$body\n"; print "\n"; print "
参加者($num):$memberリロード: \n"; if ($in{'retime'} == 0) { print "手動モード"; } else { print "$in{'retime'}秒"; } print " 行数: $in{'line'}行
\n"; $i=0; open(IN,"$logfile") || &error("Open Error : $logfile"); while () { $i++; if ($i > $in{'line'}) { last; } ($date,$name,$email,$comment,$color) = split(/<>/); print "
$name > $comment "; print "($date)
\n"; } close(IN); # 著作権を表示(削除禁止) print "
\n"; print "- COMCHAT -\n"; print "
\n\n"; exit; } #--------------------# # ログ書き込み処理 # #--------------------# sub regist { # 名前の入力がなければエラー if ($InName eq "") { &error("名前の入力がありません"); } # ロック開始 &lock if ($lockkey); $bye=0; if ($_[0] eq 'into') { if ($host_view) { $in{'comment'} = "$in{'name'}$in_msg <$host>"; } else { $in{'comment'} = "$in{'name'}$in_msg"; } $email = ""; $name = $master; $color = $rep_color; } elsif ($_[0] eq 'bye') { $in{'comment'} = "$in{'name'}$out_msg"; $email = ""; $name = $master; $color = $rep_color; $bye=1; } else { if ($in{'email'} eq "") { $name = "$pointer $in{'name'}"; } else { $name = "$pointer $in{'name'}"; } $email = $in{'email'}; $color = $in{'color'}; # 発言ランキング処理 if ($rankkey) { &ranking; } } # ログを開く open(IN,"$logfile") || &error("Open Error : $logfile"); @lines = ; close(IN); ## clear と入力することで自分の記事を削除 if ($in{'comment'} eq 'clear'){ @temp=(); local($match)=0; foreach (@lines) { ($da,$na,$em,$com,$col,$ho) = split(/<>/); if ($host eq "$ho") { $match=1; } else { push(@temp,$_); } } if ($match) { @lines=@temp; $in{'comment'}="All Clear (^-^)v"; } } # 最大記事数 while ($max <= @lines) { pop(@lines); } $in{'comment'} =~ s/\(\*\^\^\*\)/\(\*<\/font>\^\^\*<\/font>\)/; # ログをフォーマットして更新 unshift (@lines,"$date<>$name<>$email<>$in{'comment'}<>$color<>$host<>\n"); open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @lines; close(OUT); # ロック解除 &unlock if ($lockkey); } #----------------# # デコード処理 # #----------------# sub decode { local($name, $value, @pairs); if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach (@pairs) { ($name, $value) = split(/=/); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # 文字コードをシフトJIS変換 &jcode'convert(*value, 'sjis'); # タグ処理 if ($tagkey) { $value =~ s/<>/<>/g; } else { $value =~ s//>/g; } # 改行コードは削除 $value =~ s/\r//g; $value =~ s/\n//g; $in{$name} = $value; } $mode = $in{'mode'}; if ($in{'face'} ne "") { $in{'comment'} = "$in{'comment'} $in{'face'}"; } $InName = $in{'name'}; $host = $ENV{'REMOTE_ADDR'}; if ($in{'name'} eq "") { $in{'name'} = $host; } # 時間を取得 $ENV{'TZ'} = "JST-9"; $times = time; ($sec,$min,$hour,$mday,$mon) = localtime($times); $date = sprintf("%s/%s-%02d:%02d:%02d",$mon+1,$mday,$hour,$min,$sec); } #------------# # 退室処理 # #------------# sub byebye { ®ist('bye'); &member('bye'); &header; print <<"EOM"; $body

$in{'name'}さん、ご利用ありがとうございました

EOM exit; } #------------------# # クッキーの発行 # #------------------# sub set_cookie { local($gmt, $cook, @t); @t = gmtime(time + 60*24*60*60); $gmt = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", (qw(Sun Mon Tue Wed Thu Fri Sat))[$t[6]], $t[3], (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$t[4]], $t[5]+1900, $t[2], $t[1], $t[0]); $cook = "name<>$in{'name'}<>email<>$in{'email'}<>color<>$in{'color'}<>retime<>$in{'retime'}<>line<>$in{'line'}"; print "Set-Cookie: COMCHAT=$cook; expires=$gmt\n"; } #------------------# # クッキーを取得 # #------------------# sub get_cookie { local($key, $val, @cook); @cook = split(/;/, $ENV{'HTTP_COOKIE'}); foreach (@cook) { ($key, $val) = split(/=/); $key =~ s/\s//g; $tmp{$key} = $val; } %ck = split(/<>/, $tmp{'COMCHAT'}); } #------------------# # エラー表示処理 # #------------------# sub error { &unlock if ($lockkey); &header; print "\n$body\n"; print "

ERROR !

\n"; print "$_[0]
\n"; print "\n\n"; exit; } #--------------# # ロック処理 # #--------------# sub lock { # 1分以上古いロックは削除する if (-e $lockfile) { ($mtime) = (stat($lockfile))[9]; if ($mtime < time - 60) { &unlock; } } local($retry) = 5; # symlink関数式ロック if ($lockkey == 1) { while (!symlink(".", $lockfile)) { if (--$retry <= 0) { &error('Lock is busy'); } sleep(1); } # mkdir関数式ロック } elsif ($lockkey == 2) { while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error('Lock is busy'); } sleep(1); } } } #--------------# # ロック解除 # #--------------# sub unlock { if ($lockkey == 1) { unlink($lockfile); } elsif ($lockkey == 2) { rmdir($lockfile); } } #--------------# # 在室者処理 # #--------------# sub member { open(IN,"$memfile") || &error("Open Error : $memfile"); @data = ; close(IN); $member=""; @new=(); $flag=0; $flag2=0; foreach (@data) { ($time2,$name2,$host2) = split(/<>/); # 60秒以上発言のない者は削除 if ($times-60 > $time2) { next; } elsif ($host2 eq "$host") { # 退室者は削除 if ($_[0] eq 'bye') { next; } # ホスト名が同一であれば時間と名前を更新 $_ = "$times<>$in{'name'}<>$host<>\n"; $name2 = $in{'name'}; $flag=1; } # 更新用配列 @new に追加 if ($name2 ne "$host2") { push(@new,$_); # 参加者表示用文字列を作成 if (!$flag2) { $member .= "$name2◇"; $flag2=1; } else { $member .= "$name2◆"; $flag2=0; } } } # 新規参加者を追加 if (!$flag && !$bye) { if ($in{'name'} ne "$host") { push(@new,"$times<>$in{'name'}<>$host<>\n"); if (!$flag2) { $member .= "$in{'name'}◇"; } else { $member .= "$in{'name'}◆"; } } } # 参加者数を認識 $num = @new; # ファイル更新 if ($mode || $in{'retime'}) { open(OUT,">$memfile") || &error("Write Error : $memfile"); eval "flock(OUT,2);"; truncate(OUT,0); seek(OUT,0,0); print OUT @new; close(OUT); } } #--------------------------------# # IPアドレスによるアクセス拒否 # #--------------------------------# sub deny { local($flag)=0; open(IN,"$denyfile") || &error("Open Error : $denyfile"); while () { s/\n//g; next if (!$_); s/\*/\.\*/g; if ($host =~ /$_/i) { $flag=1; last; } } close(IN); &error('申し訳ありませんが現在ご利用できません') if ($flag); } #----------------------# # 発言ランキング処理 # #----------------------# sub ranking { open(IN,"$rankfile") || &error("Open Error : $rankfile"); @rank = ; close(IN); $rflag=0; @new=(); foreach (@rank) { ($r_name,$r_kaisu,$r_time) = split(/<>/); if ($times - $r_time > $limit*24*60*60) { $_=''; next; } if ($r_name eq "$in{'name'}") { $rflag=1; $r_kaisu++; $_ = "$r_name<>$r_kaisu<>$times<>\n"; } push(@new,$_); } if ($rflag == 0) { unshift(@new,"$in{'name'}<>1<>$times<>\n"); } open(OUT,">$rankfile") || &error("Write Error : $rankfile"); print OUT @new; close(OUT); } #-----------------# # URLエンコード # #-----------------# sub url_enc { local($_) = @_; s/(\W)/'%' . unpack('H2', $1)/eg; s/\s/+/g; $_; }