#!/usr/local/bin/perl #┌───────────────────────────────── #│ WEB PATIO : admin.cgi - 2022/03/26 #│ copyright (c) kentweb, 1997-2022 #│ https://www.kent-web.com/ #└───────────────────────────────── # モジュール宣言 use strict; use CGI::Carp qw(fatalsToBrowser); use vars qw(%in %cf); use lib "./lib"; use CGI::Minimal; use CGI::Session; use Digest::SHA::PurePerl qw(sha256_base64); # 設定ファイル認識 require "./init.cgi"; %cf = set_init(); # データ受理 CGI::Minimal::max_read_size($cf{maxdata}); my $cgi = CGI::Minimal->new; cgi_err('容量オーバー') if ($cgi->truncated); %in = parse_form($cgi); # 認証 require "./lib/login.pl"; auth_login(); # 条件分岐 if ($in{data_now} or $in{data_past}) { data_mgr(); } if ($in{auth_mgr}) { auth_mgr(); } if ($in{size_chk}) { size_chk(); } if ($in{pass_mgr}) { pass_mgr(); } # メニュー画面 menu_html(); #----------------------------------------------------------- # メニュー画面 #----------------------------------------------------------- sub menu_html { header("メニューTOP"); print <<EOM; <div id="body"> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <table class="form-tbl" id="menu"> <tr> <th>選択</th> <th class="w-15">処理メニュー</th> </tr><tr> <td><input type="submit" name="data_now" value="選択"></td> <td>現行ログメンテナンス</td> </tr><tr> <td><input type="submit" name="data_past" value="選択"></td> <td>過去ログメンテナンス</td> EOM if ($cf{authkey}) { print qq|</tr><tr>\n|; print qq|<td><input type="submit" name="auth_mgr" value="選択"></td>\n|; print qq|<td>会員管理(認証モード)</td>\n|; } print <<EOM; </tr><tr> <td><input type="submit" name="size_chk" value="選択"></td> <td>ファイル容量</td> </tr><tr> <td><input type="submit" name="pass_mgr" value="選択"></td> <td>パスワード管理</td> </tr><tr> <td><input type="submit" name="logoff" value="選択"></td> <td>ログアウト</td> </tr> </table> </form> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # データ編集 #----------------------------------------------------------- sub data_mgr { # 汚染チェック $in{no} =~ s/\D//g; # index定義 my ($log,$mode,$subject); if ($in{data_now}) { $log = "$cf{datadir}/index1.log"; $subject = "現行ログ"; $mode = "data_now"; } else { $log = "$cf{datadir}/index2.log"; $subject = "過去ログ"; $mode = "data_past"; } # スレッド削除 if ($in{job} eq "del" && $in{no}) { del_thread($log); # スレッドロック開閉 } elsif ($in{job} eq "lock" && $in{no} && $in{data_now}) { lock_thread($log); # スレッドの管理者コメントモード } elsif ($in{job} eq "admin" && $in{no} && $in{data_now}) { admin_thread($log); # スレッド内個別記事 } elsif ($in{job} eq "art" && $in{no}) { article($subject,$mode,$log); } header("データメンテ [ $subject ]"); back_btn(); print <<EOM; <div id="ttl"><img src="$cf{cmnurl}/db_gear.png" alt="" class="icon"> データメンテ [ $subject ]</div> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="$mode" value="1"> <div class="ope-btn"> 処理 <select name="job"> <option value="art">個別メンテ <option value="del">スレ削除 EOM if ($in{data_now}) { print qq|<option value="lock">ロック開閉\n|; print qq|<option value="admin">管理者コメ\n|; } print <<EOM; </select> <input type="submit" value="送信する"> </div> <table class="form-tbl" id="list"> <tr> <th>選択</th> <th>状態</th> <th>スレッド</th> <th>作成者</th> <th>レス数</th> <th>備考</th> </tr> EOM my %stat = (0 => 'ロック中', 2 => '管理コメ'); # スレッド一覧 open(IN,"$log") or cgi_err("open err: $log"); my $top = <IN> if ($in{data_now}); while (<IN>) { my ($no,$sub,$res,$nam,$upd,$las,$key,$upl) = split(/<>/); my $ico; if ($key == 2) { $ico = 2; } elsif ($upl) { $ico = 'image'; } else { $ico = $key; } print qq|<tr><td class="ta-c"><input type="radio" name="no" value="$no"></td>|; print qq|<td class="ta-c"><img src="$cf{iconurl}/$cf{fld_icon}->{$ico}" alt=""></td>|; print qq|<td><b>$sub</b></td>|; print qq|<td>$nam</td>|; print qq|<td class="ta-r">$res</td>|; print qq|<td>$stat{$key}<br></td></tr>\n|; } close(IN); print <<EOM; </table> </form> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # スレッド削除 #----------------------------------------------------------- sub del_thread { my ($log) = @_; # indexより削除情報抽出 my @new; open(DAT,"+< $log") or cgi_err("open err: $log"); eval "flock(DAT,2);"; my $top = <DAT> if ($in{data_now}); while(<DAT>) { my ($no) = (split(/<>/))[0]; if ($in{no} == $no) { # ログ展開 open(DB,"$cf{datadir}/log/$in{no}.cgi"); while( my $db = <DB> ) { my ($no,$sub,$nam,$eml,$com,$dat,$ho,$pw,$url,$mvw,$myid,$tim,$up1,$up2,$up3) = split(/<>/, $db); # 画像削除 my $n; foreach my $up ($up1,$up2,$up3) { $n++; my ($ex) = split(/,/, $up); next if (!$ex); if (-e "$cf{upldir}/$tim-$n$ex") { unlink("$cf{upldir}/$tim-$n$ex"); } if (-e "$cf{upldir}/$tim-s-$n$ex") { unlink("$cf{upldir}/$tim-s-$n$ex"); } } } close(DB); # スレッド削除 unlink("$cf{datadir}/log/$in{no}.cgi"); unlink("$cf{datadir}/log/$in{no}.dat"); next; } push(@new,$_); } # index更新 unshift(@new,$top) if ($in{data_now}); seek(DAT,0,0); print DAT @new; truncate(DAT,tell(DAT)); close(DAT); } #----------------------------------------------------------- # スレッドロック開閉 #----------------------------------------------------------- sub lock_thread { my ($log) = @_; open(DAT,"+< $cf{datadir}/log/$in{no}.cgi") or cgi_err("open err: $in{no}.cgi"); eval "flock(DAT,2);"; my $top = <DAT>; my @data = <DAT>; # 先頭記事分解、キー開閉 my ($num,$sub,$res,$key) = split(/<>/, $top); # 0=ロック 1=標準 2=管理用 $key = $key ? 0 : 1; # スレッド更新 unshift(@data,"$num<>$sub<>$res<>$key<>\n"); seek(DAT,0,0); print DAT @data; truncate(DAT, tell(DAT)); close(DAT); # index読み込み @data = (); open(DAT,"+< $log") or cgi_err("open err: $log"); eval "flock(DAT,2);"; my $top = <DAT>; while(<DAT>) { chomp; my ($no,$sub,$res,$nam,$da,$na2,$key,$upl) = split(/<>/); if ($in{no} == $no) { # 0=ロック 1=標準 2=管理用 $key = $key ? 0 : 1; $_ = "$no<>$sub<>$res<>$nam<>$da<>$na2<>$key<>$upl<>"; } push(@data,"$_\n"); } # index更新 unshift(@data,$top); seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); } #----------------------------------------------------------- # スレッド管理者コメント #----------------------------------------------------------- sub admin_thread { my ($log) = @_; open(DAT,"+< $cf{datadir}/log/$in{no}.cgi") or cgi_err("open err: $in{no}.cgi"); eval "flock(DAT,2);"; my $top = <DAT>; my @data = <DAT>; # 先頭記事分解、キー開閉 my ($num,$sub,$res,$key) = split(/<>/,$top); # 0=ロック 1=標準 2=管理用 $key = $key < 2 ? 2 : 1; # スレッド更新 unshift(@data,"$num<>$sub<>$res<>$key<>\n"); seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); # index読み込み my ($new,@data); open(DAT,"+< $log") or cgi_err("open err: $log"); eval "flock(DAT,2);"; my $top = <DAT>; while(<DAT>) { chomp; my ($no,$sub,$res,$nam,$da,$na2,$key,$upl) = split(/<>/); if ($in{no} == $no) { # 0=ロック 1=標準 2=管理用 if ($key == 2) { $_ = "$no<>$sub<>$res<>$nam<>$da<>$na2<>1<>$upl<>"; } else { $new = "$no<>$sub<>$res<>$nam<>$da<>$na2<>2<>$upl<>\n"; next; } } push(@data,"$_\n"); } # index更新 unshift(@data,$new) if ($new); unshift(@data,$top); seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); } #----------------------------------------------------------- # 個別記事メンテ #----------------------------------------------------------- sub article { my ($subject,$mode,$log) = @_; # レス記事個別削除 if ($in{act} eq "dele" && $in{art} ne '') { if ($in{art} eq '0') { cgi_err("親記事の削除はできません"); } # スレッド内より削除記事を抽出 my (@new,$last_nam,$last_dat); open(DAT,"+< $cf{datadir}/log/$in{no}.cgi"); eval "flock(DAT,2);"; my $top = <DAT>; my ($num,$sub2,$res,$key) = split(/<>/, $top); while(<DAT>) { my ($no,$sub,$nam,$em,$com,$dat,$ho,$pw,$url,$mvw,$myid,$tim,$up1,$up2,$up3) = split(/<>/); if ($no == $in{art}) { # 画像削除 my $n; foreach my $up ($up1,$up2,$up3) { $n++; my ($ex) = split(/,/, $up); next if (!$ex); if (-e "$cf{upldir}/$tim-$n$ex") { unlink("$cf{upldir}/$tim-$n$ex"); } if (-e "$cf{upldir}/$tim-s-$n$ex") { unlink("$cf{upldir}/$tim-s-$n$ex"); } } next; } push(@new,$_); # 最終投稿者名と時間を覚えておく $last_nam = $nam; $last_dat = $dat; } # レス個数を調整 $res--; $top = "$num<>$sub2<>$res<>$key<>\n"; # スレッド更新 unshift(@new,$top); seek(DAT,0,0); print DAT @new; truncate(DAT,tell(DAT)); close(DAT); # index内容差し替え my (@new,@sort,@top); open(DAT,"+< $log"); eval "flock(DAT,2);"; my $top = <DAT> if ($in{data_now}); while(<DAT>) { chomp; my ($no,$sb,$re,$na,$dat,$na2,$key,$upl) = split(/<>/); if ($key == 2) { push(@top,"$_\n"); next; } if ($in{no} == $no) { # レス個数と最終投稿者名を差替 $na2 = $last_nam; $dat = $last_dat; $_ = "$no<>$sb<>$res<>$na<>$dat<>$na2<>$key<>$upl<>"; } push(@new,"$_\n"); # ソート用配列 $dat =~ s/\D//g; push(@sort,$dat); } # 投稿順にソート @new = @new[sort {$sort[$b] <=> $sort[$a]} 0 .. $#sort]; # index更新 unshift(@new,@top) if (@top > 0); unshift(@new,$top) if ($in{data_now}); seek(DAT,0,0); print DAT @new; truncate(DAT,tell(DAT)); close(DAT); # レス記事個別修正フォーム } elsif ($in{act} eq "edit" && $in{art} ne '') { my $data; open(DAT,"$cf{datadir}/log/$in{no}.cgi"); my $top = <DAT>; while(<DAT>) { my ($no,$sub,$nam,$em,$com,$dat,$ho,$pw,$url,$mvw,$myid,$tim,$up1,$up2,$up3) = split(/<>/); if ($in{art} == $no) { chomp; $data = $_; last; } } close(DAT); # スレッドタイトル my ($sub2) = (split(/<>/,$top))[1]; # 個別修正フォーム edit_form($subject,$mode,$log,$data,$sub2); # レス記事個別修正実行 } elsif ($in{act} eq "edit2" && $in{art} ne '') { my @data; open(DAT,"+< $cf{datadir}/log/$in{no}.cgi"); eval "flock(DAT,2);"; my $top = <DAT>; while(<DAT>) { chomp; my ($no,$sub,$nam,$em,$com,$dat,$ho,$pw,$url,$mlo,$myid,$tim,$up1,$up2,$up3) = split(/<>/); if ($in{art} == $no) { # 画像削除 if ($in{del1}) { my ($ex) = split(/,/,$up1); unlink("$cf{upldir}/$tim-1$ex"); unlink("$cf{upldir}/$tim-s-1$ex") if (-e "$cf{upldir}/$tim-s-1$ex"); $up1 = ''; } if ($in{del2}) { my ($ex) = split(/,/,$up2); unlink("$cf{upldir}/$tim-2$ex"); unlink("$cf{upldir}/$tim-s-2$ex") if (-e "$cf{upldir}/$tim-s-2$ex"); $up2 = ''; } if ($in{del3}) { my ($ex) = split(/,/,$up3); unlink("$cf{upldir}/$tim-3$ex"); unlink("$cf{upldir}/$tim-s-3$ex") if (-e "$cf{upldir}/$tim-s-3$ex"); $up3 = ''; } $_ = "$no<>$in{sub}<>$in{name}<>$in{email}<>$in{comment}<>$dat<>$ho<>$pw<>$in{url}<>$in{mlo}<>$myid<>$tim<>$up1<>$up2<>$up3<>"; } push(@data,"$_\n"); } # 親記事の場合 if ($in{art} == 0) { my ($num,$sub2,$res,$key) = split(/<>/, $top); $top = "$num<>$in{sub}<>$res<>$key<>\n"; } unshift(@data,$top); seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); # 親記事の場合indexも更新する if ($in{art} == 0) { my $idx = $in{data_now} ? "$cf{datadir}/index1.log" : "$cf{datadir}/index2.log"; my @log; open(DAT,"+< $idx") or cgi_err("open err: $idx"); eval "flock(DAT,2);"; my $top = <DAT> if ($in{data_now}); while(<DAT>) { chomp; my ($no,$sub,$res,$nam,$upd,$las,$key,$upl) = split(/<>/); if ($in{no} == $no) { $_ = "$no<>$in{sub}<>$res<>$nam<>$upd<>$las<>$key<>$upl<>"; } push(@log,"$_\n"); } unshift(@log,$top) if ($in{data_now}); seek(DAT,0,0); print DAT @log; truncate(DAT,tell(DAT)); close(DAT); } } open(IN,"$cf{datadir}/log/$in{no}.cgi"); my $top = <IN>; my ($num,$sub,$res) = split(/<>/,$top); # スレッド内個別閲覧 header("スレッド内個別閲覧"); back_btn($mode); print <<EOM; <div id="ttl"> <img src="$cf{cmnurl}/db_gear.png" alt="" class="icon"> データメンテ[$subject] > 個別メンテ > スレッド名「$sub」 </div> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="$mode" value="1"> <input type="hidden" name="job" value="art"> <input type="hidden" name="no" value="$in{no}"> <ul> <li>修正又は削除を選択して記事をチェックします。 <li>親記事の削除はできません。 </ul> <div class="ope-btn"> 処理 : <select name="act"> <option value="edit">修正 <option value="dele">削除 </select> <input type="submit" value="送信する"> </div> <table class="form-tbl" id="list"> <tr> <th>選択</th> <th>件名</th> <th>名前</th> <th>日時</th> <th>ホスト名</th> </tr> EOM while (<IN>) { my ($no,$sub,$nam,$em,$com,$dat,$hos,$pw,$url,$mvw,$myid) = split(/<>/); print qq|<tr><td><input type="radio" name="art" value="$no"></td>\n|; print qq|<td class="ta-l">[$no] <b class="subcol">$sub</b></td>|; print qq|<td><b>$nam</b>|; print qq| [ID:$myid]| if ($cf{authkey}); print qq|</td><td>$dat</td>|; print qq|<td>$hos</td></tr>\n|; } close(IN); print <<EOM; </table> </form> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # 修正フォーム #----------------------------------------------------------- sub edit_form { my ($subject,$mode,$log,$data,$sub2) = @_; my ($no,$sub,$nam,$eml,$com,$dat,$ho,$pw,$url,$mlo,$myid,$tim,$up1,$up2,$up3) = split(/<>/, $data); $com =~ s/<br>/\n/g; # アイコン my $smile; my @smile = split(/\s+/,$cf{smile}); foreach (0 .. $#smile) { $smile .= qq|<a href="javascript:face('{ico:$_}')"><img src="$cf{iconurl}/$smile[$_]" alt=""></a>|; } # email表示 my $op_mlo; my @mlo = ('非表示','表示'); foreach (1,0) { if ($mlo eq $_) { $op_mlo .= qq|<option value="$_" selected>$mlo[$_]\n|; } else { $op_mlo .= qq|<option value="$_">$mlo[$_]\n|; } } header("修正フォーム", "js"); back_btn($mode); print <<EOM; <div id="ttl"> <img src="$cf{cmnurl}/log_edit.png" alt="" class="icon"> データメンテ[現行ログ] > 個別メンテ > スレッド名「$sub2」 > 記事「$sub」</div> <ul> <li>修正する箇所のみ変更して送信ボタンを押してください。 </ul> <form action="$cf{admin_cgi}" method="post" name="bbsform"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="$mode" value="1"> <input type="hidden" name="job" value="art"> <input type="hidden" name="no" value="$in{no}"> <input type="hidden" name="art" value="$in{art}"> <input type="hidden" name="act" value="edit2"> <table class="form-tbl" id="list"> <tr> <th>名前</th> <td><input type="text" name="name" size="30" value="$nam"></td> </tr><tr> <th>Eメール</th> <td> <input type="text" name="email" size="30" value="$eml"> <select name="mlo"> $op_mlo </select> </td> </tr><tr> <th>件名</th> <td><input type="text" name="sub" size="40" value="$sub"></td> </tr><tr> <th>URL</th> <td><input type="text" name="url" size="50" value="$url"></td> EOM if ($cf{image_upl}) { print qq|</tr><tr>\n|; print qq|<th>画像</th><td>\n|; my ($n,$k); foreach my $up ($up1,$up2,$up3) { $n++; my ($ex) = split(/,/, $up); if ($ex) { $k++; print qq|<input type="checkbox" name="del$n" value="1">削除\n|; print qq|[<a href="$cf{uplurl}/$tim-$n$ex" target="_blank">画像$n</a>]<br>\n|; } } print "<br>" if (!$k); print qq|</td></td>\n|; } print <<EOM; </tr><tr> <th>本文</th> <td class="smile"> $smile<br> <textarea name="comment" cols="55" rows="6">$com</textarea> </td> </tr> </table> <div class="ope-btn"> <input type="submit" value="修正する" class="btn"> </div> </div> </form> </body> </html> EOM exit; } #----------------------------------------------------------- # ファイルサイズ #----------------------------------------------------------- sub size_chk { # 現行ログ my $size1 = 0; my $file1 = 0; my %now; open(IN,"$cf{datadir}/index1.log") or cgi_err("open err: index1.log"); my $top = <IN>; while (<IN>) { my ($num) = split(/<>/); my $tmp = -s "$cf{datadir}/log/$num.cgi"; $size1 += $tmp; $file1++; $now{$num} = 1; } close(IN); # 過去ログ my $size2 = 0; my $file2 = 0; my %pst; open(IN,"$cf{datadir}/index2.log") or cgi_err("open err: index2.log"); while (<IN>) { my ($num) = split(/<>/); my $tmp = -s "$cf{datadir}/log/$num.cgi"; $size2 += $tmp; $file2++; $pst{$num} = 1; } close(IN); # 画像 my $img = 0; opendir(DIR,"$cf{upldir}"); while( defined($_ = readdir(DIR)) ) { next if (!/^[\d\-]+\.(jpg|gif|png)$/); $img += -s "$cf{upldir}/$_"; } closedir(DIR); $size1 = int ($size1 / 1024 + 0.5); $size2 = int ($size2 / 1024 + 0.5); $img = int ($img / 1024 + 0.5); my $all = $size1 + $size2; my $file = $file1 + $file2; header("ファイル容量"); back_btn(); print <<"EOM"; <div id="ttl"> <img src="$cf{cmnurl}/folder_db.png" alt="" class="icon"> ログ容量算出 </div> <ul> <li>以下は記録ファイルの容量(サイズ)で、小数点以下は四捨五入します。 <li>分類欄のフォームをクリックすると各管理画面に移動します。 <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <table class="form-tbl" id="list"> <tr> <th rowspan="2">分類</t> <th rowspan="2">ファイル数</t> <th colspan="2">サイズ</th> </tr><tr> <th>ログ</th> <th>画像</th> </tr><tr> <td><input type="submit" name="data_now" value="現行ログ"></td> <td class="ta-c">$file1</td> <td>$size1 KB</td> <td rowspan="2">$img KB</td> </tr><tr> <td><input type="submit" name="data_past" value="過去ログ"></td> <td class="ta-c">$file2</td> <td>$size2 KB</td> </tr><tr> <td class="ta-c">合計</td> <td class="ta-c">$file</td> <td>$all KB</td> <td>$img KB</td> </tr> </table> </form> </ul> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # 会員管理 #----------------------------------------------------------- sub auth_mgr { return if (!$cf{authkey}); # 新規フォーム if ($in{job} eq "new") { member_form(); # 新規発行 } elsif ($in{job} eq "new2") { my $err; if (!$in{name}) { $err .= "名前が未入力です<br>\n"; } if ($in{myid} =~ /\W/) { $err .= "IDは英数字のみです<br>\n"; } if (length($in{myid}) < 4 || length($in{myid}) > 8) { $err .= "IDは英数字で4~8文字です<br>\n"; } if ($in{mypw} =~ /\W/) { $err .= "パスワードは英数字のみです<br>\n"; } if (length($in{mypw}) < 4 || length($in{mypw}) > 8) { $err .= "パスワードは英数字で4~8文字です<br>\n"; } if (!$in{rank}) { $err .= "権限が未選択です<br>\n"; } cgi_err($err) if ($err); # パス暗号化 my $crypt = encrypt($in{mypw}); # IDチェック my ($flg,@data); open(DAT,"+< $cf{datadir}/memdata.cgi") or cgi_err("open err: memdata.cgi"); while(<DAT>) { my ($id,$pw,$rank,$nam) = split(/<>/); if ($in{myid} eq $id) { $flg++; last; } push(@data,$_); } if ($flg) { close(DAT); cgi_err("このIDは既に登録済です"); } # 更新 seek(DAT,0,0); print DAT "$in{myid}<>$crypt<>$in{rank}<>$in{name}<>\n"; print DAT @data; truncate(DAT,tell(DAT)); close(DAT); # 修正フォーム } elsif ($in{job} eq "edit" && $in{myid}) { my @log; open(IN,"$cf{datadir}/memdata.cgi") or cgi_err("open err: memdata.cgi"); while (<IN>) { my ($id,$pw,$rank,$nam) = split(/<>/); if ($in{myid} eq $id) { @log = ($id,$pw,$rank,$nam); last; } } close(IN); member_form(@log); # 修正実行 } elsif ($in{job} eq "edit2") { my ($err,$crypt); if (!$in{name}) { $err .= "名前が未入力です<br>\n"; } if ($in{myid} =~ /\W/) { $err .= "IDは英数字のみです<br>\n"; } if (length($in{myid}) < 4 || length($in{myid}) > 8) { $err .= "IDは英数字で4~8文字です<br>\n"; } if ($in{chg}) { if ($in{mypw} =~ /\W/) { $err .= "パスワードは英数字のみです<br>\n"; } if (length($in{mypw}) < 4 || length($in{mypw}) > 8) { $err .= "パスワードは英数字で4~8文字です<br>\n"; } # パス暗号化 $crypt = encrypt($in{mypw}); } elsif (!$in{chg} && $in{mypw} ne "") { $err .= "パスワードの強制変更はチェックボックスに選択してください<br>\n"; } if (!$in{rank}) { $err .= "権限が未選択です<br>\n"; } cgi_err($err) if ($err); my @data; open(DAT,"+< $cf{datadir}/memdata.cgi") or cgi_err("open err: memdata.cgi"); while(<DAT>) { my ($id,$pw,$rank,$nam) = split(/<>/); if ($in{myid} eq $id) { if ($crypt) { $pw = $crypt; } $_ = "$id<>$pw<>$in{rank}<>$in{name}<>\n"; } push(@data,$_); } seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); # 削除 } elsif ($in{job} eq "dele" && $in{myid}) { # 削除情報 my %del; foreach ( $cgi->param('myid') ) { $del{$_}++; } my @data; open(DAT,"+< $cf{datadir}/memdata.cgi") or cgi_err("open err: memdata.cgi"); while(<DAT>) { my ($id,$pw,$rank,$nam) = split(/<>/); next if (defined($del{$id})); push(@data,$_); } seek(DAT,0,0); print DAT @data; truncate(DAT,tell(DAT)); close(DAT); } header("会員管理"); back_btn(); print <<"EOM"; <div id="ttl"> <img src="$cf{cmnurl}/user.png" alt="" class="icon"> 会員管理 </div> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="auth_mgr" value="1"> <div class="ope-btn"> 処理 : <select name="job"> <option value="new">新規 <option value="edit">修正 <option value="dele">削除 </select> <input type="submit" value="送信する"> </div> <table class="form-tbl" id="list"> <tr> <th>選択</th> <th>ログインID</th> <th>名前</th> <th>ランク</th> </tr> EOM open(IN,"$cf{datadir}/memdata.cgi") or cgi_err("open err: memdata.cgi"); while (<IN>) { my ($id,$pw,$rank,$nam) = split(/<>/); print qq|<tr><td class="ta-c"><input type="checkbox" name="myid" value="$id"></td>|; print qq|<td>$id</td><td>$nam</td><td class="ta-c">$rank</td></tr>\n|; } close(IN); print <<EOM; </table> </form> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # 会員フォーム #----------------------------------------------------------- sub member_form { my ($id,$pw,$rank,$nam) = @_; my $job = $in{job} . '2'; header("会員管理 > 登録フォーム"); print <<EOM; <div id="body"> <div class="back-btn"> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="auth_mgr" value="1"> <input type="submit" value="< 前画面"> </form> </div> <div id="ttl"> <img src="$cf{cmnurl}/user.png" alt="" class="icon"> 会員管理 > 登録フォーム </div> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> <input type="hidden" name="auth_mgr" value="1"> <input type="hidden" name="job" value="$job"> <table class="form-tbl" id="list"> <tr> <th>名前</th> <td><input type="text" name="name" size="30" value="$nam"></td> </tr><tr> <th>ログインID</th> <td> EOM if ($in{myid}) { print qq|<b>$in{myid}</b>|; } else { print qq|<input type="text" name="myid" size="16" value="$id">\n|; print qq|(英数字で4~8文字)\n|; } print <<EOM; </td> </tr><tr> <th>パスワード</th> <td> <input type="password" name="mypw" size="16"> (英数字で4~8文字) EOM if ($in{myid}) { print qq|<br><input type="checkbox" name="chg" value="1">\n|; print qq|パスワードを強制変更する場合にチェック\n|; print qq|<input type="hidden" name="myid" value="$in{myid}">\n|; } print <<EOM; </td> </tr><tr> <th>権限</th> <td> EOM my %rank = (1 => "閲覧のみ", 2 => "閲覧&書込OK"); foreach (1,2) { if ($rank == $_) { print qq|<input type="radio" name="rank" value="$_" checked>レベル$_ ($rank{$_})<br>\n|; } else { print qq|<input type="radio" name="rank" value="$_">レベル$_ ($rank{$_})<br>\n|; } } print <<EOM; </td> </tr> </table> <div class="ope-btn"> <input type="submit" value="送信する" class="btn"> </div> </div> </form> </body> </html> EOM exit; } #----------------------------------------------------------- # 戻りボタン #----------------------------------------------------------- sub back_btn { my ($mode) = @_; print <<EOM; <div id="body"> <div class="back-btn"> <form action="$cf{admin_cgi}" method="post"> <input type="hidden" name="sid" value="$in{sid}"> @{[ $mode ? qq|<input type="submit" name="$mode" value="< 前画面">| : '' ]} <input type="submit" value="▲メニュー"> </form> </div> EOM } #----------------------------------------------------------- # エラー #----------------------------------------------------------- sub cgi_err { my $err = shift; header("ERROR"); print <<EOM; <div id="body"> <div id="err"> <b>エラー発生</b> <p>$err</p> <p><input type="button" value="前画面に戻る" onclick="history.back()"></p> </div> </div> </body> </html> EOM exit; } #----------------------------------------------------------- # HTMLヘッダ #----------------------------------------------------------- sub header { my ($ttl,$js) = @_; print <<EOM; Content-type: text/html; charset=utf-8 <!doctype html> <html lang="ja"> <head> <meta charset="UTF-8"> <link href="$cf{cmnurl}/admin.css" rel="stylesheet"> EOM if ($js) { print qq|<script>\n|; print qq|function face(smile) {\n|; print qq|bbscom = document.bbsform.comment.value;\n|; print qq|document.bbsform.comment.value = bbscom + smile;\n|; print qq|}\n</script>\n|; } print <<EOM; <title>$ttl</title> </head> <body> <div id="head">:: WEB PATIO 管理画面 ::</div> EOM } #----------------------------------------------------------- # crypt暗号 #----------------------------------------------------------- sub encrypt { my $in = shift; my @wd = ('a'..'z', 'A'..'Z', '0'..'9', '.', '/'); my $salt = $wd[int(rand(@wd))] . $wd[int(rand(@wd))]; return crypt($in, $salt) || crypt ($in, '$1$' . $salt); }