diff --git a/test/admin.cgi b/test/admin.cgi index 728d85c..13149f4 100755 --- a/test/admin.cgi +++ b/test/admin.cgi @@ -13,7 +13,8 @@ use open IO => ':encoding(cp932)'; use warnings; no warnings 'once'; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); - +use JSON; +use LWP::UserAgent; # CGIの実行結果を終了コードとする exit(AdminCGI()); @@ -29,6 +30,11 @@ exit(AdminCGI()); sub AdminCGI { require './module/constant.pl'; + + # IP + $ENV{'REMOTE_ADDR'} = $ENV{'HTTP_CF_CONNECTING_IP'} if $ENV{'HTTP_CF_CONNECTING_IP'}; + require './module/data_utils.pl'; + $ENV{'REMOTE_HOST'} = DATA_UTILS::reverse_lookup($ENV{'REMOTE_ADDR'}); # システム初期設定 my $CGI = {}; @@ -58,9 +64,15 @@ sub AdminCGI my $sid = $Form->Get('SessionID', ''); $Form->Set('PassWord', ''); #$Form->Set('SessionID', ''); + my $capt = Certification_Captcha($Sys,$Form) if ($pass && $Sys->Get('ADMINCAP')); my ($userID, $SID) = $CGI->{'SECINFO'}->IsLogin($name, $pass, $sid); - $CGI->{'USER'} = $userID; - $Form->Set('SessionID', $SID); + unless($capt){ + $CGI->{'USER'} = $userID; + $Form->Set('SessionID', $SID); + if ($CGI->{'SECINFO'}->IsAuthority($userID,$ZP::AUTH_SYSADMIN,'*')){ + $Sys->Set('LASTMOD',time); + } + } # バージョンチェック my $upcheck = $Sys->Get('UPCHECK', 1) - 0; @@ -95,6 +107,58 @@ sub AdminCGI return 0; } +#------------------------------------------------------------------------------------------------------------ +# +# Captcha検証 +# ------------------------------------------------------------------------------------- +# +#------------------------------------------------------------------------------------------------------------ +sub Certification_Captcha { + my ($Sys,$Form) = @_; + my ($captcha_response,$url); + + my $captcha_kind = $Sys->Get('CAPTCHA'); + my $secretkey = $Sys->Get('CAPTCHA_SECRETKEY'); + if($captcha_kind eq 'h-captcha'){ + $captcha_response = $Form->Get('h-captcha-response'); + $url = 'https://api.hcaptcha.com/siteverify'; + }elsif($captcha_kind eq 'g-recaptcha'){ + $captcha_response = $Form->Get('g-recaptcha-response'); + $url = 'https://www.google.com/recaptcha/api/siteverify'; + }elsif($captcha_kind eq 'cf-turnstile'){ + $captcha_response = $Form->Get('cf-turnstile-response'); + $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; + }else{ + return 0; + } + + my $ua = LWP::UserAgent->new(); + my $response = $ua->post($url,{ + secret => $secretkey, + response => $captcha_response, + remoteip => $ENV{'REMOTE_ADDR'}, + }); + + if ($response->is_success()) { + my $json_text = $response->decoded_content(); + my $out = decode_json($json_text); + + if ($out->{success} eq 'true') { + return 0; + }elsif ($out->{error_codes} =~ /(missing-input-secret|invalid-input-secret|sitekey-secret-mismatch)/){ + # 管理者側の設定ミス + return 0; + }else{ + return 1; + } + } else { + # Captchaを素通りする場合、HTTPS関連のエラーの疑いあり + # LWP::Protocol::httpsおよびNet::SSLeayが入っているか確認 + # このエラーの場合、スルーしてログインする + return 0; + } +} + #------------------------------------------------------------------------------------------------------------ # # 管理システム設定 diff --git a/test/admin/admin_cgi_base.pl b/test/admin/admin_cgi_base.pl index 9388e8c..967c315 100644 --- a/test/admin/admin_cgi_base.pl +++ b/test/admin/admin_cgi_base.pl @@ -177,6 +177,12 @@ sub PrintCSS my ($data); $data = $Sys->Get('DATA'); + + if($Sys->Get('ADMINCAP')){ + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'h-captcha'); + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'g-recaptcha'); + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'cf-turnstile'); + } $Page->Print(< diff --git a/test/admin/bbs.setting.pl b/test/admin/bbs.setting.pl index a234036..61f0caa 100644 --- a/test/admin/bbs.setting.pl +++ b/test/admin/bbs.setting.pl @@ -333,7 +333,7 @@ sub PrintBaseSetting $Page->Print("
"); $Page->Print("DAT落ちスレッド保存先"); $Page->Print(""); $Page->Print("掲示板書き込み制限"); $Page->Print("DNSBLチェック"); $Page->Print("$setInfo"); @@ -635,11 +635,11 @@ sub PrintLimitSetting $Page->Print("同一スレッド名を禁止"); $Page->Print("有効"); $Page->Print("逆引き不可のIPからの投稿を制限"); - $Page->Print(""); + $Page->Print("有効"); $Page->Print("プロキシ規制"); $Page->Print("$setInfo2"); $Page->Print("???"); - $Page->Print(""); + $Page->Print("有効"); $Page->Print(""); $Page->Print("
"); @@ -768,7 +768,7 @@ sub PrintCommandSetting $Page->Print("不落(!nopool)"); $Page->Print("有効"); $Page->Print(""); - $Page->Print("忍法帖レベル制限 ※要忍法帖(!ninLv:[レベル])"); + $Page->Print("忍法帖レベル制限 ※要忍法帖(!ninlv:[レベル])"); $Page->Print("有効"); $Page->Print("
"); @@ -919,7 +919,6 @@ sub PrintOtherSetting my $setConfirm = $Setting->Get('BBS_NEWSUBJECT'); my $setWeek = $Setting->Get('BBS_YMD_WEEKS'); my $setTripColumn = $Setting->Get('BBS_TRIPCOLUMN'); - my $setImgur = $Setting->Get('BBS_IMGUR'); my $setTwitter = $Setting->Get('BBS_TWITTER'); my $setMovie = $Setting->Get('BBS_MOVIE'); my $setURLtoTitle = $Setting->Get('BBS_URL_TITLE'); @@ -986,14 +985,11 @@ sub PrintOtherSetting $Page->Print("スレッド作成確認画面"); $Page->Print("確認あり"); - $Page->Print(""); + $Page->Print(""); $Page->Print(""); $Page->Print("一般画像埋め込み表示"); $Page->Print("システム設定に依存"); $Page->Print(""); - $Page->Print("Imgur 埋め込み表示"); - $Page->Print("有効"); - $Page->Print(""); $Page->Print("X(旧Twitter) 埋め込み表示"); $Page->Print("有効"); $Page->Print(""); @@ -1426,7 +1422,6 @@ sub FunctionOtherSetting $Setting->Set('BBS_SLIP', $Form->Get('BBS_SLIP')); $Setting->Set('BBS_NINJA', ($Form->Equal('BBS_NINJA', 'on') ? 'checked' : '')); $Setting->Set('BBS_HIDENUSI', ($Form->Equal('BBS_HIDENUSI', 'on') ? 'checked' : '')); - $Setting->Set('BBS_IMGUR', ($Form->Equal('BBS_IMGUR', 'on') ? 'checked' : '')); $Setting->Set('BBS_MOVIE', ($Form->Equal('BBS_MOVIE', 'on') ? 'checked' : '')); $Setting->Set('BBS_TWITTER', ($Form->Equal('BBS_TWITTER', 'on') ? 'checked' : '')); $Setting->Set('BBS_URL_TITLE', ($Form->Equal('BBS_URL_TITLE', 'on') ? 'checked' : '')); diff --git a/test/admin/bbs.thread.pl b/test/admin/bbs.thread.pl index e303ad8..25f4977 100644 --- a/test/admin/bbs.thread.pl +++ b/test/admin/bbs.thread.pl @@ -368,13 +368,13 @@ sub PrintThreadList if ($isStop) { $Page->Print("属性: "); $Page->Print(" "); $Page->Print(" "); @@ -463,9 +463,10 @@ sub PrintThreadCopy $Page->Print("$text\先: "); }else{ - $Page->Print(""); foreach my $listid (@bbsSet) { next if ($BBS->Get('DIR', $listid) eq $SYS->Get('BBS')); $category = $Category->Get('NAME', $BBS->Get('CATEGORY', $listid)); @@ -473,14 +474,14 @@ sub PrintThreadCopy foreach $belongID (@belongBBS) { if ($listid eq $belongID) { $name = $BBS->Get('NAME', $listid); - $Page->Print(""); } } } + $Page->Print(" "); + $Page->Print("同名のファイルがあればリネーム"); + $Page->Print(' "); } - $Page->Print(" "); - $Page->Print("同名のファイルがあればリネーム"); - $Page->Print(' "); $Page->Print("\n"); $Page->Print("
"); } @@ -864,9 +865,6 @@ sub FunctionThreadCopy $Threads->Load($Sys); $Info->Load($Sys); - - @threadList = $Form->GetAtArray('THREADS'); - return 1 if (!@threadList); $tobbs = $Form->Get('TOBBS'); $rename = $Form->Get('RENAME'); @@ -875,6 +873,9 @@ sub FunctionThreadCopy $path = $Sys->Get('BBSPATH') . "/$bbs"; $topath = $Sys->Get('BBSPATH') . "/".$Info->Get('DIR',$tobbs); + @threadList = $Form->GetAtArray('THREADS'); + return 1 if (!@threadList || !$tobbs); + my $text = $mode ? 'コピー':'移動'; foreach $id (@threadList) { diff --git a/test/admin/login.pl b/test/admin/login.pl index 158fad9..b13631f 100644 --- a/test/admin/login.pl +++ b/test/admin/login.pl @@ -55,7 +55,7 @@ sub DoPrint $Page = $BASE->Create($Sys, $Form); - PrintLogin($Page, $Form); + PrintLogin($Sys, $Page, $Form); $BASE->PrintNoList('LOGIN', 0); } @@ -75,10 +75,6 @@ sub DoFunction my $this = shift; my ($Sys, $Form, $pSys) = @_; my ($host, $Security, $Mod); - $ENV{'REMOTE_ADDR'} = $ENV{'HTTP_CF_CONNECTING_IP'} if $ENV{'HTTP_CF_CONNECTING_IP'}; - - require './module/data_utils.pl'; - $host = DATA_UTILS::reverse_lookup($ENV{'REMOTE_ADDR'}); # ログイン情報を確認 if ($pSys->{'USER'}) { @@ -107,7 +103,12 @@ sub DoFunction #------------------------------------------------------------------------------------------------------------ sub PrintLogin { - my ($Page, $Form) = @_; + my ($Sys, $Page, $Form) = @_; + + my $sitekey = $Sys->Get('CAPTCHA_SITEKEY'); + my $classname = $Sys->Get('CAPTCHA'); + my $Captcha = $Sys->Get('ADMINCAP') ? "

" : ''; + my $text = $sitekey && $classname && $Captcha ? 'Captcha認証に失敗したか、' : "" ; $Page->Print(< @@ -115,7 +116,7 @@ sub PrintLogin HTML if ($Form->Get('FALSE') == 1) { - $Page->Print("
ユーザ名もしくはパスワードが間違っています。
\n"); + $Page->Print("
${text}ユーザ名もしくはパスワードが間違っています。
\n"); } $Page->Print(<
+ $Captcha diff --git a/test/admin/sys.ninja.pl b/test/admin/sys.ninja.pl index 6a5d279..40915cf 100644 --- a/test/admin/sys.ninja.pl +++ b/test/admin/sys.ninja.pl @@ -72,6 +72,9 @@ sub DoPrint elsif ($subMode eq 'SEARCH') { # 忍法帖検索 PrintNinjaSearch($Page, $Sys, $Form); } + elsif ($subMode eq 'NIN_SEARCH') { # 忍法帖検索 + PrintNinjaSearchResult($Page, $Sys, $Form); + } elsif ($subMode eq 'SID_SEARCH') { # セッションID検索 PrintNinjaSidSearch($Page, $Sys, $Form); } @@ -336,58 +339,58 @@ sub PrintNinjaEdit $Page->Print("ID:$sid\の忍法帖を確認します。(${SESSION_ATIME}時点)"); $Page->Print("
\n"); - $Page->Print("■User Description\n"); - $Page->Print("説明"); + $Page->Print("■User Description (Key)\n"); + $Page->Print("説明 (user_desc)"); $Page->Print("\n"); - $Page->Print("■User Information\n"); - $Page->Print("忍法帖ID$ninID\n"); - $Page->Print("忍法帖Lv$lv\n"); - $Page->Print("前回LvUP日時$lvuptime\n"); - $Page->Print("作成日時$SESSION_CTIME\n"); - $Page->Print("作成時の書き込み$newmes\n"); - $Page->Print("作成時のIP$c_addr\n"); - $Page->Print("作成時のHOST$c_host\n"); - $Page->Print("作成時のUA$c_ua\n"); - $Page->Print("ユーザー認証$is_auth\n"); - $Page->Print("最終認証日時$auth_time\n"); - $Page->Print("最終スレ立て日時$last_makethread_time\n"); - $Page->Print("最新書き込み日時$last_wtime\n"); - $Page->Print("最新書き込み$last_message\n"); - $Page->Print("最新IP$last_addr\n"); - $Page->Print("最新HOST$last_host\n"); - $Page->Print("最新UA$last_ua\n"); - $Page->Print("パスワード(Hash)$password\n"); - $Page->Print("最新ロード時刻$load_time\n"); - $Page->Print("ロード元の忍法帖ID$load_from\n"); - $Page->Print("ロード時の書き込み$load_message\n"); - $Page->Print("最新ロードIP$load_addr\n"); - $Page->Print("最新ロードHOST$load_host\n"); - $Page->Print("最新ロードUA$load_ua\n"); - - $Page->Print("■Statistics\n"); - $Page->Print("書き込み数$count\n"); - $Page->Print("スレ立て数$thread_count\n"); - $Page->Print("忍法帖ロード回数$load_count\n"); - - $Page->Print("■Regulation\n"); - $Page->Print("書き込み禁止"); + $Page->Print("■User Information (Key)\n"); + $Page->Print("忍法帖ID (ninID)$ninID\n"); + $Page->Print("忍法帖Lv (ninLv)$lv\n"); + $Page->Print("前回LvUP日時 (lvuptime)$lvuptime\n"); + $Page->Print("作成日時 (_SESSION_CTIME)$SESSION_CTIME\n"); + $Page->Print("作成時の書き込み (new_message)$newmes\n"); + $Page->Print("作成時のIP (c_addr)$c_addr\n"); + $Page->Print("作成時のHOST (c_host)$c_host\n"); + $Page->Print("作成時のUA (c_ua)$c_ua\n"); + $Page->Print("ユーザー認証 (auth)$is_auth\n"); + $Page->Print("最終認証日時 (auth_time)$auth_time\n"); + $Page->Print("最終スレ立て日時 (last_mthread_time)$last_makethread_time\n"); + $Page->Print("最新書き込み日時 (last_wtime)$last_wtime\n"); + $Page->Print("最新書き込み (last_message)$last_message\n"); + $Page->Print("最新IP (last_addr)$last_addr\n"); + $Page->Print("最新HOST (last_host)$last_host\n"); + $Page->Print("最新UA (last_ua)$last_ua\n"); + $Page->Print("パスワードのハッシュ (password)$password\n"); + $Page->Print("最新ロード時刻 (load_time)$load_time\n"); + $Page->Print("ロード元の忍法帖ID (load_from)$load_from\n"); + $Page->Print("ロード時の書き込み (load_message)$load_message\n"); + $Page->Print("最新ロードIP (load_addr)$load_addr\n"); + $Page->Print("最新ロードHOST (load_host)$load_host\n"); + $Page->Print("最新ロードUA (load_ua)$load_ua\n"); + + $Page->Print("■Statistics (Key)\n"); + $Page->Print("書き込み数 (count)$count\n"); + $Page->Print("スレ立て数 (thread_count)$thread_count\n"); + $Page->Print("忍法帖ロード回数 (load_count)$load_count\n"); + + $Page->Print("■Regulation (Key)\n"); + $Page->Print("書き込み禁止 (ban)"); $Page->Print("\n"); - $Page->Print("コマンド禁止"); + $Page->Print("コマンド禁止 (ban_command)"); $Page->Print("\n"); - $Page->Print("URL禁止"); + $Page->Print("URL禁止 (ban_url)"); $Page->Print("\n"); - $Page->Print("強制sage"); + $Page->Print("強制sage (force_sage)"); $Page->Print("\n"); - $Page->Print("Captcha強制"); + $Page->Print("Captcha強制 (force_captcha)"); $Page->Print("\n"); - $Page->Print("名無し強制"); + $Page->Print("名無し強制 (force_774)"); $Page->Print("\n"); - $Page->Print("強制コテ(名無し強制優先、名前欄用コマンド使用可)"); + $Page->Print("強制コテ (force_kote)(名無し強制優先、名前欄用コマンド使用可)"); $Page->Print("\n"); }else{ $Page->Print("ID:$sid\の忍法帖データは存在しません。"); @@ -403,12 +406,19 @@ sub PrintNinjaEdit $Page->Print("
"); } + +#------------------------------------------------------------------------------------------------------------ +# +# 忍法帖検索画面 - PrintNinjaSearch +# ------------------------------------------------ +# 引 数:なし +# 戻り値:なし +# +#------------------------------------------------------------------------------------------------------------ sub PrintNinjaSearch { my ($Page, $SYS, $Form, $BBS) = @_; - my ($common); - my ($name, $dir); - my ($sMODE, $sBBS, $sKEY, $sWORD, @sTYPE, @cTYPE, $types, $BBSpath, @bbsSet, $id); + my ($sKEY, $sWORD); my $sanitize = sub { $_ = shift; @@ -419,45 +429,29 @@ sub PrintNinjaSearch return $_; }; - $sMODE = "BBS";#&$sanitize($Form->Get('SMODE', '')); - $sBBS = &$sanitize($Form->Get('SBBS', '')); $sKEY = &$sanitize($Form->Get('KEY', '')); $sWORD = &$sanitize($Form->Get('WORD')); - @sTYPE = $Form->GetAtArray('TYPE', 0); - $id = $Form->Get('TARGET_BBS', ''); - $types = ($sTYPE[0] || 0) | ($sTYPE[1] || 0) | ($sTYPE[2] || 0); - $cTYPE[0] = ($types & 1 ? 'checked' : ''); - $cTYPE[1] = ($types & 2 ? 'checked' : ''); - $cTYPE[2] = ($types & 4 ? 'checked' : ''); $SYS->Set('_TITLE', 'Ninpocho Search'); $Page->Print("
\n"); - $Page->Print(" \n"); + $Page->Print(" \n"); $Page->Print(" \n"); $Page->Print(" \n"); $Page->Print(" \n"); $Page->Print(" \n"); - $Page->Print("\n"); - $Page->Print(""); + $Page->Print("\n"); $Page->Print(< - + - + @@ -465,7 +459,7 @@ sub PrintNinjaSearch
以下の各条件に当てはまる忍法帖を検索します。
以下の条件に当てはまる忍法帖を検索します。

条件条件設定値
検索ワード検索キー -HTML - $Page->Print(""); - - $common = "DoSubmit('bbs.thread','DISP','AUTORESDEL')"; - - $Page->Print(<
検索種別検索ワード - ???
- ???
- ???
+
- +
@@ -477,13 +471,133 @@ sub PrintNinjaSearch } $Page->Print(""); } + +#------------------------------------------------------------------------------------------------------------ +# +# 忍法帖検索結果出力 - PrintNinjaSearchResult +# ------------------------------------------------ +# 引 数:なし +# 戻り値:なし +# +#------------------------------------------------------------------------------------------------------------ +sub PrintNinjaSearchResult +{ + my ($Page, $Sys, $Form) = @_; + my ($Search, $Mode, $Result, @elem, $BBS, $n, $base, $word, $id, $key); + my (@types, $Type); + my (@resList, %bbsCount, %threadCount); + + $Sys->Set('_TITLE','Ninpocho Search'); + + my $sanitize = sub { + $_ = shift; + s/&/&/g; + s//>/g; + s/"/"/g;#" + return $_; + }; + + require './module/admin_search.pl'; + $Search = ADMIN_SEARCH->new; + require './module/bbs_info.pl'; + $BBS = BBS_INFO->new; + $BBS->Load($Sys); + $word = &$sanitize($Form->Get('WORD')); + $key = &$sanitize($Form->Get('KEY')); + + + # 検索オブジェクトの設定と検索の実行 + $Search->Create($Sys, 3); + $Page->Print("
"); + $Page->Print(""); + if ($@ ne '') { + PrintSystemError($Page, $@); + return; + } + + # 検索結果セット取得 + if($key ne 'ninID' && $word){ + $Result = $Search->NinSearch($Form->Get('KEY'),$Form->Get('WORD'),undef); + }elsif((!$key && $word =~ /[0-9a-f]{32}/) || ($key eq 'ninID' && length($word) == 13)){ + $Result = $Search->NinSearch(undef,undef,$Form->Get('WORD')); + } + + $n = $Result ? @$Result : 0; + my $res = $Result->[0]; + # 検索ヒットが1件以上あり + if ($n > 0) { + my $dispNum = $Form->Get('DISPNUM', 10); + my $dispSt = $Form->Get('DISPST', 0) || 0; + $dispSt = ($dispSt < 0 ? 0 : $dispSt); + my $infoDir = $Sys->Get('INFO'); + my $ninDir = ".$infoDir/.ninpocho/"; + my @session_files = @$Result; + my $dispEd = (($dispSt + $dispNum) > $n ? $n : ($dispSt + $dispNum)); + + # ヘッダ部分の表示 + my $common = "DoSubmit('sys.ninja','DISP','NIN_SEARCH');"; + + $Page->Print("
Key:[$key] Word:[$word] の忍法帖検索結果
"); + $Page->Print("\n"); + $Page->Print("\n"); + $Page->Print(""); + $Page->Print(""); + $Page->Print(""); + $Page->Print("\n"); + + for (my $i = $dispSt ; $i < $dispEd ; $i++) { + my $id = $session_files[$i]; + my $num = $i + 1; + my $file_name = '.'.$Sys->Get('INFO').'/.ninpocho/cgisess_'.$id; + my $mtime = strftime "%Y-%m-%d %H:%M:%S", localtime((stat($file_name))[9]); + my $size = (stat($file_name))[7]; + + $Page->Print(""); + $Page->Print(""); + $common = "\"javascript:SetOption('NINJA_ID','$id');"; + $common .= "DoSubmit('sys.ninja','DISP','EDIT')\""; + $Page->Print(""); + $Page->Print("\n"); + } + } + # 検索ヒット無し + else { + PrintNoHit($Page); + $Page->Print("
Print(");$common\"><< PREV | Print("" . ($dispSt + $dispNum) . ");$common\">NEXT >>"); + $Page->Print(""); + $Page->Print("合計:$n"); + $Page->Print("表示数"); + $Page->Print("

SessionIDSizeLast Update
$num: $id$size$mtime
\n"); + return; + } + $Page->HTMLInput('hidden', 'DISPST', ''); + $Page->HTMLInput('hidden', 'NINJA_ID', ''); + $Page->HTMLInput('hidden', 'KEY', $Form->Get('KEY')); + $Page->HTMLInput('hidden', 'WORD', $Form->Get('WORD')); + if($Sys->Get('ADMIN')->{'SECINFO'}->IsAuthority($Sys->Get('ADMIN')->{'USER'}, $ZP::AUTH_RESDELETE, $Sys->Get('BBS'))){ + $Page->Print(< + +
+
+ + + +HTML + } + $Page->Print("\n"); +} + #------------------------------------------------------------------------------------------------------------ # -# 検索結果出力 - Search +# 書き込み履歴検索結果出力 - PrintNinjaSidSearch # ------------------------------------------------ # 引 数:なし # 戻り値:なし diff --git a/test/admin/sys.setting.pl b/test/admin/sys.setting.pl index 09bc833..fb9699f 100644 --- a/test/admin/sys.setting.pl +++ b/test/admin/sys.setting.pl @@ -487,7 +487,7 @@ sub PrintOtherSetting { my ($Page, $SYS, $Form) = @_; my ($urlLink, $linkSt, $linkEd, $pathKind, $headText, $headUrl, $FastMode, $BBSGET, $upCheck, $imageTag); - my ($linkChk, $pathInfo, $pathQuery, $fastMode, $bbsget, $imgtag, $CSP, $CSPSet, $ninLvmax, $cookieExp); + my ($linkChk, $pathInfo, $pathQuery, $fastMode, $bbsget, $imgtag, $CSP, $CSPSet, $ninLvmax, $cookieExp, $admCap, $srcCap); my ($common,$nin_exp,$pass_exp); $SYS->Set('_TITLE', 'System Other Setting'); @@ -672,12 +672,16 @@ sub PrintPlusSecSetting my $Captcha_sitekey = $SYS->Get('CAPTCHA_SITEKEY'); my $Captcha_secretkey = $SYS->Get('CAPTCHA_SECRETKEY'); my $Proxy_apikey = $SYS->Get('PROXYCHECK_APIKEY'); + my $admCap = $SYS->Get('ADMINCAP'); + my $srcCap = $SYS->Get('SEARCHCAP'); $kakiko = ($Kakiko == 1 ? 'checked' : ''); $trip12 = ($Trip12 == 1 ? 'checked' : ''); $torexit = ($TOREXIT == 1 ? 'checked' : ''); $s5h = ($SYS->Get('DNSBL_S5H') == 1 ? 'checked' : ''); $dronebl = ($SYS->Get('DNSBL_DRONEBL') == 1 ? 'checked' : ''); + $admCap = ($admCap == 1 ? 'checked' : ''); + $srcCap = ($srcCap == 1 ? 'checked' : ''); $common = "onclick=\"DoSubmit('sys.setting','FUNC','SEC');\""; @@ -729,6 +733,14 @@ sub PrintPlusSecSetting $Page->Print("ProxyCheck APIキー"); $Page->Print("\n"); + $Page->Print("Captchaを課すCGI\n"); + $Page->Print("admin.cgi"); + $Page->Print("\n"); + $Page->Print("search.cgi"); + $Page->Print("\n"); + $Page->Print("bbs.cgi"); + $Page->Print("各掲示板の設定で有効化してください\n"); + $Page->Print("
\n"); $Page->Print(""); $Page->Print("\n"); @@ -1269,6 +1281,8 @@ sub FunctionPlusSecSetting $SYSTEM->Set('CAPTCHA_SITEKEY', $Form->Get('CAPTCHA_SITEKEY')); $SYSTEM->Set('CAPTCHA_SECRETKEY', $Form->Get('CAPTCHA_SECRETKEY')); $SYSTEM->Set('PROXYCHECK_APIKEY', $Form->Get('PROXYCHECK_APIKEY')); + $SYSTEM->Set('ADMINCAP', ($Form->Equal('ADMINCAP', 'on') ? 1 : 0)); + $SYSTEM->Set('SEARCHCAP', ($Form->Equal('SEARCHCAP', 'on') ? 1 : 0)); $SYSTEM->Save(); { @@ -1281,6 +1295,8 @@ sub FunctionPlusSecSetting push @$pLog, '    Captchaサイトキー:' . $SYSTEM->Get('CAPTCHA_SITEKEY'); push @$pLog, '    Captchaシークレットキー:' . $SYSTEM->Get('CAPTCHA_SECRETKEY'); push @$pLog, '    ProxyChecker APIキー:' . $SYSTEM->Get('PROXYCHECK_APIKEY'); + push @$pLog, '    admin.cgiへのCaptcha:' . $SYSTEM->Get('ADMINCAP'); + push @$pLog, '    search.cgiへのCaptcha:' . $SYSTEM->Get('SEARCHCAP'); } return 0; } diff --git a/test/bbs.cgi b/test/bbs.cgi index 84f9f93..4827812 100755 --- a/test/bbs.cgi +++ b/test/bbs.cgi @@ -146,6 +146,9 @@ sub Initialize if(!defined $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_HOST'} eq '') { $ENV{'REMOTE_HOST'} = $Conv->reverse_lookup($ENV{'REMOTE_ADDR'}); } + if($ENV{'REMOTE_ADDR'} =~ /:/){ + $ENV{'REMOTE_ADDR'} = $Conv->expand_ipv6($ENV{'REMOTE_ADDR'}); + } $Form->Set('HOST', $ENV{'REMOTE_HOST'}); my $client = $Conv->GetClient(); @@ -228,7 +231,7 @@ sub Initialize } #改竄をチェック - if($sid && $sec){ + if($sid =~ /^[0-9a-fA-F]{32}$/ && $sec){ my $ctx = Digest::MD5->new; $ctx->add($Sys->Get('SECURITY_KEY')); $ctx->add(':', $sid); diff --git a/test/module/admin_search.pl b/test/module/admin_search.pl index 6cadfae..b23920d 100644 --- a/test/module/admin_search.pl +++ b/test/module/admin_search.pl @@ -152,6 +152,7 @@ sub Run return $this->{'RESULTSET'}; } +# セッションIDから書き込み検索 sub Run_LogS { my $this = shift; @@ -168,6 +169,16 @@ sub Run_LogS } return $this->{'RESULTSET'}; } + +# キーとワードから忍法帖検索 +sub Run_LogN +{ + my $this = shift; + my ($key,$word,$f) = @_; + $this->{'RESULTSET'} = [] if ($f); + $this->NinSearch($key, $word,); + return $this->{'RESULTSET'}; +} #------------------------------------------------------------------------------------------------------------ # # 検索結果取得 @@ -309,6 +320,45 @@ sub LogSearch } } } +sub NinSearch +{ + my $this = shift; + my ($key, $word, $sid) = @_; + my $ninDir = ".".$this->{'SYS'}->Get('INFO')."/.ninpocho/"; + my $pResultSet = $this->{'RESULTSET'}; + + if($sid){ + if(length($sid) == 32){ + my $set = glob($ninDir.'cgisess_'.$sid); + $set =~ s/${ninDir}cgisess_//m; + @$pResultSet = $set; + }else{ + my $allSid = []; + @$allSid = sort { (stat($b))[9] <=> (stat($a))[9] } glob($ninDir.'cgisess_*'); + foreach my $id (@$allSid){ + $id =~ s/${ninDir}cgisess_//m; + if(crypt($id,$id) eq $sid){ + push @$pResultSet,$id; + } + } + } + }else{ + my $allSid = []; + @$allSid = sort { (stat($b))[9] <=> (stat($a))[9] } glob($ninDir.'cgisess_*'); + if($key){ + require './module/ninpocho.pl'; + my $Ninja = NINPOCHO->new; + foreach my $id (@$allSid){ + $id =~ s/${ninDir}cgisess_//m; + $Ninja->LoadOnly($this->{'SYS'},$id); + if($Ninja->Get($key) =~ /\Q$word\E/i){ + push @$pResultSet,$id; + } + } + } + } + return $pResultSet; +} #============================================================================================================ # Module END #============================================================================================================ diff --git a/test/module/bbs_service.pl b/test/module/bbs_service.pl index a4535d8..9d28749 100644 --- a/test/module/bbs_service.pl +++ b/test/module/bbs_service.pl @@ -269,7 +269,6 @@ sub PrintIndexHead HEAD $Page->Print('') if ($this->{'SET'}->Get('BBS_TWITTER')); - $Page->Print('') if ($this->{'SET'}->Get('BBS_IMGUR')); if($this->{'SET'}->Get('BBS_CAPTCHA')){ $Page->Print('') if ($this->{'SYS'}->Get('CAPTCHA') eq 'h-captcha'); $Page->Print('') if ($this->{'SYS'}->Get('CAPTCHA') eq 'g-recaptcha'); @@ -585,7 +584,13 @@ sub PrintIndexFoot # footの表示 $Caption->Load($Sys, 'FOOT'); $Caption->Print($Page, $Set); - $Page->Print(""); + $Page->Print(""); + + my ($sec,$min,$hour,$day,$mon,$year) = localtime($Sys->Get('LASTMOD')); + $mon ++; + $year += 1900; + my $lastMod = sprintf("Last modified : %d/%02d/%02d %02d:%02d:%02d",$year,$mon,$day,$hour,$min,$sec); + $Page->Print("
$lastMod
"); $Page->Print(< @@ -747,7 +752,6 @@ sub PrintResponse my $aa=''; # URLと引用個所の適応 - $Conv->ConvertImgur(\$elem[3])if($Set->Get('BBS_IMGUR') eq 'checked'); $Conv->ConvertMovie(\$elem[3])if($Set->Get('BBS_MOVIE') eq 'checked'); $Conv->ConvertTweet(\$elem[3])if($Set->Get('BBS_TWITTER') eq 'checked'); $Conv->ConvertURL($Sys, $Set, 0, \$elem[3])if($Sys->Get('URLLINK') eq 'TRUE'); diff --git a/test/module/data_utils.pl b/test/module/data_utils.pl index 6c55b44..50b1a5f 100644 --- a/test/module/data_utils.pl +++ b/test/module/data_utils.pl @@ -212,19 +212,6 @@ sub ConvertURL } return $text; } -#Imgur埋め込み -sub ConvertImgur -{ - my $this = shift; - my ($text) = @_ ; - - my $reg = '(?$1|g; - - return $text; - -} =pod sub ConvertVideo { @@ -1791,6 +1778,31 @@ sub reverse_lookup { # 逆引きが成功した場合はホスト名を、失敗した場合はIPアドレスを返す return $host ? $host : $ip; } + +# IPv6展開 +sub expand_ipv6 { + my $this = shift; + my ($ip) = @_; + # "::" が含まれているか確認し、省略部分を展開する + if ($ip =~ /::/) { + my ($left, $right) = split /::/, $ip, 2; + my @left_parts = split /:/, $left; + my @right_parts = split /:/, $right; + my $left_size = scalar @left_parts; + my $right_size = scalar @right_parts; + my $missing = 8 - ($left_size + $right_size); # 展開すべき0のブロック数 + my $expanded = join(':', (@left_parts, ('0') x $missing, @right_parts)); + $ip = $expanded; + } + # 各ブロックを4桁に展開する + my @blocks = split /:/, $ip; + foreach my $i (0 .. $#blocks) { + $blocks[$i] = sprintf("%04s", $blocks[$i]); + $blocks[$i] =~ s/ /0/g; # 空白を0で埋める + } + return join(':', @blocks); +} + #============================================================================================================ # モジュール終端 #============================================================================================================ diff --git a/test/module/ninpocho.pl b/test/module/ninpocho.pl index 053e551..d781f16 100644 --- a/test/module/ninpocho.pl +++ b/test/module/ninpocho.pl @@ -43,17 +43,16 @@ sub new # 忍法帖ロード # ------------------------------------------------------------------------------------- # @param $Sys SYSTEM +# @param $slip slip文字列 # @param $isAnon 匿名化されてるかどうか # @param $password あればパスワードで忍法帖をロード。無ければ通常ロード -# @param $sid あればセッションIDで忍法帖をロード。無ければ通常ロード -# @param $mode 1なら忍法帖を作らない(セッションIDのみ利用したい場合) # @return パスワードがあり、かつセッションIDが見つからない場合0 # #------------------------------------------------------------------------------------------------------------ sub Load { my $this = shift; - my ($Sys,$isAnon,$password) = @_; + my ($Sys,$slip,$isAnon,$password) = @_; my ($sid,$sid_saved,$sid_before,$sec,$auth); my $Cookie = $Sys->Get('MainCGI')->{'COOKIE'}; @@ -65,18 +64,24 @@ sub Load $this->{'ANON_FLAG'} = $isAnon eq '8' ? 1 : 0; $sid = $Sys->Get('SID'); + my $addr = $ENV{'REMOTE_ADDR'}; + my $ctx3 = Digest::MD5->new; + $ctx3->add('ex0ch ID Generation'); + $ctx3->add(':', $Sys->Get('SERVER')); + $ctx3->add(':', $addr); + my $ip_hash = $ctx3->b64digest; + my $ctx = Digest::MD5->new; + $ctx->add('ex0ch ID Generation'); + $ctx->add(':', $Sys->Get('SERVER')); + $ctx->add(':', $slip); + my $slip_hash = $ctx->b64digest; + #cookieにsessionIDが保存されていない場合 if (!$sid && !$this->{'ANON_FLAG'}){ - my $addr = $ENV{'REMOTE_ADDR'}; - my $ctx = Digest::MD5->new; - my $expiry = 60*60*24; - $ctx->add('ex0ch ID Generation'); - $ctx->add(':', $Sys->Get('SERVER')); - $ctx->add(':', $addr); - - $sid = GetHash($ctx->b64digest,$expiry,$ninDir.'hash/ip_addr.cgi'); + my $expiry = 60*60*24; # 紐付け有効期限は24h + $sid = GetHash($ip_hash,$expiry,$ninDir.'hash/ip_addr.cgi'); if(!$sid) { - $sid = GetHash(MakeUserInfo($Sys),$expiry,$ninDir.'hash/user_info.cgi'); + $sid = GetHash($slip_hash,$expiry,$ninDir.'hash/user_info.cgi'); } } @@ -141,16 +146,8 @@ sub Load $Sys->Set('SID',$sid); # Hashテーブルを設定 if(!$this->{'ANON_FLAG'}){ - my $addr = $ENV{'REMOTE_ADDR'}; - my $ctx3 = Digest::MD5->new; - $ctx3->add('ex0ch ID Generation'); - $ctx3->add(':', $Sys->Get('SERVER')); - $ctx3->add(':', $addr); - my $ip_hash = $ctx3->b64digest; - my $user = MakeUserInfo($Sys); - SetHash($ip_hash,$sid,time,$ninDir.'hash/ip_addr.cgi'); - SetHash($user,$sid,time,$ninDir.'hash/user_info.cgi'); + SetHash($slip_hash,$sid,time,$ninDir.'hash/user_info.cgi'); } return $sid; @@ -197,6 +194,16 @@ sub Get return $val; } +sub isNew +{ + my $this = shift; + return $this->{'CREATE_FLAG'}; +} +sub isLoad +{ + my $this = shift; + return $this->{'LOAD_FLAG'}; +} #------------------------------------------------------------------------------------------------------------ # # 忍法帖情報設定 @@ -396,37 +403,6 @@ sub DeleteHashValue { } } -sub MakeUserInfo -{ - my $Sys = shift; - my $addr = $ENV{'REMOTE_ADDR'}; - my @ip = split(/\./,$addr); - my $ua = $ENV{'HTTP_SEC_CH_UA'} // $ENV{'HTTP_USER_AGENT'}; - - my $provider; - my $HOST = $ENV{'HTTP_HOST'}; - - # プロバイダのドメインを取得 - if ($HOST) { - $HOST =~ s/ne\.jp/nejp/g; - $HOST =~ s/ad\.jp/adjp/g; - $HOST =~ s/or\.jp/orjp/g; - - my @d = split(/\./, $HOST); # リモートホストからドメイン部分を取り出す - if (@d) { - my $c = scalar @d; - $provider = $d[$c - 2] . $d[$c - 1]; - } - } - my $ctx = Digest::MD5->new; - $ctx->add('ex0ch ID Generation'); - $ctx->add(':', $Sys->Get('SERVER')); - $ctx->add(':', $ip[0].$ip[1].$provider); - $ctx->add(':', $ua); - my $user = $ctx->b64digest; - - return $user; -} #============================================================================================================ # Module END #============================================================================================================ diff --git a/test/module/post_service.pl b/test/module/post_service.pl index 2b94fd9..dccd795 100644 --- a/test/module/post_service.pl +++ b/test/module/post_service.pl @@ -171,14 +171,31 @@ sub Write my $noNinja = $Sec->IsAuthority($Sys->Get('CAPID'), $ZP::CAP_REG_NONINJA, $Form->Get('bbs')); my $noCaptcha = $Sec->IsAuthority($Sys->Get('CAPID'), $ZP::CAP_REG_NOCAPTCHA, $Form->Get('bbs')); - # BBS_SLIP付加とID末尾取得 + # BBS_SLIPとID末尾取得 my $chid = substr($Sys->Get('SECURITY_KEY'),0,8); - my ($slip_result,$idEnd) = $slip->BBS_SLIP($Sys, $bbsSlip, $chid) if (!$handle || !$noAttr); + my ($slip_nickname,$slip_aa,$slip_bb,$slip_cccc,$idEnd) = $slip->BBS_SLIP($Sys, $chid); + + # slip文字列とID末尾 + my $slip_result = ''; + my $ipAddr = $ENV{'REMOTE_ADDR'}; + if($bbsSlip eq 'vvv'){ + $slip_result = ${slip_nickname}; + } + elsif($bbsSlip eq 'vvvv'){ + $slip_result = "${slip_nickname} [$ipAddr]"; + } + elsif($bbsSlip eq 'vvvvv'){ + $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc}"; + } + elsif($bbsSlip eq 'vvvvvv'){ + $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc} [${ipAddr}]"; + } $idEnd = $Set->Get('BBS_SLIP') eq 'checked' ? $Sys->Get('AGENT') : $idEnd; - my $sid = $Ninja->Load($Sys,$idEnd,undef); + # 忍法帖関連 + my $sid = $Ninja->Load($Sys,${slip_aa}.${slip_bb}.${slip_cccc},$idEnd,undef); # hCaptcha認証 - if (!$noCaptcha && $Set->Get('BBS_CAPTCHA')){ + if (!$noCaptcha && $Set->Get('BBS_CAPTCHA') && $Sys->Get('CAPTCHA') && $Sys->Get('CAPTCHA_SECRETKEY') && $Sys->Get('CAPTCHA_SITEKEY')){ if (!$Ninja->Get('auth') || $Ninja->Get('force_captcha')){ $err = $this->Certification_Captcha($Sys,$Form); return $err if $err; @@ -200,7 +217,7 @@ sub Write $password = $1; $ninmail =~ s/!load:(.{10,30})//; $Form->Set('mail',$ninmail); - $sid = $Ninja->Load($Sys,$idEnd,$password); #ロード + $sid = $Ninja->Load($Sys,${slip_aa}.${slip_bb}.${slip_cccc},$idEnd,$password); #ロード $password = ''; } elsif($ninmail =~ /!save:(.{10,30})/ && $isNinja){ @@ -209,32 +226,10 @@ sub Write $Form->Set('mail',$ninmail); } $Sys->Set('SID',$sid); - + my $ninLv = $Ninja->Get('ninLv'); + #BANチェック return $ZP::E_REG_BAN if(!$noNinja&&($Ninja->Get('ban') eq 'ban'||($Ninja->Get('ban_mthread') eq 'thread' && $Sys->Equal('MODE', 1)))); - - # レベル制限 - my $ninLv = $Ninja->Get('ninLv'); - my $write_min = $Set->Get('NINJA_WRITE_MESSAGE'); - my $lvLim = $Threads->GetAttr($threadid,'ninLv'); - my ($min_level, $factor) = split(/-/, $Set->Get('NINJA_MAKE_THREAD')); - if($isNinja && !$noNinja){ - if($Sys->Equal('MODE', 1)){ - # スレ立てモード - if($ninLv < $min_level){ - return $ZP::E_REG_NINLVLIMIT; - }else{ - $Ninja->Set('ninLv',$ninLv - $factor); - } - }else{ - # 書き込みモード - if ($ninLv < $write_min){ - return $ZP::E_REG_NINLVLIMIT; - }else{ - return $ZP::E_REG_NINLVLIMIT if($ninLv < $lvLim && $write_min <= $lvLim && !$noAttr); - } - } - } my $nusisid = GetSessionID($Sys,$threadid,1); if($sid ne $nusisid && $nusisid && $Threads->GetAttr($threadid,'ban') && !$noAttr){ @@ -262,13 +257,36 @@ sub Write my $updown = 'top'; $updown = '' if ($Form->Contain('mail', 'sage')); $updown = '' if ($Threads->GetAttr($threadid, 'sagemode')); - $updown = '' if ($Ninja->Get('force_sage')); - $updown = '' if ($Set->Get('NINJA_FORCE_SAGE') >= $ninLv && $isNinja); + $updown = '' if ($Ninja->Get('force_sage') && !$noNinja); + $updown = '' if ($Set->Get('NINJA_FORCE_SAGE') >= $ninLv && $isNinja && !$noNinja); $Sys->Set('updown', $updown); # 書き込み直前処理 $err = $this->ReadyBeforeWrite(DAT::GetNumFromFile($Sys->Get('DATPATH')) + 1,$Ninja->Get('ban_command'),$Ninja,$ninLv); return $err if ($err != $ZP::E_SUCCESS); + + # レベル制限 + my $write_min = $Set->Get('NINJA_WRITE_MESSAGE'); + my $lvLim = $Threads->GetAttr($threadid,'ninLv'); + my ($min_level, $factor) = split(/-/, $Set->Get('NINJA_MAKE_THREAD')); + if($isNinja && !$noNinja){ + if($Sys->Equal('MODE', 1)){ + # スレ立てモード + if($ninLv < $min_level){ + return $ZP::E_REG_NINLVLIMIT; + }else{ + $Ninja->Set('ninLv',$ninLv - $factor); + } + }else{ + # 書き込みモード + if ($ninLv < $write_min){ + return $ZP::E_REG_NINLVLIMIT; + }else{ + return $ZP::E_REG_NINLVLIMIT if($ninLv < $lvLim && $write_min <= $lvLim && !$noAttr); + } + } + } + # 忍法帖 if($Set->Get('BBS_NINJA')){ my $ninerr = $this->Ninpocho($Sys,$Set,$Form,$Ninja,$sid); @@ -281,7 +299,7 @@ sub Write my $mail = $Form->Get('mail', ''); my $text = $Form->Get('MESSAGE', ''); #SLIPがあった場合は付加する - $name .= " (${slip_result})" if ($slip_result && !$noslip); + $name .= " (${slip_result})" if (($slip_result && !$noslip) && (!$handle || !$noAttr)); $datepart = $Form->Get('datepart', ''); $idpart = $Form->Get('idpart', ''); @@ -328,9 +346,7 @@ sub Write # レス数が最大数を超えたらover設定をする $resNum = DAT::GetNumFromFile($datPath); my $MAXRES = $AttrResMax ? $AttrResMax : $Sys->Get('RESMAX'); - if ($resNum > $MAXRES){ - return $ZP::E_LIMIT_OVERMAXRES; - }elsif ($resNum == $MAXRES) { + if ($resNum >= $MAXRES) { # datにOVERスレッドレスを書き込む Get1001Data($Sys, \$line,$MAXRES); DAT::DirectAppend($Sys, $datPath, $line); @@ -537,12 +553,17 @@ sub ReadyBeforeWrite my $threadid = $Sys->Get('KEY'); my $commandAuth = $Sec->IsAuthority($capID, $ZP::CAP_REG_COMMAND, $Form->Get('bbs')); my $noAttr = $Sec->IsAuthority($capID, $ZP::CAP_REG_NOATTR, $Form->Get('bbs')); + my $noNinja = $Sec->IsAuthority($Sys->Get('CAPID'), $ZP::CAP_REG_NONINJA, $Form->Get('bbs')); #スレ立て時用コマンド my ($min_level, $factor) = split(/-/, $Set->Get('NINJA_USE_COMMAND')); - if($com ne 'on' && (($Set->Get('BBS_NINJA') && $ninLv >= $min_level) || !$Set->Get('BBS_NINJA'))){ + if($com ne 'on' && (($Set->Get('BBS_NINJA') && $ninLv >= $min_level) || !$Set->Get('BBS_NINJA') || $commandAuth)){ + + # Capの権限があった場合すべて許可 + $CommandSet = oct("0b11111111111111111111111") if $commandAuth; + if($Sys->Equal('MODE', 1)){ - Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,1); + Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,$noNinja,1); } else{ if($Form->Get('mail') =~ /!pass:(.{1,30})/){ @@ -561,11 +582,11 @@ sub ReadyBeforeWrite $Form->Set('mail',$mail); if($inputPass eq $threadPass){ - Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,0); + Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,$noNinja,0); } } elsif($commandAuth || GetSessionID($Sys,$threadid,1) eq $Sys->Get('SID')){ - Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,0); + Command($Sys,$Form,$Set,$Threads,$Ninja,$CommandSet,$noNinja,0); } } } @@ -607,10 +628,16 @@ sub GetSessionID return $sid; } -#ユーザーコマンド + +#------------------------------------------------------------------------------------------------------------ +# +# ユーザーコマンド +# ------------------------------------------------------------------------------------- +# +#------------------------------------------------------------------------------------------------------------ sub Command { - my ($Sys,$Form,$Set,$Threads,$Ninja,$setBitMask,$mode) = @_; + my ($Sys,$Form,$Set,$Threads,$Ninja,$setBitMask,$noNinja,$mode) = @_; $Threads->LoadAttr($Sys); my $threadid = $Sys->Get('KEY'); my $Command = ''; @@ -628,7 +655,6 @@ sub Command my $pass = $ctx->b64digest; $Threads->SetAttr($threadid, 'pass',$pass); - $Threads->SaveAttr($Sys); my $mail = $Form->Get('mail'); $mail =~ s/!pass:(.{1,30})//; @@ -649,7 +675,6 @@ sub Command $Command .= '値が過小
'; } } - $Threads->SaveAttr($Sys); } #extendコマンド if ($Form->Get('MESSAGE') =~ /^!extend:(|on|default|none|checked):(|none|default|checked|feature|verbose|v{3,6}):([1-9][0-9]*):([1-9][0-9]*)(
|$)/ && ($setBitMask & 1048576)) { @@ -659,7 +684,6 @@ sub Command my $slip = $2; my $line = $3; my $size = $4; - $Threads->SaveAttr($Sys); } } @@ -669,9 +693,9 @@ sub Command if($Form->Get('MESSAGE') =~ /(^|
)!delcmd:([0-9a-zA-Z&;]{4,20})(
|$)/ && ($setBitMask & 256)){ my $delCommand = $2; $delCommand =~ s/^sage$/sagemode/; - #BAN取り消し用 if($Threads->GetAttr($threadid, $delCommand)){ if($delCommand =~ /ban>>([1-9][0-9]*)/ ){ + #BAN取り消し用 my @banuserAttr = split(/,/ ,$Threads->GetAttr($threadid,'ban')); my $bannum = @banuserAttr; my $bansid = GetSessionID($Sys,$threadid,$1); @@ -696,7 +720,6 @@ sub Command } else{ $Threads->SetAttr($threadid, $delCommand,''); - $Threads->SaveAttr($Sys); $delCommand =~ s/^sagemode$/sage/; $Command .= '※'.$delCommand.'取り消し
'; } @@ -710,11 +733,10 @@ sub Command if($Form->Get('MESSAGE') =~ /(^|
)!stop(
|$)/ && ($setBitMask & 128)){ my $ninLv = $Ninja->Get('ninLv'); my ($min_level, $factor) = split(/-/, $Set->Get('NINJA_THREAD_STOP')); - if(($NinStat && $ninLv >= $min_level)||!$NinStat){ + if(($NinStat && $ninLv >= $min_level)||!$NinStat||$noNinja){ $Threads->SetAttr($threadid, 'stop',1); - $Threads->SaveAttr($Sys); $Command .= '※スレスト
'; - $Ninja->Set('ninLv',$ninLv - $factor); + $Ninja->Set('ninLv',$ninLv - $factor) unless $noNinja; }else{ $Command .= '※レベル不足
'; } @@ -722,7 +744,6 @@ sub Command #過去ログ送り if($Form->Get('MESSAGE') =~ /(^|
)!pool(
|$)/ && ($setBitMask & 512)){ $Threads->SetAttr($threadid, 'pool',1); - $Threads->SaveAttr($Sys); $Command .= '※過去ログ送り
';; } #スレタイ変更 @@ -775,7 +796,7 @@ sub Command if($Dat->Load($Sys,$Path,0)){ if($target2 && $target < $target2){ my $cost = $factor * ($target2 - $target + 1); - if(($NinStat && $ninLv >= $min_level && $ninLv - $min_level >= $cost) || !$NinStat){ + if(($NinStat && $ninLv >= $min_level && $ninLv - $min_level >= $cost) || !$NinStat || $noNinja){ my $li = $Dat->Get($target2-1); $li = $$li; my $count = 0; @@ -784,7 +805,8 @@ sub Command for($i = $target-1;$i <= $target2-1;$i++){ my $line = $Dat->Get($i); $line = $$line; - if ((split(/<>/,chomp($line)))[4] eq ''){ + chomp($line); + if ((split(/<>/,$line))[4] eq ''){ if($line){ my $deleteMessage = "$del<>$del<>$del<>$del<>$del\n"; $Dat->Set($i,$deleteMessage); @@ -803,7 +825,7 @@ sub Command }else{ $Command .= "※>>${target}-${target2}は削除済み
"; } - $Ninja->Set('ninLv',$ninLv - $factor*$count); + $Ninja->Set('ninLv',$ninLv - $factor*$count) unless $noNinja; }else{ $Command .= "※範囲指定が変
"; } @@ -812,17 +834,18 @@ sub Command } }else{ - if(($NinStat && $ninLv >= $min_level)||!$NinStat){ + if(($NinStat && $ninLv >= $min_level)||!$NinStat||$noNinja){ my $line = $Dat->Get($target-1); $line = $$line; - if ((split(/<>/,chomp($line)))[4] eq ''){ + chomp($line); + if ((split(/<>/,$line))[4] eq ''){ if($line){ - my $deleteMessage = "$del<>$del<>$del<>$del<>$del\n"; - $Dat->Set($target-1,$deleteMessage); - $Dat->Save($Sys); - $Command .= "※>>${target}を削除
"; + my $deleteMessage = "$del<>$del<>$del<>$del<>$del\n"; + $Dat->Set($target-1,$deleteMessage); + $Dat->Save($Sys); + $Command .= "※>>${target}を削除
"; - $Ninja->Set('ninLv',$ninLv - $factor); + $Ninja->Set('ninLv',$ninLv - $factor) unless $noNinja; }else{ $Command .= "※存在しません
"; } @@ -881,45 +904,38 @@ sub Command #強制sage if($Form->Get('MESSAGE') =~ /(^|
)!sage(
|$)/ && ($setBitMask & 4)){ $Threads->SetAttr($threadid, 'sagemode',1); - $Threads->SaveAttr($Sys); $Command .= '※強制sage
'; } #強制age if($Form->Get('MESSAGE') =~ /(^|
)!float(
|$)/ && ($setBitMask & 131072)){ $Threads->SetAttr($threadid, 'float',1); - $Threads->SaveAttr($Sys); $Command .= '※強制age
'; } #不落 if($Form->Get('MESSAGE') =~ /(^|
)!nopool(
|$)/ && ($setBitMask & 262144)){ $Threads->SetAttr($threadid, 'nopool',1); - $Threads->SaveAttr($Sys); $Command .= '※不落
'; } #BBS_SLIP if($Form->Get('MESSAGE') =~ /(^|
)!slip:(v{3,6})(
|$)/ && ($setBitMask & 2048)){ $Threads->SetAttr($threadid, 'slip',$2); - $Threads->SaveAttr($Sys); $Command .= '※BBS_SLIP='.$2.'
'; } #名無し強制 if($Form->Get('MESSAGE') =~ /(^|
)!force774(
|$)/ && ($setBitMask & 32)){ $Threads->SetAttr($threadid, 'force774',1); - $Threads->SaveAttr($Sys); $Command .= '※強制名無し
'; - $Form->Set('FROM',''); + #$Form->Set('FROM',''); } #実況モード if($Form->Get('MESSAGE') =~ /(^|
)!live(
|$)/ && ($setBitMask & 1024)){ $Threads->SetAttr($threadid, 'live',1); - $Threads->SaveAttr($Sys); $Command .= '※実況スレ
'; } #スレ主非表示 if($Form->Get('MESSAGE') =~ /(^|
)!hidenusi(
|$)/ && ($setBitMask & 32768)){ if(!$Set->Get('BBS_HIDENUSI')){ $Threads->SetAttr($threadid, 'hidenusi',1); - $Threads->SaveAttr($Sys); $Command .= '※スレ主非表示
'; } } @@ -933,7 +949,7 @@ sub Command my $ninLv = $Ninja->Get('ninLv'); my ($min_level, $factor) = split(/-/, $Set->Get('NINJA_USER_BAN')); - if(($NinStat && $ninLv >= $min_level) || !$NinStat){ + if(($NinStat && $ninLv >= $min_level) || !$NinStat ||$noNinja){ if($bansid){ if($bansid ne $nusisid){ # grepを使って$bansidが@banuserAttrに存在するかをチェック @@ -946,9 +962,8 @@ sub Command push(@banuserAttr, $bansid); # 新しい要素を配列の末尾に追加 shift @banuserAttr if ($bannum+1 > $Sys->Get('BANMAX')); $Threads->SetAttr($threadid, 'ban', join(',', @banuserAttr)); - $Threads->SaveAttr($Sys); $Command .= "※BAN:>>$2
"; - $Ninja->Set('ninLv',$ninLv - $factor); + $Ninja->Set('ninLv',$ninLv - $factor) unless $noNinja; } } else { $Command .= "※スレ主はBAN不可
"; @@ -968,7 +983,6 @@ sub Command my $new774 = $1; $new774 = HTML::Entities::encode_entities($new774); $Threads->SetAttr($threadid, 'change774',$new774); - $Threads->SaveAttr($Sys); $new774 = HTML::Entities::decode($new774); $Command .= '※名無し:'.$new774.'
'; }else{ @@ -978,12 +992,10 @@ sub Command #ID無し若しくはIDをスレッドで変更(!noidと!changeidがあった場合は!noid優先) if($Form->Get('MESSAGE') =~ /(^|
)!noid(
|$)/ && ($setBitMask & 8)){ $Threads->SetAttr($threadid, 'noid',1); - $Threads->SaveAttr($Sys); $Command .= '※ID無し
'; } if(!$Threads->GetAttr($threadid, 'noid') && $Form->Get('MESSAGE') =~ /(^|
)!changeid(
|$)/ && ($setBitMask & 16)){ $Threads->SetAttr($threadid, 'changeid',1); - $Threads->SaveAttr($Sys); $Command .= '※ID変更
'; } @@ -996,7 +1008,6 @@ sub Command if($2 <= $lvmax){ if($2 >= $write_min){ $Threads->SetAttr($threadid, 'ninLv',$2); - $Threads->SaveAttr($Sys); $Command .= "※忍法帖Lv$2未満は書き込み不可
"; }else{ $Command .= "※${write_min}未満は設定不可
"; @@ -1007,6 +1018,7 @@ sub Command } } if($Command){ + $Threads->SaveAttr($Sys); $Command =~ s/
$//; $Form->Set('MESSAGE',$Form->Get('MESSAGE')."
$Command"); } @@ -1207,13 +1219,13 @@ sub IsRegulation $Sys->Set('IPCOUNTRY','abroad'); } # PROXYチェック - if ($this->{'CONV'}->IsProxyDNSBL($this->{'SYS'}, $this->{'FORM'}, $from, $mode)) { + if ($this->{'CONV'}->IsProxyDNSBL($this->{'SYS'}, $this->{'FORM'}, $from, $mode)) { # DNSBLによるチェック #$this->{'FORM'}->Set('FROM', " [—\{}\@{}\@{}-] $from"); if (!$Sec->IsAuthority($capID, $ZP::CAP_REG_DNSBL, $bbs) && $Set->Equal('BBS_DNSBL_CHECK', 'checked')) { return $ZP::E_REG_DNSBL; } $Sys->Set('ISPROXY','bl'); - }elsif($this->{'CONV'}->IsProxyAPI($this->{'SYS'},1) && $Sys->Get('PROXYCHECK_APIKEY')){ + }elsif($Sys->Get('PROXYCHECK_APIKEY') && $this->{'CONV'}->IsProxyAPI($this->{'SYS'},1)){ # DNSBLに引っかからなかった場合に、設定されていたらProxy.ioへ if (!$Sec->IsAuthority($capID, $ZP::CAP_REG_DNSBL, $bbs) && $Set->Equal('BBS_PROXY_CHECK', 'checked')) { return $ZP::E_REG_DNSBL; } @@ -1548,8 +1560,9 @@ sub Certification_Captcha { return $ZP::E_FORM_FAILEDCAPTCHA } } else { - # HTTPS関連のエラーの疑いあり + # Captchaを素通りする場合、HTTPS関連のエラーの疑いあり # LWP::Protocol::httpsおよびNet::SSLeayが入っているか確認 + # このエラーの場合、スルーして書き込み return $ZP::E_SYSTEM_CAPTCHAERROR; } }else{ @@ -1696,6 +1709,12 @@ sub SaveHost } } +#------------------------------------------------------------------------------------------------------------ +# +# 忍法帖に関する処理 +# ------------------------------------------------------------------------------------- +# +#------------------------------------------------------------------------------------------------------------ sub Ninpocho { my $this = shift; @@ -1706,6 +1725,7 @@ sub Ninpocho # セッションから書き込み数を取得 my $count = $Ninja->Get('count') || 0; + my $today_count = $Ninja->Get('today_count') || 0; my $thread = $Ninja->Get('thread_count') || 0; # 書き込んだ時間を取得 @@ -1715,21 +1735,27 @@ sub Ninpocho # セッションから前回レベルアップしたときの時間を取得 my $lvUpTime = $Ninja->Get('lvuptime') || $time23h; - # 書き込み数をカウント - $count++; - # レベルの上限 my $lvLim = $Sys->Get('NINLVMAX'); # 前回のレベルアップから23時間以上経過していればレベルアップ - if ($resTime >= $lvUpTime && $ninLv < $lvLim) { + if ($resTime >= $lvUpTime && $ninLv < $lvLim) { # && $ninLv == $today_count $ninLv++; $lvUpTime = $time23h; } + # 書き込み数をカウント + $count++; + unless(int(time/(60*60*24)) - int($Ninja->Get('last_wtime')/(60*60*24))){ + $today_count++; + }else{ + $today_count = 1; + } + # セッションに記録 if ($Ninja) { $Ninja->Set('count', $count); + $Ninja->Set('today_count', $today_count); $Ninja->Set('ninLv', $ninLv); $Ninja->Set('lvuptime', $lvUpTime); @@ -1792,9 +1818,16 @@ sub Ninpocho return 0; } + +#------------------------------------------------------------------------------------------------------------ +# +# タイムラインにレス追加 +# ------------------------------------------------------------------------------------- +# +#------------------------------------------------------------------------------------------------------------ sub AddTimeLine { - my $this=shift; + my $this = shift; my ($Sys,$Set,$line) = @_; require './module/dat.pl'; require './module/thread.pl'; @@ -1805,14 +1838,16 @@ sub AddTimeLine $Threads->Load($Sys); my $TLpath = $Sys->Get('BBSPATH') . '/' . $Sys->Get('BBS') . '/dat/2147483647.dat'; - - my @lines = split(/<>/,chomp($line)); my $title = $Threads->Get('SUBJECT',$Sys->Get('KEY')); my $url = $Conv->CreatePath($Sys, 0, $Sys->Get('BBS'), $Sys->Get('KEY'), 'l10'); - $lines[3] += "
$title"; + + chomp($line); + my @lines = split(/<>/, $line); + $lines[3] .= "
$title"; $lines[4] = "★タイムライン★\n"; $line = join('<>',@lines); - $Dat->DirectAppend($Sys,$TLpath,$line); + + my $err = $Dat->DirectAppend($Sys,$TLpath,$line); my $resNum = DAT::GetNumFromFile($TLpath); if($resNum > $Set->Get('TL_RES_MAX')){ @@ -1820,7 +1855,7 @@ sub AddTimeLine $Dat->Delete(0); $Dat->Save($Sys); } - + return $err; } #SPAMBLOCK sub SpamBlock diff --git a/test/module/setting.pl b/test/module/setting.pl index 87f62a9..c380d54 100644 --- a/test/module/setting.pl +++ b/test/module/setting.pl @@ -373,7 +373,6 @@ sub InitSettingData 'BBS_SPAMKILLI_POINT' => 10, 'BBS_IMGTAG' => '', - 'BBS_IMGUR' => '', 'BBS_TWITTER' => '', 'BBS_MOVIE' => '', 'BBS_URL_TITLE' => '', diff --git a/test/module/slip.pl b/test/module/slip.pl index 13ddbd5..15a6503 100644 --- a/test/module/slip.pl +++ b/test/module/slip.pl @@ -43,10 +43,9 @@ sub is_denied_ip { return exists $denied_ips->{$ipAddr} ? 1 : 0; } - # 匿名化判定 sub is_anonymous { - my ($isFwifi, $country, $remoho, $ipAddr, $infoDir) = @_; + my ($isFwifi, $country, $remoho, $ipAddr) = @_; my $isAnon = 0; if (!$isFwifi && $country eq 'JP' && $remoho ne $ipAddr) { @@ -97,7 +96,6 @@ sub is_public_wifi { return $isFwifi; } - # モバイル判定 sub is_mobile { my ($country, $ipAddr, $remoho) = @_; @@ -324,17 +322,14 @@ sub is_mobile { #------------------------------------------------------------------------------------------------------------ # BBS_SLIP生成 # ------------------------------------------------------------------------------------- -# @param $bbsslip slip種別(/(undef)/vvv/vvvv/vvvvv/vvvvvv/) -# @param $infoDir infoディレクトリ # @param $chid SLIP_ID変更用 -# @param $checkKey プロキシチェックAPI問い合わせ用 # @return $slip_result # @return $idEnd ID末尾 #------------------------------------------------------------------------------------------------------------ sub BBS_SLIP { my $this = shift; - my ($Sys, $bbsslip, $chid) = @_; + my ($Sys, $chid) = @_; my ($slip_ip, $slip_remoho, $slip_ua); my $ipAddr = $ENV{'REMOTE_ADDR'}; @@ -343,17 +338,18 @@ sub BBS_SLIP my $infoDir = $Sys->Get('INFO'); # 各種判定 - my $country = $Sys->Get('IPCOUNTRY') ne 'abroad' ? 'JP': 'ガイコーク'; - my $ismobile = is_mobile($country,$ipAddr,$remoho); - my $isFwifi = is_public_wifi($country,$ipAddr,$remoho); - my $isProxy = $Sys->Get('ISPROXY'); - my $isAnon = is_anonymous($isFwifi,$country,$ipAddr,$remoho,$infoDir); + my $country = $Sys->Get('IPCOUNTRY') ne 'abroad' ? 'JP': 'ガイコーク'; # post_service側での判定を流用 + my $isProxy = $Sys->Get('ISPROXY'); # post_service側での判定を流用 + my $ismobile = is_mobile($country,$ipAddr,$remoho); # モバイル判定 + my $isFwifi = is_public_wifi($country,$ipAddr,$remoho); # 公衆wifi判定 + my $isAnon = is_anonymous($isFwifi,$country,$ipAddr,$remoho); # 匿名化判定 + #my $isDenied = is_denied_ip($ipAddr,$infoDir); # 拒否IP判定 # bbs_slipに使用する文字 my @slip_chars = (0..9, 'a'..'z', 'A'..'Z', '.', '/'); # 一週間で文字列変更 - my $week_number = int((time + 172800) / (60 * 60 * 24 * 7));# 水曜9時に + my $week_number = int((time + 172800) / (60 * 60 * 24 * 7)); # 水曜9時に変わる my ($chnum1,$chnum2,$chnum3,$chnum4); srand($week_number); $chnum1 = int(rand(1000000)); @@ -370,9 +366,13 @@ sub BBS_SLIP # slip_ip生成 my $fo = ''; my $so = ''; - $ipAddr =~ /^(\d{1,4})\.(\d{1,4})/; - $fo = $1 + $chnum1 + $chid; - $so = $2 + $chnum2 + $chid; + if ($ipAddr =~ /^(\d{1,3})\.(\d{1,3})/) { + $fo = $1 + $chnum1 + $chid; + $so = $2 + $chnum2 + $chid; + } elsif ($ipAddr =~ /^([\da-fA-F]{1,4}):([\da-fA-F]{1,4}):([\da-fA-F]{1,4}):([\da-fA-F]{1,4})/) { + $fo = hex($1) + hex($2) + $chnum1 + $chid; + $so = hex($3) + hex($4) + $chnum2 + $chid; + } my $ip_char1 = $slip_chars[$fo % 64]; my $ip_char2 = $slip_chars[$so % 64]; @@ -441,9 +441,15 @@ sub BBS_SLIP # 串判定 if ($isProxy) { - $idEnd = '8'; - $slip_nickname = 'クシザシ'; - $slip_nickname .= $fixed_nickname_end; + if($isProxy eq 'proxy'){ + $idEnd = '8'; + $slip_nickname = 'クシザシ'; + $slip_nickname .= $fixed_nickname_end; + }else{ + $idEnd = '8'; + $slip_nickname = 'ブロック'; + $slip_nickname .= $fixed_nickname_end; + } }else{ # 逆引き判定 if (!$slip_remoho || $ipAddr eq $remoho) { # 逆引きできない場合 @@ -545,352 +551,21 @@ sub BBS_SLIP } } } - } - - # slip文字列とID末尾 - my $slip_result = ''; - if($bbsslip eq 'vvv'){ - $slip_result = ${slip_nickname}; - } - elsif($bbsslip eq 'vvvv'){ - $slip_result = "${slip_nickname} [${ipAddr}]"; - } - elsif($bbsslip eq 'vvvvv'){ - $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc}"; - } - elsif($bbsslip eq 'vvvvvv'){ - $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc} [${ipAddr}]"; - } - # 匿名環境の場合は末尾が"8"になる - return $slip_result,$idEnd; -} - -# 旧式 -sub BBS_SLIP_OLD -{ - my ($ip_addr, $remoho, $ua, $bbsslip) = @_; - my ($slip_ip, $slip_remoho, $slip_ua); - - #bbs_slipに使用する文字 - my @slip_char = (0..9, "a".."z", "A".."Z", ".", "/"); - #slip_ip生成 - $ip_addr =~ /^(\d{1,4})\.(\d{1,4})/; - my $ip_char1 = $slip_char[$1 % 64]; - my $ip_char2 = $slip_char[$2 % 64]; - $slip_ip = $ip_char1 . $ip_char2; - - #slip_remoho生成 - if ($remoho eq "") { - $slip_remoho = "none"; - }else { - $remoho =~ /^([a-zA-Z]+)[\d\-\.]*([a-zA-Z][a-zA-Z\d\.\-]+)$/; - my $remoho_name = "$1 $2"; - my $remoho_dig = md5_hex($remoho_name); - $remoho_dig =~ /^(.{2})(.{2})/; - my $remoho_char1 = $slip_char[hex($1) % 64]; - my $remoho_char2 = $slip_char[hex($2) % 64]; - $slip_remoho = $remoho_char1 . $remoho_char2; - } - - #slip_ua生成 - my $ua_dig = md5_hex($ua); - $ua_dig =~ /^(.{2})(.{2})(.{2})(.{2})/; - my $ua_char1 = $slip_char[hex($1) % 64]; - my $ua_char2 = $slip_char[hex($2) % 64]; - my $ua_char3 = $slip_char[hex($3) % 64]; - my $ua_char4 = $slip_char[hex($4) % 64]; - $slip_ua = $ua_char1 . $ua_char2 . $ua_char3 . $ua_char4; - - #スマホ・タブレット判定 - my $fixed_nickname_end = ""; - my $mobile_nickname_end = ""; - if ($ua =~ /.*(iphone|ipad|android|mobile).*/i) { - $fixed_nickname_end = "W"; - $mobile_nickname_end = "M"; - }else { - $mobile_nickname_end = "T"; - } - - - #bbs_slipの初期設定 - my $slip_id = ""; - my $slip_nickname = "ワッチョイ${fixed_nickname_end}"; - my $slip_aa = $slip_ip; - my $slip_bb = $slip_remoho; - my $slip_cccc = $slip_ua; - - - #モバイル回線判定用のリモホ・事業者名・IP - my @mobile_remoho = ( - ".*\\.openmobile\\.ne\\.jp", - ".*\\.panda-world\\.ne\\.jp", - "KD027.*\\.au-net\\.ne\\.jp", - "KD036.*\\.au-net\\.ne\\.jp", - "KD106.*\\.au-net\\.ne\\.jp", - "KD111.*\\.au-net\\.ne\\.jp", - "KD119.*\\.au-net\\.ne\\.jp", - "KD182.*\\.au-net\\.ne\\.jp", - ".*\\.msa\\.spmode\\.ne\\.jp", - ".*\\.msb\\.spmode\\.ne\\.jp", - ".*\\.msc\\.spmode\\.ne\\.jp", - ".*\\.msd\\.spmode\\.ne\\.jp", - ".*\\.mse\\.spmode\\.ne\\.jp", - ".*\\.msf\\.spmode\\.ne\\.jp", - ".*\\.fix\\.mopera\\.net", - ".*\\.air\\.mopera\\.net", - ".*\\.vmobile\\.jp", - ".*\\.bmobile\\.ne\\.jp", - ".*\\.mineo\\.jp", - ".*omed01\\.tokyo\\.ocn\\.ne\\.jp", - ".*omed01\\.osaka\\.ocn\\.ne\\.jp", - ".*mobac01\\.tokyo\\.ocn\\.ne\\.jp", - ".*mobac01\\.osaka\\.ocn\\.ne\\.jp", - ".*\\.mvno\\.rakuten\\.jp", - ".*\\.nttpc\\.ne\\.jp", - "UQ.*au-net\\.ne\\.jp", - "dcm\\d(?:-\\d+){4}\\.tky\\.mesh\\.ad\\.jp", - "neoau\\d(?:-\\d+){4}\\.tky\\.mesh\\.ad\\.jp", - ".*\\.ap\\.dream\\.jp", - ".*\\.ap\\.mvno\\.net", - "fenics\\d+\\.wlan\\.ppp\\.infoweb\\.ne\\.jp" - ); - my @mobile_whois = ( - "Plus One marketing", - "LogicLinks", - "SORASIM" - ); - my @rakuten_mno_ip = ( - "101\\.102\\.(?:\\d|[1-5]\\d|6[0-3])\\.\\d{1,3}", - "103\\.124\\.[0-3]\\.\\d{1,3}", - "110\\.165\\.(?:1(?:2[89]|[3-9]\\d)|2\\d{2})\\.\\d{1,3}", - "119\\.30\\.(?:19[2-9]|2\\d{2})\\.\\d{1,3}", - "119\\.31\\.1(?:2[89]|[3-5]\\d)\\.\\d{1,3}", - "133\\.106\\.(?:1(?:2[89]|[3-9]\\d)|2\\d{2})\\.\\d{1,3}", - "133\\.106\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}", - "133\\.106\\.(?:3[2-9]|[45]\\d|6[0-3])\\.\\d{1,3}", - "133\\.106\\.(?:6[4-9]|[7-9]\\d|1(?:[01]\\d|2[0-7]))\\.\\d{1,3}", - "133\\.106\\.(?:[89]|1[0-5])\\.\\d{1,3}", - "157\\.192(?:\\.\\d{1,3}){2}", - "193\\.114\\.(?:19[2-9]|2\\d{2})\\.\\d{1,3}", - "193\\.114\\.(?:3[2-9]|[45]\\d|6[0-3])\\.\\d{1,3}", - "193\\.114\\.(?:6[4-9]|[78]\\d|9[0-5])\\.\\d{1,3}", - "193\\.115\\.(?:\\d|[12]\\d|3[01])\\.\\d{1,3}", - "193\\.117\\.(?:[9][6-9]|1(?:[01]\\d|2[0-7]))\\.\\d{1,3}", - "193\\.118\\.(?:\\d|[12]\\d|3[01])\\.\\d{1,3}", - "193\\.118\\.(?:6[4-9]|[78]\\d|9[0-5])\\.\\d{1,3}", - "193\\.119\\.(?:1(?:2[89]|[3-9]\\d)|2\\d{2})\\.\\d{1,3}", - "193\\.82\\.1(?:[6-8]\\d|9[01])\\.\\d{1,3}", - "194\\.193\\.2(?:2[4-9]|[34]\\d|5[0-5])\\.\\d{1,3}", - "194\\.193\\.(?:6[4-9]|[78]\\d|9[0-5])\\.\\d{1,3}", - "194\\.223\\.(?:[9][6-9]|1(?:[01]\\d|2[0-7]))\\.\\d{1,3}", - "202\\.176\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}", - "202\\.216\\.(?:\\d|1[0-5])\\.\\d{1,3}", - "210\\.157\\.(?:19[2-9]|2(?:[01]\\d|2[0-3]))\\.\\d{1,3}", - "211\\.133\\.(?:[6-8]\\d|9[01])\\.\\d{1,3}", - "211\\.7\\.(?:[9][6-9]|1(?:[01]\\d|2[0-7]))\\.\\d{1,3}", - "219\\.105\\.1(?:4[4-9]|5\\d)\\.\\d{1,3}", - "219\\.105\\.(?:19[2-9]|2\\d{2})\\.\\d{1,3}", - "219\\.106\\.(?:\\d{1,2}|1(?:[01]\\d|2[0-7]))\\.\\d{1,3}" - ); - - #モバイル回線のslip_id - my @mobile_ids = ( - "Sr", - "Sp", - "Sa", - "Sd", - "SD", - "MM" - ); - - #モバイル回線のニックネーム - my @mobile_nicknames = ( - "オッペケ${mobile_nickname_end}", - "ササクッテロ${mobile_nickname_end}", - "アウアウアー${mobile_nickname_end}", - "アウアウイー${mobile_nickname_end}", - "アウアウウー${mobile_nickname_end}", - "アウアウエー${mobile_nickname_end}", - "アウアウオー${mobile_nickname_end}", - "アウアウカー${mobile_nickname_end}", - "スプー${mobile_nickname_end}", - "スプッッ${mobile_nickname_end}", - "スップ${mobile_nickname_end}", - "スッップ${mobile_nickname_end}", - "スププ${mobile_nickname_end}", - "スフッ${mobile_nickname_end}", - "ペラペラ${mobile_nickname_end}", - "エアペラ${mobile_nickname_end}", - "ブーイモ${mobile_nickname_end}", - "ベーイモ${mobile_nickname_end}", - "オイコラミネオ${mobile_nickname_end}", - "ワントンキン${mobile_nickname_end}", - "ワンミングク${mobile_nickname_end}", - "バットンキン${mobile_nickname_end}", - "バッミングク${mobile_nickname_end}", - "ラクッペペ${mobile_nickname_end}", - "ラクラッペ${mobile_nickname_end}", - "アウアウクー${mobile_nickname_end}", - "ドコグロ${mobile_nickname_end}", - "ドナドナー${mobile_nickname_end}", - "トンモー${mobile_nickname_end}", - "アメ${mobile_nickname_end}", - "ニャフニャ${mobile_nickname_end}", - "イルクン${mobile_nickname_end}", - "ゲマー${mobile_nickname_end}", - "フリッテル${mobile_nickname_end}" - ); - - #公衆Wi-Fiのリモホ・ネットワーク名・IP - my @fwifi_remoho = ( - ".*\\.m-zone\\.jp", - "\\d+\\.wi-fi\\.kddi\\.com", - ".*\\.wi-fi\\.wi2\\.ne\\.jp", - ".*\\.family-wifi\\.jp" - ); - my @fwifi_whois = ( - "INPLUS-FWIFI", - "FON" - ); - my $lawson_ip = "210\\.227\\.19\\.[67]\\d\$"; - #公衆Wi-FiのID - my $fwifi_id = "FF"; - #公衆Wi-Fiのニックネーム - my @fwifi_nicknames = ( - "エムゾネ${fixed_nickname_end}[公衆]", - "アウウィフ${fixed_nickname_end}[公衆]", - "ワイーワ2${fixed_nickname_end}[公衆]", - "ファミマ${fixed_nickname_end}[公衆]", - "フォンフォン${fixed_nickname_end}[公衆]", - "マクド${fixed_nickname_end}[公衆]" - ); - - #逆引き判定 - if ($slip_remoho eq "none") { #逆引きできない場合 - my $isunknown = "yes"; - my $res = whois($ip_addr); - - #モバイル回線判定 - my $mobile_nickname_idx = -1; - for my $name (@mobile_whois) { - if ($res =~ /.*${name}.*/) { - $slip_id = "MM"; - $slip_nickname = $mobile_nicknames[$mobile_nickname_idx]; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - $isunknown = "no"; - last; - } - $mobile_nickname_idx--; - } - #楽天モバイル(MNO)判定 - if ($isunknown eq "yes") { - for my $name (@rakuten_mno_ip) { - if ($ip_addr =~ /${name}/) { - $slip_id = "MM"; - $slip_nickname = "テテンテンテンM"; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - $isunknown = "no"; - last; - } - } - } - - #公衆判定 - if ($isunknown eq "yes") { - my $fwifi_nickname_idx = -1; - for my $name (@fwifi_whois) { - if ($res =~ /.*${name}.*/) { - $slip_id = $fwifi_id; - $slip_nickname = $fwifi_nicknames[$fwifi_nickname_idx]; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - $isunknown = "no"; - last; - } - $fwifi_nickname_idx--; - } - } - #ローソン判定 - if ($isunknown eq "yes") { - if ($ip_addr =~ /${lawson_ip}/) { - $slip_id = "FF"; - $slip_nickname = "ローソン${fixed_nickname_end}[公衆]"; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - $isunknown = "no"; - } - } - - #逆引き不可能 アンタダレ - if ($isunknown eq "yes") { - $slip_id = "Un"; - $slip_nickname = "アンタダレ${fixed_nickname_end}"; + # ローカル環境 + if ($ipAddr eq '127.0.0.1'){ + $slip_id = 'lc'; + $idEnd = 'l'; + $slip_nickname = "ローカル${fixed_nickname_end}"; $slip_aa = $slip_id; $slip_bb = $slip_ip; } - }else{ #逆引きできる場合 - my $ismobile = 0; - #モバイル回線判定 - my $mobile_id_idx = 0; - my $mobile_nickname_idx = 0; - for my $name (@mobile_remoho) { - if ($remoho =~ /^${name}$/) { - $slip_id = $mobile_ids[$mobile_id_idx]; - $slip_nickname = $mobile_nicknames[$mobile_nickname_idx]; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - $ismobile = 1; - last; - } - if ($mobile_id_idx < 2 || $mobile_nickname_idx =~ /^(7|9|15)$/) { - $mobile_id_idx++; - } - $mobile_nickname_idx++; - } - - #公衆判定 - if ($ismobile == 0) { - my $fwifi_nickname_idx = 0; - for my $name (@fwifi_remoho) { - if ($remoho =~ /^${name}$/) { - $slip_id = $fwifi_id; - $slip_nickname = $fwifi_nicknames[$fwifi_nickname_idx]; - $slip_aa = $slip_id; - $slip_bb = $slip_ip; - last; - } - $fwifi_nickname_idx++; - } - } - - #社畜判定 - if ($ismobile == 0) { - if ($remoho =~ /^.+\.co\.jp$/) { - $slip_nickname = "シャチーク${fixed_nickname_end}"; - } - } - } - - #bbs_slipを生成 - my $slip_result = ''; - if($bbsslip eq 'vvv'){ - $slip_result = ${slip_nickname}; - } - elsif($bbsslip eq 'vvvv'){ - $slip_result = "${slip_nickname} [${ip_addr}]"; - } - elsif($bbsslip eq 'vvvvv'){ - $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc}"; - } - elsif($bbsslip eq 'vvvvvv'){ - $slip_result = "${slip_nickname} ${slip_aa}${slip_bb}-${slip_cccc} [${ip_addr}]"; } - return $slip_result; + # 匿名環境の場合は末尾が"8"になる + return $slip_nickname,$slip_aa,$slip_bb,$slip_cccc,$idEnd; } + #============================================================================================================ # モジュール終端 #============================================================================================================ diff --git a/test/module/system.pl b/test/module/system.pl index 702f67e..e92e819 100644 --- a/test/module/system.pl +++ b/test/module/system.pl @@ -255,7 +255,7 @@ sub InitSystemValue 'BBSPATH' => '..', # 掲示板設置パス 'SITENAME' => '', # サイトの名前 'DEBUG' => 0, # デバグモード - 'VERSION' => 'ex0ch BBS 0.9.1 20240313', # CGIバージョン + 'VERSION' => 'ex0ch BBS 0.9.2 20240503', # CGIバージョン 'PM-DAT' => 0644, # datパーミション 'PM-STOP' => 0444, # スレストパーミション 'PM-TXT' => 0644, # TXTパーミション @@ -297,16 +297,21 @@ sub InitSystemValue # DNSBL設定 'DNSBL_TOREXIT' => 0, # torexit.dan.me.uk - 'DNSBL_S5H' => 0, # all.s5h.net + 'DNSBL_S5H' => 0, # all.s5h.net 'DNSBL_DRONEBL' => 0, # dnsbl.dronebl.org 'SECURITY_KEY' => '', # セキュリティキー(初回起動時に自動設定されます) 'LAST_FLUSH' => '', # 定期的に動かす必要がある機能用 - 'CAPTCHA' => '', # キャプチャの種類 - 'CAPTCHA_SITEKEY' => '', # Captchaサイトキー + 'CAPTCHA' => '', # キャプチャの種類 + 'CAPTCHA_SITEKEY' => '', # Captchaサイトキー 'CAPTCHA_SECRETKEY' => '', # Captchaシークレットキー - 'PROXYCHECK_APIKEY' => '', # ProxyCheck.io APIキー + 'PROXYCHECK_APIKEY' => '', # ProxyCheck.io APIキー + + 'ADMINCAP' => '', + 'SEARCHCAP' => '', + + 'LASTMOD' => '', 'IMGTAG' => 0, # 画像リンクをIMGタグに変換 'CSP' => 0, diff --git a/test/read.cgi b/test/read.cgi index 32d76f3..37914a2 100755 --- a/test/read.cgi +++ b/test/read.cgi @@ -232,7 +232,6 @@ sub PrintReadHead HTML $Page->Print('') if ($Set->Get('BBS_TWITTER')); - $Page->Print('') if ($Set->Get('BBS_IMGUR')); if($Set->Get('BBS_CAPTCHA')){ $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'h-captcha'); $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'g-recaptcha'); @@ -616,7 +615,6 @@ sub PrintResponse my $aa=''; # URLと引用個所の適応 - $Conv->ConvertImgur(\$elem[3])if($Set->Get('BBS_IMGUR') eq 'checked'); $Conv->ConvertMovie(\$elem[3])if($Set->Get('BBS_MOVIE') eq 'checked'); $Conv->ConvertTweet(\$elem[3])if($Set->Get('BBS_TWITTER') eq 'checked'); $Conv->ConvertURL($Sys, $Set, 0, \$elem[3])if($Sys->Get('URLLINK') eq 'TRUE'); @@ -748,83 +746,6 @@ HTML } -#------------------------------------------------------------------------------------------------------------ -# -# read.cgi探索画面表示 -# ------------------------------------------------------------------------------------- -# @param $CGI -# @param $Page -# @return なし -# -#------------------------------------------------------------------------------------------------------------ -sub PrintReadSearch -{ - my ($CGI, $Page) = @_; - - return if (PrintDiscovery($CGI, $Page)); - - my $Sys = $CGI->{'SYS'}; - my $Set = $CGI->{'SET'}; - my $Conv = $CGI->{'CONV'}; - my $Dat = $CGI->{'DAT'}; - - my $nameCol = $Set->Get('BBS_NAME_COLOR'); - my $var = $Sys->Get('VERSION'); - my $cgipath = $Sys->Get('CGIPATH'); - my $bbs = $Sys->Get('BBS_ABS') . '/'; - my $server = $Sys->Get('SERVER'); - - # エラー用datの読み込み - $Dat->Load($Sys, $Conv->MakePath('.'.$Sys->Get('DATA').'/2000000000.dat'), 1); - my $size = $Dat->Size(); - - # 存在しないので404を返す。 - $Page->Print("Status: 404 Not Found\n"); - - PrintReadHead($CGI, $Page); - - $Page->Print("\n
\n"); - $Page->Print(" ■掲示板に戻る■\n"); - $Page->Print("
\n"); - - $Page->Print("
\n\n"); - $Page->Print("

指定されたスレッドは存在しません

\n\n"); - - $Page->Print("\n
\n"); - - for my $i (0 .. $size - 1) { - my $pDat = $Dat->Get($i); - my @elem = split(/<>/, $$pDat); - $Page->Print('
' . ($i + 1) . ' :'); - - # メール欄有り - if ($elem[1] eq '') { - $Page->Print("$elem[0]"); - } - # メール欄無し - else { - $Page->Print("$elem[0]"); - } - $Page->Print(":$elem[2]
\n
$elem[3]

\n"); - } - $Page->Print("
\n\n"); - - $Dat->Close(); - - $Page->Print("
\n\n"); - - $Page->Print(< -READ.CGI - $var
-EXぜろちゃんねる - - - - -HTML - -} - #------------------------------------------------------------------------------------------------------------ # # read.cgiエラー表示 diff --git a/test/search.cgi b/test/search.cgi index 4233564..980fce2 100755 --- a/test/search.cgi +++ b/test/search.cgi @@ -16,6 +16,8 @@ use open IO => ':encoding(cp932)'; use warnings; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); no warnings 'once'; +use JSON; +use LWP::UserAgent; BEGIN { use lib './perllib'; } @@ -32,7 +34,7 @@ exit(SearchCGI()); #------------------------------------------------------------------------------------------------------------ sub SearchCGI { - my ($Sys, $Page, $Form, $BBS); + my ($Sys, $Page, $Form, $BBS, $capt); require './module/system.pl'; require './module/buffer_output.pl'; @@ -46,10 +48,11 @@ sub SearchCGI $Form->DecodeForm(1); $Sys->Init(); $BBS->Load($Sys); + $capt = Certification_Captcha($Sys,$Form) if $Sys->Get('SEARCHCAP'); PrintHead($Sys, $Page, $BBS, $Form); # 検索ワードがある場合は検索を実行する - if ($Form->Get('WORD', '') ne '') { + if ($Form->Get('WORD', '') ne '' && !$capt) { Search($Sys, $Form, $Page, $BBS); } PrintFoot($Sys, $Page); @@ -110,7 +113,18 @@ sub PrintHead 検索@0chPlus +HTML + + if($Sys->Get('SEARCHCAP')){ + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'h-captcha'); + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'g-recaptcha'); + $Page->Print('') if ($Sys->Get('CAPTCHA') eq 'cf-turnstile'); + } + my $sitekey = $Sys->Get('CAPTCHA_SITEKEY'); + my $classname = $Sys->Get('CAPTCHA'); + my $Captcha = $Sys->Get('SEARCHCAP') ? "

" : ''; + $Page->Print(< @@ -202,6 +216,7 @@ HTML
+ $Captcha @@ -456,3 +471,61 @@ sub PrintSystemError HTML } + +#------------------------------------------------------------------------------------------------------------ +# +# 改造版で追加 +# Captchaの認証 +# ------------------------------------------------------------------------------------- +# @param なし +# @return 規制通過なら0を返す +# 規制チェックにかかったらエラーコードを返す +# +#------------------------------------------------------------------------------------------------------------ +sub Certification_Captcha { + my ($Sys,$Form) = @_; + my ($captcha_response,$url); + + my $captcha_kind = $Sys->Get('CAPTCHA'); + my $secretkey = $Sys->Get('CAPTCHA_SECRETKEY'); + if($captcha_kind eq 'h-captcha'){ + $captcha_response = $Form->Get('h-captcha-response'); + $url = 'https://api.hcaptcha.com/siteverify'; + }elsif($captcha_kind eq 'g-recaptcha'){ + $captcha_response = $Form->Get('g-recaptcha-response'); + $url = 'https://www.google.com/recaptcha/api/siteverify'; + }elsif($captcha_kind eq 'cf-turnstile'){ + $captcha_response = $Form->Get('cf-turnstile-response'); + $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; + }else{ + return 0; + } + + if($captcha_response){ + my $ua = LWP::UserAgent->new(); + my $response = $ua->post($url,{ + secret => $secretkey, + response => $captcha_response, + remoteip => $ENV{'REMOTE_ADDR'}, + }); + if ($response->is_success()) { + my $json_text = $response->decoded_content(); + + # JSON::decode_json関数でJSONテキストをPerlデータ構造に変換 + my $out = decode_json($json_text); + + if ($out->{success} eq 'true') { + return 0; + }else{ + return 1; + } + } else { + # Captchaを素通りする場合、HTTPS関連のエラーの疑いあり + # LWP::Protocol::httpsおよびNet::SSLeayが入っているか確認 + # このエラーの場合、スルー + return 0; + } + }else{ + return 1; + } +}