/** * アクセス情報をログに記録する */ public static function recAccessLog($logfile, $maxline = 100, $format = 'dataphp') { global $_conf, $_login; // ログファイルの中身を取得する if ($format == 'dataphp') { $lines = DataPhp::fileDataPhp($logfile); } else { $lines = FileCtl::file_read_lines($logfile); } if ($lines) { // 制限行調整 while (sizeof($lines) > $maxline - 1) { array_pop($lines); } } else { $lines = array(); } $lines = array_map('rtrim', $lines); // 変数設定 $date = date('Y/m/d (D) G:i:s'); // IPアドレスを取得 if (array_key_exists('HTTP_X_REAL_IP', $_SERVER)) { $remote_addr = $_SERVER["HTTP_X_REAL_IP"]; } else { $remote_addr = ''; } // HOSTを取得 if (array_key_exists('HTTP_X_REAL_IP', $_SERVER)) { $remote_host = gethostbyaddr($_SERVER['HTTP_X_REAL_IP']); } else { $remote_host = ''; } if (!$remote_host) { $remote_host = gethostbyaddr($_SERVER["HTTP_X_REAL_IP"]); } if ($remote_host == $_SERVER["HTTP_X_REAL_IP"]) { $remote_host = ''; } // UAを取得 if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) { $user_agent = $_SERVER['HTTP_USER_AGENT']; } else { $user_agent = ''; } // リファラを取得 if (array_key_exists('HTTP_REFERER', $_SERVER)) { $referrer = $_SERVER['HTTP_REFERER']; } else { $referrer = ''; } $user = isset($_login->user_u) ? $_login->user_u : ''; // 新しいログ行を設定 $newdata = implode('<>', array($date, $remote_addr, $remote_host, $user_agent, $referrer, '', $user)); //$newdata = htmlspecialchars($newdata, ENT_QUOTES); // まずタブを全て外して $newdata = str_replace("\t", "", $newdata); // <>をタブに変換して $newdata = str_replace("<>", "\t", $newdata); // 新しいデータを一番上に追加 @array_unshift($lines, $newdata); $cont = implode("\n", $lines) . "\n"; FileCtl::make_datafile($logfile, $_conf['p2_perm']); // 書き込み処理 if ($format == 'dataphp') { DataPhp::writeDataPhp($logfile, $cont, $_conf['p2_perm']); } else { FileCtl::file_write_contents($logfile, $cont); } return true; }
/** * アクセス(ログイン)情報をログに記録する * * @access public * @return boolean */ function recAccessLog($logfile, $maxline = 100, $format = 'dataphp') { global $_conf, $_login; // ログファイルの中身を取得する $lines = array(); if (file_exists($logfile)) { if ($format == 'dataphp') { $lines = DataPhp::fileDataPhp($logfile); } else { $lines = file($logfile); } } if ($lines) { // 制限行調整 while (sizeof($lines) > $maxline - 1) { array_pop($lines); } } else { $lines = array(); } $lines = array_map('rtrim', $lines); // 変数設定 $date = date('Y/m/d (D) G:i:s'); $user = isset($_login->user_u) ? $_login->user_u : ""; // 新しいログ行を設定 $newdata = implode('<>', array($date, $_SERVER['REMOTE_ADDR'], P2Util::getRemoteHost(), geti($_SERVER['HTTP_USER_AGENT']), geti($_SERVER['HTTP_REFERER']), '', $user)); //$newdata = htmlspecialchars($newdata, ENT_QUOTES); // まずタブを全て外して $newdata = str_replace("\t", "", $newdata); // <>をタブに変換して $newdata = str_replace("<>", "\t", $newdata); // 新しいデータを一番上に追加 @array_unshift($lines, $newdata); $cont = implode("\n", $lines) . "\n"; FileCtl::make_datafile($logfile, $_conf['p2_perm']); // 書き込み処理 if ($format == 'dataphp') { if (!DataPhp::writeDataPhp($logfile, $cont, $_conf['p2_perm'])) { return false; } } else { if (false === file_put_contents($logfile, $cont, LOCK_EX)) { trigger_error("file_put_contents(" . $logfile . ")", E_USER_WARNING); return false; } } return true; }
/** * レスを書き込む or 新規スレッドを立てる * スレ立ての場合は、$key は空 '' でよい * * @return boolean|string 書き込み成功なら true、失敗なら false または失敗理由文字列 */ function _postIt($host, $bbs, $key, $post, $bbs_cgi) { global $_conf, $popup, $rescount, $ttitle_en, $STYLE, $post_cache; list($request, $send_host, $send_port) = _buildRequestForPost($host, $bbs, $key, $post, $bbs_cgi); $maru_kakiko = empty($_POST['maru_kakiko']) ? 0 : 1; P2Util::setConfUser('maru_kakiko', $maru_kakiko); // 書き込みを一時的に保存 $failed_post_file = P2Util::getFailedPostFilePath($host, $bbs, $key); $cont = serialize($post_cache); if (!DataPhp::writeDataPhp($failed_post_file, $cont, $_conf['res_write_perm'])) { p2die('ファイルの書き込みエラー'); } // p2 sambaのチェック if ($p2SambaErrorMsgHtml = _getP2SambaErrorMsgHtml($host, $bbs)) { _showPostMsg(false, $p2SambaErrorMsgHtml, false); return false; } // WEBサーバへ接続 $fp = fsockopen($send_host, $send_port, $errno, $errstr, $_conf['fsockopen_time_limit']); if (!$fp) { _showPostMsg(false, "サーバ接続エラー: {$errstr} ({$errno})<br>p2 Error: 板サーバへの接続に失敗しました", false); return false; } // HTTPリクエスト送信 fwrite($fp, $request, strlen($request)); $post_seikou = false; $p2cookies = _readCookieFile(_cachePathForCookieByHost($host)); // header while (!feof($fp)) { $l = fgets($fp, 8192); // クッキーキタ if (preg_match("/Set-Cookie: (.+?)\r\n/", $l, $matches)) { $cgroups = explode(";", $matches[1]); if ($cgroups) { foreach ($cgroups as $v) { if (preg_match("/(.+)=(.*)/", $v, $m)) { $k = ltrim($m[1]); if ($k != 'path') { $p2cookies[$k] = $m[2]; } } } } // 転送は書き込み成功と判断 } elseif (preg_match("/^Location: /", $l, $matches)) { $post_seikou = true; } if ($l == "\r\n") { break; } } // クッキーをファイルに保存する _saveCookieFile($p2cookies, _cachePathForCookieByHost($host)); // body $response = ''; while (!feof($fp)) { $response .= fread($fp, 164000); } fclose($fp); // be.2ch.net or JBBSしたらば 文字コード変換 EUC→SJIS if (P2Util::isHostBe2chNet($host) || P2Util::isHostJbbsShitaraba($host)) { $response = mb_convert_encoding($response, 'SJIS-win', 'eucJP-win'); //<META http-equiv="Content-Type" content="text/html; charset=EUC-JP"> $response = preg_replace("{(<head>.*<META http-equiv=\"Content-Type\" content=\"text/html; charset=)EUC-JP(\">.*</head>)}is", "\$1Shift_JIS\$2", $response); } $kakikonda_match = "/<title>.*(書きこみました|■ 書き込みました ■|書き込み終了 - SubAll BBS).*<\\/title>/is"; $cookie_kakunin_match = "/<!-- 2ch_X:cookie -->|<title>■ 書き込み確認 ■<\\/title>|>書き込み確認。</"; if (eregi("(<.+>)", $response, $matches)) { $response = $matches[1]; } // カキコミ成功 if (preg_match($kakikonda_match, $response, $matches) or $post_seikou) { // クッキーの書き込み自動保存を消去する if (isset($_COOKIE['post_msg'])) { P2Util::unsetCookie('post_msg'); // ドメイン指定なしも入れておこ setcookie('post_msg', '', time() - 3600); } $reload = empty($_POST['from_read_new']); _showPostMsg(true, '書きこみが終わりました。', $reload); // 投稿失敗記録があれば削除する if (file_exists($failed_post_file)) { unlink($failed_post_file); } return true; //$response_ht = htmlspecialchars($response, ENT_QUOTES); //echo "<pre>{$response_ht}</pre>"; // ■cookie確認表示(post再チャレンジしてね) } elseif (preg_match($cookie_kakunin_match, $response, $matches)) { $htm['more_hidden_post'] = ''; // p2用の追加キー $more_hidden_keys = array('newthread', 'submit_beres', 'from_read_new', 'maru_kakiko', 'csrfid', 'k', UA::getQueryKey()); foreach ($more_hidden_keys as $hk) { if (isset($_POST[$hk])) { $htm['more_hidden_post'] .= sprintf('<input type="hidden" name="%s" value="%s">', hs($hk), hs($_POST[$hk])) . "\n"; } } $form_pattern = '/<form method="?POST"? action="?\\.\\.\\/test\\/(sub)?bbs\\.cgi(?:\\?guid=ON)?"?>/i'; $myname = basename($_SERVER['SCRIPT_NAME']); $host_hs = hs($host); $popup_hs = hs($popup); $rescount_hs = hs($rescount); $ttitle_en_hs = hs($ttitle_en); $form_replace = <<<EOFORM <form method="POST" action="{$myname}?guid=ON" accept-charset="{$_conf['accept_charset']}"> <input type="hidden" name="detect_hint" value="◎◇"> <input type="hidden" name="host" value="{$host_hs}"> <input type="hidden" name="popup" value="{$popup_hs}"> <input type="hidden" name="rescount" value="{$rescount_hs}"> <input type="hidden" name="ttitle_en" value="{$ttitle_en_hs}"> <input type="hidden" name="sub" value="\$1"> {$htm['more_hidden_post']} EOFORM; $response = preg_replace($form_pattern, $form_replace, $response); $h_b = explode("</head>", $response); // HTMLプリント echo $h_b[0]; if (!$_conf['ktai']) { P2View::printIncludeCssHtml('style'); P2View::printIncludeCssHtml('post'); } if ($popup) { $mado_okisa = explode(',', $STYLE['post_pop_size']); $mado_okisa_x = $mado_okisa[0]; $mado_okisa_y = $mado_okisa[1] + 200; echo <<<EOSCRIPT <script language="JavaScript"> <!-- resizeTo({$mado_okisa_x},{$mado_okisa_y}); // --> </script> EOSCRIPT; } echo "</head>"; echo $h_b[1]; //return false; return 'COOKIE'; // その他はレスポンスをそのまま表示(結果はエラーとしてfalseを返す) } else { $response = ereg_replace('こちらでリロードしてください。<a href="\\.\\./[a-z]+/index\\.html"> GO! </a><br>', "", $response); echo $response; return false; } }
/** * レスを書き込む or 新規スレッドを立てる * スレ立ての場合は、$key は空 '' でよい * * @return boolean 書き込み成功なら true、失敗なら false */ function postIt($host, $bbs, $key, $post) { global $_conf, $post_result, $post_error2ch, $popup, $rescount, $ttitle_en, $STYLE; global $bbs_cgi, $post_cache; $method = "POST"; $bbs_cgi_url = "http://" . $host . $bbs_cgi; $purl = parse_url($bbs_cgi_url); if (isset($purl['query'])) { $purl['query'] = "?" . $purl['query']; } else { $purl['query'] = ""; } // プロキシ if ($_conf['proxy_use']) { $send_host = $_conf['proxy_host']; $send_port = $_conf['proxy_port']; $send_path = $bbs_cgi_url; } else { $send_host = $purl['host']; $send_port = $purl['port']; $send_port = isset($purl['port']) ? $purl['port'] : null; $send_path = $purl['path'] . $purl['query']; } !$send_port and $send_port = 80; $request = $method . " " . $send_path . " HTTP/1.0" . "\r\n"; $request .= "Host: " . $purl['host'] . "\r\n"; $remote_host = P2Util::getRemoteHost($_SERVER['REMOTE_ADDR']); $add_user_info = ''; //$add_user_info = "; p2-client-ip: {$_SERVER['REMOTE_ADDR']}"; //$add_user_info .= "; p2-client-host: {$remote_host}"; $request .= "User-Agent: Monazilla/1.00 (" . $_conf['p2name'] . "/" . $_conf['p2version'] . "{$add_user_info})" . "\r\n"; $request .= 'Referer: http://' . $purl['host'] . '/' . "\r\n"; // クライアントのIPを送信するp2独自のヘッダ $request .= "X-P2-Client-IP: " . $_SERVER['REMOTE_ADDR'] . "\r\n"; $request .= "X-P2-Client-Host: " . $remote_host . "\r\n"; // クッキー $cookies_to_send = ""; // クッキーの読み込み $cookie_file = cachePathForCookie($host); $p2cookies = readCookieFile($cookie_file); if ($p2cookies) { foreach ($p2cookies as $cname => $cvalue) { if ($cname != 'expires') { $cookies_to_send .= " {$cname}={$cvalue};"; } } } // be.2ch 認証クッキー // be板では自動Be書き込みを試みる if (P2Util::isBbsBe2chNet($host, $bbs) || !empty($_REQUEST['submit_beres'])) { $cookies_to_send .= ' MDMD=' . $_conf['be_2ch_code'] . ';'; // be.2ch.netの認証コード(パスワードではない) $cookies_to_send .= ' DMDM=' . $_conf['be_2ch_mail'] . ';'; // be.2ch.netの登録メールアドレス } !$cookies_to_send and $cookies_to_send = ' ;'; $request .= 'Cookie:' . $cookies_to_send . "\r\n"; //$request .= 'Cookie: PON='.$SPID.'; NAME='.$FROM.'; MAIL='.$mail."\r\n"; $request .= "Connection: Close\r\n"; // {{{ POSTの時はヘッダを追加して末尾にURLエンコードしたデータを添付 if (strtoupper($method) == "POST") { $post_enc = array(); while (list($name, $value) = each($post)) { if (!isset($value)) { continue; } // したらば or be.2ch.netなら、EUCに変換 if (P2Util::isHostJbbsShitaraba($host) || P2Util::isHostBe2chNet($host)) { $value = mb_convert_encoding($value, 'eucJP-win', 'SJIS-win'); } $post_enc[] = $name . "=" . urlencode($value); } $postdata = implode("&", $post_enc); $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: " . strlen($postdata) . "\r\n"; $request .= "\r\n"; $request .= $postdata; } else { $request .= "\r\n"; } // }}} $maru_kakiko = empty($_POST['maru_kakiko']) ? 0 : 1; setConfUser('maru_kakiko', $maru_kakiko); // 書き込みを一時的に保存 $failed_post_file = P2Util::getFailedPostFilePath($host, $bbs, $key); $cont = serialize($post_cache); DataPhp::writeDataPhp($failed_post_file, $cont, $_conf['res_write_perm']); // WEBサーバへ接続 $fp = fsockopen($send_host, $send_port, $errno, $errstr, $_conf['fsockopen_time_limit']); if (!$fp) { showPostMsg(false, "サーバ接続エラー: {$errstr} ({$errno})<br>p2 Error: 板サーバへの接続に失敗しました", false); return false; } // HTTPリクエスト送信 fputs($fp, $request); $post_seikou = false; // header while (!feof($fp)) { $l = fgets($fp, 8192); // クッキーキタ if (preg_match("/Set-Cookie: (.+?)\r\n/", $l, $matches)) { //echo "<p>".$matches[0]."</p>"; // $cgroups = explode(";", $matches[1]); if ($cgroups) { foreach ($cgroups as $v) { if (preg_match("/(.+)=(.*)/", $v, $m)) { $k = ltrim($m[1]); if ($k != "path") { $p2cookies[$k] = $m[2]; } } } } if ($p2cookies) { $cookies_to_send = ''; foreach ($p2cookies as $cname => $cvalue) { if ($cname != "expires") { $cookies_to_send .= " {$cname}={$cvalue};"; } } $newcokkies = "Cookie:{$cookies_to_send}\r\n"; $request = preg_replace("/Cookie: .*?\r\n/", $newcokkies, $request); } // 転送は書き込み成功と判断 } elseif (preg_match("/^Location: /", $l, $matches)) { $post_seikou = true; } if ($l == "\r\n") { break; } } // クッキーをファイルに保存する saveCookieFile($p2cookies, $cookie_file); // body $response = ''; while (!feof($fp)) { $response .= fread($fp, 164000); } fclose($fp); // be.2ch.net or JBBSしたらば 文字コード変換 EUC→SJIS if (P2Util::isHostBe2chNet($host) || P2Util::isHostJbbsShitaraba($host)) { $response = mb_convert_encoding($response, 'SJIS-win', 'eucJP-win'); //<META http-equiv="Content-Type" content="text/html; charset=EUC-JP"> $response = preg_replace("{(<head>.*<META http-equiv=\"Content-Type\" content=\"text/html; charset=)EUC-JP(\">.*</head>)}is", "\$1Shift_JIS\$2", $response); } $kakikonda_match = "/<title>.*(書きこみました|■ 書き込みました ■|書き込み終了 - SubAll BBS).*<\\/title>/is"; $cookie_kakunin_match = "/<!-- 2ch_X:cookie -->|<title>■ 書き込み確認 ■<\\/title>|>書き込み確認。</"; if (eregi("(<.+>)", $response, $matches)) { $response = $matches[1]; } // カキコミ成功 if (preg_match($kakikonda_match, $response, $matches) or $post_seikou) { // クッキーの書き込み自動保存を消去する isset($_COOKIE['post_msg']) and setcookie('post_msg', '', time() - 3600); $reload = empty($_POST['from_read_new']); showPostMsg(true, '書きこみが終わりました。', $reload); // 投稿失敗記録があれば削除する if (file_exists($failed_post_file)) { unlink($failed_post_file); } return true; //$response_ht = htmlspecialchars($response, ENT_QUOTES); //echo "<pre>{$response_ht}</pre>"; // ■cookie確認(post再チャレンジ) } elseif (preg_match($cookie_kakunin_match, $response, $matches)) { $htm['more_hidden_post'] = ''; $more_hidden_keys = array('newthread', 'submit_beres', 'from_read_new', 'maru_kakiko', 'csrfid', 'k', 'b'); foreach ($more_hidden_keys as $hk) { if (isset($_POST[$hk])) { $value_hd = htmlspecialchars($_POST[$hk], ENT_QUOTES); $htm['more_hidden_post'] .= "<input type=\"hidden\" name=\"{$hk}\" value=\"{$value_hd}\">\n"; } } $form_pattern = '/<form method=\\"?POST\\"? action=\\"?\\.\\.\\/test\\/(sub)?bbs\\.cgi(?:\\?guid=ON)?\\"?>/i'; $myname = basename($_SERVER['SCRIPT_NAME']); $form_replace = <<<EOFORM <form method="POST" action="{$myname}" accept-charset="{$_conf['accept_charset']}"> <input type="hidden" name="detect_hint" value="◎◇"> <input type="hidden" name="host" value="{$host}"> <input type="hidden" name="popup" value="{$popup}"> <input type="hidden" name="rescount" value="{$rescount}"> <input type="hidden" name="ttitle_en" value="{$ttitle_en}"> <input type="hidden" name="sub" value="\$1"> {$htm['more_hidden_post']} EOFORM; $response = preg_replace($form_pattern, $form_replace, $response); $h_b = explode("</head>", $response); // HTMLプリント echo $h_b[0]; if (!$_conf['ktai']) { include_once './style/style_css.inc'; include_once './style/post_css.inc'; } if ($popup) { $mado_okisa = explode(',', $STYLE['post_pop_size']); $mado_okisa_x = $mado_okisa[0]; $mado_okisa_y = $mado_okisa[1] + 200; echo <<<EOSCRIPT <script language="JavaScript"> <!-- resizeTo({$mado_okisa_x},{$mado_okisa_y}); // --> </script> EOSCRIPT; } echo "</head>"; echo $h_b[1]; return false; // その他はレスポンスをそのまま表示(結果はエラーとしてfalseを返す) } else { $response = ereg_replace('こちらでリロードしてください。<a href="\\.\\./[a-z]+/index\\.html"> GO! </a><br>', "", $response); echo $response; return false; } }