#!/usr/bin/perl
###############################################
# vote5.cgi
# V2.0 (2005.7.12)
# Copyright(C) CGI-design
###############################################
require './cgi-lib.pl';
$script = 'vote5.cgi';
$base = './votedata'; #データ格納ディレクトリ
$entfile = "$base/ent.txt"; #登録データ
$nofile = "$base/no.txt"; #登録番号
$opfile = "$base/option.txt"; #オプション
$lockfile = "$base/lock"; #ロック
$cgi_lib'maxdata = 200000; #入力最大容量(byte)
open (IN,"$opfile") || &error("OPEN ERROR"); $opdata = <IN>; close IN;
if (!$opdata) {
$pass = &crypt('cgi');
chmod(0666,$opfile); open (OUT,">$opfile") || &error("OPEN ERROR");
print OUT "$pass<>画像投票<><><>$base<>$base<><><><>#fafaf5<>#000000<>#5A6D45<>#c00000<>#000000<>#5A6D45<>#CAD8CB<>140<>140<>4";
close OUT;
chmod(0666,$entfile); chmod(0666,$nofile);
}
### メイン処理 ###
&ReadParse;
$mode = $in{'mode'};
open (IN,"$opfile") || &error("OPEN ERROR");
($pass,$title,$com_adm,$home,$savedir,$loaddir,$bg_img,$home_icon,$title_icon,$bg_color,$text_color,$title_color,$rank_color,$cnt_color,$sub_color,$ent_color,$max_w,$max_h,$imgcols) = split(/<>/,<IN>);
close IN;
if ($mode eq 'admin') {&admin;} else {&main;}
print "</center></body></html>\n";
exit;
###
sub header {
print "Content-type: text/html\n\n";
print "<html><head><META HTTP-EQUIV=\"Content-type\" CONTENT=\"text/html; charset=Shift_JIS\">\n";
print "<title>$title</title><link rel=\"stylesheet\" type=\"text/css\" href=\"$loaddir/style.css\"></head>\n";
$head = 1;
}
###
sub main {
if ($mode eq 'cnt') {&cnt;}
&header;
print "<body background=\"$loaddir/$bg_img\" bgcolor=\"$bg_color\" text=\"$text_color\"><center>\n";
print "<table width=98%><tr><td width=120 valign=top>";
if ($home) {if ($home_icon) {print "<a href=\"$home\"><img src=\"$loaddir/$home_icon\" border=0></a>";} else {print "<a href=\"$home\">[HOME]</a>";}}
print "</td><td align=center>";
if ($title_icon) {print "<img src=\"$loaddir/$title_icon\">";} else {print "<font color=\"$title_color\" size=\"+1\"><b>$title</b></font>";}
print "</td><td width=120></td></tr></table>\n";
print "<table><tr><td>$com_adm</td></tr></table>\n";
&ranking;
print "<table width=97%><tr><td align=right><a href=\"$script?mode=admin\">[編集]</a></td></tr></table>\n";
# 次の行は著作権表示ですので削除しないで下さい。#
print "<a href=\"http://merlion.cool.ne.jp/cgi/\" target=\"_blank\">CGI-design</a>\n";
}
###
sub cnt {
$addr = $ENV{'REMOTE_ADDR'};
$cntfile = "$base/$in{'no'}.txt";
&lock;
open (IN,"$cntfile") || &error("OPEN ERROR"); ($cnt,$paddr) = split(/<>/,<IN>); close IN;
if ($addr ne $paddr) {
$cnt++;
open (OUT,">$cntfile") || &error("OPEN ERROR"); print OUT "$cnt<>$addr"; close OUT;
}
&unlock;
}
###
sub ranking {
open (IN,"$entfile") || &error("OPEN ERROR");
while(<IN>) {
($no) = split(/<>/);
$data{$no} = $_;
open (INC,"$base/$no.txt") || &error("OPEN ERROR"); ($rank{$no}) = split(/<>/,<INC>); close INC;
}
close IN;
if ($imgcols == 0) {$imgcols = 4;}
$perw = int(100 / $imgcols);
$k=$n=$pcnt=0;
print "<table cellspacing=8 cellpadding=10>\n";
foreach (sort{$rank{$b} <=> $rank{$a}} keys(%rank)) {
$cnt = $rank{$_};
($no,$img_type,$img_w,$img_h,$img_big,$sub) = split(/<>/,$data{$_});
if (!$k) {print "<tr bgcolor=\"$ent_color\">\n";}
if ($cnt != $pcnt) {$rank = $n + 1; $pcnt = $cnt;}
if ($mode eq 'admin' && $in{$no}) {print "<td bgcolor=\"#ffff00\" width=$perw% height=100%>";} else {print "<td width=$perw% height=100%>";}
print "<table width=100% height=100% cellpadding=0><col span=1 align=center>\n";
if ($mode eq 'admin') {print "<tr><td height=20><input type=submit name=$no value=\"修正\"></td></tr>\n";}
print "<tr><td height=10><font color=\"$rank_color\"><b>$rank位</b></font> <font color=\"$cnt_color\">($cnt票)</font></td></tr><tr><td>\n";
$imgfile = "$loaddir/$no.$img_type";
$imgsrc = "<img src=\"$imgfile\" border=0 width=$img_w height=$img_h vspace=2>";
if ($img_big) {print "<a href=\"$imgfile\" target=\"_blank\">$imgsrc</a>";} else {print $imgsrc;}
print "<br><font color=\"$sub_color\"><b>$sub</b></font></td></tr>\n";
if ($mode ne 'admin') {
print "<tr><td height=20><form action=\"$script\" method=POST>\n";
print "<input type=hidden name=mode value=\"cnt\">\n";
print "<input type=hidden name=no value=\"$no\">\n";
print "<input type=submit value=\"投票\"></td></form></tr>\n";
}
print "</table></td>\n";
$n++;
$k++;
if ($k == $imgcols) {print "</tr>\n"; $k = 0;}
}
if ($k) {
for ($k+1 .. $imgcols) {print "<td></td>";}
print "</tr>";
}
print "</table>\n";
}
###
sub admin {
&header;
print "<body><center>\n";
$inpass = $in{'pass'};
if ($inpass eq '') {
print "<table width=97%><tr><td><a href=\"$script\">[Return]</a></td></tr></table>\n";
print "<br><br><br><br><h4>パスワードを入力して下さい</h4>\n";
print "<form action=\"$script\" method=\"POST\">\n";
print "<input type=hidden name=mode value=\"admin\">\n";
print "<input type=password name=pass size=10 maxlength=8>\n";
print "<input type=submit value=\" 認証 \"></form>\n";
print "</center></body></html>\n";
exit;
}
$mat = &decrypt($inpass,$pass);
if (!$mat) {&error("パスワードが違います");}
print "<table width=95% bgcolor=\"#8c4600\"><tr><td> <a href=\"$script\"><font color=\"#ffffff\"><b>Return</b></font></a></td>\n";
print "<td align=right><form action=\"$script\" method=POST>\n";
print "<input type=hidden name=mode value=\"admin\">\n";
print "<input type=hidden name=pass value=\"$inpass\">\n";
print "<input type=submit value=\"新規/修正\">\n";
print "<input type=submit name=set value=\"基本設定\"></td></form><td width=10></td></tr></table><br>\n";
$wrt = $in{'wrt'};
if ($in{'set'}) {&setup;} else {&edtin;}
}
###
sub edtin {
if ($in{'newwrt'}) {&newwrt;}
elsif ($in{'edtwrt'}) {&edtwrt;}
elsif ($in{'delwrt'}) {&delwrt;}
&in_form;
print "<form action=\"$script\" method=POST>\n";
print "<input type=hidden name=mode value=\"admin\">\n";
print "<input type=hidden name=pass value=\"$inpass\">\n";
print "<input type=hidden name=edt value=\"1\">\n";
print "<hr width=90%>修正、削除する場合は[修正]をクリックして下さい。\n";
&ranking;
print "</form>\n";
}
###
sub in_form {
print "<form action=\"$script\" method=POST enctype=\"multipart/form-data\">\n";
print "<input type=hidden name=mode value=\"admin\">\n";
print "<input type=hidden name=pass value=\"$inpass\">\n";
if ($in{'edt'}) {
open (IN,"$entfile") || &error("OPEN ERROR");
while (<IN>) {
($no,$img_type,$img_w,$img_h,$img_big,$sub) = split(/<>/);
if ($in{$no}) {last;}
}
close IN;
print "<input type=hidden name=no value=\"$no\">\n";
} else {$sub = '';}
print "<table bgcolor=\"#e6e4ce\" cellspacing=8><tr><td><table cellspacing=1 cellpadding=0>\n";
print "<tr><td>題名 </td><td><input type=text size=40 name=sub value=\"$sub\" style=\"ime-mode:active;\"></td></tr>\n";
print "<tr><td>画像</td><td><input type=file size=60 name=img></td></tr>\n";
print "<tr><td></td><td>";
if ($in{'edt'}) {
print "<table width=200><tr><td><input type=submit name=edtwrt value=\"修正する\"></td>\n";
print "<td width=40 bgcolor=red align=center><input type=submit name=delwrt value=\"削除\"></td></tr></table>\n";
} else {print "<input type=submit name=newwrt value=\"新規登録\">";}
print "</td></tr></table></td></tr></table></form>\n";
}
###
sub newwrt {
if (!$in{'img'}) {&error("画像を入力して下さい");}
&lock;
open (IN,"$nofile") || &error("OPEN ERROR"); $no = <IN>; close IN;
$no++;
open (OUT,">$nofile") || &error("OPEN ERROR"); print OUT $no; close OUT;
&img("$savedir/$no",'img');
open (OUT,">>$entfile") || &error("OPEN ERROR"); print OUT "$no<>$type<>$width<>$height<>$big<>$in{'sub'}<>\n"; close OUT;
$cntfile = "$base/$no.txt";
open (OUT,">$cntfile") || &error("OPEN ERROR"); print OUT "0<>"; close OUT; chmod(0666,$cntfile);
&unlock;
}
###
sub edtwrt {
&img("$savedir/$in{'no'}",'img');
&lock;
@new = ();
open (IN,"$entfile") || &error("OPEN ERROR");
while (<IN>) {
($no,$img_type,$img_w,$img_h,$img_big) = split(/<>/);
if ($no eq $in{'no'}) {
if ($type) {$img_type = $type; $img_w = $width; $img_h = $height; $img_big = $big;}
push(@new,"$no<>$img_type<>$img_w<>$img_h<>$img_big<>$in{'sub'}<>\n");
} else {push(@new,$_);}
}
close IN;
open (OUT,">$entfile") || &error("OPEN ERROR"); print OUT @new; close OUT;
&unlock;
}
###
sub delwrt {
&lock;
@new = ();
open (IN,"$entfile") || &error("OPEN ERROR");
while (<IN>) {
($no,$img_type) = split(/<>/);
if ($no eq $in{'no'}) {
unlink "$savedir/$no.$img_type";
unlink "$base/$no.txt";
} else {push(@new,$_);}
}
close IN;
open (OUT,">$entfile") || &error("OPEN ERROR"); print OUT @new; close OUT;
&unlock;
}
###
sub setup {
if ($wrt) {
if ($in{'newpass'} ne '') {$pass = &crypt($in{'newpass'});}
$title = $in{'title'};
$com_adm = $in{'com_adm'}; $com_adm =~ s/\r\n|\r|\n/<br>/g;
$home = $in{'home'};
$savedir = $in{'savedir'};
$loaddir = $in{'loaddir'};
$icon = $in{'icon'};
if ($icon) {
&img("$savedir/$icon",'img');
if ($type) {$icontype = "$icon.$type";} else {$icontype = '';}
if ($icon eq 'wall') {$bg_img = $icontype;}
elsif ($icon eq 'home') {$home_icon = $icontype;}
elsif ($icon eq 'title') {$title_icon = $icontype;}
}
$bg_color = $in{'color0'};
$text_color = $in{'color1'};
$title_color = $in{'color2'};
$rank_color = $in{'color3'};
$cnt_color = $in{'color4'};
$sub_color = $in{'color5'};
$ent_color = $in{'color6'};
$max_w = $in{'max_w'};
$max_h = $in{'max_h'};
$imgcols = $in{'imgcols'};
open (OUT,">$opfile") || &error("OPEN ERROR");
print OUT "$pass<>$title<>$com_adm<>$home<>$savedir<>$loaddir<>$bg_img<>$home_icon<>$title_icon<>$bg_color<>$text_color<>$title_color<>$rank_color<>$cnt_color<>$sub_color<>$ent_color<>$max_w<>$max_h<>$imgcols";
close OUT;
}
print "下記に入力後、「設定する」を押して下さい。\n";
print "<form action=\"$script\" method=POST enctype=\"multipart/form-data\">\n";
print "<input type=hidden name=mode value=\"admin\">\n";
print "<input type=hidden name=pass value=\"$inpass\">\n";
print "<input type=hidden name=set value=\"1\">\n";
print "<input type=submit name=wrt value=\"設定する\"><br><br>\n";
print "<table bgcolor=\"#dddddd\" cellspacing=10><tr><td><table cellspacing=1 cellpadding=0>\n";
print "<tr><td><b>タイトル</b></td><td><input type=text size=40 name=title value=\"$title\" style=\"ime-mode:active;\"></td></tr>\n";
$com_adm =~ s/<br>/\r/g;
print "<tr><td valign=top><br><b>コメント</b></td><td><textarea cols=60 rows=6 name=com_adm style=\"ime-mode:active;\">$com_adm</textarea></td></tr>\n";
print "<tr><td><b>ホームURL</b></td><td><input type=text size=60 name=home value=\"$home\"></td></tr>\n";
print "<tr><td><b>画像格納ディレクトリ</b></td><td><input type=text size=60 name=savedir value=\"$savedir\"></td></tr>\n";
print "<tr><td><b>画像読出ディレクトリ</b></td><td><input type=text size=60 name=loaddir value=\"$loaddir\"></td></tr>\n";
@name = ('壁紙','ホーム','タイトル');
@data = ($bg_img,$home_icon,$title_icon);
@icon = ('wall','home','title');
print "<tr><td valign=top><br><b>壁紙、アイコン</b></td><td>\n";
for (0 .. $#name) {
print "<input type=radio name=icon value=\"$icon[$_]\">$name[$_]";
if ($data[$_]) {
if ($_) {$w = '';} else {$w = ' width=30';}
print " <img src=\"$loaddir/$data[$_]\"$w> ";
} else {print "(無) ";}
}
print "<br><input type=file size=60 name=img></td></tr>\n";
print "<tr><td></td><td><a href=\"$loaddir/color.htm\" target=\"_blank\">カラーコード</a></td></tr>\n";
@name = ('基本背景色','基本文字色','タイトル色','順位色','得票色','題名色','画像背景色');
@data = ($bg_color,$text_color,$title_color,$rank_color,$cnt_color,$sub_color,$ent_color);
for (0 .. $#name) {
print "<tr><td><b>$name[$_]</b></td><td><table cellspacing=0 cellpadding=0><tr>\n";
print "<td><input type=text size=10 name=color$_ value=\"$data[$_]\" style=\"ime-mode:inactive;\"></td>\n";
print "<td width=5></td><td width=80 bgcolor=\"$data[$_]\"></td></tr></table></td></tr>\n";
}
print "<tr><td><b>画像表\示</b></td><td>横max<input type=text size=4 name=max_w value=\"$max_w\" style=\"text-align:right; ime-mode:disabled;\">px 縦max<input type=text size=4 name=max_h value=\"$max_h\" style=\"text-align:right; ime-mode:disabled;\">px\n";
print " <input type=text size=3 name=imgcols value=\"$imgcols\" style=\"text-align:right; ime-mode:disabled;\">列</td></tr>\n";
print "<tr><td><b>パスワード変更</b></td><td><input type=password name=newpass size=10 maxlength=8> (英数8文字以内)</td></tr>\n";
print "</table></td></tr></table></form>\n";
}
###
sub img {
$type=$width=$height=$big=$mac='';
$imgdata = $in{"$_[1]"};
if (!$imgdata) {return;}
foreach (@in) {
if (/$_[1]/ and /Content-Type:(.+)/i) {
if ($1 =~ /image\/.*jpeg/i) {$type = 'jpg';}
elsif ($1 =~ /image\/gif/i) {$type = 'gif';}
elsif ($1 =~ /image\/.*png/i) {$type = 'png';}
}
if (/application\/x-macbinary/i) {$mac = 1;}
}
if (!$type) {&error("このファイルはアップロードできません");}
if ($mac) {
$leng = substr($imgdata,83,4);
$leng = unpack("%N",$leng);
$imgdata = substr($imgdata,128,$leng);
}
$img_file = "$_[0].$type";
open (IMG,">$img_file") || &error("$img_fileファイルを作成できません");
binmode IMG;
print IMG $imgdata;
close IMG;
chmod (0666,$img_file);
($t,$width,$height) = &getImageSize("$img_file");
if (!$width || !$height) {&error("ファイルを認識できません");}
$big = 0;
if ($max_w && $max_w < $width) {$rate_w = $max_w / $width; $big = 1;} else {$rate_w = 1;}
if ($max_h && $max_h < $height) {$rate_h = $max_h / $height; $big = 1;} else {$rate_h = 1;}
if ($big) {
if ($rate_w < $rate_h) {$rate = $rate_w;} else {$rate = $rate_h;}
$width = int($width * $rate);
$height = int($height * $rate);
}
}
#=========================================
# Get Image Pixel Size.(出典:stdio-902)
#=========================================
sub getImageSize {
local($file_name) = @_;
local($head);
return if (!open IMG, $file_name);
binmode IMG;
read IMG, $head, 8;
if ($head eq "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a") {
local($width, $height);
if (read(IMG, $head, 4) != 4 || read(IMG, $head, 4) != 4 || $head ne 'IHDR') {
close IMG;
return "PNG", 0;
}
read IMG, $head, 8;
close IMG;
$width = unpack "N", substr($head, 0, 4);
$height = unpack "N", substr($head, 4, 4);
return "PNG", $width, $height;
}
$head = substr $head, 0, 3;
if ($head eq "\x47\x49\x46") {
local($head, $width, $height);
seek IMG, 6, 0;
read IMG, $head, 4;
close IMG;
($width, $height) = unpack "vv", $head;
return "GIF", $width, $height;
}
$head = substr $head, 0, 2;
if ($head eq "\xff\xd8") {
local($head, $width, $height, $w1, $w2, $h1, $h2, $l1, $l2, $length);
seek IMG, 2, 0;
while (read IMG, $head, 1) {
last if ($head eq "");
if ($head eq "\xff") {
$head = getc IMG;
if ($head =~ /^[\xc0-\xc3\xc5-\xcf]$/) {
seek IMG, 3, 1;
last if (read(IMG, $head, 4) != 4);
close IMG;
($h1, $h2, $w1, $w2) = unpack "C4", $head;
$height = $h1 * 256 + $h2;
$width = $w1 * 256 + $w2;
return "JPG", $width, $height;
} elsif ($head eq "\xd9" || $head eq "\xda") {
last;
} else {
last if (read(IMG, $head, 2) != 2);
($l1, $l2) = unpack "CC", $head;
$length = $l1 * 256 + $l2;
seek IMG, $length - 2, 1;
}
}
}
close IMG;
return "JPG", 0;
}
return 0;
}
###
sub lock {
$retry = 3;
if (-e $lockfile) {
$locktime = (stat($lockfile))[9];
if ($locktime < time - 60) {&unlock;}
}
while (!mkdir($lockfile, 0755)) {
if (--$retry < 0) {&error("busy!");}
sleep(1);
}
}
###
sub unlock {rmdir($lockfile);}
###
sub crypt {
@salt = ('a' .. 'z','A' .. 'Z','0' .. '9');
srand;
$salt = "$salt[int(rand($#salt))]$salt[int(rand($#salt))]";
return crypt($_[0],$salt);
}
###
sub decrypt {
$salt = $_[1] =~ /^\$1\$(.*)\$/ && $1 || substr($_[1],0,2);
if (crypt($_[0],$salt) eq $_[1] || crypt($_[0],'$1$' . $salt) eq $_[1]) {return 1;}
return 0;
}
###
sub error {
if (!$head) {&header; print "<body><center>\n";}
print "<br><br><br><br><h3>ERROR !!</h3><font color=red><b>$_[0]</b></font>\n";
print "</center></body></html>\n";
exit;
}