#!/usr/local/bin/perl
#Lunar+
$SupPaPath = "./spam/";
require $SupPaPath. "spamcheck.cgi";
#┌─────────────────────────────────
#│ E-PAD v2.42 (2006/07/22)
#│ Copyright (c) KentWeb
#│ webmaster@kent-web.com
#│ http://www.kent-web.com/
#└─────────────────────────────────
$ver = 'E-PAD v2.42';
#┌─────────────────────────────────
#│ [注意事項]
#│ 1. このスクリプトはフリーソフトです。このスクリプトを使用した
#│ いかなる損害に対して作者は一切の責任を負いません。
#│ 2. 設置に関する質問はサポート掲示板にお願いいたします。
#│ 直接メールによる質問は一切お受けいたしておりません。
#└─────────────────────────────────
#
# 【ファイル構成例】
#
# public_html (ホームディレクトリ)
# |
# +-- epad / epad.cgi [705]
# | elog.cgi [606]
# | num.dat [606]
# |
# +-- lib / jcode.pl [604]
# | admin.pl [604]
# | ptel.pl [604]
# | pcom.pl [604]
# |
# +-- data / i2e.dat [604]
# | i2j.dat [604]
# | j2e.dat [604]
# |
# +-- img / *.gif
# |
# +-- i / *.gif *.png
# |
# +-- j / *.gif
# |
# +-- e / *.gif *.png
# |
# +-- lock [707] /
#
#-------------------------------------------------
# ▽基本設定
#-------------------------------------------------
# 外部ファイル取り込み
$jcode = './lib/jcode.pl';
$ptel = './lib/ptel.pl';
$pcom = './lib/pcom.pl';
$admin = './lib/admin.pl';
# 掲示板タイプ
# 1 : 標準タイプ(レス機能なし)
# 2 : 返信レス式(レス記事はクリック後に表示)
# 3 : 返信レス式(レス記事は初期画面から表示)
$bbstype = 3;
# 自動ソート
# → 返信時に親記事をトップへ自動ソートする
# 0 : しない
# 1 : する
$topsort = 1;
# タイトル名
$title = "";
# タイトル文字の色
$t_color = "#333333";
# タイトル文字サイズ
$t_size = '16px';
# 本文文字サイズ
$b_size = '10px';
# 本文文字のタイプ
$b_face = "MS UI Gothic, MS Pゴシック, Osaka";
# 記事題名の色
$sub_col = "#333333";
# 記事下地の色 (PCモード時)
$tbl_col = "#ffffff";
# 記事番号の色 (PCモード時)
$num_col = "#333333";
# CGI本体スクリプト (URL)
$script = './epad.cgi';
# ログファイル (サーバパス)
$logfile = './elog.cgi';
# データ番号ファイル (サーバパス)
$numfile = './num.dat';
# 管理用パスワード
$pass = '4669';
# 最大記事数
# → 親記事単位
# → これを超える記事は古い順に削除
$max = 100;
# 戻り先 (URL)
$home = "../index.html";
# bodyタグ (PCモードの場合)
$body = '
';
# URLの自動リンク (0=no 1=yes)
$autolink = 1;
# 1ページ当り記事表示件数
$pageLog = 10; # PCモード
$pageLog2 = 5; # 携帯モード
# ファイルロック形式
# → 0=no 1=symlink関数 2=mkdir関数
$lockkey = 0;
# ロックファイル名
$lockfile = './lock/epad.lock';
# メール通知機能
# 0 : 通知しない
# 1 : 通知する → 自分の投稿記事も通知する
# 2 : 通知する → 自分の投稿記事は通知しない
$mailing = 0;
# メールソフトのパス(メール通知する場合)
$sendmail = '/usr/lib/sendmail';
# メール通知先アドレス(メール通知する場合)
$mailto = 'xxx@xxx.xxx';
# ホスト取得方法
# 0 : gethostbyaddr関数を使わない
# 1 : gethostbyaddr関数を使う
$gethostbyaddr = 0;
# アクセス制限(半角スペースで区切る、アスタリスク可)
# → 拒否ホスト名を記述(後方一致)【例】*.anonymizer.com
$deny_host = '';
# → 拒否IPアドレスを記述(前方一致)【例】210.12.345.*
$deny_addr = '';
# 1回当りの最大投稿サイズ (bytes)
$maxData = 51200;
# 同一IPアドレスからの連続投稿時間(秒数)
# → 連続投稿などの荒らし対策
# → 値を 0 にするとこの機能は無効
$wait = 60;
# 禁止ワード
# → 投稿時禁止するワードをコンマで区切る
$no_wd = '';
# 日本語チェック(投稿時日本語が含まれていなければ拒否する)
# 0=No 1=Yes
$jp_wd = 0;
# URL個数チェック
# → 投稿コメント中に含まれるURL個数の最大値
$urlnum = 3;
# 一般画像ディレクトリURL
$imgurl = './img';
# i-mode画像ディレクトリURL
$img_i = './i';
# vodafone画像ディレクトリURL
$img_j = './j';
# EZweb画像ディレクトリURL
$img_e = './e';
# コメント部投稿データ制限(バイト)
$maxdata = 1000;
# ヘッダのContent-Lengthを表示する
# → 0=no 1=yes
# → 無料HPサービス等で広告バナーが自動表示される場合にはNOとする
$cont_len = 1;
# 絵文字変換データディレクトリ
$emodir = './data';
#-------------------------------------------------
# △設定完了
#-------------------------------------------------
&agent;
&decode;
&axscheck;
if ($mode eq 'regist') { ®ist; }
elsif ($mode eq 'find') { &find; }
elsif ($mode eq 'howto') { &howto; }
elsif ($mode eq 'admin') { require $admin; &admin; }
elsif ($mode eq 'usrdel') { &usrdel; }
elsif ($mode eq 'popup') { &popup; }
elsif ($mode eq 'check') { ✓ }
&html;
#-------------------------------------------------
# 機種チェック
#-------------------------------------------------
sub agent {
# 機種情報
local($agent) = $ENV{'HTTP_USER_AGENT'};
# jcode.pl使用フラグ
$jflag=1; #Lunar++
require $jcode; #Lunar++
# i-mode
if ($agent =~ /DoCoMo/i) {
$type = 'i';
$method = 'post';
$button = 'accesskey';
$emo1 = '驪';
$emo2 = '麗';
$emo3 = '黎';
$emo4 = '力';
$emo5 = '曆';
$meta = '';
require $ptel;
# vodafone
} elsif ($agent =~ m|J-PHONE/[^\/]+/([^\/]+)|i || $agent =~ /Vodafone/|i || $agent =~ /^MOT\-/|i) {
$type = 'j';
# $model = $1; # 機種
# if ($model =~ /51/) { $model=51; } else { $model=0; }
$method = 'get';
$button = 'DIRECTKEY';
$emo1 = pack('H2H2','1B','24') . 'F' . pack('H2','3c') . pack('H2','0F');
$emo2 = pack('H2H2','1B','24') . 'F' . pack('H2','3d') . pack('H2','0F');
$emo3 = pack('H2H2','1B','24') . 'F' . pack('H2','3e') . pack('H2','0F');
$emo4 = pack('H2H2','1B','24') . 'F' . pack('H2','3f') . pack('H2','0F');
$emo5 = pack('H2H2','1B','24') . 'F' . pack('H2','40') . pack('H2','0F');
$meta = '';
require $ptel;
# EZweb
} elsif ($agent =~ /UP\.Browser/i) {
$type = 'e';
$method = 'get';
$button = 'accesskey';
$emo1 = '
';
$emo2 = '
';
$emo3 = '
';
$emo4 = '
';
$emo5 = '
';
$meta = '';
require $ptel;
# PC
} else {
$type = 'p';
$method = 'post';
$meta = '';
$meta .= "\n\n";
require $pcom;
require $jcode;
$jflag++;
}
}
#-------------------------------------------------
# アクセス制限
#-------------------------------------------------
sub axscheck {
# IP&ホスト取得
$host = $ENV{'REMOTE_HOST'};
$addr = $ENV{'REMOTE_ADDR'};
if ($gethostbyaddr && ($host eq "" || $host eq $addr)) {
$host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2);
}
# IPチェック
local($flg);
foreach ( split(/\s+/, $deny_addr) ) {
s/\./\\\./g;
s/\*/\.\*/g;
if ($addr =~ /^$_/i) { $flg = 1; last; }
}
if ($flg) {
&error("アクセスを許可されていません");
# ホストチェック
} elsif ($host) {
foreach ( split(/\s+/, $deny_host) ) {
s/\./\\\./g;
s/\*/\.\*/g;
if ($host =~ /$_$/i) { $flg = 1; last; }
}
if ($flg) {
&error("アクセスを許可されていません");
}
}
if ($host eq "") { $host = $addr; }
}
#-------------------------------------------------
# 投稿受付
#-------------------------------------------------
sub regist {
&spam::regist($in{'name'},$in{'email'}, $in{'sub'},$in{'comment'}, $in{'url'},
\%in, 0, $type ne 'p'); #Lunar++
local($limit, $pwd, $time, @file, @w);
# データ制限
$limit = $maxdata / 2;
if (length($in{'comment'}) > $maxdata) {
&error("コメントは全角$limit字以内にしてください");
}
# チェック
if ($no_wd) { &no_wd; }
if ($jp_wd) { &jp_wd; }
if ($urlnum > 0) { &urlnum; }
# フォーム内容チェック
local($err);
if ($in{'name'} eq "") { $err .= "名前が未入力です
\n"; }
if ($in{'comment'} eq "") { $err .= "コメントが未入力です
\n"; }
if ($in{'email'} && $in{'email'} !~ /^[\w\.\-]+\@[\w\.\-]+\.[a-zA-Z]{2,6}$/) {
$err .= "Eメールの入力内容が不正です
";
}
if ($err) { &error($err); }
if ($in{'url'} eq "http://") { $in{'url'} = ""; }
if ($in{'sub'} eq "") { $in{'sub'} = "無題"; }
# ロック開始
&lock if ($lockkey);
# データ読み込み
open(IN,"$logfile") || &error("Open Error: $logfile");
@file = ;
close(IN);
open(IN,"$numfile") || &error("Open Error: $numfile");
$num = ;
close(IN);
($no,$tim,$hos) = split(/<>/, $num);
$no++;
# 重複投稿チェック
$time = time;
# 同一ホスト連続投稿チェック
if ($host eq $hos && $wait > $time - $tim) {
&error("連続投稿はもうしばらく時間をおいて下さい");
}
# 削除キー暗号化
if ($in{'pwd'} ne "") { $pwd = &encrypt($in{'pwd'}); }
# 日時取得
$date = &get_time($time, 'p');
# 絵文字処理
$in{'sub'} = &emoji($in{'sub'});
$in{'name'} = &emoji($in{'name'});
$in{'comment'} = &emoji($in{'comment'});
# xxxx; を復元
$in{'sub'} =~ s/\&(#\d{5};)/\&$1/ig;
$in{'name'} =~ s/\&(#\d{5};)/\&$1/ig;
$in{'comment'} =~ s/\&(#\d{5};)/\&$1/ig;
# 独自形式を復元
$in{'sub'} =~ s/<(if[0-9a-f][0-9a-f][0-9a-f])>/<$1>/ig;
$in{'name'} =~ s/<(if[0-9a-f][0-9a-f][0-9a-f])>/<$1>/ig;
$in{'comment'} =~ s/<(if[0-9a-f][0-9a-f][0-9a-f])>/<$1>/ig;
# 親記事の場合
if ($in{'res'} eq "") {
$i = 0;
$stop = 0;
foreach (@file) {
($no2,$reno2) = split(/<>/);
$i++;
if ($i > $max-1 && $reno2 eq "") { $stop=1; }
if (!$stop) { push(@data,$_); }
}
unshift(@data,"$no<><>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>$type<>0<>\n");
# レス記事の場合:トップソートあり
} elsif ($in{'res'} && $topsort) {
$f = 0;
$oyaChk = 0;
$match = 0;
@data = ();
@tmp = ();
foreach (@file) {
($no2,$reno2,$dat,$nam,$eml,$sub,$com,$url,$hos,$pw,$tim,$typ,$res) = split(/<>/);
if ($in{'res'} == $no2) {
if ($reno2) { $f++; last; }
$res++;
$oyaChk++;
$match=1;
push(@data,"$no2<>$reno2<>$dat<>$nam<>$eml<>$sub<>$com<>$url<>$hos<>$pw<>$tim<>$typ<>$res<>\n");
} elsif ($in{'res'} == $reno2) {
push(@data,$_);
} elsif ($match == 1 && $in{'res'} != $reno2) {
$match=2;
push(@data,"$no<>$in{'res'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>$type<><>\n");
push(@tmp,$_);
} else { push(@tmp,$_); }
}
if ($f) { &error("不正な返信要求です"); }
if (!$oyaChk) { &error("親記事が存在しません"); }
if ($match == 1) {
push(@data,"$no<>$in{'res'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>$type<><>\n");
}
push(@data,@tmp);
# レス記事の場合:トップソートなし
} else {
$f = 0;
$oyaChk = 0;
$match = 0;
@data = ();
foreach (@file) {
($no2,$reno2,$dat,$nam,$eml,$sub,$com,$url,$hos,$pw,$tim,$typ,$res) = split(/<>/);
if ($in{'res'} == $no2) {
$oyaChk++;
$res++;
$_ = "$no2<>$reno2<>$dat<>$nam<>$eml<>$sub<>$com<>$url<>$hos<>$pw<>$tim<>$typ<>$res<>\n";
}
if ($match == 0 && $in{'res'} == $no2) {
if ($reno2) { $f++; last; }
$match=1;
} elsif ($match == 1 && $in{'res'} != $reno2) {
$match=2;
push(@data,"$no<>$in{'res'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>$type<><>\n");
}
push(@data,$_);
}
if ($f) { &error("不正な返信要求です"); }
if (!$oyaChk) { &error("親記事が存在しません"); }
if ($match == 1) {
push(@data,"$no<>$in{'res'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>$type<><>\n");
}
}
# 更新
open(OUT,">$logfile") || &error("Write Error: $logfile");
print OUT @data;
close(OUT);
open(OUT,">$numfile") || &error("Write Error: $numfile");
print OUT "$no<>$time<>$host";
close(OUT);
# ロック解除
&unlock if ($lockkey);
# メール通知
if ($mailing == 1 || ($mailing == 2 && $in{'email'} ne $mailto)) { &mail_to; }
# 投稿後メッセージ
if ($type eq 'p') {
# クッキー記憶
&set_cookie($in{'cook'},$in{'name'},$in{'email'},$in{'url'},$in{'pwd'});
&header;
print "
\n";
print "投稿は正常に処理されました
\n";
print "\n";
print "
\n";
} else {
&header;
print "投稿完了
戻る\n";
}
print "