#! /usr/bin/perl #↑上の行はプロバイダーの環境に合わせて設定してください。 #============================================================================= # BBS Note 8.x # Copyright(C) WonderCatStudio. All rights reserved. # http://wondercatstudio.com # LastModify 2004/06/06 #============================================================================= ############################################################################## ######################### 設定項目はありません ############################# ############################################################################## #----------------------------------------------------------------------------- require 5.003; sub filelock; sub fileunlock; eval { &Initialize }; sub Initialize{ #----------------------------< CONFIG >--------------------------------------- $SYS{ VERSION } = '8.0b14'; $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 #------------------------------------------------------------------- @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; &MailCrypt; &HttpHead; &SkinHead(); &SkinMenu; print "$Data
"; &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); }#================================================================ &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"; 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 }; foreach(keys %$a){ $applets{&Paint::Setting->{$_}{ applet }}=1 if $Paint::CFG{ UseApplet }{$_}; } map{$ap.= "1\n" }keys %applets; } print <<_XML_; $CFG{ BbsTitle } $bn BBS NOTE $SYS{ VERSION } $la $mod $SYS{ VERSION } $CFG{ DirFileUrl } $LogTotal $CFG{ LogMax } $CFG{ LogView } $CFG{ NotCommentOnly } $CFG{ UseImageMagick } $SYS{ SORT_MODE } $CFG{ UseTag } $CFG{ UseImageUpload } $ap _XML_ my $mo = $SYS{ MODULE }; my $mo_cnt; foreach(keys %$mo){ next if($$mo{$_}{invisible});$mo_cnt++; print qq/\n/; } print "\n"; 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/
/ /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.="\n"; $msg =~ s//>\;/g; $items.=<<_XML_; $LogValue{title} $bn?fc%3Dthread%26log%3D$IndexNumber $msg $LogValue{name} $date $mod $IndexNumber $Data{ ImageSrc } $Data{ AnimeSrc } $Data{ ThumbnailSrc } $LogValue{ file_width } $LogValue{ file_height } $LogValue{ file_length } _XML_ }#================================================================ &CloseSysIndex(INDEX); print "\n\n$seq\n\n\n\n$items\n\n"; 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); }#================================================================ &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 '

'; print $PageLinkForm; &TabeleFrame($txt[0]); print "$txt[1]" if($AutoLogin); print ''; } } return if!$s; $LogValue{message}.=<<_HTML_;

'; local $FormCgi = "
"; $FormCgi.= &SetFormGlobalArg($SYS{ ARG }{ AdminMenuForm }); # ログ解析・修復 print <<_HTML_; $FormCgi

$FormCgi

$txt[15]

_HTML_ # トップ更新 if($CFG{ UseRefleshIndex }){ print <<_HTML_; $FormCgi

$txt[11]

_HTML_ } &Call('OpenAdminMenu'); my $f = $FormCgi; $f =~ s/(method)/name=menuform $1/; # 一括削除 if($IN{ mode } eq 'delete'){ $SYS{ FLAG }{ MENUFORM } = 'ADMIN'; print <<_HTML_; $FormCgi

$txt[8]

$f $txt[6]

$txt[9]

_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.= "

"; $s.= ""; $s.= ""; delete $$h{ action }; delete $$h{ submit }; map{ $s.= "" if $$h{$_} ne '' } keys %$h; $s.='
$s
$txt[2]
_HTML_ }; push @SkinMainInit,$cmd; push @SkinReplyBegin,$cmd; print <<_HTML_; $f

$txt[7]

_HTML_ } print <<_HTML_; _HTML_ print '

'; }; &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 = "

$text[0]

$text[1]
"; $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],"$$mo{siteurl}" if $$mo{siteurl}; push @cf,$txt[10],$$mo{comment} if $$mo{comment}; print "$txt[3] : $IN{mo} Module"; for($c=0;$c<@cf;$c+=2){ print "" } print '
$cf[$c]@cf[$c+1]
'; }else{ &Call('OpenHelpBbsVer'); # BBSNote設定出力 print "

BBSNote Ver$SYS{ VERSION }

$txt[0]"; # Cookie if(exists $IN{cookiedump}){ print "

[ Cookie Data ] *DEBUG"; foreach(keys %COOKIE){ print "" } print '
$_$COOKIE{$_}

'; } &Call('OpenHelpConfig'); print "


$txt[1]"; for($c=0;$c<@cfg;$c+=2){ print "" } if($CFG{ UseImageMagick }){ my @ver = `$CFG{ ImageMagickPath } -verion`; $ver[0] = 'Not Install' if(!@ver); print ""; } if($CFG{ UseTag }==1){ print "'; } print '
$cfg[$c]@cfg[$c+1]
ImageMagick$ver[0]
$txt[2] : "; foreach(split /,/,$CFG{ OkTag }){ print "\<\;$_\>\;\ \;"; } print '
'; &Call('OpenHelpModule'); my $mo = $SYS{ MODULE }; my $mo_cnt; foreach(keys %$mo){ next if($$mo{$_}{invisible});$mo_cnt++; print "
$txt[3]
"if$mo_cnt==1; print "[$_ : $$mo{$_}{version}]" } print '
'if$mo_cnt; &Call('OpenHelpSkin'); my $sk = $SYS{ SKIN }; print <<_HTML_;
$txt[4] : $$sk{skin}
$txt[5] : $$sk{version} $txt[6] : $$sk{lastmodify} $txt[7] : $$sk{copyright}
$txt[8] : $$sk{author} $txt[9] : $$sk{siteurl}
_HTML_ } &Call('OpenHelpEnd'); print ''; print &SkinBackButton(); print ''; &SkinFoot; exit; _SUB_ } #----------------------------------------------------------------------------- sub OpenLog(){ my($log,$res_begin,$res_end) = @_; local $LogFile = &filelog($log); if(-e "$LogFile") { open(MSG,"<$LogFile"); local @FileData=; 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 = ; 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}){ # 返信投稿モード $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($_=){ $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'); }; # 初期化フック2 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"); $_ = ; &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(){ 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=; 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]; # $el--; # $el++; 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.="\n"; } if($f1 && $fs){ $form.="\n"; $form.=$fs; $form.="\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 = "<< NEXT |'; } if($n < $maxpage){ $linktext .= '|'.$href.($n+1).'"> BACK >>'; } last; } } $linktext .= ' PAGE '; if($pl && $pblock){ $n = $pblock * $pl; $linktext .= "[$href".($pblock * $pl).'"><<]'; } for($i = 0, $n = $pos; $i < $maxpage-$pos; $i++){ $n++; if($n == $page){ $linktext .= '['.$n.']'; next; } if($pl && $i >= $pl){ $linktext .= "[$href$n\">>>]"; last; } $linktext .= "[$href$n\">$n]"; } #=========================================== # 管理モード:パスワードを付加 トップ更新時はつけない $SYS{ ARG }{ PageLink }{ password } = $CFG{ AdminPassword } if($SYS{MODE}eq'ADMIN'&&!$SYS{FLAG}{RefleshIndex}); $arg = &SetFormGlobalArg($SYS{ ARG }{ PageLink }); my $formtag=''.$arg.'
'; $linkform='
'; for($i = $maxpage, $n = 0; $i > 0; $i--){ $n++; if($n == $page){ if($n - 1 > 0){ $linkform .= $formtag.'
'; } if($n < $maxpage){ $linkform .= $formtag.'
'; } last } } $n=0; $linkform .= $formtag.''; $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.=<= 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; } #================================================================= #< MM_showHideLayers >======================================================== if('MM_showHideLayers' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<======================================================== #< MM_findObj >=============================================================== if('MM_findObj' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<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=============================================================== #< MM_swapImage >=============================================================== if('MM_swapImage' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<=============================================================== #< MM_swapImgRestore >=============================================================== if('MM_swapImgRestore' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<=============================================================== #< MM_preloadImages >============================================================ if('MM_preloadImages' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<============================================================ #< MM_reloadPage >============================================================ if('MM_reloadPage' eq $js){ $$h{FLAG}{$js} = 1; $$ref.=<============================================================ #< 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.=< 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; } #============================================================ #< 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 = ''; $submit = ''; my $farg = &SetFormGlobalArg($SYS{ ARG }{ ReplyForm }); ${$arg[0]}.=< $farg SRC }else{ $close = ''.$text[0].''; $submit = ''; } my $tag = $arg[1]; $tag =~ s/\$close/$close/; $tag =~ s/\$submit/$submit/; ${$arg[0]}.=$tag; my @text = &Info('LAYERFORM_TEXT'); # $arg[2]; 送信ボタンテキスト $$ref.=<= 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 3 ) len++ } if(len>=limit){ m = m.substring(0,i) + '...'; }else{ if(op){limit-=2}else{limit+=2} for(i=len;i1)){ 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; } #================================================================ #< 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; } #========================================================== 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 追加 # italic 追加 # under 追加 # teletype 追加 # 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,''; unshift @ed ,''; }elsif(/italic/){ push @st,''; unshift @ed ,''; }elsif(/under/){ push @st,''; unshift @ed ,''; }elsif(/teletype/){ push @st,''; unshift @ed ,''; }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|BODY)$/){ push @str,(join ' ','<'.$tag,@el).'>'; }elsif($tag eq 'TEXTAREA'){ push @str,(join ' ','<'.$tag,@el).'>'.$string.""; }else{ next if($tag eq 'FONT' && !@el); if(!$noclose){ push @st,(join ' ','<'.$tag,@el).'>'; unshift @ed , ""; }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{""}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'})} @p=split '&',$s; foreach(@p){ ($n, $v)=split '='; $v =~ tr/+/ /; &unescape(\$v); $IN{$n}=$v; } } } #----------------------------------------------------------------------------- # インデックスログを開く # &OpenSysIndex(INDEX , 'index'); sub OpenSysIndex(){eval<<'_SUB_'; my($fp, $index) = @_; $path = "$CFG{ DirSysPath }/$index.$CFG{ FileSysExe }"; (open $fp,"<$path") || &End('ERROR',&Info('SYS_NOTINDEXOPEN',$index)); 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
"; $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\x00.+/) { $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 } = 'BBS NOTE '.$SYS{ VERSION }.''; &Call('Regist'); #BNCRYPTCODE================================================================== if($SYS{ LANGUAGE }eq'JP'){eval pack'H*','6D792024426F6F74203D207375627B26476574496E3B2643616C6C282746756E6374696F6E27293B69662824494E7B66637D2065712027777269746527297B265772697465506F73747D656C7369662824494E7B66637D20657120276C6F67696E27297B264F70656E4C6F67696E7D656C7369662824494E7B66637D206571202768656C7027297B264F70656E48656C707D656C7369662824494E7B66637D206571202774687265616427297B264F70656E5468726561647D656C7369662824494E7B66637D2065712027706F737427297B264F70656E506F73747D656C7369662824494E7B66637D206571202764656C65746527297B2644656C6574654C6F677D656C7369662824494E7B66637D20657120276564697427297B26456469744C6F677D656C7369662824494E7B66637D206571202761646D696E27297B264F70656E41646D696E7D656C7369662824494E7B66637D206571202772737327297B264F70656E5273737D656C73657B264F70656E506167657D657869747D3B756E64656620245359537B20434C49454E545F434F50595249474854207D3B6D79202468203D20245061696E743A3A4346477B53657474696E677D3B696628646566696E6564202468297B6D7920246366203D20245061696E743A3A4346477B5573654170706C65747D3B6D792025663B6D61707B24667B2424687B245F7D7B6170706C65747D7D3D317D402463663B6D792024737061203D20275368695061696E74657227696624667B73706170726F7D7C7C24667B7370616E6F726D616C7D3B6D792024706273093D20275061696E7442425327696624667B7369697D3B247370612E3D272C202769662824737061262624706273293B245359537B20434C49454E545F434F50595249474854207D3D223C42523E2473706124706273222E272050726F6772616D203C4120485245463D22687474703A2F2F7777772E67742E73616B7572612E6E652E6A702F7E6F636F73616D612F22205441524745543D225F626C616E6B223E28432982B582A182BF82E182F1287368692D6379616E293C2F413E2027696628247370617C7C24706273293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E506963747572654242532050726F6772616D202843292082A8816082CC286F686E6F292769662824667B7069637D293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E4242535061696E7465722050726F6772616D203C4120485245463D22687474703A2F2F7777772E67656F6369746965732E636F2E6A702F53696C69636F6E56616C6C65792D53616E4A6F73652F383630392F22205441524745543D225F626C616E6B223E2843292082C982C8286E696E61293C2F413E2769662824667B7061697D293B7D245359537B204242535F434F505952494748545F434F4445207D3D756E7061636B22253332432A222C245359537B204242535F434F50595249474854207D3B245359537B204150505F434F505952494748545F434F4445207D3D39353934323B2624426F6F7420696628245359537B204242535F434F505952494748545F434F4445207D3D3D3737363920262620245359537B204150505F434F505952494748545F434F4445207D3D3D393539343229'} else{eval pack'H*','6D792024426F6F74203D207375627B26476574496E3B2643616C6C282746756E6374696F6E27293B69662824494E7B66637D2065712027777269746527297B265772697465506F73747D656C7369662824494E7B66637D20657120276C6F67696E27297B264F70656E4C6F67696E7D656C7369662824494E7B66637D206571202768656C7027297B264F70656E48656C707D656C7369662824494E7B66637D206571202774687265616427297B264F70656E5468726561647D656C7369662824494E7B66637D2065712027706F737427297B264F70656E506F73747D656C7369662824494E7B66637D206571202764656C65746527297B2644656C6574654C6F677D656C7369662824494E7B66637D20657120276564697427297B26456469744C6F677D656C7369662824494E7B66637D206571202761646D696E27297B264F70656E41646D696E7D656C7369662824494E7B66637D206571202772737327297B264F70656E5273737D656C73657B264F70656E506167657D657869747D3B756E64656620245359537B20434C49454E545F434F50595249474854207D3B696628646566696E656420265061696E743A3A53657474696E67297B6D7920246366203D20245061696E743A3A4346477B5573654170706C65747D3B6D79202468203D20265061696E743A3A53657474696E673B6D792025663B6D61707B24667B2424687B245F7D7B6170706C65747D7D3D3120696620242463667B245F7D7D6B65797320252463663B6D792024737061203D20275368695061696E74657227696624667B73706170726F7D7C7C24667B7370616E6F726D616C7D3B6D792024706273093D20275061696E7442425327696624667B7369697D3B247370612E3D272C202769662824737061262624706273293B245359537B20434C49454E545F434F50595249474854207D3D223C42523E2473706124706273222E272050726F6772616D203C4120485245463D22687474703A2F2F7777772E67742E73616B7572612E6E652E6A702F7E6F636F73616D612F22205441524745543D225F626C616E6B223E284329207368692D6379616E3C2F413E2027696628247370617C7C24706273293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E506963747572654242532050726F6772616D20284329206F686E6F27696628242463667B506963747572654242537D293B245359537B20434C49454E545F434F50595249474854207D2E3D273C42523E4242535061696E7465722050726F6772616D203C4120485245463D22687474703A2F2F7777772E67656F6369746965732E636F2E6A702F53696C69636F6E56616C6C65792D53616E4A6F73652F383630392F22205441524745543D225F626C616E6B223E284329206E696E613C2F413E27696628242463667B4242535061696E7465727D293B7D245359537B204242535F434F505952494748545F434F4445207D3D756E7061636B22253332432A222C245359537B204242535F434F50595249474854207D3B245359537B204150505F434F505952494748545F434F4445207D3D39363236333B2624426F6F7420696628245359537B204242535F434F505952494748545F434F4445207D3D3D3737363920262620245359537B204150505F434F505952494748545F434F4445207D3D3D393632363329'} #BNCRYPTCODE================================================================== } #----------------------------------------------------------------------------- # ブラウザ関係 # sub GetUserAgent{eval << '_SUB_'; my($a,$c,$o); my $b = $ENV{'HTTP_USER_AGENT'}; $b =~ s//>/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=~ /Safari\/?([\d\.]*)/) { $a='Safari'; $c="Safari $1" } elsif($b=~ /Mozilla\/5/) { $a='NN'; if($b=~ /Netscape\/?([\w\.]+)/) { $c="NN $1" } else { $c='Mozilla' } } 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', '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', 'BSD/OS:HP-UX', 'Linux:Linux', ); foreach(@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' if(!$o); 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(){ &GetLogReplyValue($_, \%LogValue, \%LogExValue); if($LogValue{num} eq $res){ close MSG; return $LogValue{password}; } } }else{ $_ = ; &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}); $SYS{ FLAG }{ ALLTAG } ? &EscapeInput(2,\$IN{message}) : &EscapeInput(0,\$IN{message}); # 文字列のチェック &CheckString; &Call('CheckInputBegin'); # 画像アップロード if($SYS{ FLAG }{ FILE_CAPTOR }){ local $h = \$FILES{'file'}; ( $$h->{'mime'}, $$h->{'width'}, $$h->{'height'}, $$h->{'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$_
"}@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($_=){ 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 CheckReplyEnable(){ my($num, $size) = @_; return 0 if $SYS{ MODE } =~ /REPLY|DELETE|EDIT/; return 0 if($SYS{ MODE } eq 'ADMIN' && $IN{ mode } eq 'deletewide'); 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+\;)/\&\;/go; ${$_}=~s/\"/\"\;/go; ${$_}=~s//\n/g; $$s =~ s/

/\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/ / /go; $Message=~ s/\t/    /go; # 使用可能タグ my $errstr; if(!$SYS{ FLAG }{ ALLTAG } && $CFG{ UseTag } && ($errstr = &ConvertTag(\$Message,\$CFG{ OkTag }))){ push @ERR,&Info('CHECK_TAG',$errstr); } &Call('ConvertMessageAutoLink'); # リンクを有効に if($CFG{ AutoLinkUrl }){$Message =~ s/https?:\/\/([-.!~*'()\w;\/?:\@&=+\$,%#]+)/&ConvertURI($1)/eg} if($CFG{ AutoLinkMail }){$Message =~ s/mailto\:([\w\.\?\#\_\:\;\/\%\&\$\"\!\'\(\)\=\~\^\-\+\|\@]*)/$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.''.$q.$s.''.$e }else{ return $h.''.$q.$s.''.$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/

/img); $line*=2; $line+=($Message =~ s/\n/
/img); if($CFG{ LimitLine } < $line){ push @ERR,&Info('CHECK_MESSAGELINEOVER',$line) } &CheckError(@ERR); &Call('ConvertMessageEnd'); return $Message; } #----------------------------------------------------------------------------- # タグ変換 sub ConvertTag(){ my($ref_str,$ref_tag) = @_; my($str,$end,@parts,@_cnt,$flag_pre,$_pertag); my @ref_tags = split ',',$$ref_tag; $$ref_str =~ s/\<\;BR>/\n/igo; $$ref_str =~ s/\<\;P>/\n\n/igo; @parts = split(/(>)/,$$ref_str); undef $$ref_str; $end = pop @parts; foreach(@parts){ if(index $_,'<' > -1){ my($n,$aliment,$need,$slash,@l); foreach $_pertag(@ref_tags){ my($tag,@tag_element) = split /:/,$_pertag; if(s/\<\;(\/)?$tag([\&\w\s]+.*|$)/<$1$tag/i){ $slash = $1; $flag_pre = $flag_pre != 1?1:0 if($tag eq 'PRE'); if($slash eq ''){$_cnt[$n]++}else{$_cnt[$n]--} if(!$flag_pre){ if(length $2 > 1){ $aliment = $2; $aliment =~ s/\=/\&equ\;/gi; $aliment =~ s/\ \;/ /gi; my $ln; while($aliment =~ /\&equ\;\"\;([\\\w-.!~*'();\/?:\@\&\+\$,%\#\x80-\xFF ]+)\"\;(\s|$)/){ my $v = $1; $v =~ s/\"\;.+//; my $t = $v; $v =~ s/\&equ\;/=/g; $v =~ s/(https?):/$1%3A/g; $aliment =~ s/(\&equ\;\"\;)$t(\"\;)(\s|$)/$1$v\e$2$3/; $ln++; last if($ln>10); } if($tag eq 'FONT'){ push @tag_element,qw/size color face/; }elsif($tag eq 'IMG'){ $_cnt[$n]--; }elsif($tag eq 'DIV'){ push @tag_element,'align'; } foreach $e(@tag_element){ $aliment =~ s/(\s*)$e\&equ\;\"\;([^\e]+)(?:\e)\"\;/$1$e\=\"$2\"/si; } } }elsif($tag ne 'PRE'){s/0){ ($tag) = split /:/,$ref_tags[$n],1; $s = join '',$_,&Info('CHECK_TAGPOINT') if $_>1; $errstr.= "<$tag>$s "; } $n++ } $$ref_str = $str.$end; return $errstr if($errstr); return 0; } #----------------------------------------------------------------------------- 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 "

$txt[1]

"; $SYS{ ARG }{ BackButton }{ fc } = 'admin'; $SYS{ ARG }{ BackButton }{ password } = $IN{password}; undef $IN{'mode'}; print &SkinBackButton(); print '
'; &SkinFoot; fileunlock; exit; } #----------------------------------------------------------------------------- sub RecoverFileIndexForm{ &HttpHead; &SkinHead($txt[0]); print '

'; &TabeleFrame($txt[0]); print <<_HTML_;
$txt[3]
$txt[1]
_HTML_ $SYS{ ARG }{ BackButton }{ fc } = 'admin'; $SYS{ ARG }{ BackButton }{ password } = $IN{password}; undef $IN{'mode'}; print &SkinBackButton(); print <<_HTML_;


_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 "

$txt[0]

"; if($progress_on){ print <

HTML } #****************************************** eval('$stime = sprintf "%.3f",((times)[0]-$start)'); print "TIME : $stime
" if $stime; print ''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 = ; 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
"; print ''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 '\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
"; print "Max Msg Count : $MaxMsgCount
"; #****************************************** eval('$stime = sprintf "%.3f",((times)[0]-$start)'); print "TIME : $stime
" if $stime; print '
'; 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 = ; close NUM; print '\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 "TIME : $stime
" if $stime; print ''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 ''if($progress_on); rmtree($dir_cash); print ''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 $uri= $_[0]; my $e; $uri =~ s/\"\;/\%22/g; $e = '<'.$2 if($uri =~ s/([-.!~*'()\w;\/?:\@&=+\$,%#]+)\<\;(.+)/$1/g); $e .= '"' if($uri=~s/\%22$//); return "http\:\/\/$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 '
'; print &SetTag(\%form_table1); print ''.&SetTag({ color => $CFG{ TagTableIn }{bgcolor}, string=>$caption, size=>4, bold=>1}); print &SetTag(\%form_table2); print ''; } #----------------------------------------------------------------------------- # メール暗号 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; foreach(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/
/\n/ig; s/(<[\/\w]>)//ig; print; }else{ &HttpHead; eval('&SkinHead($ERRTITLE)'); $ERRMESG =~ s/\n/
/ig; print "

$ERRTITLE


$ERRMESG
"; 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 }バージョンと互換性がありません!
対応するバージョンは[$SYS{ CONFIG_VERSION }]です。
互換した設定ファイルを使用して下さい。/;} 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]?"
[$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]='致命的エラーです。
システムインデックスは破損している可能性があります。'.join '
',@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]='致命的エラーです。
ログが多すぎるか何らかの事情により
正常なカウンタを取得できませんでした。';} elsif('SYS_CRYPTERROR' eq $s){$r[0]='システムエラー';$r[1]='暗号文字列が破損しています'} elsif('PASSWORD_ERROR' eq $s){$r[0]='パスワード不一致';$r[1]='パスワードが違います!
もう一度よくお確かめ下さい。

'} elsif('DEFF_FORM_ARRAY_TYPE_ROW' eq $s){$r[0]='変数エラー';$r[1]='フォーム 行構造体の指定が間違っています。'} elsif('POST_UPLOADSIZEINFO' eq $s){$r[0]=qq/受信できる画像の最大データサイズは /.($CFG{ LimitUpLoadData }>1000?int $CFG{ LimitUpLoadData }/1000:1). qq/<\/B> KB までです。(最大解像度 : $CFG{ LimitImageWidth } x $CFG{ LimitImageHeight } )/} elsif('POST_UPLOADEXEINFO' eq $s){$r[0]='画像ファイルには '.(join '・',(map uc $_,split ',',$SYS{ CAPTOR_FORMAT })).' が使用できます。'} elsif('POST_PASSWORDINFO' eq $s){$r[0]=qq/パスワードは半角英数で8文字まで有効です。/} elsif('CHECK_MULTIPLEPOST' eq $s){$r[0]='投稿エラー!';$r[1]='連続投稿です!

投稿は拒否されました。
もう一度よくお確かめ下さい。'} 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]='アップロードデータサイズが制限値を超えました。
'.$arg[0].'byte 以下のデータサイズにして下さい。
現在値:'.$arg[1].' byte'} elsif('CHECK_UPPIXELSIZEOVER' eq $s){$r[0]='画像サイズが大きすぎます。
'. $CFG{ LimitImageWidth }.'x'.$CFG{ LimitImageHeight }.'ピクセル以下の画像をアップロードして下さい。
現在値 '.$arg[0].'x'.$arg[1]} elsif('CHECK_TAG' eq $s){$r[0]='タグが閉じられていません!
'.$arg[0].'
タグは閉じる必要があります。'} elsif('CHECK_TAGPOINT' eq $s){$r[0]='個所'} elsif('CHECK_POSTERROR' eq $s){$r[0]='投稿エラー!';$r[1]="

投稿エラー!

$arg[0]

もう一度よくお確かめ下さい。"} 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]='不明なファイル形式がアップロードされました。
対応している形式のみアップロードして下さい。'} 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=( 'ファイルより復帰', 'システムインデックスファイル:','送信','ローカルに保存されたシステムインデックスファイルをアップロードして下さい。', 'アップロードされたファイルは破損または改変により使用できません
正常なファイルをアップロードし直してください')} elsif('ADMIN_TEXT' eq $s){my $d = $SYS{USER_BROWSER}eq'NN'?'inline':'none'; @r=('管理メニュー','自動ログインしました','管理コマンド', '通常削除モード','一括削除モード','投稿削除','番号', '複数の投稿を一括で削除できるモードにします。', '通常削除モードに戻ります。', '削除するメッセージをチェック、または番号を指定して下さい。', '最新情報に更新','「'.($CFG{ IndexFilePath }=~/([\w\.]+)$/?$1:'').'」を最新の情報に書き換えします。', 'システム修復','バックアップ','ファイルより復帰する', '

「'.($CFG{ DirFilePath }=~/([\w\.]+)$/?$1:'').'」ディレクトリのファイルを解析しシステムインデックスを修復します。
何らかの原因でシステムインデックスが破損、初期化してしまった場合に行って下さい。

「バックアップ」によりシステムインデックスをローカルファイルで保存できます。
 

「ファイルより復帰する」ではローカルに保存したシステムインデックスより
復帰する事ができます。
', )} 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=( '
WonderCatStudio
Powerd by WonderCatStudio
', '環境設定','使用可能タグ','モジュール情報','スキン情報', 'バージョン','最終更新日','著作権','作者','サイト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;