#! /usr/local/bin/perl
#↑上の行はプロバイダーの環境に合わせて設定してください。
#=============================================================================
#                                BBS Note 8.x
#            Copyright(C) WonderCatStudio. All rights reserved.
#                        http://wondercatstudio.com
#                           LastModify 2005/01/12
#=============================================================================
##############################################################################
#########################  設定項目はありません  #############################
##############################################################################

#-----------------------------------------------------------------------------
require 5.003;

sub filelock;
sub fileunlock;
eval { &Initialize };

sub Initialize{
#----------------------------< CONFIG >---------------------------------------

	$SYS{ VERSION } = '8.0b17';
	$SYS{ CONFIG_VERSION } = '2004011500';
	$SYS{ CONFIGDIR } = './';
	$SYS{ CONFIG } = 'config.cgi';
	$SYS{ SKINDIR } = './';
	$SYS{ SKIN } = 'skin.cgi';
	$SYS{ SKINCONFIG } = 'skincfg.cgi';
	$SYS{ BBSNote } = $1 if($ENV{ SCRIPT_NAME } =~ /([^\\\/]+)$/);

	$SYS{ LANGUAGE } = 'JP';				# language [JP=Japanese or EN=English]
	$SYS{ RECOVER_SLEEP } = 1;				# recover sleep flag
	$SYS{ CAPTOR_FORMAT } = 'jpg,png,gif';
	$SYS{ SYSINDEX_HEAD } = 'BBSNOTE-SYSTEM-INDEX:';

	$CFG{ VIEW_ROTATION } = 'normal,catalog,thumbnail,noimage';

	(-e $SYS{ CONFIGDIR }.$SYS{ CONFIG })||&End('ERROR',&Info('CONFIG_NOTFOUND'));
	require $SYS{ CONFIGDIR }.$SYS{ CONFIG };

	(-e $SYS{ SKINDIR }.$SYS{ SKIN })||&End('ERROR',&Info('SKIN_NOTFOUND'));
	require $SYS{ SKINDIR }.$SYS{ SKIN };

	$SYS{ SORT_MODE } = $CFG{ ViewSortType };

	# *RO = Read Only
	$SYS{ MODE } = '';				# system mode *RO
	$SYS{ INDEX } = '';				# system index *RO
	$SYS{ BBS_COPYRIGHT } = '';			# bbsnote copyright *RO
	$SYS{ CLIENT_COPYRIGHT } = '';			# client program copyright *RO
	$SYS{ MODULE_COPYRIGHT } = '';			# module copyright *RO

	# file lock config
	$SYS{ LOCK_SLEEP } = 1;				# lock sleep sec *RO
	$SYS{ LOCK_TRY } = 5;				# lock try count *RO
	$SYS{ LOCK_SEC } = 60;				# lock sec *RO
	$SYS{ LOCK_DIR } = $CFG{ DirSysPath }.'/lock';	# lock directory *RO
	$SYS{ LOCKED } = 0;				# lock flag

	# Flag
	$SYS{ FLAG }{ HTTPHEAD } = '';			# HTTPHEAD flag
	$SYS{ FLAG }{ MANUALHTTP } = '';		# maual mode http response flag
	$SYS{ FLAG }{ GETTEMPFILENAME } = '';		# use tempfile flag
	$SYS{ FLAG }{ ALLTAG } = 0;			# use all tags flag

	$SYS{ Jcode } = '';				# use jcode flag
	$SYS{ JAVASCRIPT } = {};			# global javascript

	$SYS{ ARG }{ Global } = ();			# global all arg
	$SYS{ ARG }{ Menu } = ();			# all menu arg
	$SYS{ ARG }{ PageLink } = ();			# page link arg
	$SYS{ ARG }{ PostForm } = ();			# post form value arg * = replry post form
	$SYS{ ARG }{ ReplyForm } = ();			# replry form value arg * = res form or button
	$SYS{ ARG }{ DeleteForm } = ();			# delete form value arg
	$SYS{ ARG }{ EditForm } = ();			# edit form value arg
	$SYS{ ARG }{ ReplyForm } = ();			# replry form value arg * = res form or button

#----------------------------</CONFIG/>---------------------------------------


	@SYS{'USER_AGENT','USER_OS','USER_BROWSER','USER_BROWSER_VER'} = &GetUserAgent;

	&Call('InitializeInit');

	&RegVersion;

}

#-----------------------------------------------------------------------------
# ページ表示
sub OpenPage{

	%COOKIE = &GetCookie; # global hash

	&Call('OpenPageBegin');

	&OpenSysIndex(INDEX , 'index');

	$CFG{ LogView } = $CFG{ CatalogCol } * $CFG{ CatalogRow } if $IN{mode} eq 'catalog';

	local $LogTotal = $SYS{ INDEX }{ INDEX }{total};
	local $Page = int $IN{page} ? int $IN{page} : 1 ;
	local $Index = ($Page - 1) * $CFG{ LogView };

	$Index = $Page = 0 if($Index >= $LogTotal);

	local $IndexPos;
	local($PageLinkText, $PageLinkForm) = &CreatePageLink;

	$SYS{ SORT_MODE } = $IN{sort} eq '' ? $SYS{ SORT_MODE } : $IN{sort} ? 1 : 0;

    push @SkinHeadFormat,sub{push @$META,{
			TAG => "LINK", rel => "alternate", type => "application/xml",
			title => "RSS:$CFG{BbsTitle}", href => "$CFG{ BBSNoteUrl }?fc=rss" }};

	&MailCrypt;
	&HttpHead;
	&SkinHead();
	&SkinMenu;

	&Call('OpenPageMenu');
for(#< LOG LOOP >=============================================================
		$IndexPos = 0;
		$IndexPos < $CFG{ LogView } && $Index < $LogTotal;
		$Index++, $IndexPos++
   ){

	local $IndexNumber = &ReadSysIndex(INDEX ,$Index, $SYS{ SORT_MODE });
	local $ThreadNumber;
	if($SYS{ SORT_MODE }){
		$ThreadNumber = &ReadSysIndex(INDEX ,$Index, 2);
	}else{
		$ThreadNumber = $LogTotal - $Index;
	}

	&OpenLog($IndexNumber);


}#===</LOG LOOP/>=============================================================


	&CloseSysIndex(INDEX);

	&Call('OpenPageFoot');

	&SkinFoot;

	exit;

}

#-----------------------------------------------------------------------------
# RSS表示
sub OpenRss{
	&OpenSysIndex(INDEX , 'index');

	$rdate = sub{	if($_[0] =~ /(\d*)\/(\d\d)\/(\d\d) \((\w*)\) (\d\d):(\d\d):?(\d\d)?/){
		my($year,$month,$day,$week,$hour,$min,$sec) = ($1,$2,$3,$4,$5,$6,$7);
		$sec = '00'if!$7;
		return "$year-$month-$day\T$hour:$min:$sec+09:00";
	}};

	$mod = &GetDate((stat INDEX)[9]);
	$mod = &$rdate($mod);

	$SYS{ HTTPCONTENTTYPE } = 'text/xml';
	&HttpHead;

	if(exists $IN{ modified } && "$IN{ modified }+09:00" ge $mod){
		print "304 Not Modified\n";
		exit;
	}
	my $view = int $IN{ view };

	$SYS{ SORT_MODE } = $IN{sort} eq '' ? $SYS{ SORT_MODE } : $IN{sort} ? 1 : 0;

	$CFG{ LogView } = $view if 0 < $view && $view <= 30 ;

	local $IndexPos;
	local $Page = int $IN{page} ? int $IN{page} : 1 ;
	local $LogTotal = $SYS{ INDEX }{ INDEX }{total};
	local $Index = ($Page - 1) * $CFG{ LogView };

	$Index = $Page = 0 if($Index >= $LogTotal);

	my $la = lc $SYS{ LANGUAGE };
	my $bn = "http://$ENV{HTTP_HOST}$ENV{REQUEST_URI}";
	my(%applets, $ap, $seq, $items);

	if(exists $SYS{ MODULE }{ Paint }){
		# 有効アプレットを示す変数列挙
		my $a = $Paint::CFG{ UseApplet };
		for (@$a) {
			$applets{$Paint::CFG{Setting}->{$_}{ applet }}=1 if $_;
		}
		map{$ap.= "<bn:$_>1</bn:$_>\n" }keys %applets;
	}

print <<_XML_;
<?xml version="1.0" encoding="Shift-JIS"?>

<rdf:RDF
  xmlns="http://purl.org/rss/1.0/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:bn="http://wondercatstudio.com/bn/1.0/"
  xml:lang="$la"
>

<channel rdf:about="$bn">
<title>$CFG{BbsTitle}</title>
<link>$bn</link>
<description>BBS NOTE $SYS{ VERSION }</description>
<dc:language>$la</dc:language>
<dc:date>$mod</dc:date>
<bn:home href="$CFG{ HomePageUrl }" />
<bn:skin href="$SYS{ SKIN }{ siteurl }"
 name="$SYS{ SKIN }{ skin }"
 version="$SYS{ SKIN }{ version }"
 lastmodify="$SYS{ SKIN }{ lastmodify }"
 copyright="$SYS{ SKIN }{ copyright }"
 author="$SYS{ SKIN }{ author }"
 />
<bn:verion>$SYS{ VERSION }</bn:verion>
<bn:data>$CFG{ DirFileUrl }</bn:data>
<bn:cfg>
<bn:log>$LogTotal</bn:log>
<bn:limit>$CFG{ LogMax }</bn:limit>
<bn:view>$CFG{ LogView }</bn:view>
<bn:co>$CFG{ NotCommentOnly }</bn:co>
<bn:im>$CFG{ UseImageMagick }</bn:im>
<bn:sort>$SYS{ SORT_MODE }</bn:sort>
<bn:tag>$CFG{ UseTag }</bn:tag>
<bn:upload>$CFG{ UseImageUpload }</bn:upload>
$ap
</bn:cfg>
_XML_

for(#< LOG LOOP >=============================================================
		$IndexPos = 0;
		$IndexPos < $CFG{ LogView } && $Index < $LogTotal;
		$Index++, $IndexPos++
   ){

	local $IndexNumber = &ReadSysIndex(INDEX ,$Index, $SYS{ SORT_MODE });
	local $ThreadNumber = &ReadSysIndex(INDEX ,$Index, 2);
	local(%Data, %LogValue, %LogExValue);

	&GetLog($IndexNumber,'',\%LogValue, \%LogExValue);
	&SetLogMainValue(\%Data, \%LogValue, \%LogExValue);

	my $msg = $LogValue{message};
	my $date = $LogValue{date};

	$mod = &GetDate((stat &filelog($IndexNumber))[9]);
	$mod = &$rdate($mod);
	$date = &$rdate($date);

	my $pos = 0;
	my($len,$s);

	$msg =~ s/&nbsp;/ /g;
	$msg =~ s/&/%26/g;
	$msg =~ s/(<BR>|<P>)/ /g;
	$msg =~ s/ +/ /g;

	while($pos >= 0){
		$pos = index $msg,'<',$pos;
		if($pos >= 0){
			$s = index $msg,'>',$pos + 1;
			if($s >= 0){
				my $a = substr $msg, 0, $pos if$pos;
				$msg = $a.(substr $msg, $s+1);
			}else{
				$pos++
			}
		}else{last}
	}

	$seq.="<rdf:li rdf:resource=\"$bn?fc=thread%26log=$IndexNumber\" />\n";

	$msg =~ s/</&lt\;/g;
	$msg =~ s/>/&gt\;/g;

	$items.=<<_XML_;
<item rdf:about="$bn?fc=thread%26log=$IndexNumber">
<title>$LogValue{title}</title>
<link>$bn?fc=thread%26log=$IndexNumber</link>
<description>$msg</description>
<dc:creator>$LogValue{name}</dc:creator>
<dc:date>$date</dc:date>
<bn:lastmodify>$mod</bn:lastmodify>
<bn:log>$IndexNumber</bn:log>
<bn:image>$Data{ ImageSrc }</bn:image>
<bn:anime>$Data{ AnimeSrc }</bn:anime>
<bn:thumbnail>$Data{ ThumbnailSrc }</bn:thumbnail>
<bn:image_width>$LogValue{ file_width }</bn:image_width>
<bn:image_height>$LogValue{ file_height }</bn:image_height>
<bn:image_length>$LogValue{ file_length }</bn:image_length>
</item>
_XML_


}#===</LOG LOOP/>=============================================================

	&CloseSysIndex(INDEX);

	print "<items>\n<rdf:Seq>\n$seq</rdf:Seq>\n</items>\n\n</channel>\n$items\n\n</rdf:RDF>";

	exit;

}
#-----------------------------------------------------------------------------
# スレッド表示
sub OpenThread{eval<<'_SUB_';

	&Call('OpenThreadBegin');

	local $LogTotal = (-s "$CFG{ DirSysPath }/index.$CFG{ FileSysExe }") / 2;
	local $IndexNumber = $IN{log};
	local $ThreadNumber = $IN{log};
	local $ReplyNumber = $IN{res};

	$SYS{MODE} = "DELETE" if(exists $IN{delete});
	$SYS{MODE} = "ADMIN" if(exists $IN{admin});
	$IN{no} = $IN{log}if!$IN{no};
	&OpenPost if(exists $IN{reply});

	&MailCrypt;
	&HttpHead;
	&SkinHead();
	&SkinMenu;

	&Call('OpenThreadMenu');

	$loopOpen = sub{
		my $n;
		foreach(@_){
			last if($n >= $CFG{ LogView });
			$IndexNumber = $_;
			&OpenLog($_);
			$n++;
		}
	};

	if($IndexNumber=~/(\d+)-(\d+)/){
		my($st,$ed) = ($1,$2);
		my($bs,$be,@l);
		$bs = $st < $ed ? $st : $ed;
		$be = $st < $ed ? $ed : $st;

		if($st < $ed){
			$be = $bs + ($CFG{ LogView }-1) if($bs + ($CFG{ LogView }-1) < $be);
		}else{
			$bs = $be - ($CFG{ LogView }-1) if($be - ($CFG{ LogView }-1) > $bs);
		}

		@l = $bs..$be;
		@l = reverse @l if($st > $ed);
		&$loopOpen(@l);

	}elsif($IndexNumber=~/(\d+),(\d+)/){

		&$loopOpen(split /,/,$IndexNumber,$CFG{ LogView }+1);
	}else{

		if($ReplyNumber=~/(\d+)-(\d+)/){
			&OpenLog($IndexNumber,$1,$2);
		}else{
			&OpenLog($IndexNumber,$ReplyNumber);
		}
	}

	&Call('OpenThreadEnd');

	&SkinFoot;

	exit;

_SUB_
}
#-----------------------------------------------------------------------------
# インデックス更新
sub RefleshIndex{eval<<'_SUB_';
	return if(!$CFG{ UseRefleshIndex });

	$SYS{ FLAG }{ RefleshIndex } = 1;

	filelock;

	# 変数バックアップ
	local $BACK_MO = $SYS{ MODE };
	local(%BACK_IN ,%BACK_CO,%BACK_ENV);

	map{$BACK_IN{$_}=$IN{$_}}keys %IN;
	map{$BACK_ENV{$_}=$ENV{$_}}keys %ENV;
	map{$BACK_CO{$_}=$COOKIE{$_}}keys %COOKIE;

	# 入力ハッシュ初期化
	undef $SYS{ MODE };
	undef %IN;
	undef %ENV;
	undef %COOKIE;

	&Call('RefleshIndexInit');

	my $path = $CFG{ IndexFilePath };
	(-w $path) || &End('ERROR',&Info('SYS_NOTWRITE',$path));
	open(INDEXTOP,">$path") || &End('ERROR',&Info('SYS_NOTOPEN',$path));

	# 出力先変更
	select INDEXTOP;

	&OpenSysIndex(INDEX , 'index');
	local $LogTotal = $SYS{ INDEX }{ INDEX }{total};
	local $Page = 0 ;
	local $Index = 0;
	local $IndexPos;
	local($PageLinkText, $PageLinkForm) = &CreatePageLink;

	&MailCrypt;

	&SkinHead();
	&SkinMenu;


for(#< LOG LOOP >=============================================================
		$IndexPos = 0;
		$IndexPos < $CFG{ LogView } && $IndexPos < $LogTotal;
		$Index++, $IndexPos++
   ){
	local $IndexNumber = &ReadSysIndex(INDEX ,$Index, $SYS{ SORT_MODE });
	local $ThreadNumber;
	if($SYS{ SORT_MODE }){
		$ThreadNumber = &ReadSysIndex(INDEX ,$Index, 2);
	}else{
		$ThreadNumber = $LogTotal - $Index;
	}

	&OpenLog($IndexNumber);
}#===</LOG LOOP/>=============================================================

	&CloseSysIndex(INDEX);

	&SkinFoot;

	close INDEXTOP;

	# 標準出力
	select STDOUT;

	fileunlock;

	# 変数復帰
	$SYS{ MODE } = $BACK_MO;

	map{$IN{$_}=$BACK_IN{$_}}keys %BACK_IN;
	map{$ENV{$_}=$BACK_ENV{$_}}keys %BACK_ENV;
	map{$COOKIE{$_}=$BACK_CO{$_}}keys %BACK_CO;

	$SYS{ FLAG }{ SkinHead } = 0;
	$SYS{ FLAG }{ CreatePageLink } = 0;
	undef $SYS{ JAVASCRIPT }{ FLAG };
	$SYS{ FLAG }{ SkinPostFormInit } = 0;
	$SYS{ FLAG }{ RefleshIndex } = 0;

_SUB_
}
#-----------------------------------------------------------------------------
# 管理モード表示
sub OpenAdmin{eval<<'_SUB_';

	$SYS{ MODE } = 'ADMIN';

	if($SYS{ FLAG }{ AUTHORITY } ne 'ADMIN'){
		my($pwd, $usr) = &GetAdminPass;

		# パスワードチェック
		my $ok = &CheckAuthority($pwd,$usr);

		&End('ERROR',&Info('PASSWORD_ERROR'))if(!$ok);


	}

	&Call('OpenAdminInit');

	if($IN{mode} eq 'reflesh_index'){
		&RefleshIndex;
	}elsif($IN{mode} eq 'delete'){
		&DeleteLog;
	}elsif($IN{mode} eq 'recover_sysindex'){
		&RecoverSysIndex;
	}elsif($IN{mode} eq 'recover_backupindex'){
		&BackupSysIndex;
	}elsif($IN{mode} eq 'recover_fileindex'){
		&RecoverFileIndex;
	}

	# OFF
	$CFG{ ViewLimitReply } = 0;

	# フック
push @OpenPageMenu,sub{

	my @txt = &Info('ADMIN_TEXT');

	print '<CENTER><P>';
	print $PageLinkForm;
	&TabeleFrame($txt[0]);

	print "<B>$txt[1]</B>" if($AutoLogin);
	print '<TABLE width=500><TR><TD><SMALL>';

	local $FormCgi = "<FORM method=post action='$CFG{ BBSNoteUrl }'><INPUT type=hidden name=password value='$IN{password}'><INPUT type=hidden name=name value='$IN{name}'><INPUT type=hidden name=page value='$IN{page}'><INPUT type=hidden name=sort value='$IN{sort}'>";
	$FormCgi.= &SetFormGlobalArg($SYS{ ARG }{ AdminMenuForm });


	# ログ解析・修復
print <<_HTML_;
<SCRIPT>
function BN_admin_infoinit(){
	a = BN_admin_infoinit.arguments
	t = new Array()
	for(n=0;a.length > n; n++){
		t[n] = a[n]
	}

	if(!t.length)return
	for(n=0;t.length > n; n++){
		document.all['ad_'+t[n]].style.display = 'none'
	}
}
function BN_admin_recoverinfo(t){
	BN_admin_infoinit('recover_index','recover_backup','recover_file')
	document.all['ad_'+t].style.display = 'inline'
}
</SCRIPT>
<TABLE>
$FormCgi
<TR><TD>
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=recover_sysindex>
<INPUT type=submit class=button value='$txt[12]' onmouseover='BN_admin_recoverinfo("recover_index")'><P>
</FORM>
</TD><TD>
<FORM method=post action='$CFG{ BBSNoteUrl }?.sys'>
<INPUT type=hidden name=password value='$IN{password}'>
<INPUT type=hidden name=name value='$IN{name}'>
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=recover_backupindex>
<INPUT type=submit class=button value='$txt[13]' onmouseover='BN_admin_recoverinfo("recover_backup")'><P>
</FORM>
</TD><TD>
$FormCgi
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=recover_fileindex>
<INPUT type=submit class=button value='$txt[14]' onmouseover='BN_admin_recoverinfo("recover_file")'><P>
</FORM>
</TD></TR>
</TABLE>
$txt[15]<P>
_HTML_

	# トップ更新
	if($CFG{ UseRefleshIndex }){

print <<_HTML_;
$FormCgi
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=reflesh_index>
<INPUT type=submit class=button value='$txt[10]'><P>
$txt[11]<P>
</FORM>
_HTML_

	}


	&Call('OpenAdminMenu');





my $f = $FormCgi;
$f =~ s/(method)/name=menuform $1/;

# 一括削除
if($IN{ mode } eq 'delete'){
	$SYS{ FLAG }{ MENUFORM } = 'ADMIN';
print <<_HTML_;
$FormCgi
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=''>
<INPUT type=submit class=button value='$txt[3]'>
<P>$txt[8]<P></FORM>

$f
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=delete>
<INPUT type=submit class=button value='$txt[5]'> 
$txt[6]<INPUT style="text-align:center" name="number" type="text" size="10" class="button">
<P>$txt[9]<P>
_HTML_
}else{
# 通常管理

	# フック
my $cmd = sub{
	local($Bg1,$Bg2,$Size,@cell,@Command);
	$Bg1=$CFG{ TagTableOut }{bgcolor};
	$Bg2=$CFG{ TagTableIn }{bgcolor};
	$Size=$CFG{ TagMessage }{size};
	@Cell = (1,1,3,0);	# cell space padding
	my $cmd_del={
		action	=>	$CFG{ BBSNoteUrl },
		fc	=>	'admin',
		mode	=>	'delete',
		page	=>	$IN{page},
		submit	=>	$txt[5],
		number	=>	$_[0] eq 'SkinMainInit'?$IndexNumber:"$IndexNumber\-$LogValue{num}",
	};

	push @Commad,$cmd_del;

	&Call('OpenAdminCommand');

	my $s;
	foreach $h(@Commad){
		if($$h{ action }){
			$s.= "<FORM action='$$h{ action }' method=post><TD>";
			$s.= "<INPUT type=hidden name=password value='$IN{password}'>";
			$s.= "<INPUT class=button type=submit value='$$h{ submit }'>";
			delete $$h{ action };
			delete $$h{ submit };
			map{ $s.= "<INPUT type=hidden name='$_' value='$$h{$_}'>" if $$h{$_} ne '' } keys %$h;
			$s.='</TD></FORM>';
		}
	}

	return if!$s;
	$LogValue{message}.=<<_HTML_;
<P><TABLE cellpadding=$Cell[0] cellspacing=$Cell[1] bgcolor=$Bg1><TR><TD>
<TABLE cellpadding=$Cell[2] cellspacing=$Cell[3] bgcolor=$Bg2>
<TR><TD bgcolor=$Bg1><FONT color=$Bg2 size=$Size>$txt[2]</TD>
$s
</TD></TR></TABLE></TD></TR></TABLE>
_HTML_

};
push @SkinMainInit,$cmd;
push @SkinReplyBegin,$cmd;

print <<_HTML_;
$f
<INPUT type=hidden name=fc value=admin>
<INPUT type=hidden name=mode value=delete>
<INPUT type=submit class=button value='$txt[4]'> 
<P>$txt[7]<P>
</FORM>
_HTML_

}

print <<_HTML_;
</TD></TR></TABLE></TD></TR></TABLE></TD></TR></TABLE>
_HTML_

	print '</CENTER></P>';

};

	&OpenPage;

_SUB_
}
#-----------------------------------------------------------------------------
# 管理モードログイン用フォームの表示
sub OpenLogin{eval<<'_SUB_';

	local $AutoLogin;

	my($pwd, $usr)=&GetAdminPass;

	if($pwd){

		# パスワードチェック
		my $ok = &CheckAuthority($pwd,$usr);

		# パス不一致
		if(!$ok || $SYS{ FLAG }{ AUTHORITY } ne 'ADMIN'){
			delete $COOKIE{adminpass};
			&WriteCookie(\%COOKIE);
			&End('ERROR',&Info('PASSWORD_ERROR'))if!$AutoLogin;
		}else{
			# 管理パスのみ別途保存
			$COOKIE{adminpass} = $pwd;
			&WriteCookie(\%COOKIE);
			&OpenAdmin
		}

	}


	&Call('OpenLoginInit');

	my @text = &Info('LOGIN_TEXT');

	&HttpHead;
	&SkinHead("$CFG{ BbsTitle } : $text[0]");

	local @FORMS;
	local $LoginText = "<H2>$text[0]</H2>$text[1]<BR>";

	$SYS{ FLAG }{ MENUFORM } = 'LOGIN';

	&Call('OpenLoginForm');

	# フック:番号フォームを削除
	push @SkinCreateMenuFormInit,sub{
		# エレメント文字ターゲット
		my @p = &GetForm(\@FORMS,'number');
		@p[2]--;
		&SetForm(\@FORMS,\$form_form,'delete',join ',',@p);
		&SetForm(\@FORMS,\$form_form,'delete','number');
	};


	print &SkinCreateMenuForm('login',$LoginText,'LoginForm');

	&SkinFoot;

	exit;

_SUB_
}
#-----------------------------------------------------------------------------
# 設定表示
sub OpenHelp{eval<<'_SUB_';

	%COOKIE = &GetCookie;

	# タイトル拾い
	local $T;
	push @SkinHeadFormat,sub{$T = $Title};


	$SYS{ MODE } = 'HELP';
	&HttpHead;
	&SkinHead();

	&Call('OpenHelpBegin');

	&TabeleFrame($T);
	my $bg1 = $CFG{ TagTableOut }{bgcolor};
	my $bg2 = $CFG{ TagTableIn }{bgcolor};
	my @cfg = &Info('CONFIG_TEXT');
	my @txt = &Info('HELP_TEXT');

	# モジュール情報出力
	if($IN{mo}){
		my $mo = $SYS{ MODULE }{ $IN{mo} };
		my @cf;
		push @cf,$txt[5],$$mo{version} if $$mo{version};
		push @cf,$txt[6],$$mo{lastmodify} if $$mo{lastmodify};
		push @cf,$txt[7],$$mo{copyright} if $$mo{copyright};
		push @cf,$txt[8],$$mo{author} if $$mo{author};
		push @cf,$txt[9],"<A href='$$mo{siteurl}'><FONT color=$bg2>$$mo{siteurl}</A>" if $$mo{siteurl};
		push @cf,$txt[10],$$mo{comment} if $$mo{comment};

		print "<B>$txt[3] : $IN{mo} Module</B><TABLE style='font-size:10pt;color:$bg2' cellspacing=2 cellpadding=3 width=100%>";
		for($c=0;$c<@cf;$c+=2){
			print "<TR><TD bgcolor=$bg1>$cf[$c]</TD><TD bgcolor=$bg1>@cf[$c+1]</TD></TR>"
		}
		print '</TABLE>';
	}else{

	&Call('OpenHelpBbsVer');

	# BBSNote設定出力
	print "<H3>BBSNote Ver$SYS{ VERSION }</H3> $txt[0]";

	# Cookie
	if(exists $IN{cookiedump}){
	print "<p><B>[ Cookie Data ]</B> *DEBUG<TABLE style='font-size:10pt;color:$bg2' cellspacing=2 cellpadding=3 width=100%>";
	foreach(keys %COOKIE){
		print "<TR><TD bgcolor=$bg1 width=50%>$_</TD><TD bgcolor=$bg1>$COOKIE{$_}</TD></TR>"
	}
	print '</TABLE><P>';
	}


	&Call('OpenHelpConfig');

	print "<HR color=$bg1><B>$txt[1]</B><TABLE style='font-size:10pt;color:$bg2' cellspacing=2 cellpadding=3 width=100%>";
	for($c=0;$c<@cfg;$c+=2){
		print "<TR><TD bgcolor=$bg1 width=50%>$cfg[$c]</TD><TD bgcolor=$bg1>@cfg[$c+1]</TD></TR>"
	}

	if($CFG{ UseImageMagick }){
		my @ver = `$CFG{ ImageMagickPath } -verion`;
		$ver[0] = 'Not Install' if(!@ver);
		print "<TR><TD bgcolor=$bg1 width=50%>ImageMagick</TD><TD bgcolor=$bg1>$ver[0]</TD></TR>";
	}

	if($CFG{ UseTag }==1){
		print "<TR><TD bgcolor=$bg1 colspan=2>$txt[2] : <TT>";
		foreach(split /,/,$CFG{ OkTag }){
			print "\&lt\;$_\&gt\;\&nbsp\;<NOBR>";
		}
		print '</TD></TR>';
	}

	print '</TABLE>';

	&Call('OpenHelpModule');

	my $mo = $SYS{ MODULE };
	my $mo_cnt;
	foreach(keys %$mo){
		next if($$mo{$_}{invisible});$mo_cnt++;
		print "<HR color=$bg1><B>$txt[3]</B><TABLE style='font-size:10pt;font-weight:bold' cellspacing=2 cellpadding=3><TR><TD>"if$mo_cnt==1;
		print "[<A href='$CFG{ BBSNoteUrl }?fc=help&mo=$_'>$_</A> : $$mo{$_}{version}]"
	}
	print '</TD></TR></TABLE>'if$mo_cnt;


	&Call('OpenHelpSkin');
	my $sk = $SYS{ SKIN };
	print <<_HTML_;
<HR color=$bg1>
<B>$txt[4] : $$sk{skin}</B>
<TABLE bgcolor='$bg1' cellspacing=0 cellpadding=0>
<TR><TD><TABLE style='font-size:10pt' cellspacing=1 cellpadding=3>
<TR style='background-color:$bg2'>
<TD><B>$txt[5]</B> : $$sk{version}</TD>
<TD><B>$txt[6]</B> : $$sk{lastmodify}</TD>
<TD><B>$txt[7]</B> : $$sk{copyright}</TD></TR>
<TR style='background-color:$bg2'>
<TD><B>$txt[8]</B> : $$sk{author}</TD>
<TD colspan=2><B>$txt[9]</B> : <A href='$$sk{siteurl}'>$$sk{siteurl}</A></TD>
</TR></TABLE></TD></TR></TABLE>
_HTML_


	}

	&Call('OpenHelpEnd');
	print '</TD></TR></TABLE></TD></TR></TABLE>';

	print &SkinBackButton();
	print '</CENTER>';


	&SkinFoot;

	exit;

_SUB_
}
#-----------------------------------------------------------------------------
sub OpenLog(){
	my($log,$res_begin,$res_end) = @_;
	local $LogFile = &filelog($log);
	if(-e "$LogFile") {

		open(MSG,"<$LogFile");
		local @FileData=<MSG>;
		local $LogSize = (stat MSG)[7];
		close MSG;

		local $Manual;

		&Call('OpenLogManual');
		if(!$Manual){
			if($res_begin ne '' || $res_end ne ''){
				$res_end = @FileData if($res_end > @FileData);
				if($res_begin > 0){
					if($res_end < $res_begin || !$res_end){
						@FileData = @FileData[$res_begin];
					}else{
						@FileData = @FileData[$res_begin..$res_end];
					}
					&SkinReply(\@FileData);
				}else{
					@FileData = @FileData[$res_begin..$res_end];
					&SkinMain(\@FileData);
				}
			}else{
				&SkinMain(\@FileData);
			}
		}
	}
}
#-----------------------------------------------------------------------------
sub GetLog(){
	my($log,$res,$ref_val,$ref_ex) = @_;
	local $LogFile = &filelog($log);
	my $flag;
	if(-e "$LogFile"){

		open(MSG,"<$LogFile");
		local @FileData = <MSG>;
		local $LogSize = (stat MSG)[7];
		close MSG;

		if($res ne ''){
			local $ResTotal = @FileData -1;
			for($n=1;$n<=$ResTotal;$n++){
				undef %$ref_val;
				undef %$ref_ex;
				&GetLogReplyValue($FileData[$n], $ref_val, $ref_ex);
				if($$ref_val{num} eq $res){
					$flag = $n;
					last;
				}
			}
			&End('ERROR',&Info('DATA_NOTFOUND')) if !$flag;
		}else{
			&GetLogMainValue($FileData[0], $ref_val, $ref_ex);
		}

	}else{&End('ERROR',&Info('DATA_NOTFOUND'))}

	return  $flag;
}

#-----------------------------------------------------------------------------
# 書き込み処理
sub WritePost{eval<<'_SUB_';
	%COOKIE = &GetCookie; # global hash

	&Call('WritePostInit');

	utime time,time,$SYS{ BBSNote }if($CFG{ UseMetaCookie });

	($IP, $HOST)	=	&GetUserIP;
	$DATE		=	&GetDate();

	&End('ERROR',&Info('BAD_REQUEST'))if($ENV{'REQUEST_METHOD'} ne 'POST');


	if($CFG{ JcodePath } && $SYS{ LANGUAGE } eq 'JP'){
		(-e $CFG{ JcodePath }) || &End('ERROR',&Info('BAD_REQUIRE',$CFG{ JcodePath }));
		require $CFG{ JcodePath };
		$SYS{ Jcode } = 1;
	}
	if(exists $IN{edit}){

		# パスワードチェック
		my $pass_ok = &CheckPassword($IN{checkpass}, &GetLogPassword($IN{log}, $IN{edit}));

		&Call('EditLogCheckUser');

		# パス不一致
		if(!$pass_ok){
			&End('ERROR',&Info('PASSWORD_ERROR'));
		}

		# システムカウンタを回さない
		$SYS{ FLAG }{ NO_COUNT } = 1;

		if($IN{edit}){
			# 編集返信モード
			$SYS{ MODE } = 'EDIT_REPLY';
		}else{
			# 編集メインモード
			$SYS{ MODE } = 'EDIT_POST';
			$SYS{ FLAG }{ POST_FORM_TITLE } = 1;

			# ファイル受信許可フラグ
			$SYS{ FLAG }{ FILE_CAPTOR } = 1;
		}

		$IN{resno} = &GetLog($IN{log}, $IN{edit}, \%BLogValue, \%BLogExValue);
		# 書込みフック
		unshift @WriteFilesModeEdit,sub{
			# ファイル番号加算
			if($BLogValue{'file_name'}=~/([a-zA-Z0-9]+\_)(\d+)(\_\d+)?(\.\w+)$/){
				my @f = ($1,$2,$3);
				$FILES{file}{ filename }=~/([a-zA-Z0-9]+\_)(\d+)(\_\d+)?(\.\w+)$/;
				$f[0] = $1;
				$f[2] =~ s/\_(\d+)/$1/;
				$FILE_INC = ++$f[2];
				my $fp = $FILES{file}{ path };
				$FILES{file}{ filename } = $f[0]."$f[1]\_$f[2].$FILES{file}{mime}";
				$FILES{file}{ path } = "$CFG{ DirFilePath }/$FILES{file}{ filename }";
				rename $fp,$FILES{file}{ path };
			}
		
		};
		unshift @WritePostLog,sub{
			$LogValue{num} = $BLogValue{num};
			local $EditPurge = 1 if $FILES{file}{size};

			&Call('WritePostEditPurge');

			# アップロードがあった場合
			if($EditPurge){
				&DeleteFiles($BLogValue{'file_name'},@BLogExValue{'thumbsrc','animesrc'});
				if(!$FILES{object}{size}){
					&DeleteFiles($BLogValue{object});
					delete $LogValue{object};
				}
				delete $BLogExValue{'paint_time'};
				delete $BLogExValue{'thumbsrc'};
				delete $BLogExValue{'animesrc'};
			# アップロードがない場合
			}else{
				my @data = qw/file_name file_width file_height file_length object paint_time applet/;
				@LogValue{@data} = @BLogValue{@data};
			}
			%LogExValue = %BLogExValue;

			# 編集元時間、IP、HOST　保持
			$LogExValue{edit} .= ",$BLogValue{date}@".($BLogValue{iphost}?$BLogValue{iphost}:"$BLogValue{ip}($BLogValue{host})");
			$LogExValue{edit} =~ s/^\,//;
		};

	}elsif(exists $IN{log}){
		# 返信投稿モード
        &CheckReplyEnable(&GetReplyStatus($IN{log}))
            or &End('ERROR',$SYS{ MODE },&Info('CHECK_REPLYERROR'));
		$SYS{ MODE } = 'WRITE_REPLY';
	}else{
		# 通常投稿モード
		$SYS{ MODE } = 'WRITE_POST';

		# ファイル受信許可フラグ
		$SYS{ FLAG }{ FILE_CAPTOR } = 1;

		# タイトル未記入チェックをする
		$SYS{ FLAG }{ POST_FORM_TITLE } = 1;
	}

	# パスワード暗号化
	my $crypt_pass = &CryptString($IN{'password'});

	local %Count;	# カウント用ハッシュ
	local %PM;	# Paintモジュール用ハッシュ
	local %OUT;	#メッセージ出力用ハッシュ
	local %FILES;	#ファイル用ハッシュ

	# 入力チェック
	&CheckInput;

	%OUT = %IN;

	$OUT{message} = &ConvertMessage($IN{message});

	# 二重投稿チェック
	&CheckHistory;

	&Call('WriteCheckInput');

	# ロック
	filelock;

	# カウント取得
	&OpenCount(\%Count);

	local $LogFile = &filelog($IN{log});

	&Call('WritePostMode');

	if($SYS{ MODE } eq 'WRITE_POST'){

		# ログナンバー重複チェック
		my $try;
		while($try < $CFG{ LogMax }){
			$Count{log} = 0 if($Count{log} > 65025);
			$LogFile = &filelog( ++$Count{log} );
			last if(!-e $LogFile);
			$try++;
		}

		# カウント取得不能
		&End('ERROR',&Info('SYS_COUNTERROR')) if($try >= $CFG{ LogMax });

		&Call('WritePostModePost');

		# インデックス追加
		&AddSysIndex($Count{log},'index');

		# ファイルネームヘッダ設定

		&WriteFileNameHead($FILES{file});
		&Call('WriteFilesModePost');

		# ファイル書出
		&WriteFiles(\%FILES);

	}elsif($SYS{ MODE } eq 'WRITE_REPLY' || $SYS{ MODE } eq 'EDIT_REPLY'){

		&End('ERROR',&Info('DATA_NOTFOUND')) if!-e $LogFile;

		&Call('WritePostModeReply');
		&ReplySysIndex($IN{log},'index') if $IN{mail} ne 'sage';

	}elsif($SYS{ MODE } eq 'EDIT_POST'){

		&End('ERROR',&Info('DATA_NOTFOUND')) if!-e $LogFile;

		&Call('WritePostModeEdit');
		$Count{log} = int $IN{log};
		&ReplySysIndex($IN{log},'index') if $IN{mail} ne 'sage';

		# ファイルネームヘッダ設定
		&WriteFileNameHead($FILES{file});

		&Call('WriteFilesModeEdit');

		# ファイル書出
		&WriteFiles(\%FILES);

	}

	# ログ変数
	local %LogValue;

	# 拡張ログ変数
	local %LogExValue;
	undef %LogExValue;


	# ImageMagick
	if(
		$CFG{ UseImageMagick } &&
		$FILES{file}{size} &&
		$FILES{file}{mime} =~ /(jpg|png|gif)/ &&
		!$FILES{object}{size} &&
		-e $FILES{file}{path}
	){
		$FILES{object}={
			mime	=>	$CFG{ ImageMagickFormat },
			size	=>	1,
		};
		&WriteFileNameHead($FILES{object},$CFG{ FileHeadThumb },'',$FILE_INC);
		$CFG{ ImageMagickOption } = "-geometry $CFG{ ImageMagickGeometory }" if!$CFG{ ImageMagickOption };
		`$CFG{ ImageMagickPath } $CFG{ ImageMagickOption } $FILES{file}{path} $FILES{object}{path}`;
		if(!-e $FILES{object}{path}){
			my $n = 0;
			while(-e "$FILES{object}{path}.$n"){
				$n?unlink "$FILES{object}{path}.$n":rename "$FILES{object}{path}.$n",$FILES{object}{path};
				$n++;
			}
		}
		$FILES{object}{size} = -s $FILES{object}{path};
		undef $FILES{object} if(!$FILES{object}{size});
	}


	&Call('WritePostValues');

	@LogValue{&LOG_MAIN_VALUE} = (
		++$Count{num},			# メッセージカウント
		$OUT{name},			# 名前
		$DATE,				# 投稿時間
		$OUT{title},			# タイトル
		$OUT{mail},			# メール
		$OUT{url},			# URL
		$OUT{message},			# メッセージ
		$HOST,				# ホスト
		$IP,				# IP
		$SYS{USER_AGENT},		# ブラウザ
		$FILES{file}{filename},	# 画像ファイル名
		$FILES{file}{width},	# 画像幅
		$FILES{file}{height},	# 画像高さ
		$FILES{file}{size},		# 画像データサイズ
		$crypt_pass,			# パスワード
		$FILES{object}{filename},	# サムネイル or アニメデータのファイル名
		$PM{ paint_time },		# 描画時間
		$PM{ applet_name },		# アプレット情報
	);
	$LogValue{iphost}	=	"$IP\($HOST\)";
	$LogValue{browser}	=	$SYS{USER_BROWSER_VER};
	$LogValue{os}		=	$SYS{USER_OS};

	my @val = qw/name mail url password/;
	@COOKIE{@val} = @IN{@val};

	&Call('WritePostLog');

	# ログ書き込み
	&WriteLogValue($LogFile,\%LogValue,\%LogExValue);

	# ヒストリー書き込み
	local %HistoryValue = (
		'mode'		=>	$SYS{ MODE },
		'time'		=>	time(),
		'log'		=>	$IN{log},
		'ip'		=>	$IP,
		'host'		=>	$HOST,
		'name'		=>	$IN{name},
		'title'		=>	$IN{title},
		'message'	=>	$IN{message},
		'file_size'	=>	$FILES{file}{size},
	);
	&WriteHistory(\%HistoryValue);

	# カウンタ更新
	&SetSysItem('count',"$Count{log}\t$Count{num}") if!$SYS{ FLAG }{ NO_COUNT };

	# トップインデックス更新
	&RefleshIndex;

	# ロック解除
	fileunlock;

	# クッキー出力
	&WriteCookie(\%COOKIE,1);

	$SYS{ MODE } = $IN{log} = '';

	&OpenPage;

_SUB_
if ($@) {
	print "Content-Type: text/html\n\n";
	print "Got an error: $@";
}

}
#-----------------------------------------------------------------------------
# ファイルネームヘッダ設定
sub WriteFileNameHead(){
	my($h,$ih,$num,$inc) = @_;
	return if(!$h->{size});
	$ih = $CFG{ FileHeadImage } if(!$ih);
	$num = $Count{log} if(!$num);

	my $head=(grep{$$h{mime} eq $_}
		$Paint::CFG{ ShiPainter }{anime_ext},$Paint::CFG{ PaintBBS }{anime_ext})?
		$CFG{ FileHeadAnime }:$ih;
	$$h{path}=&filelog($num, $head, $$h{mime}, $inc);
	$$h{filename}=$1 if($$h{path}=~/$CFG{ DirFilePath }\/(.+)/);
}
#-----------------------------------------------------------------------------
sub WriteHistory(){eval<<'_SUB_';
	local $Value = $_[0];

	local($path,$history,$log) = &GetHistoryPath;

	(-w $path) || &End('ERROR',&Info('SYS_NOTWRITE',$path));
	if(!open(LOG,$path)){
		open(LOG,">$path");
	}

	&Call('WriteHistoryBegin');

	my $tmp = &GetTempFileName;
	open TMP,">$tmp";
	print TMP join "\t",map{
		my($name, $val) = ($_,$$Value{$_});

		$name =~ s/([\t\n\r\=])/sprintf("%%%02X", unpack("C", $1))/eg;
		$val =~ s/([\t\n\r\=])/sprintf("%%%02X", unpack("C", $1))/eg;
		"$name=$val";

	}grep $$Value{$_},keys %$Value;
	print TMP "\n";


	my $i = 1;
	while($_=<LOG>){
		$i++;
		last if($i>$log);
		print TMP;
	}

	close TMP;
	close LOG;

	(rename $tmp, $path) || unlink $tmp && &End('ERROR',&Info('SYS_NOTWRITE',$path));
	$SYS{ FLAG }{ GETTEMPFILENAME }--;

	&Call('WriteHistoryEnd');


_SUB_
}
#-----------------------------------------------------------------------------
sub GetHistoryPath{
	my $h = $CFG{ MultiplePosting };
	my $path;
	my $history = 0;
	my $log = 0;
	if(ref $h eq 'ARRAY'){
		my $a;
		foreach $a(@$h){
			foreach(keys %$a){
				if($_ eq 'path'){
					$path = $$a{$_};
					last if $history && $log;
				}elsif($_ eq 'history'){
					$history = $$a{$_};
					last if $path && $log;
				}elsif($_ eq 'log'){
					$log = $$a{$_};
					last if $path && $history;
				}
			}
			last if $path && $history && $log;
		}
	}
	return "$CFG{ DirSysPath }/$path.$CFG{ FileSysExe }",$history,$log;
}
#-----------------------------------------------------------------------------
# 削除処理
sub DeleteLog{eval<<'_SUB_';

	$SYS{ MODE } = $SYS{ MODE }.'DELETE';

	local(@DelList,%List);
	map{push @DelList,$1 if(/^log([\d\-]+)/)}keys %IN;

	&Call('DeleteLogInit');

	# ログ番号指定がない場合、削除モードに戻る
	if($IN{'number'} eq '' && !@DelList){
		return if $SYS{ MODE }=~/ADMIN/;
		&OpenPage;
	}

	# 番号チェック
	my $f;
	foreach(@DelList){if($_ eq $IN{'number'}){$f = 1;last}}
	push @DelList,$IN{'number'} if(!$f);

	# ログ番号分解
	foreach $number(@DelList){
		if($number=~/^(\d+)$/){
			my $log = $1;
			$List{$log} = '';
		}
	}
	# レス番号分解
	foreach $number(@DelList){
		if($number=~/(\d+)\-(\d+)/){
			my $log = $1;
			my $res = $2;
			next if(exists $List{$log} && !$List{$log});
			$List{$log}.= "$res:";
		}
	}


	foreach $log(keys %List){
		my @r = split /:/,$List{$log};
		$r[0] =''if!@r;
		foreach $res(@r){
			# パスワードチェック
			my $pass_ok = &CheckPassword($IN{password}, &GetLogPassword($log, $res));

			&Call('DeleteLogCheckUser');

			# パス不一致
			if(!$pass_ok){
				&End('ERROR',&Info('PASSWORD_ERROR'));
			}
		}
	}


	&Call('DeleteLogBegin');

	filelock;

	foreach $log(keys %List){
		my @r = split /:/,$List{$log};
		$r[0] =''if!@r;
		foreach $res(@r){
			# 返信削除処理
			if($res){	&DeleteLogReply($log,$res)	}
			# メイン削除処理
			else{		&DeleteLogMain($log)	}
		}

	}

	&Call('DeleteLogEnd');

	# トップインデックス更新
	&RefleshIndex;

	# ロック解除
	fileunlock;

	if($SYS{ MODE }=~/ADMIN/){
		$IN{mode}='' if!$#DelList;
		return
	}
	&OpenPage;

_SUB_
}
#-----------------------------------------------------------------------------
# 編集処理
sub EditLog{eval<<'_SUB_';

	$SYS{ MODE } = 'EDIT';

	&Call('EditLogInit');

	# ログ番号指定がない場合、削除モードに戻る
	&OpenPage if($IN{'number'} eq '');


	&Call('EditLogBegin');

	# ログ番号分解
	if($IN{'number'}=~/(\d+)\-(\d+)/)	{	$IN{log} = $1;	$IN{res} = $2	}
	if($IN{'number'}=~/^(\d+)$/)		{	$IN{log} = $1	}

	# パスワードチェック
	my $pass_ok = &CheckPassword($IN{password}, &GetLogPassword($IN{log}, $IN{res}));

	&Call('EditLogCheckUser');

	# パス不一致
	&End('ERROR',&Info('PASSWORD_ERROR'))if(!$pass_ok);

	# 編集元データ取得
	local(%LogValue, %LogExValue);
	$IN{resno} = &GetLog($IN{log},$IN{res}, \%LogValue, \%LogExValue);

	# 初期化フック
	push @SkinPostFormInitBegin,sub{

		# ログデータの取得
		my @data = qw/name mail url message title/;
		@$Values{@data} = @LogValue{@data};
		$$Values{password} = $IN{password};

		# メッセージのタグ解除
		&DeleteTag(\$$Values{message});

		# パスワードの名称変更
		$ITEM_NAME{password} = $ITEM_NAME{newpassword};

		# 返信時のモード変更
		$SYS{ FLAG }{ POST_FORM_TITLE } = 1;


		if($IN{resno}){
			$SYS{ FLAG }{ POST_FORM_TITLE } = 0;
			$CFG{ UseImageUpload } = 0;
		}

		&Call('EditLogPostFormInit');

	};

	# 初期化フック２
	push @SkinPostFormInitEnd,sub{
		# パスワード値を追加
		my $form_p = {
				TAG	=>	'INPUT',
				type	=>	'hidden',
				name	=>	'checkpass',
				value	=>	$IN{password},
			};
		&SetForm(\@FORMS,\$form_p,'right','fc');


		# 編集フラグを追加
		my $form_f = {
				TAG	=>	'INPUT',
				type	=>	'hidden',
				name	=>	'edit',
				value	=>	$IN{res},
			};
		&SetForm(\@FORMS,\$form_f,'right','fc');
	};


	&Call('EditLogEnd');

	&MailCrypt;

	&SkinPostForm;

	&SkinFoot;

	exit;

_SUB_
}
#-----------------------------------------------------------------------------
# メイン削除処理
sub DeleteLogMain(){eval<<'_SUB_';
	my $log = $_[0];
	local $LogFile = &filelog($log);
	local $NotDelSysIndex;
	open(MSG,"<$LogFile");
	$_ = <MSG>;

	&GetLogMainValue($_, \%LogValue, \%LogExValue);

	&Call('DeleteLogMainBegin');

	&DeleteFiles(@LogValue{'file_name','object'},@LogExValue{'thumbsrc','animesrc'});
	close MSG;

	unlink $LogFile;

	&Call('DeleteLogMainEnd');

	&DeleteSysIndex($log,'index')if!$NotDelSysIndex;

_SUB_
}
#-----------------------------------------------------------------------------
# 返信削除処理
sub DeleteLogReply(){eval<<'_SUB_';
	my($log,$res) = @_;
	local $LogFile = &filelog($log);
	local $NotDelSysIndex;

	&Call('DeleteLogReplyBegin');

	# 返信削除
	my $tmp = &GetTempFileName;
	open TMP,">$tmp";
	open MSG,"<$LogFile";
	while(<MSG>){
		local(%LogValue, %LogExValue);
		&GetLogReplyValue($_, \%LogValue, \%LogExValue);
		if($LogValue{num} eq $res){
			&Call('DeleteLogReplyData');
		}else{
			print TMP
		}
	}
	close MSG;
	close TMP;
	(rename $tmp, $LogFile) || unlink $tmp && &End('ERROR',&Info('SYS_NOTWRITE',$path));
	$SYS{ FLAG }{ GETTEMPFILENAME }--;

	if(!-s $LogFile){
		unlink $LogFile;
		&DeleteSysIndex($log,'index')if!$NotDelSysIndex;
	}

	&Call('DeleteLogReplyEnd');

_SUB_
}
#-----------------------------------------------------------------------------
# ログ書き込み処理
sub WriteLogValue(){eval<<'_SUB_';
	my($logfile,$val,$ex) = @_;

	# 拡張領域
	my $add_format = join"\b",(map{
		$$ex{$_}=~s/\x08|\n//go;
		"$_=$$ex{$_}";
	}grep{$$ex{$_}ne''}keys %$ex);

	$add_format =~ s/\x08$//;

	map{$$val{$_}=~s/\t|\n//go}keys %$val;

	# ログ メッセージフォーマット
	local $MsgFormat;
	if($SYS{ MODE } =~ /WRITE/){

		if($SYS{ MODE } =~ /POST/){
			open(LOG,">$logfile")||&End('ERROR',&Info('BAD_WRITE',$logfile));
			$MsgFormat= join "\t",@$val{&LOG_MAIN_VALUE}, $add_format;
		}elsif($SYS{ MODE } =~ /REPLY/){
			open(LOG,">>$logfile")||&End('ERROR',&Info('BAD_WRITE',$logfile));
			$MsgFormat= join "\t",@$val{&LOG_REPLY_VALUE}, $add_format;
		}
		&Call('WriteLogValuePrint');
		print LOG $MsgFormat."\n" if $MsgFormat;

	}elsif($SYS{ MODE } =~ /EDIT/){

		open(MSG,"<$logfile");
		local @FileData=<MSG>;
		local $LogSize = (stat MSG)[7];
		close MSG;

		open(LOG,">$logfile")||&End('ERROR',&Info('BAD_WRITE',$logfile));

		if($SYS{ MODE } =~ /POST/){
			$MsgFormat= join "\t",@$val{&LOG_MAIN_VALUE}, $add_format;
			&Call('WriteLogValuePrint');
			$FileData[0] = $MsgFormat."\n";
			foreach(@FileData){
				print LOG;
			}
		}elsif($SYS{ MODE } =~ /REPLY/){
			$MsgFormat= join "\t",@$val{&LOG_REPLY_VALUE}, $add_format;
			foreach(@FileData){
				if(/^(\d+)/ && $$val{num} eq $1){
					print LOG $MsgFormat."\n";
					next;
				}
				print LOG;
			}
		}
	}

	close LOG;

	chmod $CFG{ FileLogPermission },$logfile;

_SUB_
}
#-----------------------------------------------------------------------------
# ログスレッド変数セット
sub SetLogMainValue(){
	my($ref_data,$ref_val,$ref_ex) = @_;

	$ref_data->{ThumbnailSrc}	= (grep /\.(jpg|png|gif)$/i,$ref_val->{object},$ref_ex->{thumbsrc})[0];
	$ref_data->{AnimeSrc}		= (grep /\.(pch|spch|jpeg|pnm)$/i,$ref_val->{file_name},$ref_val->{object},$ref_ex->{animesrc})[0];
	$ref_data->{ImageSrc}		= (grep /\.(jpg|png|gif)$/i,$ref_val->{file_name})[0];
	$ref_data->{ImageEnable}	= $ref_data->{ImageSrc} || $ref_data->{ThumbnailSrc} ? 1:0;

}
#-----------------------------------------------------------------------------
# ログ読み込み処理
sub GetLogValue(){
	my($ref_data,$ref_val,$ref_ex,$format) = @_;

	chomp $ref_data;
	my $add_format;
	if($format eq 'MAIN'){
		(@$ref_val{&LOG_MAIN_VALUE},$add_format) = split "\t",$ref_data;
	}else{
		(@$ref_val{&LOG_REPLY_VALUE},$add_format) = split "\t",$ref_data;
	}

	foreach(split/\x08/, $add_format){s/^([^=]*)=(.*)$/$ref_ex->{$1} = $2/e};

}
sub GetLogMainValue(){	&GetLogValue(@_[0..2], 'MAIN')	}
sub GetLogReplyValue(){	&GetLogValue(@_, 'REPLY')	}
#-----------------------------------------------------------------------------
# 投稿ページの表示
sub OpenPost{eval<<'_SUB_';

	if(exists $IN{log}){
	&MailCrypt;
		$SYS{ MODE } = exists $IN{edit}?'EDIT':'REPLY';
		$CFG{ UseImageUpload } = 0;
	}else{
		$SYS{ MODE } = 'POST';
		$SYS{ FLAG }{ POST_FORM_TITLE } = 1;
		if(!$CFG{ UseImageUpload } && $CFG{ NotCommentOnly }){
			&End('ERROR',&Info('FUNCTION_CANNOTEXE'));
		}
	}

	%COOKIE = &GetCookie;

	&Call('OpenPostInit');

	&SkinPostForm;

	&SkinFoot;

	exit;

_SUB_
}
#-----------------------------------------------------------------------------
# カウントの取得
sub OpenCount(){eval<<'_SUB_';
	return if $SYS{ FLAG }{ NO_COUNT };
	$ref = $_[0];
	my $l_count;
	&GetSysItem('count',\$l_count) || ($l_count = "1\t1");
	@$ref{'log','num','obj'} = split /\t/,$l_count;
	$$ref{log} = 1 if($$ref{log} > 65025);
	$$ref{num} = 1 if($$ref{num} > 65025);

_SUB_
}
#-----------------------------------------------------------------------------
# &GetForm(\@forms) フォームの縦横構造数を配列[縦、横]で返す。0=NULL
# &GetForm(\@forms,[name]) フォームの[name]がどの位置にあるか配列[縦、横]返す。
sub GetForm(){
	my($a,$name) = @_;
	my($r,$c,$d,$e);
	$r = 0;
	$d = 0;
	foreach(@$a){
		$c = 0;
		foreach(@$_){
			my @array;
			$e = 0;
			&GetRef($_,\@array);
				foreach(@array){
					if($name){
						if($$_{name} eq $name){
							return ++$r,$c,$e,$_;
						}
					}
					$e++;
				}
			$c++ if(@array);
		}
		$d = $c if($d < $c);
		$r++ if($c);
	}

	if(!$name){	return $r,$d	}
	else{		return -1,-1	}

}
#-----------------------------------------------------------------------------
# ファーム構造体の操作
# 成功 操作先座標(row col),失敗 (-1,-1)
sub SetForm(){
	my $a = $_[0];		# structure forms array reference
	my $e = $_[1]; 		# structure forms tag elements reference
	my $option = $_[2];	# option : insert,add,left,right,replace,delete
	my $target = $_[3];	# target : pos[row,col] or form name

	my($row,$col,$el,$ref_name) = split ',',$target;
	my $name = $row if($col eq '');
	if($option eq 'add' && !$name){
		$row = $#$a;
	}else{
		($row,$col,$el,$ref_name) = &GetForm($a,$name)if($name);
	}

	return -1,-1 if($row<0 || $col<0);

	if($option eq 'add' || $option eq 'insert'){
		my @ref = $$e;
		if(ref $$e eq 'ARRAY' && ref $ref[0] eq 'ARRAY' && ref $ref[0][0] eq 'ARRAY'){
			if($option eq 'add')		{	$row++		}
			elsif($option eq 'insert')	{	$row--		}
			splice @$a,$row,0,@ref;
			return $row,0;
		}
		&End('ERROR',&Info('DEFF_FORM_ARRAY_TYPE_ROW'));
	}

	$row--;
	if($option eq 'delete'){
#		my $ref = $$a[$row];
#		return $row,$col if(splice @$ref,$col,1)
		my $ref = $$a[$row][$col];
		return $row,$col if(splice @$ref,$el,1)
	}
	if($option eq 'replace'){
		my @ref = $$e;
		if(ref $$e eq 'ARRAY'){
			if(ref $ref[0] eq 'ARRAY'){
				if(ref $ref[0][0] eq 'ARRAY'){
					splice @$a,$row,1,@ref;
					return $row,0;
				}elsif(ref $ref[0][0] eq 'HASH'){
					my $ref = $$a[$row][$col];
					my $r = $$e;
					@$ref = @$r;
					return $row,$col;
				}
			}
		}elsif(ref $$e eq 'HASH'){
			my $ref = $$e;
			%$ref_name = %$ref;
			return $row,$col;
		}
		&End('ERROR',&Info('DEFF_FORM_ARRAY_TYPE_ROW'));
	}
	if($option eq 'left'){
		my $ref = $$a[$row][$col];
		if($el>0){
			splice @$ref,$el,0,$$e;
		}else{
			unshift @$ref,$$e;
		}
		return $row,$col,$el;
	}
	if($option eq 'right'){
		my $ref = $$a[$row][$col];
		$el+=2;
		splice @$ref,$el,0,$$e;
		return $row,$col;
	}

	return -1,-1;
}
#-----------------------------------------------------------------------------
# ファーム構造体は使い捨て。 同配列のファーム構造体を再使用する時は再構築する事
# colspan or rowspan は2以下が指定される場合は属性削除される。
sub CreateForm(){
	my $a = $_[0];		# structure forms array reference
	my $e = $_[1];		# structure forms tag elements reference
	my $t = $_[2];		# structure table tag elements reference
	my($r,$c,$h);
	my $form;
	my($mr,$mc) = &GetForm($a);
	$r = 0;
	$t={TAG=>TABLE}if(!$t);

	foreach(@$a){
		$c=0;
		my $f1 = 1;
		my $fs;
		foreach(@$_){
			my $f2 = 1;
			my $fv;
			$fs.="<TD";
			&End('ERROR',&Info('DEFF_FORM_ARRAY_TYPE_ROW')) if(ref ne 'ARRAY');
			foreach(@$_){
				my @array;
				my $ref;
				my $cref = ref;
				&GetRef($_,\@array);
				foreach $ref(@array){
					if($cref eq 'ARRAY'){
						if($$ref{TAG} eq 'TD'){
							delete $$ref{TAG};
							$$ref{rowspan}=$mr if($$ref{rowspan} eq '*');
							$$ref{colspan}=$mc if($$ref{colspan} eq '*');
							delete $$ref{rowspan} if($$ref{rowspan}<2);
							delete $$ref{colspan} if($$ref{colspan}<2);
							foreach(keys %$ref){
								if($_ eq 'nowrap'){
									$fs.=qq/ $_/;
								}else{
									$fs.=qq/ $_="$$ref{$_}"/;
								}
							}
							undef %$ref;
							next;
						}
					}
					if($f2){
						$fs.=">";
						$f2 = 0;
					}
					$f1=0 if($$ref{type} eq 'hidden');

				}
				if(!$f1){
					$h.="\n".&SetTag(@array);
				}elsif(@array){
					$fv.=&SetTag(@array);
				}
			}
			$f1=0 if(!$fv);
			$fs.=$fv."</TD>\n";
		}
		if($f1 && $fs){
			$form.="<TR>\n";
			$form.=$fs;
			$form.="</TR>\n";
		}
	}
	return &SetTag($t,{string=>&SetTag($e,{string=>$h.$form})})."\n";

}
#-----------------------------------------------------------------------------
# ページ切り替えタグ生成
sub CreatePageLink{eval<<'_SUB_';

	$CFG{ StylePageLink } = 1 if($SYS{ MODE } =~ /ADMIN/);

	my($linktext, $linkform);

	my($fc, $mode, $page, $sort, $pl) = (@IN{'fc', 'mode', 'page', 'sort'},$CFG{ ViewLimitPageLink });


	if($SYS{ FLAG }{ RefleshIndex }){
		$passwrd=$fc=$mode='';
	}
	if(!$SYS{ FLAG }{ CreatePageLink }){
		my $maxpage = int ($LogTotal / $CFG{ LogView });
		$maxpage++ if($LogTotal-($maxpage * $CFG{ LogView }) > 0);
		return if($maxpage < 2);

		$fc = 'page'if($fc eq '' || $fc eq 'write');

		$page = int $page;
		$page= 1 if(!$page > 0);


		$SYS{ ARG }{ PageLink }{'fc'} = $fc;
		$SYS{ ARG }{ PageLink }{'mode'} = $mode;
		$SYS{ ARG }{ PageLink }{'sort'} = $sort;

		&Call('CreatePageLinkInit');

		my($i,$n,$mblock,$pblock,$pos);
		if($pl){
			$mblock = int($maxpage / $pl);
			$pblock = int(($page-1) / $pl);
			$pos = $pblock * $pl;
		}
		my $arg = &SetTextGlobalArg($SYS{ ARG }{ PageLink });
		my $href = "<A href=\"$CFG{ BBSNoteUrl }?$arg&page=";

		for($i = 0; $i <= $maxpage; $i++){
			$n++;
			if($n == $page){
				if($n - 1 > 0){
					$linktext .= $href.($n-1).'">&lt;&lt; <B>NEXT</B> </A>|';
				}
				if($n < $maxpage){
					$linktext .= '|'.$href.($n+1).'"> <B>BACK</B> &gt;&gt;</A>';
				}
				last;
			}
		}
		$linktext .= '<A name="pages"> PAGE </A>';

		if($pl && $pblock){
			$n = $pblock * $pl;
			$linktext .= "[$href".($pblock * $pl).'">&lt;&lt;</A>]';
		}
		for($i = 0, $n = $pos; $i < $maxpage-$pos; $i++){
			$n++;
			if($n == $page){
				$linktext .= '[<B><FONT style="text-decoration:underline">'.$n.'</FONT></B>]';
				next;
			}
			if($pl && $i >= $pl){
				$linktext .= "[$href$n\">&gt;&gt;</A>]";
				last;
			}
			$linktext .= "[$href$n\">$n</A>]";
		}

		#===========================================

		# 管理モード：パスワードを付加 トップ更新時はつけない
		$SYS{ ARG }{ PageLink }{ password } = $CFG{ AdminPassword } if($SYS{MODE}eq'ADMIN'&&!$SYS{FLAG}{RefleshIndex});

		$arg = &SetFormGlobalArg($SYS{ ARG }{ PageLink });

		my $formtag='<TABLE><TR><FORM method=post action="'.$CFG{ BBSNoteUrl }.'">'.$arg.'<TD>';

		$linkform='<TABLE><TR><TD>';
		for($i = $maxpage, $n = 0; $i > 0; $i--){
			$n++;
			if($n == $page){
				if($n - 1 > 0){
					$linkform .= $formtag.'<INPUT type=hidden name=page value='.($n-1).'><INPUT class=button type=submit value="<< NEXT"></TD></FORM></TR></TABLE></TD><TD>';
				}
				if($n < $maxpage){
					$linkform .= $formtag.'<INPUT type=hidden name=page value='.($n+1).'><INPUT class=button type=submit value="BACK >>"></TD></FORM></TR></TABLE></TD><TD>';
				}
				last
			}
		}

		$n=0;
		$linkform .= $formtag.'<SELECT name=page class=button onchange="this.form.submit()">';

		while($maxpage > 0){
			$n++;
			$maxpage--;
			my $select=' selected' if($n == $page);
			$linkform .= "<OPTION value='$n'$select>$n</OPTION>";
		}

		$linkform .= '</SELECT></TD></FORM></TR></TABLE></TD></TR></TABLE>';

		$SYS{ FLAG }{ CreatePageLink } = 1;
	}

	return $linktext, $linkform;

_SUB_
}
#-----------------------------------------------------------------------------
sub ResetJavaScript(){eval<<'_SUB_';
	my $h = $SYS{ JAVASCRIPT }{FLAG};
	if($_[0]){	undef $$h{$_[0]}	}
	else{		undef %$h		}
_SUB_
}
#-----------------------------------------------------------------------------
# 内蔵Javascript
sub GetJavaScript(){
	my($js,$ref,@arg) = @_;
	my $h = $SYS{ JAVASCRIPT };
	return 0 if($$h{FLAG}{$js});

if($$h{$js}){
	$$h{FLAG}{$js} = 1;
	$$ref.=$$h{$js};
	return 1;
}

#< GetAgent >=================================================================
if('GetAgent' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
var ua,an,type,nn,ie,op,mac,win;
ua = navigator.userAgent.toUpperCase();
an = navigator.appName.toUpperCase();
av = navigator.appVersion;
function GetAgent(){
if (an.indexOf("NETSCAPE") >= 0){
	s = av.indexOf(" ",0);
	type = eval(parseInt(av.substring(0,s)));
}else if (an.indexOf("MICROSOFT") >= 0){
	s = av.indexOf("MSIE ",0) + 5;
	e = av.indexOf(";",s);
	type = eval(parseInt(av.substring(s,e))-4);
}
if (ua.indexOf("MAC") >= 0)			{ mac=1 }
else if (ua.indexOf("WIN") >= 0)		{ win=1 }
if (ua.indexOf("OPERA") >= 0 || window.opera)	{ op=1 }
else if (an.indexOf("NETSCAPE") >= 0)		{ nn=1 }
else if (an.indexOf("MICROSOFT") >= 0)		{ ie=1 }
}GetAgent();

SRC
return 1;
}
#</GetAgent/>=================================================================

#< MM_showHideLayers >========================================================
if('MM_showHideLayers' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_showHideLayers() { //v3.0
  var i,p,v,obj,args=MM_showHideLayers.arguments;
  for (i=0; i<(args.length-2); i+=3) if ((obj=MM_findObj(args[i]))!=null) { v=args[i+2];
    if (obj.style) { obj=obj.style; v=(v=='show')?'visible':(v='hide')?'hidden':v; }
    obj.visibility=v; }
}

SRC
return 1;
}
#</MM_showHideLayers/>========================================================

#< MM_findObj >===============================================================
if('MM_findObj' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_findObj(n, d) { //v4.0
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && document.getElementById) x=document.getElementById(n); return x;
}

SRC
return 1;
}
#</MM_findObj/>===============================================================

#< MM_swapImage >===============================================================
if('MM_swapImage' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}

SRC
return 1;
}
#</MM_swapImage/>===============================================================

#< MM_swapImgRestore >===============================================================
if('MM_swapImgRestore' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

SRC
return 1;
}
#</MM_swapImgRestore/>===============================================================

#< MM_preloadImages >============================================================
if('MM_preloadImages' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_preloadImages() { //v3.0
 var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
   var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
   if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

SRC
return 1;
}
#</MM_preloadImages/>============================================================

#< MM_reloadPage >============================================================
if('MM_reloadPage' eq $js){
	$$h{FLAG}{$js} = 1;
$$ref.=<<SRC;
function MM_reloadPage(init) {  //reloads the window if Nav4 resized
  if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
    document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
  else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
}
MM_reloadPage(true);

SRC
return 1;
}
#</MM_reloadPage/>============================================================

#< BN_mailcrypt >============================================================
if('BN_mailcrypt' eq $js){
	$$h{FLAG}{$js} = 1;
	my @a = (A..Z,a..z);
	my($s,$i1,$i2);
	srand;
	foreach(@a){
		$i1 = int rand 51;
		$i2 = int rand 51;
		$s = $a[$i1];
		$a[$i1] = $a[$i2];
		$a[$i2] = $s;
	}
	$SYS{ FLAG }{ mailcrypt } = join ',',@a;
	my $b = join ',',map{"\'$_\'"}@a;

$$ref.=<<SRC;
function BN_mailcrypt(str){
	var len = str.length
	var a = new Array($b);
	var n = 0
	var r = ''
	while(n<len){
		s = str.substr(n,1)
		c = s.charCodeAt(0)
		if(c > 64 && 91 > c){
			r+=a[c-65]
		}else if(c > 96 && 123 > c){
			r+=a[c-71]
		}else{
			r+=s
		}
		n++
	}
	return 'mailto:' + r
}

SRC
return 1;
}
#</BN_mailcrypt/>============================================================

#< LayerForm >================================================================
if('LayerForm' eq $js){
	$$h{FLAG}{$js} = 1;
	my($close,$submit);
	local $NNSendScript;
	my $logno = $CFG{ ViewThreadNumber }==2?'no':'log';
	my $arg = &SetTextGlobalArg($SYS{ ARG }{ LayerFormOut });
	$arg = "+\'&$arg\'"if($arg);
if($SYS{ USER_BROWSER_VER } =~ /NN 4/){

	&Call('GetJavaScriptLayerFormNN4');

	$close = '<FONT size=2><INPUT type=button value="Ｘ" onclick="MM_showHideLayers(\'Comment\',\'\',\'hide\')" width=20 height=20>';
	$submit = '<INPUT type=button value="'.$arg[2].'" onclick="LF_nnsend()">';
	my $farg = &SetFormGlobalArg($SYS{ ARG }{ ReplyForm });

${$arg[0]}.=<<SRC;
<form method=post name="nnsend" action="$CFG{ BBSNoteUrl }">
<input type=hidden name="fc" value="write"><input type=hidden name="log">
<input type=hidden name="name"><input type=hidden name="mail">
<input type=hidden name="url"><input type=hidden name="message">
<input type=hidden name="mode" value="$IN{mode}">
<input type=hidden name="sort" value="$IN{sort}">
<input type=hidden name="page" value="$IN{page}">
<input type=hidden name="password">
$farg</form>

SRC
}else{
	$close = '<A onclick="MM_showHideLayers(\'Comment\',\'\',\'hide\')"><IMG src="'.$CFG{ DirImagesUrl }.'/lf_close.gif" alt="'.$text[0].'"></A>';
	$submit = '<INPUT class=button type=submit value="'.$arg[2].'">';
}


	my $tag = $arg[1];
	$tag =~ s/\$close/$close/;
	$tag =~ s/\$submit/$submit/;
	${$arg[0]}.=$tag;

	my @text = &Info('LAYERFORM_TEXT');

	# $arg[2]; 送信ボタンテキスト

$$ref.=<<SRC;
var d = document;
var log,no,t,d_d,p,lfb,lfx,iex,gX,gY;
function LF_open(lrn,lvn,e,m){
	var d = document;

	log = lrn;
	no = lvn;
	d_d = 0;
	window.onerror=LF_out;
	if(ie && type >= 0){
		x = e.clientX; y = e.clientY;
	}else if(nn && type == 5){
		x = e.pageX; y = e.pageY;
	}else if(op || ( nn && type == 4)){
		x = gX; y = gY;
	}else{
		LF_out()
	}
	LF_title(m);
	lfb = MM_findObj("layerbar");
	lfb.value=t;
	p = MM_findObj("Comment");
	status= type + " " + gX + "x" + gY
	if((!op && type < 4) || (op && type!=1)){
		if(document.body.scrollTop) y+=document.body.scrollTop
		if(document.body.scrollLeft) x+=document.body.scrollLeft
	}
	if(p.style){p=p.style}
	p.left = x - 370;
	iex = parseInt(p.left);

	if (ie){
		p.top = y + 15;
		p.filter = "Alpha(Opacity=100, FinishOpacity=85, Style=1, StartX=1, StartY=1, FinishX=30, FinishY=30)";
	}else if(op || (nn && type > 3)){
		p.top = y + 18;
	}

	MM_showHideLayers('Comment','','show');
	if(type==4){d.nnsend.log.value = log}
	else{d.layerform.log.value = log}
}
var d = document
if(d.layers){
	d.captureEvents(Event.MOUSEMOVE);
}
	d.onmousemove=LF_capture;
function LF_out() {window.location=unescape('$CFG{ BBSNoteUrl }?fc=post&log='+log+'&no='+no$arg)}
function LF_title(m){
	a="";len=0;
	tlen = m.length+(log+"").length
	limit = win?type>=4?55:60:35;
	for (i=0; i<tlen && len < limit; i++,len++){
		c = escape(m.charAt(i));
		if( c.length > 3 ) len++
	}
	if(len>=limit){
		m = m.substring(0,i) + '...';
	}else{
		if(op){limit-=2}else{limit+=2}
		for(i=len;i<limit;i+=2){a+="　"}
	}
	t="No."+ $logno +"$text[1]" + m + "$text[2]$text[3]"+a;
}
function LF_drag(event){
	d_d=d_d?0:1;
	if(event.clientX){lfx = event.clientX}
	lfb.value="DRAG";
	if((op||type==4||(mac&&ie))&&!d_d){lfb.value=t}
}
function LF_drop(){
	if(op||type == 4){return}
	if(mac && ie){iex = parseInt(p.left);return}
	d_d=0;lfb.value=t;
	if (d.all && type){iex = parseInt(p.left)}
}
function LF_move(gX,gY){
	if(ie|(op && type>1)){
		p.visibility = "hidden";
		p.left = gX - ( lfx - iex);
		p.top = gY + document.body.scrollTop - 15;
		p.visibility = "visible";
	}else{
		p.left = gX - 200;
		p.top = gY - 20;
	}
}

function LF_capture(e){
	var p = MM_findObj("Comment");
	if(document.all){gX=event.clientX;gY=event.clientY}
	else if(op){gX=e.clientX;gY=e.clientY}
	else if(nn){gX=e.pageX;gY=e.pageY}
	if(d_d){LF_move(gX,gY)}
}
function LF_nnsend(){
	lff = MM_findObj("layerform");
	s = MM_findObj('nnsend');
	s.name.value = lff.name.value;
	s.mail.value = lff.mail.value;
	s.url.value = lff.url.value;
	s.message.value = lff.message.value;
	s.password.value = lff.password.value;
	$NNSendScript
	s.submit();
}

SRC

return 1;
}
#</LayerForm/>================================================================

#< LayerFormScript >==========================================================
if('LayerFormScript' eq $js){
	$$h{FLAG}{$js} = 1;
	&GetJavaScript('GetAgent',$ref);
	&GetJavaScript('LayerForm',$ref,@arg);
	&GetJavaScript('MM_findObj',$ref);
	&GetJavaScript('MM_showHideLayers',$ref);
	&GetJavaScript('MM_reloadPage',$ref);
return 1;
}
#</LayerFormScript/>==========================================================

	return -1;

}
#-----------------------------------------------------------------------------
# 内蔵Javascriptにセット
sub SetJavaScript(){
	my($js,$src) = @_;
	my $h = $SYS{ JAVASCRIPT };
	$$h{$js} = $src;
}
#-----------------------------------------------------------------------------
# GetRef([hash],[hash reference put array ref])
sub GetRef(){
	my($ref,$p) = @_;
	my $r = ref $ref;
	if($r eq 'HASH'){
		push @$p,$ref;
	}elsif($r eq 'REF'){
		&GetRef($$ref,$p);
	}elsif($r eq 'ARRAY'){
		foreach(@$ref){	&GetRef($_,$p) }
	}
}
#-----------------------------------------------------------------------------
sub SetTag(){
# FONT stringがない場合はタグ生成しない
# noclose の指定がある場合はstringが無くてもタグ生成する。
# bold <B> 追加
# italic <I> 追加
# under <U> 追加
# teletype <TT> 追加
# bgcolor style="background-color" 追加
# background style="background-image:url()" 追加

# IMG src 必須
# A href 必須

	my @ref = @_;
	my($hash,%t,$r);

	foreach(@ref){
		my($tag,@a,%e);

		&GetRef($_,\@a);
		foreach $hash(@a){
			$tag = $$hash{TAG} ? uc $$hash{TAG} : 'FONT';
			if($t{$tag}){
				$r = $t{$tag};
				foreach(keys %$r){
					$e{$_}=$$r{$_};
				}
			}
			$t{$tag}=\%e;

			foreach(keys %$hash){
				my $l = lc $_;
				if('tag' eq $l){
					$tag = uc $$hash{$_};
					$t{$tag}=\%e;
				}
				else{
					$e{$l}=$$hash{$_};
				}
			}
		}
	}

	my(@si,@st,@ed,@str);
	foreach(keys %t){
		my $tag = $_;
		my($noclose,$string,@s,@el,@style,%css);
		@style  = qw/bold italic under teletype bgcolor background/ if($tag!~/^(IMG|INPUT|TABLE|META|BODY)$/);
		$r=$t{$_};

		next if(($tag eq 'IMG' && !$$r{src})||($tag eq 'A' && !$$r{href}));

		if($$r{string}){
			$string = delete $$r{string};
			push @str,$string if($tag ne 'TEXTAREA');
		}
		if(exists $$r{string}){	delete $$r{string} }
		if(exists $$r{noclose}){
			$noclose = $$r{noclose};
			delete $$r{noclose};
		}
		if($$r{alt}&&!$$r{title}){
			$$r{title} = $$r{alt};
		}
		if($$r{face}){
			my $f = 1;
			foreach(split ',',$$r{face}){
				if(/Osaka/){
					$f = 0;
					last;
				}
			}
			$$r{face}.=',Osaka'if($f);
		}

		if(exists $$r{style}){
			foreach(split ';',$$r{style}){
				my($name,$val) = split ':';
				$name=~s/[^\w\-]//g;
				$name=~s/(^\s+|\s+$)//g;
				$val =~s/(^\s+|\s+$)//g;
				if($name){
					$css{$name}=$val;
				}
			}
			delete $$r{style};
		}

		foreach(@style){
			if(exists $$r{$_}){
				if($$r{$_}){
					if(/bold/){
						push @st,'<B>';
						unshift @ed ,'</B>';
					}elsif(/italic/){
						push @st,'<I>';
						unshift @ed ,'</I>';
					}elsif(/under/){
						push @st,'<U>';
						unshift @ed ,'</U>';
					}elsif(/teletype/){
						push @st,'<TT>';
						unshift @ed ,'</TT>';
					}elsif(/bgcolor/){
						$css{'background-color'}=$$r{$_};
					}elsif(/background/){
						$css{'background-image'}="url($$r{$_})";
					}
				}
				delete $$r{$_};
			}
		}
		foreach(keys %css){ push @s,"$_:$css{$_}" }
		if(@s){push @el,'style="'.(join ';',@s).'"'}

		foreach(keys %$r){ if($$r{$_} ne ''){push @el,"$_=\"$$r{$_}\""} }


		if($tag=~/^(IMG|INPUT|HR|META|LINK|BODY)$/){
			push @str,(join ' ','<'.$tag,@el).'>';
		}elsif($tag eq 'TEXTAREA'){
			push @str,(join ' ','<'.$tag,@el).'>'.$string."</$tag>";
		}else{
			next if($tag eq 'FONT' && !@el);
			if(!$noclose){
				push @st,(join ' ','<'.$tag,@el).'>';
				unshift @ed , "</$tag>";
			}else{

				push @si,(join ' ','<'.$tag,@el).'>';
			}
		}

	}
	$s = join '',@si;
	$s .= (join '',@st).(join '',@str).(join '',@ed)if(@str);
	return $s;
}
#-----------------------------------------------------------------------------
# 引数設定
sub SetGlobalArg(){
	my $flag = shift @_;
	push @_,$SYS{ ARG }{ Global };
	my %h;
	foreach $a(@_){
		map{$h{$_}=$$a{$_}}keys %$a;
	}
	return join '&',(map{"$_=$h{$_}"}grep{$h{$_}ne''}keys %h) if($flag == 0);
	return join '',(map{"<INPUT type=hidden name='$_' value='$h{$_}'>"}keys %h)if($flag == 1);
	return %h;

}
sub SetTextGlobalArg(){return &SetGlobalArg(0,@_)}
sub SetFormGlobalArg(){return &SetGlobalArg(1,@_)}
sub SetInitGlobalArg(){
	my($form,@arg) = ($_[0],@_[1..$#_]);
	my %h = &SetGlobalArg(2,@arg);
	foreach(keys %h){
		my $form_info=[[[{
			TAG	=>	'INPUT',
			type	=>	'hidden',
			name	=>	$_,
			value	=>	$h{$_},

		}]]];
		&SetForm($form,\$form_info,'insert','0,0');
	}
}
#-----------------------------------------------------------------------------
sub HttpHead{

	return if $SYS{ FLAG }{ HTTPHEAD };
	$SYS{ FLAG }{ HTTPHEAD } = 1;
	&Call('HttpHeadInit');

	if(!$SYS{ FLAG }{ MANUALHTTP }){
		$SYS{ HTTPCONTENTTYPE } = 'text/html' if!$SYS{ HTTPCONTENTTYPE };
		print "Content-type: $SYS{ HTTPCONTENTTYPE }\n";
		if($CFG{ HttpPragma }){
			print "Expires: 0\n";
			print "Pragma: no-cache\n";
		}
		print "\n";
	}

}

#-----------------------------------------------------------------------------
sub GetIn{
	undef %IN;my($s,@p,$n,$v);
	binmode(STDIN);binmode(STDOUT);

	if($ENV{'CONTENT_TYPE'} =~ /^multipart\/form-data/) {
		my($b,@forms);
		my $CR="\r\n";
		if($ENV{'REQUEST_METHOD'} eq 'GET'){$s=$ENV{QUERY_STRING}}
		else{read (STDIN, $s, $ENV{'CONTENT_LENGTH'})}
		split(/$CR/,$s,2);
		$b=quotemeta @_[0];
		@forms=split /$CR$b(?:--)?$CR/,$s;

		foreach(@forms) {
			my(%names,$f);
			my($head,$data)=split(/$CR$CR/,$_,2);
			$head =~ s/$CR/; /g;
			$head =~ s/: /=/g;
			$head =~ s/"//g;

			my @p=split(/; /,$head);
			foreach(@p){
				my($n,$v)=split /=/,$_,2;
				if($n eq 'name'){
					next if($f);
					$f=1;
				}
				if($n =~ /^(name|filename)$/){
					$names{$n}=$v
				}
			}
			foreach(keys(%names)){
				$IN{"$names{name}_$_"}=$names{$_}if($_ ne'name');
			}
			$IN{$names{name}}=$data;
		}
	}else{
		&Call('GetInStream');
		if($ENV{'REQUEST_METHOD'} eq 'GET'){ $s=$ENV{QUERY_STRING} }
		else{read (STDIN, $s, $ENV{'CONTENT_LENGTH'})}
		&unescape(\$s);
        @p = split '&', $s;
		for(@p){
			($n, $v)=split '=', $_, 2;
			$IN{$n}=$v;
		}
	}
}

#-----------------------------------------------------------------------------
# インデックスログを開く
# &OpenSysIndex(INDEX , 'index');
sub OpenSysIndex(){eval<<'_SUB_';

	my($fp, $index) = @_;
	$path = "$CFG{ DirSysPath }/$index.$CFG{ FileSysExe }";
	open $fp,"<$path" or &End('ERROR',&Info('SYS_NOTINDEXOPEN',$path));
	binmode $fp;
	$SYS{ INDEX }{$fp}{total} = int((-s $path) / 6);

_SUB_
}
#-----------------------------------------------------------------------------
# インデックスログを閉じる
# &CloseSysIndex(INDEX);
sub CloseSysIndex(){eval<<'_SUB_';

	my($fp) = @_;
	if(exists $SYS{ INDEX }{$fp}){ delete $SYS{ INDEX }{$fp} }
	close $fp;

_SUB_
}
#-----------------------------------------------------------------------------
# &AddSysIndex('999','index'); インデックスログにログ番号追加
# システムインデックスは閉じておかなければ行けない。
sub AddSysIndex(){eval<<'_SUB_';

	my($num, $index, $sindex) = @_;
	my($i,$s,$log,$list,@del_no);

	my $path = "$CFG{ DirSysPath }/$index.$CFG{ FileSysExe }";
	my $bin = pack 'S', $num;
	my $tmp = &GetTempFileName;

	&OpenSysIndex(INDEX, $index);
	my $total = $SYS{ INDEX }{ INDEX }{total};
	my $max = $total+1 > $CFG{ LogMax } ? $CFG{ LogMax } : $total+1;


	(open TMP,"+>$tmp") || &End('ERROR',&Info('SYS_NOTADDINDEX'));
	binmode TMP;

	print TMP $bin;
	# index
	while( read INDEX, $s, 2 ){

		$i++;
		if( $i < $CFG{ LogMax } ){
			print TMP $s;
		}else{
			push @del_no,$s;
			$s = unpack 'S', $s;
			# ログ削除 仮名
			&DeleteLogMain($s);
		}
		last if( $i >= $total);
	}
	seek TMP,2,0;
	read TMP, $list, ($max-1)*2;
	seek TMP,0,2;

	$i = 0;
	print TMP $bin;


	# sort index
	while( read INDEX, $s, 2 ){

		my $f;
		$i++;
		last if( $i >= $max);
		foreach(@del_no){
			if($_ eq $s){
				$f = 1;
				$i--;
				last;
			}
		}
		next if($f);

		print TMP $s;
		my $no;
		for($n=0;$n<$total;$n++){
			if($s eq substr $list,$n*2,2){
				$no = $max - $n -1;
				last;
			}
		}
		if($no){
			seek TMP, $max * 2 - 2 , 1;
			print TMP pack 'S', $no;
			seek TMP, $max * -2, 1;
		}else{
			&End('ERROR',&Info('SYS_BLOKENINDEX'));
		}
	}


	seek TMP, $max * 4, 0;
	print TMP pack 'S', $max;
	close TMP;

	&CloseSysIndex( INDEX );

	unlink $path;
	(rename $tmp, $path) || &End('ERROR',&Info('SYS_NOTINDEXWRITE',$path));
	$SYS{ FLAG }{ GETTEMPFILENAME }--;

	return 1;

_SUB_
}
#-----------------------------------------------------------------------------
# &DeleteSysIndex('999','index'); インデックスログのログ番号を削除
sub DeleteSysIndex(){eval<<'_SUB_';
	return if(exists $SYS{ INDEX }{ INDEX });
	my($num, $index) = @_;
	my($i,$e,$s,$list);

	my $path = "$CFG{ DirSysPath }/$index.$CFG{ FileSysExe }";
	my $bin = pack 'S', $num;
	my $tmp = &GetTempFileName;

	&OpenSysIndex(INDEX, $index);
	my $total = $SYS{ INDEX }{ INDEX }{total};

	(open TMP,"+>$tmp") || &End('ERROR',&Info('SYS_NOTADDINDEX'));
	binmode TMP;
	while( read INDEX, $s, 2 ){
		$i++;
		if($s eq $bin){
			$e++;
		}else{
			print TMP $s;
		}
		last if( $i >= $total*2);
	}
	$e/=2;
	my $max = $total - $e;
	seek TMP,0,0;
	read TMP, $list, $max*2;

	$i = 0;
	# sort index
	while( read TMP, $s, 2 ){

		$i++;

		my $no;
		for($n=0;$n<=$max;$n++){
			if($s eq substr $list,$n*2,2){
				$no = $max - $n;
				last;
			}
		}
		if($no){
			seek TMP, $max * 2 - 2 , 1;
			print TMP pack 'S', $no;
			seek TMP, ($max + $i) * 2, 0;
		}else{
			&End('ERROR',&Info('SYS_BLOKENINDEX'));
		}
		last if( $i >= $max);
	}

	close TMP;

	&CloseSysIndex( INDEX );

	(rename $tmp, $path) || &End('ERROR',&Info('SYS_NOTINDEXWRITE',$path));
	$SYS{ FLAG }{ GETTEMPFILENAME }--;

_SUB_
}
#-----------------------------------------------------------------------------
# &ReplySysIndex('999','index'); ソートインデックスログのログ番号を一番上に移動
sub ReplySysIndex(){eval<<'_SUB_';

	my($num, $index) = @_;
	my($i,$s,$no,$list);

	my $bin = pack 'S', $num;
	my $tmp = &GetTempFileName;
	my $path = "$CFG{ DirSysPath }/$index.$CFG{ FileSysExe }";

	&OpenSysIndex(INDEX, $index);
	my $total = $SYS{ INDEX }{ INDEX }{total};

	seek INDEX, $total*2, 0;
	read INDEX, $s, 2;
	return 0 if($s eq $bin);

	(open TMP,"+>$tmp") || &End('ERROR',&Info('SYS_NOTADDINDEX'));
	binmode TMP;

	seek INDEX, 0, 0;
	read INDEX, $list, $total*2;
	print TMP $list.$bin;

	while( read INDEX, $s, 2 ){
		$i++;
		last if($i > $total);
		next if($s eq $bin);

		print TMP $s;
		for($n=0;$n<$total;$n++){
			if($s eq substr $list,$n*2,2){
				$no = $total - $n;
				last;
			}
		}
		if($no){
			seek TMP, $total * 2 - 2 , 1;
			print TMP pack 'S', $no;
			seek TMP, $total * -2, 1;
		}else{
			&End('ERROR',&Info('SYS_BLOKENINDEX'));
		}
	}

	for($n=0;$n<$total;$n++){
		if($bin eq substr $list,$n*2,2){
			$no = $total - $n;
			last;
		}
	}
	if($no){
		seek TMP, $total * 4, 0;
		print TMP pack 'S', $no;
	}else{
		&End('ERROR',&Info('SYS_BLOKENINDEX'));
	}

	close TMP;

	&CloseSysIndex( INDEX );

	$SYS{ FLAG }{ GETTEMPFILENAME }--;


	rename $tmp, $path;
	return 1;

_SUB_
}
#-----------------------------------------------------------------------------
# インデックスログからログ番号を読込む * OpenSysIndex必須
# &ReadSysIndex(INDEX , 5, [sortmode]);
sub ReadSysIndex(){

	my($fp, $index, $mode) = @_;
	return -1 if(!exists $SYS{ INDEX }{$fp});
	my $total = $SYS{ INDEX }{$fp}{total};
	my $pos = 0;
	my $block = $total * 2 * $mode;
	my $s;
	if($index<0){
		$pos = 2;
	}

	return -1 if(abs $index >= $total);

	(seek $fp, (($index * 2) + $block), $pos) || &End('ERROR',&Info('SYS_NOTREADINDEX',$index));
	(read $fp, $s, 2) || &End('ERROR',&Info('SYS_NOTREADINDEX',$index));

	return unpack 'S',$s;

}
#-----------------------------------------------------------------------------
# システムファイルに値をセットする　&SetSysItem('count','value');
sub SetSysItem(){eval<<'_SUB_';

	my($item, $val) = @_;
	&End('ERROR',&Info('SYS_NOTITEM'))if(!$item);
	my $path = "$CFG{ DirSysPath }/$item.$CFG{ FileSysExe }";
	(-w $path) || &End('ERROR',&Info('SYS_NOTWRITE',$path));
	my $tmp = &GetTempFileName;

	(open TMP,">$tmp") || &End('ERROR',&Info('SYSDIR_NOTWRITE'));
	print TMP $val;
	close TMP;
	(rename $tmp, $path) || unlink $tmp && &End('ERROR',&Info('SYS_NOTWRITE',$path));
	$SYS{ FLAG }{ GETTEMPFILENAME }--;

_SUB_
}
#-----------------------------------------------------------------------------
# システムファイルから値を取得する　&GetSysItem('count',\$val);
sub GetSysItem(){eval<<'_SUB_';

	my($item, $val) = @_;
	my $path = "$CFG{ DirSysPath }/$item.$CFG{ FileSysExe }";
	return 0 if(!-e $path);

	my $s;
	(open SYS,$path) || &End('ERROR',&Info('SYS_NOTOPEN',$path));
	read SYS, $s, -s $path;
	close SYS;
	$$val = $s;
	return 1;

_SUB_
}
#-----------------------------------------------------------------------------
# 一時ファイル名の取得
sub GetTempFileName{

	$dir = $CFG{ DirSysPath };
	my $i;
	my $s;
	srand;
	while($i<100){
		my $f = "$dir/$ENV{ REMOTE_ADDR }_".(int(rand(999999))).".tmp";
		if(!-e $f){
			$SYS{ FLAG }{ GETTEMPFILENAME }++;
			return $f
		}
		$s .= "$f<br>";
		$i++;
	}
	&End('ERROR',&Info('SYSDIR_NOTWRITE').$s);

}
#-----------------------------------------------------------------------------
# 一時ファイルの削除
sub PurgeTempFile{eval<<'_SUB_';

	return if(!$SYS{ FLAG }{ GETTEMPFILENAME });

	opendir SYSDIR, $CFG{ DirSysPath };

	my $f;
	while( $_ = readdir SYSDIR ){
		unlink "$CFG{ DirSysPath }/$_" if(/\.tmp$/);
	}
	closedir SYSDIR;

_SUB_
}



#-----------------------------------------------------------------------------
# データ解析 : ('mime','width','height','datasize') = &FileAnalyze([filedata])
sub FileAnalyze(){
	local $Data = $_[0];
	local($Mime,$Width,$Height);
	my $data_length = length $$Data;
	return 0,0,0,0 if(!$data_length);

	$Width	=	0;
	$Height	=	0;

	&Call('FileAnalyzeInit');

	#--- バイナリヘッダでチェック
	if($$Data =~ /^GIF\d\d[a-z].+/) {
		$Mime = 'gif';
	} elsif($$Data =~ /^\x89\x50\x4E\x47\r\n\x1A\n.+/) {
		$Mime = 'png';
	} elsif($$Data =~ /^\xFF\xD8\xFF(\xE0|\xE1).+/) {
		$Mime = 'jpg';
	}

	return '',0,0,$data_length if(!$Mime);

	&Call('FileAnalyzeBegin');

	#--- Width Height
	if($Mime eq 'gif') {
		# ヘッダ所得
		if($$Data =~ /^GIF\d\d[a-z](.)(.)(.)(.).+/s) {
			$Width	=	ord($2)*256 + ord($1);
			$Height	=	ord($4)*256 + ord($3);
		}else{
			# ヘッダ異常
			$Width	=	0;
			$Height	=	0;
		}

	}elsif($Mime eq 'png') {
		if($$Data =~ /^\x89\x50\x4E\x47\r\n\x1A\n.{10}(.)(.)..(.)(.).+/s) {
			$Width	=	ord($1)*256 + ord($2);
			$Height	=	ord($3)*256 + ord($4);
		}
		else {
			# ヘッダ異常
			$Width	=	0;
			$Height	=	0;
		}
	}elsif($Mime eq 'jpg') {
		$pos = 2;
		while(){
			my $jhead = substr($$Data, $pos, 9);
			# SOF(Start Of Frame)マーカーを検索
			#   FFC0 : Baseline DCT, Huffman coding
			#   FFC1 : Extended sequential DCT, Huffman coding
			#   FFC2 : Progressive DCT, Huffman coding

			if($jhead =~ /\xff(.)(.)(.)(.?)(.?)(.?)(.?)(.?)/s) {
				if(($1 eq "\xc0") ||($1 eq "\xc1") ||($1 eq "\xc2")) {

					$Width	=	ord($7)*256 + ord($8);
					$Height	=	ord($5)*256 + ord($6);
					last;
				}else{
					$pos += ord($2)*256 + ord($3) + 2;
				}
			}else{
				# 所得不能
				$Width	=	0;
				$Height	=	0;
				last;
			}
		}
	}


	&Call('FileAnalyzeEnd');

	return $Mime,$Width,$Height,$data_length;
}
#-----------------------------------------------------------------------------
sub RegVersion(){
	undef $SYS{ CLIENT_COPYRIGHT };
	undef $SYS{ MODULE_COPYRIGHT };
	$SYS{ BBS_COPYRIGHT } = '<A TITLE="WonderCatStudio" HREF="http://wondercatstudio.com/" TARGET="_blank">BBS NOTE '.$SYS{ VERSION }.'</A>';

	&Call('Regist');

#BNCRYPTCODE==================================================================
if($SYS{ LANGUAGE }eq'JP'){eval pack'H*','6D792024426F6F74203D207375627B26476574496E3B2643616C6C282746756E6374696F6E27293B69662824494E7B66637D2065712027777269746527297B265772697465506F73747D656C7369662824494E7B66637D20657120276C6F67696E27297B264F70656E4C6F67696E7D656C7369662824494E7B66637D206571202768656C7027297B264F70656E48656C707D656C7369662824494E7B66637D206571202774687265616427297B264F70656E5468726561647D656C7369662824494E7B66637D2065712027706F737427297B264F70656E506F73747D656C7369662824494E7B66637D206571202764656C65746527297B2644656C6574654C6F677D656C7369662824494E7B66637D20657120276564697427297B26456469744C6F677D656C7369662824494E7B66637D206571202761646D696E27297B264F70656E41646D696E7D656C7369662824494E7B66637D206571202772737327297B264F70656E5273737D656C73657B264F70656E506167657D657869747D3B756E64656620245359537B20434C49454E545F434F50595249474854207D3B6D79202468203D20245061696E743A3A4346477B53657474696E677D3B696628646566696E6564202468297B6D7920246366203D20245061696E743A3A4346477B5573654170706C65747D3B6D792025663B6D61707B24667B2424687B245F7D7B6170706C65747D7D3D317D402463663B6D792024737061203D20275368695061696E74657227696624667B73706170726F7D7C7C24667B7370616E6F726D616C7D3B6D792024706273093D20275061696E7442425327696624667B7369697D3B247370612E3D272C202769662824737061262624706273293B245359537B20434C49454E545F434F50595249474854207D3D223C42523E2473706124706273222E272050726F6772616D203C4120485245463D22687474703A2F2F7368696368616E2E6A702F22205441524745543D225F626C616E6B223E28432982B582A182BF82E182F1287368692D6379616E293C2F413E2027696628247370617C7C24706273293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E506963747572654242532050726F6772616D202843292082A8816082CC286F686E6F292769662824667B7069637D293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E4242535061696E7465722050726F6772616D203C4120485245463D22687474703A2F2F7777772E67656F6369746965732E636F2E6A702F53696C69636F6E56616C6C65792D53616E4A6F73652F383630392F22205441524745543D225F626C616E6B223E2843292082C982C8286E696E61293C2F413E2769662824667B7061697D293B7D245359537B204242535F434F505952494748545F434F4445207D3D756E7061636B22253332432A222C245359537B204242535F434F50595249474854207D3B245359537B204150505F434F505952494748545F434F4445207D3D39343139323B2624426F6F7420696628245359537B204242535F434F505952494748545F434F4445207D3D3D3737373220262620245359537B204150505F434F505952494748545F434F4445207D3D3D393431393229'}
else{eval pack'H*','6D792024426F6F74203D207375627B26476574496E3B2643616C6C282746756E6374696F6E27293B69662824494E7B66637D2065712027777269746527297B265772697465506F73747D656C7369662824494E7B66637D20657120276C6F67696E27297B264F70656E4C6F67696E7D656C7369662824494E7B66637D206571202768656C7027297B264F70656E48656C707D656C7369662824494E7B66637D206571202774687265616427297B264F70656E5468726561647D656C7369662824494E7B66637D2065712027706F737427297B264F70656E506F73747D656C7369662824494E7B66637D206571202764656C65746527297B2644656C6574654C6F677D656C7369662824494E7B66637D20657120276564697427297B26456469744C6F677D656C7369662824494E7B66637D206571202761646D696E27297B264F70656E41646D696E7D656C7369662824494E7B66637D206571202772737327297B264F70656E5273737D656C73657B264F70656E506167657D657869747D3B756E64656620245359537B20434C49454E545F434F50595249474854207D3B696628646566696E656420265061696E743A3A53657474696E67297B6D7920246366203D20245061696E743A3A4346477B5573654170706C65747D3B6D79202468203D20265061696E743A3A53657474696E673B6D792025663B6D61707B24667B2424687B245F7D7B6170706C65747D7D3D3120696620242463667B245F7D7D6B65797320252463663B6D792024737061203D20275368695061696E74657227696624667B73706170726F7D7C7C24667B7370616E6F726D616C7D3B6D792024706273093D20275061696E7442425327696624667B7369697D3B247370612E3D272C202769662824737061262624706273293B245359537B20434C49454E545F434F50595249474854207D3D223C42523E2473706124706273222E272050726F6772616D203C4120485245463D22687474703A2F2F7777772E67742E73616B7572612E6E652E6A702F7E6F636F73616D612F22205441524745543D225F626C616E6B223E284329207368692D6379616E3C2F413E2027696628247370617C7C24706273293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E506963747572654242532050726F6772616D20284329206F686E6F27696628242463667B506963747572654242537D293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E4242535061696E7465722050726F6772616D203C4120485245463D22687474703A2F2F7777772E67656F6369746965732E636F2E6A702F53696C69636F6E56616C6C65792D53616E4A6F73652F383630392F22205441524745543D225F626C616E6B223E284329206E696E613C2F413E27696628242463667B4242535061696E7465727D293B7D245359537B204242535F434F505952494748545F434F4445207D3D756E7061636B22253332432A222C245359537B204242535F434F50595249474854207D3B245359537B204150505F434F505952494748545F434F4445207D3D39363236333B2624426F6F7420696628245359537B204242535F434F505952494748545F434F4445207D3D3D3737373220262620245359537B204150505F434F505952494748545F434F4445207D3D3D393632363329'}
#BNCRYPTCODE==================================================================

}
#-----------------------------------------------------------------------------
# ブラウザ関係
#
sub GetUserAgent{eval << '_SUB_';
	my($a,$c,$o);
	my $b = $ENV{'HTTP_USER_AGENT'};

	$b =~ s/</&lt;/g;
	$b =~ s/>/&gt;/g;
	$b =~ s/\n|\t//g;

    if($b=~ /Opera\/? ?(\d+)/)        { $a = 'Opera';   $c = "Opera $1"      }
    elsif($b=~ /MSIE (\d+)/)          { $a = 'MSIE';    $c = "MSIE ".$1      }
    elsif($b=~ /DreamPassport/)       { $a = 'DC';      $c = 'DreamPassport' }
    elsif($b=~ /iCab \w\/?([\d\.]*)/) { $a = 'iCab';    $c = "iCab $1"       }
    elsif($b=~ /Firefox\/?([\d\.]*)/) { $a = 'Firefox'; $c = "Firefox $1"    }
    elsif($b=~ /Safari\/?([\d\.]*)/)  { $a = 'Safari';  $c = "Safari $1"     }
    elsif($b=~ /Mozilla\/5/)          {
        if ($b =~ /Netscape\/?([\w\.]+)/) { $a = 'NN'; $b = "NN $1" }
        else {$a = 'Mozilla'; $c = "Mozilla" . ($b =~ /rv:([\d\.]+)/?" $1":'')} }
    elsif($b=~ /Mozilla\/(4|3)/ && $b!~ /Compatible/)
                                      { $a = 'NN';      $c = "NN $1"         }
    elsif($b=~ /MSIE/)                { $a = 'MSIE';    $c = 'MSIE'          }
    else                              { $a = 'OTHER';   $c = 'OTHER'         }

    my @hash = ('Windows XP:WinXP', 'Windows NT 5.1:WinXP', 'Windows NT 5:Win2000',
    'Windows NT:WinNT', 'Windows 2000:Win2000', 'Win2000:Win2000', 'WinNT:WinNT',
    'Win98:Win98', 'Win95:Win95', 'Windows 95:Win95', 'Windows 98:Win9x',
    'Mac OS X:MacOSX', 'Mac_PowerPC:Mac', 'Macintosh:Mac', 'PPC:Mac', '68K:Mac',
    'DreamPassport:DC', 'FREEBSD:FreeBSD', 'FRINBSD:FrinBSD', 'Linux:Linux');

    for (@hash) {
        @_ = split /:/;
        if($b =~ /\Q$_[0]\E/){ $o = $_[1];last }
    }

    if ($o eq "Win9x") {$o=$b =~ /Win 9x/?'WinMe':'Win98'}
    if ($o eq "Mac" && $b =~ /MSIE 5.22/){$o='MacOSX'}
    $o ||= 'OTHER';
    return ($b,$o,$a,$c);

_SUB_

}
sub GetUserIP{

	my $IP		=	$ENV{'REMOTE_ADDR'};
	my $HOST	=	$ENV{'REMOTE_HOST'};
	if($HOST eq '') { $HOST = $IP }
	if($HOST eq $IP){ $HOST = gethostbyaddr(pack('C4',split(/\./,$IP)),2) || $IP }
	return $IP, $HOST
}
#-----------------------------------------------------------------------------
# 時間関係
#
sub GetDate(){
	my $TIME = @_[0] eq ''? time + $CFG{ TimeDiffSec }:@_[0];

	my @youbi=('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
	my @tuki=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
	my($sec,$min,$hour,$mday,$month,$year,$wday) = gmtime(time + 2*365*24*3600);
	$SYS{ COOKIE_LIMIT } = sprintf( "%s, %02d-%s-%4d %02d:%02d:%02d GMT",$youbi[$wday],$mday,$tuki[$month],$year+1900,$hour,$min,$sec);

	my @T=localtime($TIME);
	return sprintf( "%4d/%02d/%02d (%s) %02d:%02d:%02d",$T[5]+1900,++$T[4],$T[3],$youbi[$T[6]],$T[2],$T[1],$T[0]);

}
#-----------------------------------------------------------------------------
# クッキー取得
#
sub GetCookie{
	if($ENV{'HTTP_COOKIE'}){
		my $c = $ENV{"HTTP_COOKIE"};
		my $s = index $c,"BBSNote=";
		local %Cookie;
		if($s != -1){
			my $e = index $c,">",$s;
			$e = length $c if($e == -1);
			my @data = split ',' , substr $c,$s,$e-$s;
			foreach(@data){
				my($name, $val) = split ':';
				&unescape(\$val);
				$Cookie{$name} = $val;
			}
			&Call('GetCookieValue');
			return %Cookie;
		}
	}
}
#-----------------------------------------------------------------------------
# クッキー出力
#
sub WriteCookie(){eval<<'_SUB_';
	local $RefCookie = $_[0];
	local $OverWrite = $_[1];
	return if $SYS{ FLAG }{ COOKIE };
	$SYS{ FLAG }{ COOKIE } = 1;
	&GetDate() if!$SYS{ COOKIE_LIMIT };
	my $val = $SYS{ VERSION };
	my $vkey = 'BBSNote=Version';
	delete $$RefCookie{$vkey};

	&Call('WriteCookieInit');

	&escape(\$val);
	local $Data = "$vkey:$val,";
	$Data.= join ',',map{$val = $$RefCookie{$_};&escape(\$val);"$_:$val"}grep{$_ && $$RefCookie{$_} ne ''}keys %$RefCookie;
	$Data.= '>';
	my $cookie = $Data."; expires=$SYS{ COOKIE_LIMIT }";
	if($CFG{ UseMetaCookie }){
		$SYS{ META_COOKIE } = $cookie;
		push @SkinHeadFormat,sub{
			push @$META,{
				TAG		=>	'META',
				'http-equiv'	=>	'Set-Cookie',
				content		=>	$SYS{ META_COOKIE },
			};
		}
	}
	print "Set-Cookie: $cookie\n";
	$ENV{'HTTP_COOKIE'} = $Data if $OverWrite;
_SUB_
}

#-----------------------------------------------------------------------------
# パスワード取得
#
sub GetLogPassword(){
	my($log, $res) = @_;
	local $LogFile = &filelog($log);
	if(-e "$LogFile") {
		open(MSG,"<$LogFile");
		my(%LogValue, %LogExValue);
		if($res){
			while(<MSG>){
				&GetLogReplyValue($_, \%LogValue, \%LogExValue);
				if($LogValue{num} eq $res){
					close MSG;
					return $LogValue{password};
				}
			}
		}else{
			$_ = <MSG>;
			&GetLogMainValue($_, \%LogValue, \%LogExValue);
			close MSG;
			return $LogValue{password};
		}
	}
	&End('ERROR',&Info('DATA_NOTFOUND'));

}
#-----------------------------------------------------------------------------
sub WriteFiles(){eval<<'_SUB_';
	my $r = $_[0];
	if(ref $r eq 'HASH'){
		foreach(keys %$r){
			my $h = $r->{$_};
			if(exists $h->{path} && $h->{size} > 0){
				open(FILE, ">$h->{path}");
				binmode FILE;
				if(ref $h->{data} eq 'SCALAR'){
					print FILE ${$h->{data}};
				}else{
					print FILE $h->{data};
				}
				close FILE;
				$SYS{ FLAG }{ WriteFiles }{ $h->{path} } = $h->{size};
			}
		}
	}
_SUB_
}
#-----------------------------------------------------------------------------
sub DeleteFiles(){eval<<'_SUB_';
	foreach $f(@_){
		$f =~ s/[\/\\\t\n\r\f]//g;
		unlink "$CFG{ DirFilePath }/$f";
	}
_SUB_
}
#-----------------------------------------------------------------------------
sub GetAdminPass{
	%COOKIE = &GetCookie;

	my($pwd, $usr);

    if($IN{password}){
		($pwd, $usr) = @IN{'password','name'}
	}else{
		$AutoLogin = 1;
		if($COOKIE{'adminpass'}){
			($pwd, $usr) = @COOKIE{'adminpass','name'}
		}else{
			($pwd, $usr) = @COOKIE{'password','name'}
		}
		$usr = $IN{name} if!$usr;
		$IN{name} = $usr if!$IN{name};
		$IN{password} = $pwd;
	}
	return ($pwd, $usr);
}
#-----------------------------------------------------------------------------
# パスワード確認
sub CheckPassword(){
	my($pass, $crypt_pass) = @_;
	return 0 if($pass eq '');
	return 1 if($crypt_pass eq &CryptString($pass));

	# ユーザー権限認証
	return &CheckAuthority($pass,$IN{name});
}
#-----------------------------------------------------------------------------
# 権限付パスワード確認
sub CheckAuthority(){
	my($pwd, $usr) = @_;
	$SYS{ FLAG }{ AUTHORITY }='';
	$SYS{ FLAG }{ AUTHORITY_NAME }='';
	# 管理人,副管理人パス有効時
	foreach ('AdminPassword','SubPassword'){
		if($CFG{ $_ } ne ''){
			# ネーム権限
			my $password = ($usr && ref $CFG{ $_ } eq 'HASH')?$CFG{ $_ }->{$usr}:$CFG{ $_ };
			if($password && $pwd eq $password){
				$SYS{ FLAG }{ AUTHORITY } = $_ eq 'AdminPassword'?'ADMIN':'SUB';
				$SYS{ FLAG }{ AUTHORITY_NAME } = $usr;
				return 1;
			}
		}
	}
}
#-----------------------------------------------------------------------------
# 入力チェック
sub CheckInput{

	local @ERR;

	&Call('CheckInputInit');

	&End('ERROR',&Info('DIR_NOTFOUND',$CFG{ DirFilePath }))if!-d "$CFG{ DirFilePath }";

	# エスケープ
	&EscapeInput(0,\$IN{name},\$IN{title});
	&EscapeInput(1,\$IN{mail},\$IN{url});
	&EscapeInput(0,\$IN{message});


	# 文字列のチェック
	&CheckString;

	&Call('CheckInputBegin');

	# 画像アップロード
	if($SYS{ FLAG }{ FILE_CAPTOR }){

		my $h = $FILES{file} = {};
        @{$h}{'mime','width','height','size'} = &FileAnalyze(\$IN{file});

		local($CheckSize,$CheckMime,$CheckFormat);

		&Call('CheckInputFile');

		if($h->{size}){

			# 画像サイズが大きい
			if(!$CheckSize && ($CFG{ LimitImageWidth } < $h->{width} || $CFG{ LimitImageHeight } < $h->{height})){
				push @ERR,&Info('CHECK_UPPIXELSIZEOVER',$h->{width},$h->{height})
			}
			# データサイズが大きい
			if(!$CheckMime && $CFG{ LimitUpLoadData } < $h->{size}){
				push @ERR,&Info('CHECK_UPDATASIZEOVER',$CFG{ LimitUpLoadData },$h->{size})
			}
			# フォーマットが不適切
			if(!$CheckFormat && (!grep $h->{mime} eq $_ ,split ',',$SYS{ CAPTOR_FORMAT })){
				push @ERR,&Info('UNKNOWN_FORMAT');
			}
			# 適切ならばハッシュ結び付け
			$h->{data} = \$IN{file};

		}elsif($CFG{ NotCommentOnly } && $SYS{ MODE } !~ /^EDIT/){
			# 画像がなくてコメントのみ投稿できない設定時
			push @ERR,&Info('CHECK_UPCOMMENTONLY');
		}

	}

	&CheckError(@ERR);

	&Call('CheckInputEnd');

}
#-----------------------------------------------------------------------------
# エラー表示
sub CheckError(){
	if(@_){
		my $errorstr;
		my $errormark = $CFG{ ErrorMark } ? $CFG{ ErrorMark } : '■';
		if($IN{fc} eq 'captor'){
			map{$errorstr.="$errormark$_\n"}@ERR;
			&End('PAINT_POST','',$errorstr);
		}else{

			&Call('CheckInputError');

			map{$errorstr.="$errormark$_<br>"}@ERR;

			$IN{no} = $IN{log} if!$IN{no};

			&End('DEFAULTPOST',&Info('CHECK_POSTERROR',$errorstr));

		}
	}
}
#-----------------------------------------------------------------------------
sub CheckHistory(){eval<<'_SUB_';
	my $mode = $SYS{ MODE };

	local($path,$history,$log) = &GetHistoryPath;
	open(LOG,$path) || &End('ERROR',&Info('SYS_NOTOPEN',$path));
	my $h = $CFG{ MultiplePosting };
	my %ch;
	map{
		my $a=$_;
		map{
			$ch{$$a{mode}}{$_}=$$a{$_}if $mode=~/$$a{mode}/ && $_ ne 'mode' && $$a{$_};
		}keys %$a if$$a{mode}
	}@$h if(ref $h eq 'ARRAY');

	my $checked;
	while($_=<LOG>){
		chomp;
		my %data;
		foreach(split /\t/){
			 my($name, $val) = split /=/;
			 $data{$name} = $val;
		}

		# チェック動作
		if($data{mode} =~ /$mode/){
			$checked++;

			foreach(keys %ch){
				my $a = $ch{$_};
				my($i,$n);
				foreach(keys %$a){
					if($data{$_}){
						$n++;
						if($_ eq 'time' && $$a{'time'}){
							$i++ if($data{$_} + $$a{'time'}) > time;
						}elsif($_ eq 'ip'){
							$i++ if($data{$_} && $data{$_} eq $IP)
						}else{
							$i++ if($data{$_} && $data{$_} eq $IN{$_})
						}
					}
				}

				if($i >= $n){
					&End('ERROR',&Info('CHECK_MULTIPLEPOST'));
				}
			}

		}

		last if($checked >= $history);
	}

	close LOG;

_SUB_
}
#-----------------------------------------------------------------------------
sub CheckString{

	my $len;

	if($SYS{ FLAG }{ POST_FORM_TITLE }){
		if($CFG{ NeedTitle }	&& !$IN{title}		){push @ERR,&Info('CHECK_TITLE')}
	}

	if(	$CFG{ NeedName }	&& !$IN{name}		){push @ERR,&Info('CHECK_NAME')}
	if(	$CFG{ NeedMail }	&& !$IN{mail}		){push @ERR,&Info('CHECK_MAIL')}
	if(	$CFG{ NeedUrl }		&& !$IN{url}		){push @ERR,&Info('CHECK_URL')}
	if(	$CFG{ NeedPassword }	&& !$IN{password}	){push @ERR,&Info('CHECK_PASSWORD')}
	if(				   !$IN{message}		){push @ERR,&Info('CHECK_MESSAGE')}

	$len = length $IN{name};
	if($len > $CFG{ LimitName }){ push @ERR,&Info('CHECK_NAMEOVER',$len)}

	$len = length $IN{mail};
	if($len > 0 && $IN{mail} !~ /(.*)\@(.*)\.(.*)/ && $IN{mail} ne 'sage'){ push @ERR,&Info('CHECK_MAILFORMAT')}
	if($len > $CFG{ LimitMail }){ push @ERR,&Info('CHECK_MAILOVER',$len)}

	$len = length $IN{title};
	if($len > $CFG{ LimitTitle }){ push @ERR,&Info('CHECK_TITLEOVER',$len)}

	$len = length $IN{url};
	if($len > $CFG{ LimitUrl }){ push @ERR,&Info('CHECK_URLOVER',$len)}

	$len = length $IN{message};
	if($len > $CFG{ LimitMessage }){ push @ERR,&Info('CHECK_MESSAGEOVER',$len)}

}
#-----------------------------------------------------------------------------
sub GetReplyStatus() {
    my $log = $_[0];
    my $log_file = &filelog($log);
    if (-e $log_file) {
        local *FH;
        open FH ,"<$log_file";
        my $log_size = (stat FH)[7];
        my $log_count = -1;
        if (exists $SYS{MODULE}{Tree} && $Tree::CFG{ UseThreadLock }) {
            delete $SYS{ FLAG }{thread_lock};
		    my (%val,%ex);
            $_ = <FH>; $log_count++;
            &GetLogMainValue($_, \%val, \%ex);
            $SYS{ FLAG }{thread_lock} = 1 if $ex{thread_lock};
        }
        while ( <FH> ) { $log_count++ }
        close FH;
        return ($log_count, $log_size)
    }
    &End('ERROR',&Info(DATA_NOTFOUND));
}
#-----------------------------------------------------------------------------
sub CheckReplyEnable(){
	my($num, $size) = @_;
	return 0 if $SYS{ MODE } =~ /REPLY|DELETE|EDIT/ ||
	    ($SYS{ MODE } eq 'ADMIN' && $IN{ mode } eq 'deletewide');
	return 0 if $SYS{ FLAG }{thread_lock};
	my $res_enable_size = $CFG{ LimitResLogSize } > $size?1:0;
	my $res_enable_total = $CFG{ LimitResTotal } > $num?1:0;
	if($CFG{ LimitResType }==0){return $res_enable_total}
	if($CFG{ LimitResType }==1){return $res_enable_size}
	if($CFG{ LimitResType }==2){return ($res_enable_total && $res_enable_size)}
	if($CFG{ LimitResType }==3){return ($res_enable_total || $res_enable_size)}
}
#-----------------------------------------------------------------------------
# Jcode ＆ タグ除去
sub EscapeInput(){
	my($f,@v)=@_;
	foreach(@v){
		if($f == 1){
			${$_}=~s/^\w+\:\/*//go;
			${$_}=~s/( |\x81\x40)//go;
		}else{
			&jcode::convert(\$_,"sjis")if $SYS{ Jcode };
		}
		if($f < 2){
			${$_}=~s/\&(?!hearts\;|nbsp\;|\#\w+\;)/\&amp\;/go;
			${$_}=~s/</\&lt\;/go;
		}
	}
}
#-----------------------------------------------------------------------------
sub DeleteTag(){
	my $s = $_[0];

	$$s =~ s/<BR>/\n/g;
	$$s =~ s/<P>/\n\n/g;
	$$s =~ s/<\/?SPAN class="quot">//g;
	$$s =~ s/<\/?A["-.!~*'()\w;\/?:\@&=+\$,%# ]*class="(?:quot|autolinkurl|autolinkmail)">//g;

}
#-----------------------------------------------------------------------------
sub ConvertMessage(){
	local $Message = $_[0];

	&Call('ConvertMessageInit');

	# 改行をBRに変換
	$Message=~ s/\x0D\x0A/\n/go;
	$Message=~ s/\x0D/\n/go;
	$Message=~ s/\x0A/\n/go;
	$Message=~ s/\n+$//go;
	$Message=~ s/^\n+//go;

	&Call('ConvertMessageBegin');

	$Message=~ s/ /&nbsp;/go;
	$Message=~ s/\t/&nbsp;&nbsp;&nbsp;&nbsp;/go;

	# 使用可能タグ
	my $errstr;
	if($SYS{ FLAG }{ ALLTAG }){
        &ConvertTag(\$Message,\$CFG{ OkTag },$SYS{ FLAG }{ ALLTAG });
	}elsif($CFG{ UseTag } && ($errstr = &ConvertTag(\$Message,\$CFG{ OkTag })) ){
		push @ERR,&Info('CHECK_TAG',$errstr);
	}

	&Call('ConvertMessageAutoLink');

	# リンクを有効に
	if($CFG{ AutoLinkUrl }){$Message =~ s/(https?:\/\/)([-.!~*'()\w;\/?:\@&=+\$,%#]+)/&ConvertURI($1,$2)/eg}
	if($CFG{ AutoLinkMail }){$Message =~ s/mailto\:([\w\.\?\#\_\:\;\/\%\&\$\"\!\'\(\)\=\~\^\-\+\|\@]*)/<A HREF=\"mailto\:$1\" TARGET=\"_BLANK\" class=\"autolinkmail\">$1<\/A class=\"autolinkmail\">/ig}
	$Message =~ s/(https?)%3A/$1:/g;

	&Call('ConvertMessageQuotation');

	# 引用文
	if($CFG{ Quotation }){
		my $m;
		my $link = sub(){
			my($h,$q,$s,$e) = @_;
			if($q eq '>' && $s =~ />([\d\,\-]+)/){
				return $h.'<A href="'."$CFG{ BBSNoteUrl }?fc=thread&log=$1".'" id="threadjump" class="quot">'.$q.$s.'</A id="threadjump" class="quot">'.$e
			}else{
				return $h.'<SPAN class="quot">'.$q.$s.'</SPAN class="quot">'.$e
			}
		};
		for($m=0;$m<2;$m++){$Message=~ s/(^|\n)([>#]|\x81\x84+)(.+)(\n|$)/&$link($1,$2,$3,$4)/eg}
	}

	&Call('ConvertMessageLineCheck');

	# 行数チェック
	my $line = ($Message =~ s/\n\n/<P>/img);	$line*=2;
	$line+=($Message =~ s/\n/<BR>/img);
	if($CFG{ LimitLine } < $line){
		push @ERR,&Info('CHECK_MESSAGELINEOVER',$line)
	}

	&CheckError(@ERR);

	&Call('ConvertMessageEnd');

	return $Message;

}
#-----------------------------------------------------------------------------
# タグ変換
sub ConvertTag(){
    my($str, $tag, $tag_all) = @_;
    my(%ok_tags, %check_tag);
    unless ($tag_all) {
        my @tags = ref $tag eq 'ARRAY' ? @$tag :
        ref $tag eq 'SCALAR' ? split ',', $$tag : split ',', $tag;
        $ok_tags{BR}{noclose} = 1; $ok_tags{P}{noclose} = 1;
        for (@tags) {
            my($name, @element) = split /:/;
            $name = uc $name;
            $ok_tags{$name} = {};
            for (@element) { $ok_tags{$name}{lc $_} = 1 }
        }
        if (exists $ok_tags{FONT}) { my $f = $ok_tags{FONT};
            unless (keys %$f) { $f->{size} = 1; $f->{color} = 1; $f->{face} = 1 }
        }
        if (exists $ok_tags{DIV}) { my $f = $ok_tags{DIV}; unless (keys %$f) { $f->{align} = 1} }
        if (exists $ok_tags{IMG}) { $ok_tags{IMG}{noclose} = 1 }
    }

    while ($$str =~ /&lt;(\/)?(\w+)/g) {
        my $slash = $1;
        my $tag = uc $2;
        my $s = pos $$str;
        if ($tag_all || exists $ok_tags{$tag}) {
	        my($element, $end_pos) = &_get_element($str);

            my @el;
            last unless $end_pos;
            unless ($tag_all) {
                $slash ? $check_tag{$tag}-- : $check_tag{$tag}++;
		        for (keys %$element) { push @el, $element->{$_} ? qq/$_="$element->{$_}"/ : $_ if exists $ok_tags{$tag}{$_}}
		    } else {
		        for (keys %$element) { push @el, $element->{$_} ? qq/$_="$element->{$_}"/ : $_ }
		    }
	        my $e = join ' ', "<$slash$tag" , @el;
	        my $st = $s - (length $tag) - (length $slash) - 4;
	        my $st_str = substr $$str, 0, $st if $st;
	        my $ed_str = substr $$str, $end_pos -1;
	        $$str = $st_str . $e . $ed_str;
	        pos $$str = $st + length $e + 1
        }
    }

    unless ($tag_all) {
        my $errstr;
	    for my $tag(keys %check_tag) {
	        if (!exists $ok_tags{$tag}{noclose} && $check_tag{$tag} != 0) {
	            my $s = join '', $check_tag{$tag} , &Info('CHECK_TAGPOINT') if $check_tag{$tag} > 1;
	            $errstr .= "&lt;$tag&gt;$s ";
	        }
	    }
	    return $errstr if $errstr;
    }

    return 0;
}
sub _get_element {
    my($str) = @_;
    my $len = length $$str;
    my(@elments, $elment_alias, $i, $buf , $alias_mark, $alias_hit, $alias_end);
	for ($i = pos $$str ; $i < $len; $i++) {
	    $_ = substr $$str, $i, 1;
        if (!$elment_alias && $buf =~ /&nbsp$/ && $_ eq ';') {
            $buf =~ s/&nbsp$//;
            push @elments, $buf if $buf ne '' && !$alias_end;
            undef $buf;
            $alias_end = 1;
        } elsif (!$alias_mark && />/) {
            $i++;
            $buf =~ s/&nbsp$//;
            push @elments, $buf if $buf ne '' && !$alias_end;
            last;
        } else {
            if (/$alias_mark/ && $buf !~ /\\$/) {
                $elment_alias = 0;
                $alias_mark = undef;
                next;
            }
            if ($alias_hit) {
                $alias_hit = 0;
                if (/('|")/ && $buf !~ /\\$/) {
                    $alias_mark = $1;
                    next;
                } else {
                    $elment_alias = 0;
                    $buf .= $_;
                }
            } else {
	            $buf .= $_;
                if (/=/ && !$elment_alias){
                    $elment_alias = 1;
                    $alias_hit = 1;
                }
                $alias_end = 0;
            }
        }
	}
    return (0,0) unless (substr $$str, $i-1, 1) eq '>';

	my %element;
    for (@elments) {
        my($name, $val) = split /=/, $_, 2;
        $name = lc $name;
        $val =~ s/&nbsp;/ /g;
        $element{$name} = $val;
    }
    return (\%element, $i);

}
#-----------------------------------------------------------------------------
sub BackupSysIndex{

	my $sys_index_cgi = "$CFG{ DirSysPath }/index.$CFG{ FileSysExe }";
	my $sys_count_cgi = "$CFG{ DirSysPath }/count.$CFG{ FileSysExe }";

	$SYS{ HTTPCONTENTTYPE } = 'application/octet-stream';
	&HttpHead;

	# バッファリングしない
	$|=1;

	print $SYS{ SYSINDEX_HEAD };

	$size = -s $sys_index_cgi;
	if($size){
		$buf.=":$size:";
		open(BIN,$sys_index_cgi);
		binmode BIN;
		read BIN, $bin, $size;
		close BIN;
	}

	$size = -s $sys_count_cgi;
	if($size){
		$buf.="$size:";
		open(BIN,$sys_count_cgi);
		binmode BIN;
		read BIN, $cnt, $size;
		close BIN;
	}

	@sum_bin = &CheckSumFile(\$bin);
	@sum_cnt = &CheckSumFile(\$cnt);

	$buf.=join ':',@sum_bin,@sum_cnt;

	print sprintf "%04d",(length $buf)-1;
	print $buf;
	print $bin;
	print $cnt;

	exit;

}
#-----------------------------------------------------------------------------
sub RecoverFileIndex{

	@txt = &Info('FILERECOVER_TEXT');

	&RecoverFileIndexForm if(!$IN{file});

	$l = length $SYS{ SYSINDEX_HEAD };

	# file head check
	&End('ERROR',&Info('UNKNOWN_FORMAT'))if($SYS{ SYSINDEX_HEAD } ne (substr $IN{file},0,$l));

	$header_len = int substr $IN{file},$l,4;
	$header = substr $IN{file},$l+5,$header_len;

	($index_len,$count_len,@index_sum[0..2],@count_sum[0..2]) = split ':',$header;

	$index_bin = substr $IN{file},$l+5+$header_len,$index_len;
	$count_bin = substr $IN{file},$l+5+$header_len+$index_len,$count_len;


	@sum_bin = &CheckSumFile(\$index_bin);
	@sum_cnt = &CheckSumFile(\$count_bin);

	# check sum err
	&End('ERROR',@txt[0,4]) unless((join ':',@sum_bin,@sum_cnt) eq (join ':',@index_sum,@count_sum));

	# recover
	filelock;

	open(BIN,">$CFG{ DirSysPath }/index.$CFG{ FileSysExe }");
	binmode BIN;
	print BIN $index_bin;
	close BIN;

	open(BIN,">$CFG{ DirSysPath }/count.$CFG{ FileSysExe }");
	binmode BIN;
	print BIN $count_bin;
	close BIN;

	@txt = &Info('RECOVER_TEXT');

	&HttpHead;
	&SkinHead($txt[0]);
	print "<CENTER><H2>$txt[1]</H2>";

	$SYS{ ARG }{ BackButton }{ fc } = 'admin';
	$SYS{ ARG }{ BackButton }{ password } = $IN{password};
	undef $IN{'mode'};
	print &SkinBackButton();
	print '</CENTER>';

	&SkinFoot;

	fileunlock;

	exit;

}
#-----------------------------------------------------------------------------
sub RecoverFileIndexForm{

	&HttpHead;
	&SkinHead($txt[0]);

	print '<BR><BR>';
	&TabeleFrame($txt[0]);


print <<_HTML_;

<TABLE width=500><TR><TD><SMALL><CENTER>
$txt[3]
<FORM enctype="multipart/form-data" method=post action='$CFG{ BBSNoteUrl }'>
<INPUT type=hidden name=password value='$IN{password}'>
<INPUT type=hidden name=name value='$IN{name}'>
<INPUT type=hidden name=fc value='$IN{fc}'>
<INPUT type=hidden name=mode value='$IN{'mode'}'>
$txt[1]<INPUT type=file name=file class=button> 
<INPUT type=submit value='$txt[2]' class=button></FORM>
_HTML_

	$SYS{ ARG }{ BackButton }{ fc } = 'admin';
	$SYS{ ARG }{ BackButton }{ password } = $IN{password};
	undef $IN{'mode'};
	print &SkinBackButton();

print <<_HTML_;
</TD></TR></TABLE></TD></TR></TABLE></TD></TR></TABLE>
<BR><BR>
_HTML_


	&SkinFoot;

	exit;
}
#-----------------------------------------------------------------------------
sub CheckSumFile(){
	my $h = $_[0];
	my($i,$sum1,$sum2,$sum3);
	foreach(unpack "v*",$$h){
		$i++;
		if($i % 2){
			$sum1+=$_;
			$sum2+=$_;
		}else{
			$sum1-=$_;
			$sum3-=$_;
		}

		if($i % 3){
			$sum2-=$_;
			$sum3+=$_;
		}

	}
	$sum1 = abs $sum1;
	$sum2 = abs $sum2;
	$sum3 = abs $sum3;

	return ($sum1,$sum2,$sum3);
}
#-----------------------------------------------------------------------------
sub RecoverSysIndex{

	my $p = $CFG{ DirFilePath };
	my $dir_cash = "$p/recover";
	my $cash_index = "$dir_cash/index";
	my $cash_sort = "$dir_cash/sort";
	my $cash_number = "$dir_cash/number";
	my $cash_index_cgi = "$dir_cash/index.$CFG{ FileSysExe }";
	my $cash_count_cgi = "$dir_cash/count.$CFG{ FileSysExe }";
	my $sys_index_cgi = "$CFG{ DirSysPath }/index.$CFG{ FileSysExe }";
	my $sys_count_cgi = "$CFG{ DirSysPath }/count.$CFG{ FileSysExe }";
	my $cash_number_bin = "$dir_cash/number.bin";
	my $dir_permission = 0707;
	my $progress_on = 1 if($SYS{USER_BROWSER_VER} ne 'NN 4');

	@txt = &Info('RECOVER_TEXT');

	eval('$start = (times)[0]');

	filelock;

	my @dir;

	push @SkinHeadFormat,sub{
		undef $JavaScript;
		ResetJavaScript();

		if($progress_on){
			&GetJavaScript('MM_findObj', \$JavaScript);
$JavaScript.=<<_SCRIPT_;
var bar_t
var bar_max
var navi_t
function BN_prog(n,s){
	if(s){
		MM_findObj('navi').innerHTML= s
	}else if(n > 1){
		p = parseInt(n * 100 / bar_max);
		if(1 > p) p = 1
		bar_t.width = p + "%"
		navi_t.innerHTML= bar_t.width
	}
}
function BN_proginit(m){
	bar_max = m
	bar_t = MM_findObj('bar');
	navi_t = MM_findObj('navi');
}

_SCRIPT_

		}

	};

	&HttpHead;
	&SkinHead($txt[0]);

	&Call('RecoverSysIndexBegin');

	# バッファリングしない
	$|=1;

	print "<H2>$txt[0]</H2>";

if($progress_on){
print <<HTML;
<TABLE width=500 border=1 bgcolor=$CFG{ TagTableIn }{bgcolor}><TR><TD>
<TABLE id=bar bgcolor=$CFG{ TagTableOut }{bgcolor} width=0%><TR><TD>
</TD></TR></TABLE></TD></TR></TABLE>
<TABLE width=500 border=0><TR><TD align=center>
<FONT id=navi size=2></FONT>
</TD></TR></TABLE><HR>
HTML
}

	#******************************************
	eval('$stime = sprintf "%.3f",((times)[0]-$start)');
	print "<B>TIME : $stime </B><BR>" if $stime;
	print '<script>BN_prog(0,"'.$txt[2].'")</script>'if($progress_on);

	rmtree($dir_cash) if( -e $dir_cash );

	# インデックス用調査ディレクトリの作成
	mkdir $dir_cash,$dir_permission;
	mkdir $cash_sort,$dir_permission;
	mkdir $cash_index,$dir_permission;
	mkdir $cash_number,$dir_permission;

	opendir(DIR,$p) || &End('ERROR',&Info(DATA_NOTFOUND));

	local $LogCount = 0;
	local $IndexCount = 1;
	local $MaxLogCount = 0;
	local $MaxMsgCount = 0;


	my $nlen = length "\n";
	while($LogFile = readdir DIR){
		if($LogFile =~/(\d+)\.$CFG{ FileLogExe }$/){
			my $thread_no = $1;
			open(MSG,"<$p/$LogFile");
			my $thread = <MSG>;
			my $endres;
			my $ep = tell MSG;
			my $size = (stat MSG)[7];
			my($msgno,$n);

			# スレッドの日付を取得
			($msgno,$n,$thread) = split/\t/,$thread, 4;
			$MaxMsgCount = $msgno if($MaxMsgCount < $msgno);
			$thread =~ /(\d+)\/(\d+)\/(\d+) \(\w+\) (\d\d):(\d\d):?(\d\d)?/;

			my $thread_sec = $6?$6:'00';
			my @dates = ($1.$2, $3, "$4$5$thread_sec-$thread_no");
			my $dir_thread = "$cash_index/$dates[0]";
			my $dir_thread_day = "$dir_thread/$dates[1]";
			mkdir $dir_thread,$dir_permission if(!-d $dir_thread);
			mkdir $dir_thread_day,$dir_permission if(!-d $dir_thread_day);
			open FILE, ">$dir_thread_day/$dates[2]";
			close FILE;

			# 最終レスの日付を取得
			if($size > $ep + 32){
				my $line;
				my $hitpos;
				for($pos = $size - 34;$pos >= $ep-32;$pos-=31){
					seek MSG, $pos, 0;
					read(MSG, $line, 32);
					$hitpos = rindex $line,"\n";
					if($hitpos >= 0){
						$hitpos+=$pos+$nlen+1;
						seek MSG, $hitpos, 0;
						read(MSG,$endres,$size-$hitpos-$nlen);
						($msgno,$n,$endres) = split/\t/,$endres, 4;
						$MaxMsgCount = $msgno if($MaxMsgCount < $msgno);
						last;
					}
				}
			}

			# sort index
			if($endres){
				$endres =~ /(\d+)\/(\d+)\/(\d+) \(\w+\) (\d\d):(\d\d):?(\d\d)?/;
				my $res_sec = $6?$6:'00';
				undef @dates;
				@dates = ($1.$2, $3, "$4$5$res_sec-$thread_no");
				$dir_thread = "$cash_sort/$dates[0]";
				$dir_thread_day = "$dir_thread/$dates[1]";
			}else{
				$dir_thread = "$cash_sort/$dates[0]";
				$dir_thread_day = "$dir_thread/$dates[1]";
			}
			mkdir $dir_thread,$dir_permission if(!-d $dir_thread);
			mkdir $dir_thread_day,$dir_permission if(!-d $dir_thread_day);
			open FILE, ">$dir_thread_day/$dates[2]";
			close FILE;

			$LogCount++;
			sleep 1 if$SYS{ RECOVER_SLEEP }&&!($LogCount % 200);

			close MSG;

		}
	}
	closedir DIR;


	# recover
	print "Log Count : $LogCount<br>";
	print '<script>BN_proginit('.($LogCount*2).')</script>'if($progress_on);

	open IBIN, ">$cash_index_cgi";
	binmode IBIN;

	opendir(DIR,$cash_index);
	@dir = readdir DIR;
	closedir DIR;
	@dir = map("$cash_index/$_", grep $_!~/^\.{1,2}$/s,@dir);
	@dir = reverse sort @dir;

	foreach $root_mon(@dir){
		if( -d $root_mon){
			opendir(DIR, $root_mon);
			my @dir_day = readdir DIR;
			closedir DIR;
			@dir_day = map("$root_mon/$_", grep $_!~/^\.{1,2}$/s,@dir_day);
			@dir_day = reverse sort @dir_day;
			foreach $root_day(@dir_day){
				if( -d $root_day){
					opendir(DIR, $root_day);
					my @day = readdir DIR;
					closedir DIR;
					@day = map("$root_day/$_", grep $_!~/^\.{1,2}$/s,@day);
					@day = reverse sort @day;
					foreach $day_log(@day){
						if($day_log =~ /(\d+)$/){
							my $no = int $1;
							my $block = int($no / 100);
							my $bdir = "$cash_number/$block";
							$MaxLogCount = $no if($MaxLogCount < $no);
							print '<script>BN_prog('.$IndexCount.")</script>\n"if($progress_on);
							print IBIN pack 'S',$no;	# write bin index
							mkdir $bdir,$dir_permission if(!-e $bdir);
							open(NUM,">$bdir/$no");
							print NUM ($LogCount - $IndexCount);
							close NUM;
							$IndexCount++;
							sleep 1 if$SYS{ RECOVER_SLEEP }&&!($IndexCount % 100);
						}
					}

				}
			}
			
		}
	}

	#=================================================
	&Call('RecoverSysIndexCount');
	print "Max Log Count : $MaxLogCount<br>";
	print "Max Msg  Count : $MaxMsgCount<br>";
	#******************************************
	eval('$stime = sprintf "%.3f",((times)[0]-$start)');
	print "<B>TIME : $stime </B><BR>" if $stime;

	print '<HR>';

	open NBIN, ">$cash_number_bin";
	binmode NBIN;

	opendir(DIR,$cash_sort);
	@dir = readdir DIR;
	closedir DIR;
	@dir = map("$cash_sort/$_", grep $_!~/^\.{1,2}$/s,@dir);
	@dir = reverse sort @dir;

	foreach $root_mon(@dir){
		if( -d $root_mon){
			opendir(DIR, $root_mon);
			my @dir_day = readdir DIR;
			closedir DIR;
			@dir_day = map("$root_mon/$_", grep $_!~/^\.{1,2}$/s,@dir_day);
			@dir_day = reverse sort @dir_day;
			foreach $root_day(@dir_day){
				if( -d $root_day){
					opendir(DIR, $root_day);
					my @day = readdir DIR;
					closedir DIR;
					@day = map("$root_day/$_", grep $_!~/^\.{1,2}$/s,@day);
					@day = reverse sort @day;
					foreach $day_log(@day){
						if($day_log =~ /(\d+)$/){
							my $no = int $1;
							my $block = int($no / 100);
							my $bdir = "$cash_number/$block";
							open(NUM,"$cash_number/$block/$no");
							my $number = <NUM>;
							close NUM;

							print '<script>BN_prog('.$IndexCount.")</script>\n"if($progress_on);
							$IndexCount++;
							print IBIN pack 'S',$no;	# write bin sort index
							print NBIN pack 'S',$number;	# write bin number

							sleep 1 if$SYS{ RECOVER_SLEEP }&&!($IndexCount % 100);
						}
					}

				}
			}
			
		}
	}

	#******************************************
	eval('$stime = sprintf "%.3f",((times)[0]-$start)');
	print "<B>TIME : $stime </B><BR>" if $stime;

	print '<script>BN_prog(0,"'.$txt[3].'")</script>'if($progress_on);
	my $bin;
	open(NBIN,$cash_number_bin);
	binmode NBIN;
	read NBIN, $bin, -s $cash_number_bin;
	close NBIN;
	print IBIN $bin;

	close IBIN;

	open(CNT,">$sys_count_cgi");
	print CNT "$MaxLogCount\t$MaxMsgCount";
	close CNT;

	unlink $cash_number_bin;
	unlink $sys_index_cgi;
	rename $cash_index_cgi,$sys_index_cgi;

	sleep 1 if $SYS{ RECOVER_SLEEP };

	print '<script>BN_prog(0,"'.$txt[4].'")</script>'if($progress_on);
	rmtree($dir_cash);

	print '<script>BN_prog(0,"'.$txt[1].'")</script>'if($progress_on);
	print $txt[1];

	$SYS{ ARG }{ BackButton }{ fc } = 'admin';
	$SYS{ ARG }{ BackButton }{ password } = $IN{password};
	undef $IN{'mode'};

	print &SkinBackButton();

	&Call('RecoverSysIndexEnd');

	&SkinFoot;

	fileunlock;

	exit;

}
#-----------------------------------------------------------------------------
# URL
sub ConvertURI(){
    my($prot, $uri) = @_;
	my $e;
    my $l = length $prot.$uri;
    my $p = pos $Message;
    my $apt = substr $Message, $p - 1, 1;
#&End('ERROR',"$prot @ $uri" , $apt);
    if ($apt eq substr $Message, $p + $l, 1) {
        return $prot.$uri;
    }

	$uri =~ s/\&quot\;/\%22/g;
	$e = '&lt;'.$2 if($uri =~ s/([-.!~*'()\w;\/?:\@&=+\$,%#]+)\&lt\;(.+)/$1/g);
	$e .= '"' if($uri=~s/\%22$//);
    return '<A href="' . $prot . $uri . '" target="_blank" class="autolinkurl">' . $prot . $uri . '</A class="autolinkurl">' . $e;
}
#-----------------------------------------------------------------------------
# ファームを囲むテーブルのタグ
sub TabeleFrame(){
	my $caption = $_[0];

	my %form_table1=%{$CFG{ TagTableOut }};
	$form_table1{TAG}='TABLE';
	$form_table1{noclose}=1;

	my %form_table2=%{$CFG{ TagTableIn }};
	$form_table2{TAG}='TABLE';
	$form_table2{noclose}=1;

	print '<CENTER>';
	print &SetTag(\%form_table1);
	print '<TR><TD>'.&SetTag({ color => $CFG{ TagTableIn }{bgcolor}, string=>$caption, size=>4, bold=>1});
	print &SetTag(\%form_table2);
	print '<TR><TD align=center>';

}
#-----------------------------------------------------------------------------
# メール暗号
sub MailCrypt{
	if($CFG{ UseMailCrypt }){
		my $q = sub{
			my @c = split /,/,$SYS{ FLAG }{ mailcrypt };
			my($d,$i);
			for $d(qw(name mail)){
				if($Data{$d} =~ /href="mailto:([^\"]+)"/){
					my $s = $1;
					my $n = 0;
					my($a,$r,$l);
					$l = length $s;
					while($n < $l || $n < 100){
						my $b = substr $s,$n,1;
						for($i=0;$i<52;$i++){
							last if($c[$i] eq $b);
						}
						if(0 <= $i && $i < 26){
							$r.=chr $i+65
						}elsif(25 < $i && $i < 51){
							$r.=chr $i+71
						}else{
							$r.=$b
						}
						$n++;
					}
					$a = "\;$1" if($Data{$d} =~ s/onmouseover="([^\"]+)"//);
					$Data{$d} =~ s/([^\x81-\x9F])@/$1\x81\x97/g; # WIN IEでhref不具合がでるため@を全角化する
					$Data{$d} =~ s/(href="mailto:)([^\"]+)"/$1" onmouseover="this.href=BN_mailcrypt('$r')$a"/;
				}
			}
		};
		push @SkinHeadFormat,sub{&GetJavaScript('BN_mailcrypt', \$JavaScript)};
		push @SkinMainBegin,$q;
		push @SkinReplyValue,$q;
	}
}
#-----------------------------------------------------------------------------
# 標準フォームへ返すエラー
sub ErrDefaultPost(){

	$errorstr = $_[0];

	&Call('ErrDefaultPostInit');

	if(exists $IN{edit} && $IN{edit} eq '' && $CFG{ UseImageUpload }){
		push @OpenPostInit,sub{$CFG{ UseImageUpload } = 1}
	}

	push @SkinPostFormInitBegin,sub{
		my @v = qw/fc mode sort page name mail url title message password/;
		@$Values{@v} = @IN{@v};
		if(exists $IN{edit}){
			$IN{number} = $IN{log};
			$IN{number}.="-$IN{edit}" if $IN{edit} ne '';
			$SYS{ ARG }{ PostForm }{ edit } = $IN{edit};
			$SYS{ ARG }{ PostForm }{ checkpass } = $IN{checkpass};
		}
	};
	push @SkinPostFormInitEnd,sub{
		# 注意文構造体
		my $form_info=
		[[
			[
				{
					TAG	=>	'TD',
					colspan	=>	'*',
					align	=>	'center',
					nowrap	=>	1,
				}
			],[
			 	{	string	=>	$errorstr	}
		 	]
		]];

		&SetForm(\@FORMS,\$form_info,'insert','name');
	};

	&OpenPost;

}
#-----------------------------------------------------------------------------
# メインログ 格納配列定数
sub LOG_MAIN_VALUE{(
	'num',
	'name',
	'date',
	'title',
	'mail',
	'url',
	'message',
	'host',
	'ip',
	'agent',
	'file_name',
	'file_width',
	'file_height',
	'file_length',
	'password',
	'object',
	'paint_time',
	'applet',
)}
#-----------------------------------------------------------------------------
# リプレイログ 格納配列定数
sub LOG_REPLY_VALUE{(
	'num',
	'name',
	'date',
	'message',
	'password',
	'iphost',
	'mail',
	'url',
	'browser',
	'os',
)}
#-----------------------------------------------------------------------------
# ヒストリーログ 格納配列定数
sub LOG_HISTORY_VALUE{(
	'times',
	'mode',
	'name',
	'title',
	'message',
	'ip',
	'host',
	'file_length',
)}
#----------------------------------------------------------------------------
# Flag [ 1 = ascii, 2 = sjis high, 3 = sjis low, 0 = etc ]
sub analyse(){
	my($msg,$bit) = @_;
	undef @$bit;
	my($i,$f);
	my $max = length $$msg;
	for($i=0;$i<$max;$i++){
		$_ = substr $$msg,$i,1;
		if($f>1){
			if(/[\x40-\xFC]/){
				$f = 3;
			}else{
				$f = 0;
			}
		}elsif(/[\x81-\x9F\xE0-\xEA\xED-\xEE\xFA-\xFB\xFC]/){
			$f = 2;
		}elsif(/[\x20-\x7E\xA1-\xDF]/){
			$f = 1;
		}else{
			$f = 0;
		}
		$$bit[$i] = $f;
		$f = 0 if($f==3);
	}
}
#-----------------------------------------------------------------------------
sub bn_crypt(){
	return if!$CFG{ UseCrypt };
	my($f,$str,$h,$k) = @_;
	my($s,$i,$n,@r);
	$h = $CFG{ AdminPassword }if!$h;
	$k = $CFG{ UseCryptKey }if!$k;
	my $key = ref $h eq 'HASH'?$$h{each %$h}:$h;
	my $rkey = pack "C*",reverse unpack "C*",$key;

	$key = crypt($key,$k);
	$key =~ s/^$k//;
	$rkey = crypt($rkey,$k);
	$rkey =~ s/^$k//;

	my @ck = unpack "C*",$key;
	push @ck,unpack "C*",$rkey;;

	my $klen = $#ck;
	my @c = unpack "C*",join '',('%','0'..'9','A'..'Z','_','a'..'z');

	$n = $i = 0;
	foreach(@c){
		$s = splice @c, $n,1;
		$ck[$i] % 2 ? push @c,$s : unshift @c,$s;
		$n++;$i++;
		$i = 0 if($i>$klen);
	}

	if(!$f){
		my @cm;
		for($i=0,$n=0;$n < length $str;$n++){
			$cm[$n] = $ck[$i] % 2;
			$i++;
			$i = 0 if($i>$klen);
		}
		@cm = reverse @cm;

		@r = unpack "C*",$str;
		$n = $i = 0;
		foreach(@r){
			if($cm[$i] % 2){
				$s = pop @r;
				splice @r,$#cm - $n,0,$s;
			}else{
				$s = splice @r,0,1;
				splice @r,$#cm - $n,0,$s;
			}
			$n++;$i++;
			$i = 0 if($i>$klen);
		}
		$str = join '',pack "C*",@r;
	}

	$s = ''; $n = 0; $o = ord $k;

	for (unpack "C*",$str){
		if(/[\x25\x30-\x39\x41-\x5A\5F\x61-\x7A]/){
			$i = 0;
			while($_ != $c[$i]){$i++;&End('ERROR',&Info('SYS_CRYPTERROR'))if$i>$#c}
			if($f){
				$i+=$ck[$n];
				$i+= $o;
				$o+= $_;
				while($i>$#c){$i-=@c}
			}else{
				$i-=$ck[$n];
				$i-= $o;
				while($i<0){$i+=@c}
				$o+= $c[$i];
			}
			$n++;
			$n = 0 if($n>$klen);
			$s.= chr $c[$i];
		}
	}

	if($f){
		@r = unpack "C*",$s;
		$n = $i = 0;
		foreach(@r){
			$s = splice @r, $n,1;
			$ck[$i] % 2 ? push @r,$s : unshift @r,$s;
			$n++;$i++;
			$i = 0 if($i>$klen);
		}
		$s = join '',pack "C*",@r;
	}

	return $s;
}
sub encrypt(){return &bn_crypt(1,@_)}
sub decrypt(){return &bn_crypt(0,@_)}
#-----------------------------------------------------------------------------
sub escape(){
	${$_[0]} =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;
}
sub unescape(){
	${$_[0]} =~ s/%([0-9A-F][0-9A-F])/pack("C", hex($1))/eg;
}
#-----------------------------------------------------------------------------
sub rmtree(){
	my $roots = $_[0];

  	if( defined($roots) && length($roots) ) {
		$roots = [$roots] unless ref $roots;
	}else{
		return 0;
	}
	my $root;
	my $count = 0;
	foreach $root(@{$roots}){
		$root =~ s#/$##;
		lstat $root or next;
		if( -d _){

		    	opendir RMDIR, $root || return 0;
			my @files = readdir RMDIR;
			closedir RMDIR;

			@files = map("$root/$_", grep $_!~/^\.{1,2}$/s,@files);

			$count += &rmtree(\@files);
			++$count if rmdir $root;
		}else{
			last if !unlink $root;
			++$count;
		}

	}

	return $count;

}
#-----------------------------------------------------------------------------
# &filelog([count],[head],[exe]); *need count value
sub filelog(){
	my $head	= $_[1]?$_[1]:$CFG{ FileHeadLogs };
	my $exe		= $_[2]?$_[2]:$CFG{ FileLogExe };
	my $inc		= "_$_[3]" if $_[3];
	$head =~ s/[^a-zA-Z]//g;
	return sprintf "$CFG{ DirFilePath }/$head\_%06d$inc\.$exe",$_[0];
}
sub filelock{
	return if $SYS{ LOCKED };
	my $try = $SYS{ LOCK_TRY };
	while(!mkdir($SYS{ LOCK_DIR },0755)){
		if(--$try <= 0) { 
			if((-M $SYS{ LOCK_DIR })*86400 > $SYS{ LOCK_SEC }) {
	                    rmdir($SYS{ LOCK_DIR })if(-e $SYS{ LOCK_DIR });
	                    last;
	                }
	                my($e0,$e1,$e2) = &Info('SYS_LOCKED');
			&End('ERROR',$e1,$e2) if($IN{ fc } ne 'captor');
	                print "Content-type: text/plain\n\nerror\n$e0\n$e1\n$e2";
	                exit;
		}
		sleep($SYS{ LOCK_SLEEP });
	}
	$SYS{ LOCKED } = 1;
}
sub fileunlock{
	rmdir($SYS{ LOCK_DIR })if(-e $SYS{ LOCK_DIR });
	$SYS{ LOCKED } = 0;
}

sub CryptString(){
	my($s,$f) = @_;
	my $c = $CFG{ UseCrypt } ? crypt($s,$CFG{ UseCryptKey }):$s;
	$c =~ s/^$CFG{ UseCryptKey }// if($f);
	return $c;
}

sub End(){eval<<'_SUB_';
	($ERRMODE, $ERRTITLE, $ERRMESG) = @_;
	fileunlock if $SYS{ LOCKED };

	# 標準出力
	select STDOUT;

	# テンポラリファイルの削除
	&PurgeTempFile;
	&ResetJavaScript;

	&ErrDefaultPost($ERRMESG) if($ERRMODE eq 'DEFAULTPOST');

	if($SYS{ FLAG }{ PAINT_CAPTOR }){
		print "Content-type: text/plain\n\nerror\n";
		undef $_;
		$_ = "$ERRTITLE\n" if $ERRTITLE;
		$_.= "$ERRMESG";
		s/<br>/\n/ig;
		s/(<[\/\w]>)//ig;
		print;
	}else{

		&HttpHead;
		eval('&SkinHead($ERRTITLE)');
		$ERRMESG =~ s/\n/<br>/ig;
		print "<center><h2>$ERRTITLE</h2><br>$ERRMESG</center>";

		eval('&SkinFoot');

	}

	exit;
_SUB_
}
sub Call(){foreach(eval '@'.$_[0]){&$_ if('CODE'eq ref $_)}}
sub Info(){
 local($s,@arg)=@_;
 local @r;
    if('CONFIG_NOTFOUND' eq $s){$r[0]='起動エラー';$r[1]='設定ファイル('.$SYS{ CONFIG }.')が見つかりませんでした。';}
 elsif('CONFIG_VER_ERROR' eq $s){$r[0]='設定ファイルの互換性エラー';$r[1]=qq/設定ファイル($SYS{ CONFIG })バージョン[$CFG{ CONFIG_VERSION }]はこの$SYS{ VERSION }バージョンと互換性がありません！<BR>対応するバージョンは[$SYS{ CONFIG_VERSION }]です。<BR>互換した設定ファイルを使用して下さい。/;}
 elsif('SKIN_NOTFOUND' eq $s){$r[0]='起動エラー';$r[1]=qq/スキンファイル($SYS{ SKIN })が見つかりませんでした。/;}
 elsif('DIR_NOTFOUND' eq $s){$r[0]='エラー';$r[1]=qq/ディレクトリ($arg[0])が見つかりませんでした。/;}
 elsif('DATA_NOTFOUND' eq $s){$r[0]='エラー';$r[1]='指定されたデータは見つかりませんでした。'.($arg[0]?"<BR>[$arg[0]]":'');}

 elsif('TMP_FILENAME' eq $s){$r[0]='システムエラー';$r[1]='テンポラリファイル名が取得できませんでした。';}


 elsif('FUNCTION_CANNOTEXE' eq $s){$r[0]='エラー';$r[1]='この機能は使用できません。';}

 elsif('SYS_NOTREADINDEX' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムインデックスは指定された番号($arg[0])を読込むことができませんでした。/;}
 elsif('SYS_NOTINDEXNUM' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムインデックスは指定された番号($arg[0])は存在しません。/;}
 elsif('SYS_NOTADDINDEX' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムインデックスはインデックスを追加できませんでした。/;}
 elsif('SYS_NOTINDEXOPEN' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムインデックス($arg[0])を読込むことができませんでした。/;}
 elsif('SYS_NOTINDEXWRITE' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムインデックス($arg[0])を書き込むことができませんでした。/;}
 elsif('SYS_BLOKENINDEX' eq $s){$r[0]='システムファイルエラー';$r[1]='致命的エラーです。<br>システムインデックスは破損している可能性があります。'.join '<br>',@arg;}

 elsif('SYSDIR_NOTWRITE' eq $s){$r[0]='システムエラー';$r[1]=qq/システムディレクトリ($CFG{ DirSysPath })に書き込むことができませんでした。/;}
 elsif('SYS_NOTITEM' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムファイルの指定がありませんでした。/;}
 elsif('SYS_NOTOPEN' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムファイル($arg[0])を読込むことができませんでした。/;}
 elsif('SYS_NOTWRITE' eq $s){$r[0]='システムファイルエラー';$r[1]=qq/システムファイル($arg[0])に書き込むことができませんでした。/;}

 elsif('SYS_COUNTERROR' eq $s){$r[0]='システムファイルエラー';$r[1]='致命的エラーです。<br>ログが多すぎるか何らかの事情により<br>正常なカウンタを取得できませんでした。';}
 elsif('SYS_CRYPTERROR' eq $s){$r[0]='システムエラー';$r[1]='暗号文字列が破損しています'}


 elsif('PASSWORD_ERROR' eq $s){$r[0]='パスワード不一致';$r[1]='パスワードが違います！<BR>もう一度よくお確かめ下さい。<P>'}

 elsif('DEFF_FORM_ARRAY_TYPE_ROW' eq $s){$r[0]='変数エラー';$r[1]='フォーム 行構造体の指定が間違っています。'}


 elsif('POST_UPLOADSIZEINFO' eq $s){$r[0]=qq/受信できる画像の最大データサイズは <B>/.($CFG{ LimitUpLoadData }>1000?int $CFG{ LimitUpLoadData }/1000:1). qq/<\/B> KB までです。(最大解像度 : $CFG{ LimitImageWidth } x $CFG{ LimitImageHeight } )/}
 elsif('POST_UPLOADEXEINFO' eq $s){$r[0]='画像ファイルには<B> '.(join '・',(map uc $_,split ',',$SYS{ CAPTOR_FORMAT })).' </B>が使用できます。'}
 elsif('POST_PASSWORDINFO' eq $s){$r[0]=qq/パスワードは半角英数で8文字まで有効です。/}

 elsif('CHECK_MULTIPLEPOST' eq $s){$r[0]='投稿エラー！';$r[1]='連続投稿です！<P>投稿は拒否されました。<BR>もう一度よくお確かめ下さい。'}

 elsif('CHECK_TITLE' eq $s)	{$r[0]='タイトルの記述がありません！'}
 elsif('CHECK_NAME' eq $s)	{$r[0]='名前の記述がありません！'}
 elsif('CHECK_MAIL' eq $s)	{$r[0]='メールの記述がありません！'}
 elsif('CHECK_URL' eq $s)	{$r[0]='URLの記述がありません！'}
 elsif('CHECK_PASSWORD' eq $s)	{$r[0]='パスワードの記述がありません！'}
 elsif('CHECK_MESSAGE' eq $s)	{$r[0]='メッセージの記述がありません！'}

 elsif('CHECK_TITLEOVER' eq $s)	{$r[0]='タイトルの文字数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitTitle }"}
 elsif('CHECK_NAMEOVER' eq $s)	{$r[0]='名前の文字数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitName }"}
 elsif('CHECK_MAILOVER' eq $s)	{$r[0]='メールの文字数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitMail }"}
 elsif('CHECK_URLOVER' eq $s)	{$r[0]='URLの文字数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitUrl }"}
 elsif('CHECK_MESSAGEOVER' eq $s){$r[0]='メッセージの文字数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitMessage }"}
 elsif('CHECK_MAILFORMAT' eq $s){$r[0]='メールの入力内容が正しくありません！'}

 elsif('CHECK_MESSAGELINEOVER' eq $s){$r[0]='メッセージの行数が多すぎます！'." 現在値 $arg[0]\/制限値 $CFG{ LimitLine }"}

 elsif('CHECK_UPCOMMENTONLY' eq $s){$r[0]='コメントのみの投稿はできません! 必ず画像も投稿して下さい'}
 elsif('CHECK_UPDATASIZEOVER' eq $s){$r[0]='アップロードデータサイズが制限値を超えました。<br>'.$arg[0].'byte 以下のデータサイズにして下さい。<BR>現在値：'.$arg[1].' byte'}
 elsif('CHECK_UPPIXELSIZEOVER' eq $s){$r[0]='画像サイズが大きすぎます。<br>'. $CFG{ LimitImageWidth }.'x'.$CFG{ LimitImageHeight }.'ピクセル以下の画像をアップロードして下さい。<BR>現在値 '.$arg[0].'x'.$arg[1]}

 elsif('CHECK_TAG' eq $s){$r[0]='タグが閉じられていません！<br><b>'.$arg[0].'</b><br>タグは閉じる必要があります。'}
 elsif('CHECK_TAGPOINT' eq $s){$r[0]='個所'}

 elsif('CHECK_POSTERROR' eq $s){$r[0]='投稿エラー！';$r[1]="<H1>投稿エラー！</H1><TABLE><TR><TD>$arg[0]</TD></TR></TABLE><p>もう一度よくお確かめ下さい。"}
 elsif('CHECK_REPLYERROR' eq $s){$r[0]='投稿エラー！';$r[1]='このスレッドには返信することができませんでした。'}

 elsif('LAYERFORM_TEXT' eq $s){@r=('閉じる',' 【','】 ','へ返信')}
 elsif('PAINT_ERR_IMAGESIZE' eq $s){$r[0]='エラー！！'."\n".'画像の受信データサイズが制限値を超えました。'."\n".'SEND : '.$arg[0].' byte / MAX : '.$arg[1].' byte'}
 elsif('PAINT_ERR_IMAGEPIXELSIZE' eq $s){$r[0]='エラー！！'."\n".'画像サイズが制限値を超えました。'."\n SEND : $arg[0]x$arg[1] / MAX : $arg[2]x$arg[3]"}
 elsif('PAINT_ERR_ANIMESIZE' eq $s){$r[0]='エラー！！'."\n".'アニメデータの受信データサイズが制限値を超えました。'."\n".'SEND : '.$arg[0].' byte / MAX : '.$arg[1].' byte'}
 elsif('PAINT_ERR_THUMBSIZE' eq $s){$r[0]='エラー！！'."\n".'サムネイル画像の受信データサイズが制限値を超えました。'."\n".'SEND : '.$arg[0].' byte / MAX : '.$arg[1].' byte'}

 elsif('UNKNOWN_FORMAT' eq $s){$r[0]='不明なファイル形式がアップロードされました。<br>対応している形式のみアップロードして下さい。'}
 elsif('SYS_LOCKED' eq $s){$r[0]='エラー！！';$r[1]='只今他の方が書き込み中です';$r[2]='しばらく待ってから再度投稿を行って下さい。'}
 elsif('BAD_REQUIRE' eq $s){$r[0]='呼び出しエラー';$r[1]='指定されたファイル('.$arg[0].')は呼び出すことができませんでした。'}
 elsif('BAD_WRITE' eq $s){$r[0]='エラー！！';$r[1]="ファイル($arg[0])".'に書き込みできませんでした。'}
 elsif('BAD_REQUEST' eq $s){$r[0]='エラー！！';$r[1]='不正なリクエストが送信されました。'}

 elsif('LOGIN_TEXT' eq $s){@r=('ログイン','パスワードを入力して下さい。')}
 elsif('RECOVER_TEXT' eq $s){@r=('システム修復','システムは修復されました','データディレクトリを解析中です...','システムインデックスを復元しています','作業ディレクトリを削除しています...')}
 elsif('FILERECOVER_TEXT' eq $s){@r=( 'ファイルより復帰', 'システムインデックスファイル：','送信','ローカルに保存されたシステムインデックスファイルをアップロードして下さい。',
 'アップロードされたファイルは破損または改変により使用できません<BR>正常なファイルをアップロードし直してください')}
 elsif('ADMIN_TEXT' eq $s){my $d = $SYS{USER_BROWSER}eq'NN'?'inline':'none';
	@r=('管理メニュー','自動ログインしました','管理コマンド',
 	'通常削除モード','一括削除モード','投稿削除','番号',
 	'複数の投稿を一括で削除できるモードにします。',
 	'通常削除モードに戻ります。',
 	'削除するメッセージをチェック、または番号を指定して下さい。',
 	'最新情報に更新','「'.($CFG{ IndexFilePath }=~/([\w\.]+)$/?$1:'').'」を最新の情報に書き換えします。',
 	'システム修復','バックアップ','ファイルより復帰する',
 	'<DIV id=ad_recover_index style="display:inline">「'.($CFG{ DirFilePath }=~/([\w\.]+)$/?$1:'').'」ディレクトリのファイルを解析しシステムインデックスを修復します。<BR>
 	何らかの原因でシステムインデックスが破損、初期化してしまった場合に行って下さい。<P></DIV>
 	<DIV id=ad_recover_backup style="display:'.$d .'">「バックアップ」によりシステムインデックスをローカルファイルで保存できます。<BR>&nbsp;<P></DIV>
 	<DIV id=ad_recover_file style="display:'.$d .'">「ファイルより復帰する」ではローカルに保存したシステムインデックスより<BR>
 	復帰する事ができます。</DIV>',
 )}
 elsif('CONFIG_TEXT' eq $s){@r=(
	'ログ保存件数',"$CFG{ LogMax } 件",
	'メッセージ最大文字数',"$CFG{ LimitMessage } byte",
	'返信許容制限',($CFG{ LimitResType }==0?"返信 $CFG{ LimitResTotal } 件":
	$CFG{ LimitResType }==1?"容量 $CFG{ LimitResLogSize } byte":
	$CFG{ LimitResType }==2?"返信 $CFG{ LimitResTotal } 件 または 容量 $CFG{ LimitResLogSize } byte":
	$CFG{ LimitResType }==3?"返信 $CFG{ LimitResTotal } 件 かつ 容量 $CFG{ LimitResLogSize } byte":''
	));

	push @r,('アップロード画像の最大受信データサイズ',"$CFG{ LimitUpLoadData } byte")if$CFG{ UseImageUpload };

	push @r,('お絵描き最大受信データサイズ',"$Paint::CFG{ LimitPaintData } byte",
	'お絵かきアニメ最大受信データサイズ',"$Paint::CFG{ LimitAnimeData } byte",
	'サムネイル最大受信データサイズ',"$Paint::CFG{ LimitThumbnailData } byte",
	'受信オーバー時の処置',($Paint::CFG{ LimitOverFlowDataAlert }&&'エラー表示'||'データ破棄'))if(exists $SYS{ MODULE }{ Paint });

	push @r,('受信する画像の最大解像度',"$CFG{ LimitImageWidth } x $CFG{ LimitImageHeight }",
	'閲覧時の画像の最大解像度',"$CFG{ ViewLimitImageWidth } x $CFG{ ViewLimitImageHeight }",
	'URL自動リンク',($CFG{ AutoLinkUrl }&&'する'||'しない'),
	'Mailto自動リンク',($CFG{ AutoLinkMail }&&'する'||'しない'),
	'引用文の認識',($CFG{ Quotation }&&'する'||'しない'),
	'コメントのみの投稿',($CFG{ NotCommentOnly }&&'禁止'||'許可'),
	'画像アップロード',($CFG{ UseImageUpload }&&'許可'||'禁止'),
	'Perl '.$],'OS '.$^O,
 )}
 elsif('HELP_TEXT' eq $s){@r=(
 	'<A href="http://wondercatstudio.com/" target="_blank"><IMG src="http://wondercatstudio.com/wcs_logo.gif" ALT="WonderCatStudio" border=0><BR>
	<SMALL><TT>Powerd by WonderCatStudio</SMALL></TT></A>',
 	'環境設定','使用可能タグ','モジュール情報','スキン情報',
 	'バージョン','最終更新日','著作権','作者','サイトURL','コメント',
 )}

	&Call('InfoInit');

	return @r;
}
sub module($){
	my $mo = $_[0];
	my $ex = '.cgi';
        
	if($mo eq 'multiskin')	{ $SYS{ SKIN }=$mo.$ex if -e $mo.$ex}
	else			{
        	eval{ require $mo.$ex if -e $mo.$ex };
                if ($@) {
			print "Content-Type: text/html\n\n";
			print "Got an error: $@";
		}
        }
	
	

}

if ($@) {
	print "Content-Type: text/html\n\n";
	print "Got an error: $@";
}

1;