#!/usr/bin/perl
#============================================
#newsup.cgi
#News.up Board
#Copyright (C) 2005,by p.ink
#All rights reserved
#Script written by Maruyama Toru (p.ink)
#Web Site : http://pink.obi.ne.jp

#Edition. 		2006.4.18		v1.8 メッセージにタグが使えるのを選択可にしました。
#Edition. 		2005.11.7		v1.7 クッキー機能強化
#Edition. 		2005/04/19	v1.6	追加項目の文字化けバグ修正
#(前バージョンとの追加項目データに関しての互換性はありません。)
#Edition. 		2005/03/30	v1.51	tagetタイプミス修正
#Edition. 		2005/03/11	v1.5	バイナリー読み込み改良
#Edition. 		2004/12/9		v1.4
#Edition. 		2004/11/4		v1.3
#Edition. 		2004/10/29
#Edition. 		2004/9/26
#First Edition. 	2004/8/27
#============================================
#☆この書類のタブ幅は、24ptです。
#注意；HTML出力ファイル、各ページ、全てに著作権表示して下さい。
#本スクリプトの特徴は、当サイトで発案した、
#スキンファイルと出力ファイルが同じ、というところです。
#============================================
#☆【ファイル設置例】
#	上位ディレクトリー
#		newsup												[777] 
#	下位ディレクトリー
#		HTM_xxx.html			各スキンファイル			[644]
#		img/xxx.gif			画像ホルダー/画像			[755]/
#		jcode.pl  				変換ファイル				[644]
#		loc/					ロックホルダー				[777]
#		log数字.cgi				ID別ログファイル			[666]
#		newsup.cgi				メインスクリプト			[755]
#		newsupfine.cgi			関連スクリプト				[755]
#		newsupkin数字.cgi		ID別スキン設定ファイル		[755]
#		newsupsearch.cgi		関連スクリプト				[755]
#		past数字/				ID別過去ログホルダー		[777]
#		photo/					アップロードディレクトリー	[777]
#		thumb/					サムネイル画像ディレクトリー[777]

#「outファイル」を置くディレクトリーは「書込み可」に設定します。

#●ID設定
##############################
#IDに英数字で名前を付け順番に「,」で分けて記述して下さい。
#例；ID=1(更新履歴)　ID=2(今週のお薦め)　ID=topic(トピックサイト)
@id = (whatnew,2,topic);

#ID毎の表示する名前。日本語可。
@myid = ("更新履歴","今週のお薦め","注目");

#ID毎のログファイルのパス。各ファイルをアップロード。
@logfile = ("./log1.cgi","./log2.cgi","./log3.cgi");

#ID毎スキン設定ファイルのパス
@skindatafile = ("./newsupkin1.cgi","./newsupkin1.cgi","./newsupkin1.cgi");

#ID毎トップページへ新着上位をサンプル表示します。機能を使うとき	1
@dofine = (1,1,1);

@utarget = ("_blank","_blank","_blank");		#ID毎画像のリンク先ターゲットタグ
@ttarget = ("_blank","_blank","_blank");		#ID毎タイトルのリンク先ターゲットタグ
@mtarget = ("_blank","_blank","_blank");		#ID毎メッセージのリンク先ターゲットタグ

@betitle = (1,0,1);	#ID毎タイトル入力必須の時1
@bemsg = (1,1,0);	#ID毎メッセージ入力必須の時1

#ID毎過去ログ機能を使うとき　1　	使わないとき　0
@pastmode = ("1","1","0");

#ID毎過去ログディレクトリー
@pastdir = ("./past1","./past2","");

#ID毎最大現行ログ数。これ以上は過去ログへ又は削除。
@maxlog = (200,200,20);

#ID毎CGIが１ページに表示する最大ログ数
@pagemax = (15,15,20);

#ID毎HTML出力ページに表示するニュース記事数($pagemaxと、小さい方が有効)
@maxnews = (3,6,20);

#ID毎サムネイル画像のalignタグ
@align = ("align = 'left'","align = 'left'","align = 'left'");

#ID毎HTMLアウトファイルのサムネイル画像のalignタグ
@falign = ("align = 'left'","align = 'left'","align = 'right'");

#ID毎gif/jpeg/png 形式の画像の縦横比率を保ちサムネイル表示するなら1
#それ以外のファイルの場合、固定サイズで表示されます。
@samtype = (1,1,1);

#ID毎サムネイルのwidth、height
#固定なら指定された大きさで、
#縦横比率を保つ時は出来るだけ指定の大きさに近づけます。
@samw = (80,80,140);		#横幅
@samh = (80,80,140);		#高さ

#●基本設定
#######################################
#管理用パスワード
$adminpass = "123";

#本スクリプトの名前
$scriptname = "newsup.cgi";

#スクリプトヘの直リンク
$scripturl = "http://www.sumainokensa.com/topics/newsup.cgi";

#アップロードするディレクトリー
$updir1 = "./photo";											#スクリプトからのパス
$justurl1 = "http://www.sumainokensa.com/topics/photo";		#直リンク

#サムネイルを保管するディレクトリー
#イメージマジックを使わない場合はアップロードディレクトリーと同じにして下さい。
$thumb1 = "./thumb";
$justurl2 = "http://www.sumainokensa.com/topics/thumb";	

#メニューに表示するhomeヘのリンク。http:// からのダイレクトリンク。
$acthome = "http://www.sumainokensa.com/";

#jcode.pl のパス
$jcode = "./jcode.pl";

#●諸設定
$docookie = 1;	#管理パスワードをクッキーで保存する時　1

#クッキーのタイトル
$cookietitle = "newsup_1";		

#グリニッジ標準時からの修正
$areatime = 32400;

#二重投稿を禁止する場合は 1 を設定。
$doublecheck = 1;

#次のどれか一つだけを選択できます。
#メッセージにリンクを付けるときは0
#メッセージにURLが書かれたら自動的にリンクを貼る場合は 1 を設定。
#メッセージにHTMLタグを使うときは2。
$autolink = 1;

#他ページからの投稿を禁止するなら 1 を設定。
$referercheck = 0;

#アクセス拒否をするホストを設定
@acsdeny = ("aaa.bbb.co.jp","xxx.yyy.ne.jp");

#曜日設定
@week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');

#●ファイルアップロード関連
#最大ファイルサイズ	Kb
$maxsize = 200;

#拡張子チェックをするなら1
$excheck = 1;

#アップを許可するファイルの拡張子
@permit = ('gif','jpeg','jpg','jpe','png');

#イメージマジックでサムネイルを作成するなら 1 を設定。
$imagic = "1";

#●メインルーチン
################################
require $jcode;

#ハッシュフォームの設定
$noctbuf = $ENV{"QUERY_STRING"};
if ($noctbuf){
&getdata1;
} elsif($ENV{"CONTENT_LENGTH"} > 0 ) {
&getdata2;
}

#ハッシュフォームからの各パラメーター設定
$act 	= "$form{'act'}";
$page 	= "$form{'page'}";
$no 	= "$form{'no'}";
$title 	= "$form{'title'}";
$pass 	= "$form{'pass'}";
$msg 	= "$form{'msg'}";
$pastno = "$form{'pastno'}";
$srchword = "$form{'srchword'}";
$searchmethod = "$form{'searchmethod'}";
$change = "$form{'change'}";
$mlink = "$form{'mlink'}";
$tlink = "$form{'tlink'}";
$ulink = "$form{'ulink'}";
$id = "$form{'id'}";
$page||=0;

$id = $id[0] if !$id;
#ID別の変数設定
for (0 .. $#id) {if ($id eq $id[$_]){ $idno = $_; }}

$logfile = $logfile[$idno];
$skindatafile = $skindatafile[$idno];
$dofine = $dofine[$idno];
$utarget = $utarget[$idno];
$ttarget = $ttarget[$idno];
$mtarget = $mtarget[$idno];
$betitle = $betitle[$idno];
$bemsg = $bemsg[$idno];
$pastmode = $pastmode[$idno];
$pastdir = $pastdir[$idno];
$maxlog = $maxlog[$idno];
$pagemax = $pagemax[$idno];
$align = $align[$idno];
$samtype = $samtype[$idno];
$samw = $samw[$idno];
$samh = $samh[$idno];
$falign = $falign[$idno];
$maxnews = $maxnews[$idno];
$myid = $myid[$idno];

$acttopview = "./$scriptname?id=$id";
$actsearch = "./$scriptname?id=$id&act=search";
require $skindatafile;

&getenv;

$today = time();

#アクセス制御
foreach (@acsdeny){
	&error("$host は、アクセス制御されています。") if $host =~ /$_/i;}

#サンプルスクリプトとして使うとき
#if (($act eq "newwrite") || ($act eq "modifywrite")|| ($act eq "delete")|| ($act eq "renew")){&error("<br>これはサンプルスクリプトのため、act = $act は、出来ません。");}

if ($act eq "newwrite"){&cookiecheck; &newwrite;}
elsif ($act eq "modesw"){&cookiecheck;  &modesw;}
elsif ($act eq "modifywrite"){&cookiecheck; &modifywrite;}
elsif ($act eq "modify"){&cookiecheck; &modify;}
elsif ($act eq "delete"){&cookiecheck; &delete;}
elsif ($act eq "search"){ require "./newsupsearch.cgi";}
elsif ($act eq "admin"){&cookiecheck; &admin;}
elsif ($act eq "renew"){&cookiecheck; require "./newsupfine.cgi"; &renew;}
elsif ($act eq ""){&topview;}
else{&error("不正なコマンドです。");}

#	●クッキーでパスチェック
#####################
#パスをクッキーでチェックし、無かったらパス入力ウィンドーを表示し、合っていた時もし
#クッキーが合っていたのならそのまま何もせずパスで合っていたのならそのパスをクッキーへ。
sub cookiecheck{
&getcookie;
if (($pass ne $adminpass) && ($cpass ne $adminpass)){

my @selected;
$selected[$idno] = "selected";

foreach (0 .. $#id) {
$options .= "<option value=$id[$_] $selected[$_]>$id[$_]";
}

my $alart =<<ALT;

<form method="post" enctype="multipart/form-data" action="./$scriptname">
<div align=center>
<font size=2>●管理用パスワードを入力して下さい。
</font></div><br>
<center>
<table border=0>
<tr>
	<td nowrap>
		<font size=2>ID = </font></td>
	<td>
	<select name="id" class=input>
	$options
	</select>
	</td>
	<td>&#160;</td>
	<td nowrap>
		<font size=2>pass>></font></td>
	<td nowrap>
		<input type="hidden" name="act" value="$act" >
		<input type="password" name="pass" value="$cpass" maxlength=8 size=9 class=textarea>
		<input type="submit"  value="管理モードへ" class=input>
	</td>
</tr>
</table>
</center>
</form>
ALT
&error($alart);
}

if ($docookie && $pass){
&setcookie;
}

}

#	●バイナリー書込み
#####################
sub imgwrite{

my $a1;
#$first[0] が有るならここへ来る
#@upname = ($upname[1],$upname[2]);		#拡張子付き名前
#@first =($first[1],$first[2]);				#拡張子前の名前
#@filext = ($filext[1],$filext[2]);				#拡張子
#@upfile = ($upfile1,$upfile[2]);			#バイナリデータ
#@updir = ($updir1,$updir2);				#一時アップするディレクトリー$updir1のみ。

for (0 .. $#first){
&error("$upname[$_]のファイルサイズ が $maxsize Kbより大きすぎます。") if length($upfile[$_]) > $maxsize*1024;
}

for (0 .. $#first){
&error(" ファイル名 $upname[$_] には、<br>半角英数字とアンダーバー、ハイフォン、以外の文字が含まれています。<br>スペースも禁止です。") if $upname[$_] =~ /[^0-9a-zA-Z_\-\.]/;
}

if ($excheck){
	for (0 .. $#first){
	&error("ファイル名 $upname[$_] には拡張子がついていません。") if !$filext[$_];
	}
	
	#拡張子のチェック。既に小文字に変換済み。
	$a1=0;
	my $perm;
	
	for (0 .. $#first){
		foreach $perm(@permit){
			if ($perm eq $filext[$_]){$a1=1;last;}
		}
		&error("拡張子 $filext[$_] は添付が許可されていません。種類=$contenttype") if !($a1);
	}
}


for (0 .. $#first){
#同じ名前が有ったら「ファイル名_連番.jpg」という名前にする。
if (-e "$updir1/$upname[$_]"){
	$a1=0;
	for($i=0;$i<=9999;$i++){
		if (!-e "$updir/$first[$_]"."_$i.".$filext[$_]){
			$upname[$_]=$first[$_]."_$i.".$filext[$_];
			$a1=1;last;
			}
		}
	&error("ファイル名 $upname[$_] は重複しているので登録出来ません。") if !($a1);
}
}

#バイナリー書込み	
for (0 .. $#first){
open(IMGOUT,">$updir1/$upname[$_]") || die &error("バイナリーファイル書込み出来ませんでした。「$updir1/$upname[$_]」");;
binmode(IMGOUT);
print IMGOUT $upfile[$_];					#ディスク上のファイルurlの中身
close(IMGOUT);
}

#gifの時のファイル情報
for (0 .. $#first){
if($filext[$_] eq "gif"){
	($width[$_],$height[$_]) = unpack("v*",substr($upfile[$_],6,4));

#pngの時
} elsif ($filext[$_] eq "png"){
	$a1=0;
	while(1){
		$a1+=4;
		last if substr($upfile[$_],$a1,4) eq 'IHDR';		#ディスク上のファイルurlの中身
		last if $a1 > 255;
		}
	($width[$_],$height[$_]) = unpack("N*",substr($upfile[$_],$a1+4,8)) if $a1 < 255;

#jpgの時
} elsif(($filext[$_] eq "jpg") || ($filext[$_] =~ /^jpe/)){
	open(IMGIN,"$updir1/$upname[$_]");
	binmode(IMGIN);
	seek(IMGIN,2,0);									#読み初めの場所
	$a1=0;
	while(1){
		$a1++;
		last if $a1 > 256;
		read(IMGIN,$t,4);								#読み初めの場所から4だけ読む。
		($a3,$a4,$a5) = unpack("C C n",$t);
		if(($a4 > 0xc3) || ($a4 < 0xc0)){
			seek(IMGIN,$a5-2,1);
			}else{
			seek(IMGIN,1,1);
			read(IMGIN,$t,4);
			($height[$_],$width[$_]) = unpack("n*",$t);
			last;
			}
		}
	close(IMGIN);
}
}

#サムネイルの計算。$samw,h　以内にする。
for (0 .. $#first){
($width[$_],$height[$_]) = ($samw,$samh) if !$height[$_] || !$width[$_] || ($samtype == 0);
if (($height[$_] > $samh) || ($width[$_] > $samw)){
		if ($width[$_] >= $height[$_]){
			$height[$_]=int($height[$_]*$samh/$width[$_]);
			$width[$_]=$samw;
			}else{
			$width[$_]=int($width[$_]*$samw/$height[$_]);
			$height[$_]=$samh;
			}
}
$filesize[$_]=int(length($upfile[$_])/102.4)/10;	
}

my ($inimg,$outimg);
if ($imagic){
for (0 .. $#first){
	$inimg=  "$updir1/$upname[$_]";
	$outimg = "$thumb1/$upname[$_]"; 
	
	use Image::Magick;
	
	$i = Image::Magick->new;							#新しい画像を用意
	$i->Read("$inimg");								#Image::Read(filename) 画像ファイルの読込
	$i->Scale(width=>$width[$_],height=>$height[$_]);		#Image::Scale(width,height) 画像のリサイズ 
	$i->Write("$outimg");
#chmod(0644,"$outimg");						#何故かファインダー上でアップファイルが見えないこと有り。
}
}

}
#●データ受け取り1
############################
sub getdata1{
my (@pairs,$pair,$key,$value,$i);

@pairs = split(/&/,$noctbuf);
foreach $i (0 .. $#pairs) {
	($key,$value)= split(/=/,$pairs[$i]);
	$value =~ tr/+/ /;
	$value =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("C",hex($1))/ge;	
# タグ処理
	$value =~ s/&/&amp;/g;
	$value =~ s/\$/＄/g;
	$value =~ s/</&lt;/g;
	$value =~ s/>/&gt;/g;
	$value =~ s/\"/&quot;/g;
	$value =~ s/\'/&#39;/g;
# 改行等処理
	if ($key eq "msg") {
		$value =~ s/\r\n/<br>/g;
		$value =~ s/\r/<br>/g;
		$value =~ s/\n/<br>/g;
	} else {
		$value =~ s/\r//g;
		$value =~ s/\n//g;
	}		
	
	&jcode'convert(*value,"sjis");	
	
	$form{$key} = $value;
}

}
#●データ受け取り2
############################
sub getdata2{

my ($delimiter,$dish);
#アタッチファイル<input name=の名前は必ず "file$uplist" とする。
$uplist = "0";

#変数メモ
#@upname;			#拡張子付き名前
#@first;			#拡張子前の名前
#@filext;			#拡張子
#@upfile;			#バイナリデータ

$delimiter = <STDIN>;
$delimiter =~ s/\r\n//g;
$delimiter =~ s/\r|\n//g;
$lastdelimiter = "$delimiter"."--";

while(<STDIN>){
last if $_ =~ /^$lastdelimiter/;

if($_ =~ /file$uplist/){

	~s/\r\n//;	
	~s/\n//;	
	~s/"//g; 
	($dish,$upname[$uplist]) = split(/filename=/, $_);
	$upname[$uplist] = $1 if $upname[$uplist] =~ /[\\|\/]([0-9a-zA-Z_\-\.]+)$/;		#正しいファイル名
	
	($first[$uplist],$filext[$uplist]) = split(/\./, $upname[$uplist]);
	$filext[$uplist] =~tr /A-Z/a-z/;						#小文字へ変換
	$upfile[$uplist] = '';
	$contenttype = <STDIN>; 								#Content-Typeヘッダー=次の行=
	$contenttype =~s /\r\n//;								#改行を消す。
	$contenttype =~s /\n//;	
	($dish, $contenttype) = split(/\//,$contenttype);		#後ろがアプリタイプ名
	$dish = <STDIN>; 										# 空行。次行は無視
	
	while(<STDIN>){ 
	if ($_ =~ /^$delimiter/){
		$endflag = 1 if $_ =~ /^$lastdelimiter/;
	last;
	}
	
	$upfile[$uplist] .= $_; 
	}

	if ($first[$uplist]){$uplist++;} else { pop (@first); pop (@upname); }

} elsif (($_ =~ /form-data/) && ($_ !~ /file/)) {		#以後データ有るなしは@firstで判断する。

	($dish, $key) = split(/name=/,$_);	
	$key =~s /\r\n//g;
	$key =~s /\r|\n//g;
	$key =~s /"//g;
	
	$dish = <STDIN>; 	
	$value = '';
	while(<STDIN>){
	
	if ($_ =~ /^$delimiter/){
	$endflag = 1 if $_ =~ /^$lastdelimiter/;
	last;
	}
	$value .= $_; 
	}

	
# タグ処理
	$value =~ s/&/&amp;/g;
	$value =~ s/\$/＄/g;
	$value =~ s/</&lt;/g;
	$value =~ s/>/&gt;/g;
	$value =~ s/\"/&quot;/g;
	$value =~ s/\'/&#39;/g; 
# 改行等処理
	if ($key eq "msg") {
		$value =~ s/(\r\n)$//g;
		$value =~ s/\r\n/<br>/g;
		$value =~ s/\r/<br>/g;
		$value =~ s/\n/<br>/g;
	} else {
		$value =~ s/\r//g;
		$value =~ s/\n//g;
	}

	&jcode'convert(*value,"sjis");	

	$form{$key} = $value;


} 

last if $endflag;
}

}

#●環境変数取得
##############################
sub getenv{
$addr = $ENV{"REMOTE_ADDR"};
$host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2);
$host = $ENV{"REMOTE_HOST"} if $host eq "";
$host = $addr if $host eq "";
$referer = $ENV{"HTTP_REFERER"};
}

#	●削除
##########################################
sub delete{
&error("記事番号が指定されていません。") if $no eq "";
local (@data,@logs,$alart,@njname);
my $mflag = "0";
open (IN,"$logfile") || die &error("Open Error : ログファイル＝$logfile");
#一行目処理
my ($xxx,$pastpage, $mcount,$msum) = split(/<>/,scalar(<IN>));
while(<IN>){

	@data = split(/<>/,$_);
	if ($data[0] == $no){

	@njname = split(/,/,$data[5]);
	foreach (@njname){
	unlink("$updir1/$_");				#元画像削除
	unlink("$thumb1/$_") if $imagic;	#サムネイル削除、名前はイメージと同じ。
	}

	$alart =<<ART; 
<b>「$data[3]」</b>を削除しました。
<br>
<center><A HREF="./newsup.cgi?act=admin&id=$id">《管理へ戻る》</A></center>
ART
	$mflag = "1";
	}else{
	push(@logs,$_);
	}

}

if (!$alart){
	close(IN);
	&error("該当記事がありません。");
}
close(IN);

$msum--;
#記事を削除すると次の過去ログの総数はその分減る。$mcount はコントロールしない。

open(WR,">$logfile") || &error("Write Error : $logfile");
print WR "$xxx<>$pastpage<>$mcount<>$msum<>\n";
print WR @logs;
close(WR);

if ($dofine){require "./newsupfine.cgi"; &doit;}

&error($alart);
}

#	●新規書き込み
##########################################
sub newwrite{

&datacheck;

#最初のファイル名が有るなら先ずは書き込む。
if ($first[0]) {
&imgwrite;
$joiname = join (",",@upname);
$joinwidth = join (",",@width);
$joinheight = join (",",@height);
$joinfilesize = join (",",@filesize);
}

my (@data,@vineset,$adds);
my ($mlot,$lastestime,$xno) = (0,0,0);
$lastmsg = "";

#追加項目のデータ
foreach(@addname){$adds .= "$_=$form{$_}><";}
open (IN,"$logfile") || die &error("Open Error : ログ＝$logfile");
#ログファイル１行目
local ($xxx,$pastpage,$mcount)= split(/<>/,scalar(<IN>));
#規定数になったら、データを書き込むと同時に現行ログをコピーした過去ログも作る。
if ($pastpage eq ""){
	$pastpage=0;
	$mcount=1;
}else{
	$mcount++;
	if ($mcount >= $maxlog){
		$pastpage++;
		$mcount=0;
		$pastflag=1;
	}
}

#ログファイル2行目から記事
while(<IN>){
	@data = split(/<>/,$_);
		$mlot++;
		push(@logs,@vineset);				#@logsはグローバル変数
		@vineset=();
	push(@vineset,$_);	
	if ($lastestime < $data[1]){			#ラストデータ
		$lastestime = $data[1];
		$lastmsg = $data[4];
		}
	$xno = $data[0] if $data[0] > $xno;		#ラスト記事番号
}
if (($lastmsg eq $msg) && ($doublecheck)){
	close(IN);
	&error("二重投稿は禁止されています。");
}
close(IN);

$msum = ++$mlot;
$xno++;
#最大保存記事数までは書き込んでいき、最大保存数になったらそれ以上は
#既に過去ログに保存されているので、現行ログには保存しないで無視。
#過去ログを使わない場合、最後の記事は無視
push(@logs,@vineset) if $msum <= $maxlog;
$msum = $maxlog if $msum > $maxlog;

unshift(@logs,"$xno<>$today<>$adds<>$title<>$msg<>$joiname<>$joinwidth<>$joinheight<>$joinfilesize<>$ulink<>$tlink<>$mlink<>\n");

#データ書き込み
open(WR,">$logfile") || &error("Write Error : ログ＝$logfile");
my $xxx = "pink";
print WR "$xxx<>$pastpage<>$mcount<>$msum<>\n";
print WR @logs;
close(WR);
#過去ログ書き込み。$pastpageは、(1、2、3、、、)
	if (($pastflag == 1) && ($pastmode == 1)){
	open (OUT,">$pastdir/pastlog".$pastpage.".dat") || die &error("Open Error : 過去ログ=pastlog");
	print OUT "$xxx<><><>$msum<>\n";
	print OUT @logs;
	close(OUT);
	chmod(0666,"$pastdir/pastlog".$pastpage.".dat");
	}
$nextflag = 1 if $mlot > $pagemax;

if ($dofine){require "./newsupfine.cgi"; &doit;}

my $alart=<<ART;
新規書き込みしました。<br><br>
<A HREF="$scripturl?act=admin&id=$id">
<center>《管理モードへ戻る》</center>
</A>
ART

&error("$alart");
}

#	●管理モード
##########################################
sub admin{

#管理人の時のみ表示


my $mlot = -1;
my (%check,$optionbuf,$viewfile);
$viewfile   = "$logfile";

#次の何件の初期化
$nextflag = 0;
&readskin($mainskin);
&selectview;

#表示開始
print "Content-type:text/html; charset=shift_jis\n\n";

&printform;		#ヘッダとフォーム表示

open (IN,"$viewfile") || die &error("Open Error : ログ=$viewfile");
my @firstline = split(/<>/,scalar(<IN>));
$msum = $firstline[3];	

#記事が規定数以上になったら、そのデータを送る前にループを抜ける
while(<IN>){
	$mlot++;
		if ($mlot >= $pagemax*$page){				#ページ始めの記事
		&printlogs if @logs;
		@logs = ();
			if ($mlot >= $pagemax*($page+1)){		#規定数以上ならぬけて
			$nextflag = 1;
			last;
			}
		push (@logs,$_);						#親記事代入開始
		}
}
close(IN);
&printlogs;		#残りを表示
&printfoot2;



}

#	●フッタ表示設定2
##########################################
sub printfoot2{
#管理モード時
my ($pmark);
#ダイレクト数字ボタンの設定と表示
my $marklist = "";
#表示するページマークの数を計算して、
my $marks = int(($msum - 1) / $pagemax) + 1;
my ($r,$ii);
for ($r = 0; $r < $marks; $r++){
	$ii = $r + 1;
	if ($page == $r){
		$pmark = "$xopen2$ii$xclose2\n";
	} else {
		$pmark = "<a href=\"./$scriptname?page=$r&act=admin&id=$id\">$xopen1$ii$xclose1</a>\n";
	}
	$marklist = "$marklist"."$pmark";
}
my $directbotton = $marklist if $marks > 1;
$foothtml =~ s/\$directbotton/$directbotton/ig;

#ページリンク先の設定
if ($page != 0){
	$pagelink=$page-1;
	$foothtml =~ s/\n([^\n]*)\$prevpage([^\n]*)\n/\n$1.\/$scriptname?page=$pagelink&act=admin&id=$id$2\n/ig;
	}else{
	$foothtml =~ s/\n([^\n]*)\$prevpage([^\n]*)\n/\n/ig;
	}
if ($nextflag){
	$pagelink=$page+1;
	$foothtml =~ s/\n([^\n]*)\$nextpage([^\n]*)\n/\n$1.\/$scriptname?page=$pagelink&act=admin&id=$id$2\n/ig;
	}else{
	$foothtml =~ s/\n([^\n]*)\$nextpage([^\n]*)\n/\n/ig;
	}

#過去ログセレクトボタン表示
if ($pastviewflag){
	$foothtml =~ s/\n([^\n]*)\$selectbuton([^\n]*)\n/\n$1$selectbuton$2\n/ig;
	$foothtml =~ s/\n([^\n]*)\$viewbuton([^\n]*)\n/\n$1$viewbuton$2\n/ig;
}else{
	$foothtml =~ s/\n([^\n]*)\$selectbuton([^\n]*)\n/\n/ig;
	$foothtml =~ s/\n([^\n]*)\$viewbuton([^\n]*)\n/\n/ig;
}

$foothtml =~ s/\n([^\n]*)<form>([^\n]*)\n/\n$1<form method=\"post\" enctype=\"multipart\/form-data\" action=\".\/$scriptname\">
<input type=\"hidden\" name=\"id\" value=\"$id\">$2\n/ig;

print $foothtml;
exit;
}

#	●モディファイ・デリート確認フォーム
##########################################
sub modesw{

my $alart =<<TBL;
<div align=center>
<font size=2>●選択した記事の「編集」、「削除」をします。
</font></div><br>

<center>
<table border=0 CELLSPACING=5>
<tr>
	<form method="post" enctype="multipart/form-data" action="./$scriptname">
	<td nowrap>	
		<input type="hidden" name="act" value="modify">
		<input type="hidden" name="pass" value="$pass">
		<input type="hidden" name="id" value="$id">
		<input type="submit" value="《この記事を編集する》" class=input>
	</td>
<input type="hidden" name="no" value="$no">
</form>

<form method="post" enctype="multipart/form-data" action="./$scriptname">
<input type="hidden" name="pass" value="$pass">
<input type="hidden" name="id" value="$id">
<input type="hidden" name="act" value="delete">
	<td nowrap>
		<input type="submit"  value="《この記事を削除する》" class=input>
	</td>
</tr>
</table>
</center>
<input type="hidden" name="no" value="$no">
</form>

TBL
&error($alart);
}

#	●修正フォーム
##########################################
sub modify{
#指定された記事データを、修正フォームテーブルのvalueの値の中に表示し、act=modfywriteへ渡す準備をする。
my ($adminflg);
local ($ino,$itoday,$iadds,$ititle,$imsg,$ijoiname,$ijoinwidth,$ijoinheight,$ijoinfilesize,$iulink,$itlink,$imlink);

&error("記事番号を入力してください。") if $no eq "";

open (IN,"$logfile") || die &error("Open Error : ログ＝$logfile");
my $cut = <IN>;	
while(<IN>){
if ($_ =~ /^$no<>/){
 ($ino,$itoday,$iadds,$ititle,$imsg,$ijoiname,$ijoinwidth,$ijoinheight,$ijoinfilesize,$iulink,$itlink,$imlink) = split(/<>/,$_);
 $adminflg = 1;
}
}
close(IN);

#フォーム内に表示するために変換
$imsg =~ s/<br>/\r/g;
$imsg =~ s/&quot;/\"/g;
$imsg =~ s/&#39;/\'/g; 
$imsg =~ s/&lt;/</g;
$imsg =~ s/&gt;/>/g;
$imsg =~ s/&amp;/&/g;

&error("該当する記事はありません！") if !$adminflg;

open(IN,"$alartskin") || die &error("Open Error : スキン＝$mainskin");
while(<IN>){$basshtml .= $_;}
close(IN);

&showform2;

#追加項目データ$iaddsの、addname=value|  から得た値を、クッキーと同じように表示する。

my $value = "";
foreach(0 .. $#addname){

	$value = $1 if $iadds =~ /$addname[$_]=([^><]*)></;

if ($addtype[$_] == 0){ 
	$entryform =~ s/(<input type="radio" name="$addname[$_]" value="$value")/$1 checked/i;
} elsif ($addtype[$_] == 1){ 
	$entryform =~ s/(<select name="$addname[$_]".*<option value="$value")>(.*<\/select>)/$1 selected>$2\n/is;
} else {
	$entryform =~ s/(<input type="text" name="$addname[$_]")/$1 value="$value"/i;
}

}


$basshtml =~ s/\$warnings/$entryform/ig;
&printout;
}

#	●修正書き込み
##########################################
sub modifywrite{
&error("修正書込みには、記事番号を入力してください。") if $no eq "";

if ($first[0]) {
&imgwrite;
$joiname = join (",",@upname);
$joinwidth = join (",",@width);
$joinheight = join (",",@height);
$joinfilesize = join (",",@filesize);
}

local (@logs);
my (@temp,$xday,@data);

&datacheck;

#追加項目のデータ
foreach(@addname){$adds .= "$_=$form{$_}><";}

open (IN,"$logfile") || die &error("Open Error : 修正読み込みログ=$logfile");
local ($xxx,$pastpage, $mcount,$msum) = split(/<>/,scalar(<IN>));		#my、は不可
while(<IN>){
	if ($_ =~ /^$no<>/){
	 ($ino,$itoday,$iadds,$ititle,$imsg,$ijoiname,$ijoinwidth,$ijoinheight,$ijoinfilesize,$iulink,$itlink,$imlink)= split(/<>/,$_);
#		0	1		2		3		4		5			6			7			8				9		10		11
			if ($change){$xday = $today;} else {$xday = $itoday;}		#日付も替えるか？
			#画像入力があった場合は前のファイルを全て削除して、新しいファイル名へ替える。
			if ($first[0]){
			@njname = split(/,/,$ijoiname);
				foreach (@njname){
				unlink("$updir1/$_");				#元画像削除
				unlink("$thumb1/$_") if $imagic;	#サムネイル削除、名前はイメージと同じ。
				}
				$ijoiname = $joiname;
				$ijoinwidth = $joinwidth;
				$ijoinheight = $joinheight;
				$ijoinfilesize = $joinfilesize;
			}
			push(@logs,"$ino<>$xday<>$adds<>$title<>$msg<>$ijoiname<>$ijoinwidth<>$ijoinheight<>$ijoinfilesize<>$ulink<>$tlink<>$mlink<>\n");
	}else{
		push(@logs,$_);
	}
}

close (IN);
open(WR,">$logfile") || &error("Write Error : $logfile");
print WR "$xxx<>$pastpage<>$mcount<>$msum<>\n";
print WR @logs;
close (WR);
$nextflag = 1 if $msum > $pagemax;

if ($dofine){require "./newsupfine.cgi"; &doit;}

my $alart=<<ART;
修正しました。<br><br>
<A HREF="$scripturl?act=admin&id=$id">
<center>《管理モードへ戻る》</center>
</A>
ART

&error("$alart");
}

#	●フォームと、コメント表示設定
##########################################
sub printform{
my $printhtml = $headhtml;
local $entryform = "";

$printhtml =~ s/\$id/$id/;
$printhtml =~ s/\$acttopview/$acttopview/;
$printhtml =~ s/\$actsearch/$actsearch/;
$printhtml =~ s/\$acthome/$acthome/;
$printhtml =~ s/\$myid/$myid/;

&showform if $act;
#&error("$entryform");
#ファイルのアラート/コメント表示
if ($pastno){
	$printhtml =~ s/\n([^\n]*)\$pastalart([^\n]*)\n/\n$1$pastalart$2\n/ig;
} else {
	$printhtml =~ s/\n([^\n]*)\$pastalart([^\n]*)\n/\n/ig;
}

$printhtml =~ s/<!--ENTRY FORM-->/$entryform/;

print $printhtml;
}

#	●フッタ表示設定
##########################################
sub printfoot{
my ($pmark);
#ダイレクト数字ボタンの設定と表示
my $marklist = "";
#表示するページマークの数を計算して、
my $marks = int(($msum - 1) / $pagemax) + 1;
my ($r,$ii);
for ($r = 0; $r < $marks; $r++){
	$ii = $r + 1;
	if ($page == $r){
		$pmark = "$xopen2$ii$xclose2\n";
	} else {
		$pmark = "<a href=\"./$scriptname?page=$r&pastno=$pastno&id=$id\">$xopen1$ii$xclose1</a>\n";
	}
	$marklist = "$marklist"."$pmark";
}
my $directbotton = $marklist if $marks > 1;
$foothtml =~ s/\$directbotton/$directbotton/ig;

#ページリンク先の設定
if ($page != 0){
	$pagelink=$page-1;
	$foothtml =~ s/\n([^\n]*)\$prevpage([^\n]*)\n/\n$1.\/$scriptname?page=$pagelink&pastno=$pastno&id=$id$2\n/ig;
	}else{
	$foothtml =~ s/\n([^\n]*)\$prevpage([^\n]*)\n/\n/ig;
	}
if ($nextflag){
	$pagelink=$page+1;
	$foothtml =~ s/\n([^\n]*)\$nextpage([^\n]*)\n/\n$1.\/$scriptname?page=$pagelink&pastno=$pastno&id=$id$2\n/ig;
	}else{
	$foothtml =~ s/\n([^\n]*)\$nextpage([^\n]*)\n/\n/ig;
	}

#過去ログセレクトボタン表示
if ($pastviewflag){
	$foothtml =~ s/\n([^\n]*)\$selectbuton([^\n]*)\n/\n$1$selectbuton$2\n/ig;
	$foothtml =~ s/\n([^\n]*)\$viewbuton([^\n]*)\n/\n$1$viewbuton$2\n/ig;
}else{
	$foothtml =~ s/\n([^\n]*)\$selectbuton([^\n]*)\n/\n/ig;
	$foothtml =~ s/\n([^\n]*)\$viewbuton([^\n]*)\n/\n/ig;
}

$foothtml =~ s/\n([^\n]*)<form>([^\n]*)\n/\n$1<form method=\"post\" enctype=\"multipart\/form-data\" action=\".\/$scriptname\">
<input type=\"hidden\" name=\"id\" value=\"$id\">$2\n/ig;

print $foothtml;
exit;

}

#	●トップビュー表示
##########################################
sub topview{
my $mlot = -1;
my (%check,$optionbuf,$viewfile);

#過去ログの時は、コメントを用意する。検索の時もある。現行ログの時には無い。
if ($pastno == 0){
	$viewfile   = "$logfile";
} else {
	$viewfile  = "$pastdir/pastlog$pastno\.dat";
}

#次の何件の初期化
$nextflag = 0;

&readskin($mainskin);
&selectview;

#表示開始
print "Content-type:text/html; charset=shift_jis\n\n";

&printform;		#ヘッダとフォーム表示

open (IN,"$viewfile") || die &error("Open Error : ログ=$viewfile");
my @firstline = split(/<>/,scalar(<IN>));
$msum = $firstline[3];	
#親記事が規定数以上になったら、そのデータを送る前にループを抜ける
while(<IN>){
	$mlot++;
		if ($mlot >= $pagemax*$page){				#ページ始めの記事
		&printlogs if @logs;
		@logs = ();
			if ($mlot >= $pagemax*($page+1)){		#規定数以上ならぬけて
			$nextflag = 1;
			last;
			}
		push (@logs,$_);						#親記事代入開始
		}
}
close(IN);
&printlogs;		#残りを表示
&printfoot;
}

#●記事の表示
##############################
sub printlogs{
my ($i,$pagelink,$tgt,@data,$mombuf,$mainbuffer);
my $mlot = 1;

foreach (@logs){
@data = split(/<>/,$_);
	$mombuf = $momhtml;			#リセット
	#編集・削除ボタンの表示
	if ($act eq  "admin"){
		$mombuf =~ s/\n([^\n]*)\$scriptname\?act=modesw([^\n]*)\n/\n$1$scriptname?act=modesw&no=$data[0]&id=$id$2\n/i;
	}else{
		$mombuf =~ s/\n([^\n]*)\$scriptname\?act=modesw"?([^\n]*)\n/\n/i;
	}
	
	&transform($mombuf,@data);	
	$mombuf =~ s/<input type="?hidden"? name="?no"?>/<input type="hidden" name="no" value="$data[0]">/i;
	$mlot++;
	$mainbuffer .= $mombuf;		#編集書き込み時１ページ目の表示記事数	
	if ($mlot > $pagemax) {last;}	#新規書込み後に一ページ目を表示するためカウントする
}
print $mainbuffer;
}

#●変数変換
###################################

#記事ごとに変数変換
sub transform{
local ($mombuf,$ino,$itoday,$iadds,$ititle,$imsg,$ijoiname,$ijoinwidth,$ijoinheight,$ijoinfilesize,$iulink,$itlink,$imlink) = @_;
&maketime("$itoday","$timlengs");

#URLには自動的にリンクを行う
if (($autolink == 1) && ($imsg !~ /img src=/i) && ($imsg !~/A HREF=/i)){
	$imsg =~ s/(http:\/\/[a-zA-Z0-9\.\/\-+#_?~&%=^\@:;]+)/<B><A HREF="$1">url<\/A><\/B>/g;
}

if ($autolink == 2){

foreach ($imsg){
$_ =~ s/&amp;/&/g;
$_ =~ s/&quot;/\"/g;
$_ =~ s/&#39;/\'/g; 
$_ =~ s/<br>/\n/g;	
$_ =~ s/&lt;/</g;
$_ =~ s/&gt;/>/g;
}

}


#ファイル情報
my @njname = split(/,/,$ijoiname);
my @njwidth = split(/,/,$ijoinwidth);
my @njheight = split(/,/,$ijoinheight);
my @njfilesize = split(/,/,$ijoinfilesize);

my ($up,$uploads);

#画像のリンク先を、元画像か、$iulinkヘ振り分ける。
if (($iulink eq "" ) && $ijoiname) {
	for (0 .. $#njname){
$up =<<TBL;
	 <A HREF="$justurl1/$njname[$_]" TARGET="$utarget">
	<img src="$justurl2/$njname[$_]" width="$njwidth[$_]" height="$njheight[$_]" border="0" alt="$njfilesize[$_]" $align $xspaces>
	</A>
TBL
	$uploads .= "$up";
	}
} elsif ($iulink) {
	for (0 .. $#njname){
$up =<<TBL;
	 <A HREF="$iulink" TARGET="$utarget">
	<img src="$justurl2/$njname[$_]" width="$njwidth[$_]" height="$njheight[$_]" border="0" alt="$njfilesize[$_]" $align $xspaces>
	</A>
TBL
	$uploads .= "$up";
	}
}


#タイトルリンク先が有ったらタイトルにリンクを付ける。
$ititle = "<A HREF=\"$itlink\" TARGET=\"$ttarget\">$ititle<\/A>" if $itlink;

if ($imlink && $autolink == 0 ){
$imsg = "<A HREF=\"$imlink\" TARGET=\"$mtarget\">$imsg<\/A>" ;
}

$mombuf=~ s/\$uploads/$uploads/ig;
$mombuf=~ s/\$no/$ino/ig;
$mombuf =~ s/\$message/$imsg/ig;
$mombuf =~ s/\$title/$ititle/ig;
$mombuf =~ s/\$time/$timeword/ig;

#追加項目addname="___"  の実際の値を設定
my $value = "";
foreach(@addname){
	$value = $1 if $iadds =~ /$_=([^><]*)></;
	$mombuf =~ s/\$$_/$value/ig;
}

#ニューマーク設定
if ($itoday+$lasttime*3600 > $today){
	$mombuf =~ s/\n([^\n]*)\$newmark([^\n]*)\n/\n$1$newmark$2\n/ig;
} else {$mombuf=~ s/\n([^\n]*)\$newmark([^\n]*)\n/\n/ig;}

$_[0] = $mombuf;	#値を戻す

}

#●スキンファイル読み込み
####################################
sub readskin{
my $skinfile = $_[0];
my $flag = 0;			
#($basshtml,$momhtml) = ("","","");
open(IN,$skinfile) || die &error("スキン $skinfile の読み込みに失敗しました。");
while(<IN>){
	$_ =~ s/\r\n/\n/g;	
	if ($_ =~ /<!--START-->\n/i){
		$flag = 1;	
	}
	elsif ($_ =~ /<!--END-->\n/i){
		$flag = 2;
	}
	
	$headhtml .= $_ if $flag == 0;		#ヘッダ		
	$momhtml .= $_ if $flag == 1;		#<!--START-->記事
	$foothtml .= $_ if $flag == 2;		#<!--END-->フッタ	
}
close(IN);
}


#	●セレクトボタンと、ビューボタンの表示設定
##########################################
#使用中の変数は、my不可
sub selectview{

#過去ログファイルをチェックし、オプションボタン表示$optionbufの設定準備
$pastno ||= 0;
$check[$pastno]="selected";
$pastviewflag = "0";		#groval variable

if ($pastmode == 1){
	for (1 .. 99){
		if (-e "$pastdir/pastlog$_.dat"){
		$optionbuf .= "<option value=\"$_\" $check[$_]>$kako$_\n";
		$pastviewflag = "1";
		}
	}
}

#セレクトボタン。
$selectbuton =<<TBL;
	<select name="pastno" class=input><option value="0" checked>$genko	
	$optionbuf
	</select>
TBL

#ビューボタン設定。
$viewbuton =<<TBL;
	<input type="submit" value="$submit" class=input>
TBL
}

#●データ出力
#######################################
sub printout{
$basshtml =~ s/\$acttopview/$acttopview/;
$basshtml =~ s/\$actsearch/$actsearch/;
$basshtml =~ s/\$acthome/$acthome/;
$basshtml =~ s/\$myid/$myid/;

print "Content-type:text/html; charset=shift_jis\n\n";
print $basshtml;
exit;
}

#	●時間設定
##########################################
sub maketime{
my ($time, $style) = @_;
my ($sec,$min,$hour,$day,$mon,$year,$wday) = gmtime($time+$areatime);	
	if ($style == "0"){
		$timeword = sprintf("%04d/%02d/%02d",
				 $year+1900,$mon+1,$day);
		return $timeword;
	} else {
		$timeword = sprintf("%04d/%02d/%02d (%s) ",
				$year+1900,$mon+1,$day,$week[$wday]);
		return $timeword;
	}
}

#	●入力チェック
##########################################
sub datacheck{

if (($msg eq "") && $bemsg){push(@errors,"メッセージを入力して下さい。<br>");}
if (($title eq "") && $betitle){push(@errors,"タイトルを入力して下さい。<br>");}

if (($referer !~ /^$scripturl/i) && ($referercheck)){
	push(@errors,"別ページからの投稿は出来ません。<br>");}
#エラーメッセージがあれば入力エラー表示する
if (@errors) { &error('●入力エラーがあります。●'); }
}

#	●エラー表示
##########################################
sub error{
my ($warns);
my $warning = $_[0];
my @buffer = ();
for (0 .. $#errors){
	$warns .= "$errors[$_]\n";}
my $warnings = "$warning<br><br>$warns";
open(IN,$alartskin);
while(<IN>){$basshtml .= $_;}
close(IN);
$basshtml =~ s/\$warnings/$warnings/ig;
&printout;
}

#	●クッキー設定
##########################################
sub setcookie{
my $cookiedays = "60";		#(クッキー保存日数)
	my (@mon,$gmt,$cook);
	my ($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time + $cookiedays*24*60*60);

	@mon = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
	$gmt  = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT",$week[$wday],$mday,$mon[$mon],$year+1900,$hour,$min,$sec);
	$cook = "cpass,$pass";
	print "Set-Cookie: $cookietitle=$cook; expires=$gmt\n";
#クッキーを最新のものに換える。
#$cpass = $pass;
}

#	●クッキーを取得
##########################################
sub getcookie{
my ($cookies,@pairs,$name,$value,%DUMMY,%COOKIE);

	$cookies = $ENV{"HTTP_COOKIE"};
	@pairs = split(/;/, $cookies);
	foreach (@pairs) {
		($name, $value) = split(/=/);
		$value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg;	
		$name =~ s/\s//g;
		$DUMMY{$name} = $value;
	}
	%COOKIE = split(/,/, $DUMMY{"$cookietitle"});
	$cpass 	= $COOKIE{'cpass'};
}