#!/usr/bin/perl

use Fcntl;
require './jcode.pl';

#初期設定ファイルのパス
$iniconf = './init.dat';

#CGIを使用する時間帯のグリニッジ標準時からのズレ(秒単位)
# 日本 9時間x60分x60秒=32400秒 。
$timecheck = 32400;

&inidataload;

@name_list = &decoding();
unless (defined $FORM{disp}){
	$FORM{disp} = 'off';
}
unless (defined $FORM{cate}){
	$FORM{cate} = '1';
}

$now = $FORM{cate};
$logfile = './log'.$now.'.dat'; 
$twidth = ${"NEWS$now"}{width} + 150;
$GifFlag = 1 if ${"NEWS$now"}{listg} =~ /\.gif/;

$FORM{msg} =~ s/\n/<br>/g;
$FORM{msg} =~ s/　/&nbsp;/g;
if (($FORM{act} =~ /^ad/) && ($FORM{pass} ne $INIT{pass})){&enter;}
elsif ($FORM{act} eq "admmenu"){&dataload;&admmenu;}
elsif ($FORM{act} eq "admadd"){&add;&mkinc;&admmenu;}
elsif ($FORM{act} eq "admdel"){&del;&admmenu;}
elsif ($FORM{act} eq "admedit"){&edit;}
elsif ($FORM{act} eq "admchg"){&chg;&mkinc;&admmenu;}
elsif ($FORM{act} eq "onoff"){&onoff;&admmenu;}
else{&enter;}
$admsg = "";
exit;

######################
#   データデコード   #
######################
sub decoding {

    my($buf,$name,$value,$before,@name_list);

    if ($ENV{REQUEST_METHOD} eq "POST") {
        read(STDIN, $buf, $ENV{CONTENT_LENGTH});
    } else {
        $buf = $ENV{QUERY_STRING};
    }
#    $buf || error("データがありません");

    foreach (split(/&/,$buf)) {
        ($name, $value) = split(/=/);
        $name  =~ tr/+/ /;
        $value =~ tr/+/ /;
        $name  =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
        $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
        $name  =~ s/\n//g;
        jcode::convert(\$name,'sjis');
        jcode::convert(\$value,'sjis');
        push(@name_list, $name) if $before ne $name;
        $before = $name;

        if (defined($FORM{$name})) {
            $FORM{$name} = join('!!!', $FORM{$name}, $value);
        } else {
            $FORM{$name} = $value;
        }
    }

    @name_list;

}



############################
#  初期設定データ読み込み  #
############################
sub inidataload{
	my @msg;
	open (IN,"$iniconf") || push(@msg, "$iniconfオープン失敗");
    &error(@msg) if @msg;
	eval{flock(IN,1)};
	@ini = <IN>;
	close (IN);
	#設定データを分解
	@INIT = split(/<>/,$ini[0]) ;
	%INIT = ('pass' => "$INIT[0]", 'sitename' => "$INIT[1]",
			 'maxlog' => "$INIT[2]", 'maxcat' => "$INIT[3]");
	for ($i = 1; $i <= $INIT{maxcat}; ++$i){
		@{"News$i"} = split(/<>/,$ini["$i"]) ;
		%{"NEWS$i"} = ('title' => ${"News$i"}[0], 'path' => ${"News$i"}[1], 'width' => ${"News$i"}[2],
					   'listg' => ${"News$i"}[3], 'header' => ${"News$i"}[4], 'footer' => ${"News$i"}[5]);
		${"NEWS$i"}{header} =~ s/<#>/\n/g;
		${"NEWS$i"}{footer} =~ s/<#>/\n/g;
	}
}

############################
#  ログからデータ読み込み  #
############################
sub dataload{
	my @msg;
	open (IN,"$logfile") || push(@msg, "$logfileオープン失敗");
    &error(@msg) if @msg;
	eval{flock(IN,1)};
	@log = <IN>;
	close (IN);
}

############################
#   記事削除               #
############################
sub del{
	my @msg;
	my $flag = 0;
	my @temp;
	my $i = 1;
	open (IO,"+<$logfile") || push(@msg, "$logfileオープン失敗");
    &error(@msg) if @msg;
	eval{flock(IO,2)};
	while(<IO>){
		@temp=split(/<>/,$_);
		if ($temp[0] eq $FORM{number}){
			$flag = 1;
			$i--;
		}elsif($flag ==0){
			push(@log,$_);
		}else{
			push(@log,"$i<>$temp[1]<>$temp[2]<>$temp[3]<>$temp[4]<>$temp[5]<>\n");
		}
		$i++;
	}
	if ($flag == 0){
		$admsg = "削除元が見つかりませんでした。";
	}else{
		truncate(IO,0);
		seek(IO,0,0);
		print IO @log;
		$admsg = "記事を削除しました。";
	}
	close (IO);
	&mkinc unless $flag == 0;
}
############################
#   編集記事呼び出し       #
############################
sub edit{

	my $ednum;
	my @temp;
	my @msg;
	my $i;
#	my $j = 2;
	$ednum = $FORM{number} - 1;
#	if(($ednum =~ m/^\d/) || ($ednum < 0)){
	if($ednum < 0){
	    $admsg = "編集記事の番号を選択してください。";
		&dataload;
    	&admmenu;
    }
	&dataload;
	@temp=split(/<>/,$log[$ednum]);
 	if($log[$ednum] eq ''){
 	    $admsg = "該当記事が見つかりませんでした。";
     	&admmenu;
     }
	$admsg = "記事を編集後、実行ボタンを押してください。";
	$temp[3] =~ s/<br>/\n/g; 
	&hphead;
	print '<ul id="tabmenu">'."\n";
    for($i = 1; $i <= $INIT{maxcat}; ++$i){
    	print '      <li><a';
    	if($now == $i){
    		print ' class="active" ';
    	} else {
    		print ' ';
    	}
    	print 'href="./nacn.cgi?cate='.$i.'&act=admmenu&pass='.$INIT{pass}.'">'.${"NEWS$i"}{title}.'</a></li>'."\n";
#    	$j += 2;
	}
	print <<'EOD';
    </ul>
    <div id="content">
EOD
    print '<div class="navbar1">'.$INIT{sitename}.'</div>'."\n";
	print '<div class="admsg">'.$admsg.'</div>'."\n" if ($admsg);

	@tptime=gmtime(time()+$timecheck);
	$tptime[4]++;

	print <<EOD;
	<div class="submit">
	<form method="post" action="./nacn.cgi">
	<table summary="操作メニュー">
	<tr>
    	<td class="submit"><strong>記事編集呼び出し</strong></td>
	</tr>
    <tr>
        <td><strong>記事の内容</strong>(タグ自由。改行した場所は自動的にBRタグが入ります。)<br />
	                <textarea name="msg" cols="60" rows="5" tabindex="2" accesskey="m">$temp[3]</textarea><br />
	                リンク先URL<input type="text" name="lurl" size="60" value="$temp[4]" maxlength="80" tabindex="3" accesskey="l" />
	    </td>
    </tr>
    <tr>
	<td>記事No.$temp[0]</td>
	<td>
EOD
	print '		<input type="hidden" name="act" value="admchg" />'."\n";
	print '		<input type="hidden" name="disp" value="on" />'."\n";
	print '		<input type="hidden" name="number" value="'.$temp[0].'" />'."\n";
	print '		<input type="hidden" name="cate" value="'.$now.'" />'."\n";
	print '	  	<input type="hidden" name="pass" value="'.$INIT{pass}.'" />'."\n";
	print '	    <input type="hidden" name="wmonth" value="'.$tptime[4].'" />'."\n";
	print '	    <input type="hidden" name="wday" value="'.$tptime[4].'" />'."\n";
	print <<EOD;
     <input type="submit" value="実行" tabindex="6" accesskey="s" />
  </td>
  </tr>
</table>
</form>
</div>
EOD
	&hpfoot;

}
############################
#   記事編集実行           #
############################
sub chg{
	my @msg;
	if ($FORM{msg} eq ""){
		$admsg = "記事の内容を入力してください。";
		&dataload;
	}else{
		my $flag = 0;
		my @temp;
		open (IO,"+<$logfile") || push(@msg, "$logfileオープン失敗");
    	&error(@msg) if @msg;
		eval{flock(IO,2)};
		while(<IO>){
			@temp=split(/<>/,$_);
			if ($FORM{number} eq $temp[0]){
				push(@log,"$temp[0]<>$FORM{wmonth}<>$FORM{wday}<>$FORM{msg}<>$FORM{lurl}<>$FORM{disp}<>\n");
			$flag = 1;
			}else{
				push(@log,$_);
			}
		}
		if ($flag == 0){
			$admsg = "変更元が見つかりませんでした。";
		}else{
			truncate(IO,0);
			seek(IO,0,0);
			print IO @log;
			$admsg = "記事を変更しました。";
		}
		close (IO);
	}
}

############################
#  記事追加                #
############################
sub add{
	my @msg;
	if ($FORM{msg} eq ""){
		$admsg = "記事の内容を入力してください。";
		&dataload;
	}else{
		my @temp;
		my $i = 2;
		open (IO,"+<$logfile") || push(@msg, "$logfileオープン失敗");
    	&error(@msg) if @msg;
		eval{flock(IO,2)};
		push(@log,"1<>$FORM{wday}<>$FORM{wmonth}<>$FORM{msg}<>$FORM{lurl}<>$FORM{disp}<>\n");
		while(<IO>){
			@temp=split(/<>/,$_);
			push(@log,"$i<>$temp[1]<>$temp[2]<>$temp[3]<>$temp[4]<>$temp[5]<>\n");
			$i++;
		}
		pop(@log) if $#log >= $INIT{maxlog};
		truncate(IO,0);
		seek(IO,0,0);
		print IO @log;
		close (IO);
		$admsg = "記事を追加しました。";
	}
}

############################
#  メニュー 表示           #
############################
sub admmenu{
	my ($a1,@temp,$a2);
	my $i;
#	my $j = 2;
	&hphead;
	print '<ul id="tabmenu">'."\n";
    for($i = 1; $i <= $INIT{maxcat}; ++$i){
    	print '      <li><a';
    	if($now == $i){
    		print ' class="active" ';
    	} else {
    		print ' ';
    	}
    	print 'href="./nacn.cgi?cate='.$i.'&act=admmenu&pass='.$INIT{pass}.'">'.${"NEWS$i"}{title}.'</a></li>'."\n";
#    	$j += 2;
	}
	print <<'EOD';
    </ul>
    <div id="content">
EOD
    print '<div class="navbar1">'.$INIT{sitename}.'</div>'."\n";
	print '<div class="admsg">'.$admsg.'</div>'."\n" if ($admsg);
	print '<table width="'.$twidth.'" border="0" cellspacing="2" cellpadding="3" class="spec" summary="22">'."\n";
	print '<colgroup>'."\n";
	print '<col span="2" width="50" />'."\n";
	print '<col span="1" width="'.$iniwidth.'" />'."\n";
	print '<col span="1" width="50" />'."\n";
	print '</colgroup>'."\n";
	print <<EOD;
	  <tr>
	    <th abbr="no" class="spec">No.</th><th abbr="day" class="spec">日付</th><th abbr="mess" class="spec">内容</th><th abbr="onoff" class="spec">表\示</th>
	  </tr>
EOD
#	$a1 = " checked";
	$no = 1;
	for (0 .. $INIT{maxlog}){
		last if $log[$_] eq "";
		@temp = split(/<>/,$log[$_]);

		print "	  <tr>\n";
		print '	    <td class="list">'.$temp[0].'</td>'."\n";
		print '<td class="list">'.$temp[2].'/'.$temp[1].'</td>'."\n";
#		print '<td class="list">'.$temp[3].'</td>';
		
		if($temp[4]){
			if($GifFlag){
				print '<td class="list"><img src="'.${"NEWS$now"}{listg}.'" width="9" height="12" border="0" /><a href="'.$temp[4].'">'.$temp[3].'</a></td>'."\n";
			} else {
				print '<td class="list">'.${"NEWS$now"}{listg}.'<a href="'.$temp[4].'">'.$temp[3].'</a></td>'."\n";
			}
		}else{
			if($GifFlag){
				print '<td class="list"><img src="'.${"NEWS$now"}{listg}.'" width="9" height="12" border="0" />'.$temp[3].'</td>'."\n";
			} else {
				print '<td class="list">'.${"NEWS$now"}{listg}.$temp[3].'</td>'."\n";
			}
		}
		if($temp[5] eq "on"){
			print '<td class="on">'.$temp[5].'</td>'."\n";
		}else{
			print '<td class="off">'.$temp[5].'</td>'."\n";
		}
		print "	  </tr>\n";
#		$a1 = "";
		$no++;
	}
	$no--;
	@tptime=gmtime(time()+$timecheck);
	$tptime[4]++;

	print <<EOD;
	</table>
	<div class="submit">
	<form method="post" action="./nacn.cgi">
	<table summary="操作メニュー">
	<tr>
    	<td><strong>メニュー</strong>
		<select name="act" tabindex="1">
		<option value="admadd" selected="selected">記事追加</option>
		<option value="admedit">記事編集呼び出し</option>
		<option value="admdel">記事削除</option>
		<option value="onoff">記事\表\示・非\表\示の変更</option>
		</select>
		</td>
		<td>記事No.	
	    <select name="number" tabindex="5">
			<option value="0" selected="selected">追加</option>
EOD
	for($j = 1; $j <= $no; $j++){
		print "\t\t\t".'<option value="'.$j.'">'.$j.'</option>'."\n";
	}
	print <<EOD;
	    </select>
	    </td>
		<td>表\示:<input type="checkbox" name="disp" value="on" tabindex="4" accesskey="v" checked="checked" />
	    </td>
	</tr>
    <tr>
        <td colspan="3"><strong>記事の内容</strong>(タグ自由。改行した場所は自動的にBRタグが入ります。)<br />
	                    <textarea name="msg" cols="60" rows="5" tabindex="2" accesskey="m">本文</textarea><br />
	                    リンク先URL<input type="text" name="lurl" size="60" maxlength="80" tabindex="3" accesskey="l" />
	   </td>
    </tr>
    <tr>
	    <td>&nbsp;</td><td>&nbsp;</td><td>
EOD
	print '		<input type="hidden" name="cate" value="'.$now.'" />'."\n";
	print '	  	<input type="hidden" name="pass" value="'.$INIT{pass}.'" />'."\n";
	print '	    <input type="hidden" name="wmonth" value="'.$tptime[4].'" />'."\n";
	print '	    <input type="hidden" name="wday" value="'.$tptime[4].'" />'."\n";
	print <<EOD;
     <input type="submit" value="実行" tabindex="6" accesskey="s" />
        </td>
    </tr>
</table>
</form>
</div>
EOD
	&hpfoot;
}

############################
#   管理人確認             #
############################
sub enter{
	&hphead;
	print <<'EOD';
<div>
	<div>
	パスワードを入力してください。
	</div>
	<div>
	<form method="post" action="./nacn.cgi">
	<p>	password
	<input type="password" name="pass" size="16" tabindex="1" accesskey="p" />
	<input type="submit" value="進む" accesskey="s" tabindex="2" />
	<input type="hidden" name="act" value="admmenu" />
	</p>
	</form>
	</div>
EOD
	&hpfoot;
}

############################
#  ヘッダ部表示            #
############################
sub hphead{
print "Content-type:text/html; charset=shift_jis\n\n";
print <<EOD;
<?xml version="1.0" encoding="Shift_JIS" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta http-equiv="content-type"	content="text/html;	charset=shift_jis" />
	<meta name="author"	content="i-Live" />
	<meta name="MSSmartTagsPreventParsing" content="true" />
	<meta name="description" content="CSS techniques demonstrating pure CSS navigation tabs / tabbed menus"	/>
    <meta http-equiv="Content-Style-Type" content="text/css" />
	<link rel="stylesheet" href="./def.css" type="text/css" media="screen" />
	<link rel="stylesheet" href="./nacn.css" type="text/css" media="screen" />
    <title>Auto Change News</title>
</head>

<body>
EOD
}

############################
#フッタ部表示              #
############################
sub hpfoot{
print <<EOD;
    <div class="navbar2"> 管理モード </div>
</div>
</body>
</html>
EOD
exit;
}
############################
#  差込ファイル作成        #
############################
sub mkinc{
	my @msg;
	my @temp;
	my $ThisInc;
	
	$ThisInc = ${"NEWS$now"}{path};
	open (IO,"<$logfile") || push(@msg, "$logfileオープン失敗");
	open (OUT,">$ThisInc") || push(@msg, "$ThisIncオープン失敗");
    &error(@msg) if @msg;

	${"NEWS$now"}{header} =~ s/<#>/\n/g;
	${"NEWS$now"}{footer} =~ s/<#>/\n/g;

	print OUT ${"NEWS$now"}{header};

	while(<IO>){
		@temp=split(/<>/,$_);
		if($GifFlag){
			if ($temp[4] && $temp[5] eq "on"){
				print OUT '        <p class="news"><img src="'.${"NEWS$now"}{listg}.'" width="9" height="12" border="0" alt="" /><a href="'.$temp[4].'">'.$temp[3].'</a></p>'."\n";
			}elsif($temp[4] eq "" && $temp[5] eq "on"){
				print OUT '        <p class="news"><img src="'.${"NEWS$now"}{listg}.'" width="9" height="12" border="0" alt="" />'.$temp[3].'</p>'."\n";
			}
		} else {
			if ($temp[4] && $temp[5] eq "on"){
				print OUT '        <p class="news">'.${"NEWS$now"}{listg}.'<a href="'.$temp[4].'">'.$temp[3].'</a></p>'."\n";
			}elsif($temp[4] eq "" && $temp[5] eq "on"){
				print OUT '        <p class="news">'.${"NEWS$now"}{listg}.$temp[3].'</p>'."\n";
			}
		}
	}

	print OUT ${"NEWS$now"}{footer};

	close (OUT);
	close (IO);
	$admsg .= "  記事を再編集しました。";
	&dataload;
}
############################
# 記事の表示・非表示を変更 #
############################
sub onoff{
	my @msg;
	my $flag = 0;
	my @temp;
	open (IO,"+<$logfile") || push(@msg, "$logfileオープン失敗");
    &error(@msg) if @msg;
	eval{flock(IO,2)};
	while(<IO>){
		@temp=split(/<>/,$_);
		if ($FORM{number} eq $temp[0]){
			push(@log,"$temp[0]<>$temp[1]<>$temp[2]<>$temp[3]<>$temp[4]<>$FORM{disp}<>\n");
		$flag = 1;
		}else{
			push(@log,$_);
		}
	}
	if ($flag == 0){
		$admsg = "変更元が見つかりませんでした。";
	}else{
		truncate(IO,0);
		seek(IO,0,0);
		print IO @log;
		$admsg = "記事の\表\示・非\表\示を変更しました。";
	}
	close (IO);
	&mkinc unless $flag == 0;
}

############################


####################
#   エラー処理     #
####################
sub error {
    foreach (@_) {
        $FORM{ERROR_MSG} .= "<tr><td class=\"list\"><li>$_<br /></td></tr>";
    }
    
	&hphead;
	print <<'EOD';
<table class="spec">
    <tr>
      <th class="spec">入力項目に誤りがあるようです。</th>
    </tr>
EOD
    print "$FORM{ERROR_MSG}";
	print <<'EOD';
    <tr>
      <td class="list"><input type="button" value="戻　る" onclick="history.back()"></td>
    </tr>
</table>
EOD
	&hpfoot;
    exit;
}


########################
#   ファイルLock       #
########################
sub my_flock {
  my %lfh = (dir => './lockdir/', basename => 'lockfile',
	     timeout => 60, trytime => 10, @_);

  $lfh{path} = $lfh{dir} . $lfh{basename};

  for (my $i = 0; $i < $lfh{trytime}; $i++, sleep 1) {
    return \%lfh if (rename($lfh{path}, $lfh{current} = $lfh{path} . time));
  }
  opendir(LOCKDIR, $lfh{dir});
  my @filelist = readdir(LOCKDIR);
  closedir(LOCKDIR);
  foreach (@filelist) {
    if (/^$lfh{basename}(\d+)/) {
      return \%lfh if (time - $1 > $lfh{timeout} and
	  rename($lfh{dir} . $_, $lfh{current} = $lfh{path} . time));
      last;
    }
  }
  undef;
}

##########################
#   ファイルUnLock       #
##########################
sub my_funlock {
  rename($_[0]->{current}, $_[0]->{path});
}
