/** * DATをダウンロードする */ public function downloadDat() { global $_conf; // まちBBS if (P2Util::isHostMachiBbs($this->host)) { DownloadDatMachiBbs::invoke($this); // JBBS@したらば } elseif (P2Util::isHostJbbsShitaraba($this->host)) { if (!function_exists('shitarabaDownload')) { include P2_LIB_DIR . '/read_shitaraba.inc.php'; } shitarabaDownload($this); // 2ch系 } else { $this->getDatBytesFromLocalDat(); // $aThread->length をset // 2ch bbspink●読み if (P2Util::isHost2chs($this->host) && !empty($_GET['maru'])) { // ログインしてなければ or ログイン後、24時間以上経過していたら自動再ログイン if (!file_exists($_conf['sid2ch_php']) || !empty($_REQUEST['relogin2ch']) || filemtime($_conf['sid2ch_php']) < time() - 60 * 60 * 24) { if (!function_exists('login2ch')) { include P2_LIB_DIR . '/login2ch.inc.php'; } if (!login2ch()) { $this->getdat_error_msg_ht .= $this->get2chDatError(); $this->diedat = true; return false; } } include $_conf['sid2ch_php']; $this->_downloadDat2chMaru($uaMona, $SID2ch); // 2ch bbspink モリタポ読み } elseif (P2Util::isHost2chs($this->host) && !empty($_GET['moritapodat']) && $_conf['p2_2ch_mail'] && $_conf['p2_2ch_pass']) { if (!array_key_exists('csrfid', $_GET) || $this->_getCsrfIdForMoritapoDat() != $_GET['csrfid']) { p2die('不正なリクエストです'); } $this->_downloadDat2chMoritapo(); // 2chの過去ログ倉庫読み } elseif (!empty($_GET['kakolog']) && !empty($_GET['kakoget'])) { if ($_GET['kakoget'] == 1) { $ext = '.dat.gz'; } elseif ($_GET['kakoget'] == 2) { $ext = '.dat'; } $this->_downloadDat2chKako($_GET['kakolog'], $ext); // 2ch or 2ch互換 } else { // DATを差分DLする $this->_downloadDat2ch($this->length); } } }
/** * DATをダウンロード保存する * * @access public * @return boolean */ function downloadDat() { global $_conf; // まちBBS if (P2Util::isHostMachiBbs($this->host)) { require_once P2_LIB_DIR . '/downloadDatMachiBbs.func.php'; downloadDatMachiBbs($this); // JBBS@したらば } elseif (P2Util::isHostJbbsShitaraba($this->host)) { require_once P2_LIB_DIR . '/downloadDatShitaraba.func.php'; downloadDatShitaraba($this); /* // cha2.net(→2ch互換として扱ってみる) } elseif (P2Util::isHostCha2($this->host)) { require_once P2_LIB_DIR . '/downloadDatCha2.func.php'; downloadDatCha2($this); */ // 2ch系 } else { $this->getDatBytesFromLocalDat(); // $aThread->length をset // 2ch bbspink●読み if (P2Util::isHost2chs($this->host) && !empty($_GET['maru'])) { // ログインしてなければ or ログイン後、24時間以上経過していたら自動再ログイン if (!file_exists($_conf['sid2ch_php']) || !empty($_REQUEST['relogin2ch']) or filemtime($_conf['sid2ch_php']) < time() - 60 * 60 * 24) { require_once P2_LIB_DIR . '/login2ch.func.php'; if (!login2ch()) { $this->pushDownloadDatErrorMsgHtml($this->get2chDatError()); $this->diedat = true; return false; } } $this->downloadDat2chMaru(); // 2chの過去ログ倉庫読み } elseif (!empty($_GET['kakolog']) && !empty($_GET['kakoget'])) { if ($_GET['kakoget'] == 1) { $ext = '.dat.gz'; } elseif ($_GET['kakoget'] == 2) { $ext = '.dat'; } $this->downloadDat2chKako($_GET['kakolog'], $ext); // 2ch or 2ch互換 } else { // DATを差分DLする $this->downloadDat2ch($this->length); } } return true; }
/** * 元スレURLを返す * * @access public * @param boolean $original 携帯でも2chのスレURLを返す * @return string URL */ function getMotoThread($original = false) { global $_conf; // 携帯カスタマイズ指定 if ($_conf['ktai'] && !$original && $_conf['k_motothre_external']) { $motothre_url = $this->compileMobile2chUri(); // まちBBS } elseif (P2Util::isHostMachiBbs($this->host)) { // PC if (!$_conf['ktai'] || $original) { /* $motothre_url = sprintf( 'http://%s/bbs/read.cgi?BBS=%s&KEY=%s', $this->host, rawurlencode($this->bbs), rawurlencode($this->key) ); */ $motothre_url = "http://{$this->host}/bbs/read.cgi/{$this->bbs}/{$this->key}/{$this->ls}"; // 携帯 } else { $motothre_url = sprintf('http://%s/bbs/read.cgi?IMODE=TRUE&BBS=%s&KEY=%s', $this->host, rawurlencode($this->bbs), rawurlencode($this->key)); } // まちびねっと } elseif (P2Util::isHostMachiBbsNet($this->host)) { $motothre_url = sprintf('http://%s/test/read.cgi?bbs=%s&key=%s', $this->host, rawurlencode($this->bbs), rawurlencode($this->key)); // JBBSしたらば } elseif (P2Util::isHostJbbsShitaraba($this->host)) { $preg = '{(jbbs\\.shitaraba\\.com|jbbs\\.livedoor\\.com|jbbs\\.livedoor\\.jp)}'; $host_bbs_cgi = preg_replace($preg, '$1/bbs/read.cgi', $this->host); $motothre_url = "http://{$host_bbs_cgi}/{$this->bbs}/{$this->key}/{$this->ls}"; // $motothre_url = "http://{$this->host}/bbs/read.cgi?BBS={$this->bbs}&KEY={$this->key}"; // 2ch系 } elseif (P2Util::isHost2chs($this->host)) { // PC if (!UA::isK() || UA::isIPhoneGroup() || $original) { $motothre_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/{$this->ls}"; // 携帯 } else { // BBS PINK if (P2Util::isHostBbsPink($this->host)) { // r.iはもう使われていない //$motothre_url = "http://{$this->host}/test/r.i/{$this->bbs}/{$this->key}/{$this->ls}"; $motothre_url = "http://speedo.ula.cc/test/r.so/{$this->host}/{$this->bbs}/{$this->key}/{$this->ls}?guid=ON"; // 2ch(c.2ch) } else { $motothre_url = $this->compileMobile2chUri(); } } // その他 } else { $motothre_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/{$this->ls}"; } return $motothre_url; }
} // sbject ツールバー ===================================== include P2_LIB_DIR . '/sb_toolbar.inc.php'; if ($have_sb_footer_links) { echo "<p>"; echo $dat_soko_ht; echo $taborn_link_ht; echo $taborn_now_ht; echo $buildnewthread_ht; echo $import_dat_ht; echo "</p>"; } // スペシャルモードでなければフォーム入力補完======================== $ini_url_text = ''; if (!$aThreadList->spmode) { if (P2Util::isHostJbbsShitaraba($aThreadList->host)) { // したらば $ini_url_text = "http://{$aThreadList->host}/bbs/read.cgi?BBS={$aThreadList->bbs}&KEY="; } elseif (P2Util::isHostMachiBbs($aThreadList->host)) { // まちBBS $ini_url_text = "http://{$aThreadList->host}/bbs/read.pl?BBS={$aThreadList->bbs}&KEY="; } elseif (P2Util::isHostMachiBbsNet($aThreadList->host)) { // まちビねっと $ini_url_text = "http://{$aThreadList->host}/test/read.cgi?bbs={$aThreadList->bbs}&key="; } else { $ini_url_text = "http://{$aThreadList->host}/test/read.cgi/{$aThreadList->bbs}/"; } } //if(!$aThreadList->spmode || $aThreadList->spmode=="fav" || $aThreadList->spmode=="recent" || $aThreadList->spmode=="res_hist"){ $onclick_ht = <<<EOP var url_v=document.forms["urlform"].elements["url_text"].value;
/** * subject.txtを一括ダウンロード&保存する * * @param array|string $subjects * @param bool $force * @return void */ public static function fetchSubjectTxt($subjects, $force = false) { global $_conf; // {{{ ダウンロード対象を設定 // お気に板等の.idx形式のファイルをパース if (is_string($subjects)) { $lines = FileCtl::file_read_lines($subjects, FILE_IGNORE_NEW_LINES); if (!$lines) { return; } $subjects = array(); foreach ($lines as $l) { $la = explode('<>', $l); if (count($la) < 12) { continue; } $host = $la[10]; $bbs = $la[11]; if ($host === '' || $bbs === '') { continue; } $id = $host . '<>' . $bbs; if (isset($subjects[$id])) { continue; } $subjects[$id] = array($host, $bbs); } // [host, bbs] の連想配列を検証 } elseif (is_array($subjects)) { $originals = $subjects; $subjects = array(); foreach ($originals as $s) { if (!is_array($s) || !isset($s['host']) || !isset($s['bbs'])) { continue; } $id = $s['host'] . '<>' . $s['bbs']; if (isset($subjects[$id])) { continue; } $subjects[$id] = array($s['host'], $s['bbs']); } // 上記以外 } else { return; } if (!count($subjects)) { return; } // }}} // {{{ キューをセットアップ // キューおよびその他の変数を初期化 $queue = new P2HttpRequestQueue(); $hosts = array(); $time = time() - $_conf['sb_dl_interval']; $eucjp2sjis = null; // 各subject.txtへのリクエストをキューに追加 foreach ($subjects as $subject) { list($host, $bbs) = $subject; $file = P2Util::datDirOfHostBbs($host, $bbs) . 'subject.txt'; if (!$force && file_exists($file) && filemtime($file) > $time) { continue; } $url = 'http://' . $host . '/' . $bbs . '/subject.txt'; if (P2Util::isHostJbbsShitaraba($host) || P2Util::isHostBe2chNet($host)) { if ($eucjp2sjis === null) { $eucjp2sjis = new P2HttpCallback_SaveEucjpAsSjis(); } $req = new P2HttpGet($url, $file, null, $eucjp2sjis); } else { $req = new P2HttpGet($url, $file); } // 同一ホストに対しての同時接続は MAX_REQUESTS_PER_HOST まで if (!isset($hosts[$host])) { $hosts[$host] = new P2HttpRequestQueue(); $queue->push($req); } elseif (count($hosts[$host]) < self::MAX_REQUESTS_PER_HOST) { $queue->push($req); } else { $hosts[$host]->pop()->setNext($req); } $hosts[$host]->push($req); } // }}} // リクエストを送信 if (count($queue)) { self::send(new HttpRequestPool(), $queue); clearstatcache(); } }
/** * 元スレURLを返す * * @param bool $force_pc trueなら携帯モードでもPC用の元スレURLを返す * @param string $ls レス表示番号or範囲。nullならlsプロパティを使う * 掲示板によっては無視される場合もある * @return string 元スレURL */ public function getMotoThread($force_pc = false, $ls = null) { global $_conf; if ($force_pc) { $mobile = false; } elseif ($_conf['iphone']) { $mobile = false; } elseif ($_conf['ktai']) { $mobile = true; } else { $mobile = false; } if ($ls === null) { $ls = $this->ls; } // 2ch系 if (P2Util::isHost2chs($this->host)) { // PC if (!$mobile) { $motothre_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/{$ls}"; // 携帯 } else { if (P2Util::isHostBbsPink($this->host)) { //$motothre_url = "http://{$this->host}/test/r.i/{$this->bbs}/{$this->key}/{$ls}"; $motothre_url = "http://speedo.ula.cc/test/r.so/{$this->host}/{$this->bbs}/{$this->key}/{$ls}"; } else { $mail = rawurlencode($_conf['my_mail']); // c.2chはl指定に非対応なので、代わりにn $ls = substr($ls, 0, 1) == 'l' ? 'n' : $ls; $motothre_url = "http://c.2ch.net/test/--3!mail={$mail}/{$this->bbs}/{$this->key}/{$ls}"; } } // まちBBS } elseif (P2Util::isHostMachiBbs($this->host)) { if ($mobile) { $motothre_url = "http://{$this->host}/bbs/read.pl?IMODE=TRUE&BBS={$this->bbs}&KEY={$this->key}"; } else { $motothre_url = "http://{$this->host}/bbs/read.cgi/{$this->bbs}/{$this->key}/{$ls}"; } // まちびねっと } elseif (P2Util::isHostMachiBbsNet($this->host)) { $motothre_url = "http://{$this->host}/test/read.cgi?bbs={$this->bbs}&key={$this->key}"; if ($mobile) { $motothre_url .= '&imode=true'; } // JBBSしたらば } elseif (P2Util::isHostJbbsShitaraba($this->host)) { list($host, $category) = explode('/', P2Util::adjustHostJbbs($this->host), 2); $bbs_cgi = $mobile ? 'i.cgi' : 'read.cgi'; $motothre_url = "http://{$host}/bbs/{$bbs_cgi}/{$category}/{$this->bbs}/{$this->key}/{$ls}"; // その他 } else { $motothre_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/{$ls}"; } return $motothre_url; }
/** * SETTING.TXT をダウンロードして、パースして、キャッシュする * * @return boolean 実行成否 */ public function downloadSettingTxt() { global $_conf; // まちBBS・したらば は SETTING.TXT が存在しないものとする if (P2Util::isHostMachiBbs($this->_host) || P2Util::isHostJbbsShitaraba($this->_host)) { return false; } FileCtl::mkdirFor($this->_setting_txt); // 板ディレクトリが無ければ作る if (file_exists($this->_setting_srd) && file_exists($this->_setting_txt)) { // 更新しない場合は、その場で抜けてしまう if (!empty($_GET['norefresh']) || isset($_REQUEST['word'])) { return true; // キャッシュが新しい場合も抜ける } elseif ($this->isCacheFresh()) { return true; } $modified = http_date(filemtime($this->_setting_txt)); } else { $modified = false; } // DL $params = array(); $params['timeout'] = $_conf['http_conn_timeout']; $params['readTimeout'] = array($_conf['http_read_timeout'], 0); if ($_conf['proxy_use']) { $params['proxy_host'] = $_conf['proxy_host']; $params['proxy_port'] = $_conf['proxy_port']; } $req = new HTTP_Request($this->_url, $params); $modified && $req->addHeader('If-Modified-Since', $modified); $req->addHeader('User-Agent', "Monazilla/1.00 ({$_conf['p2ua']})"); $response = $req->sendRequest(); if (PEAR::isError($response)) { $error_msg = $response->getMessage(); } else { $code = $req->getResponseCode(); if ($code == 302) { // ホストの移転を追跡 $new_host = BbsMap::getCurrentHost($this->_host, $this->_bbs); if ($new_host != $this->_host) { $aNewSettingTxt = new SettingTxt($new_host, $this->_bbs); $body = $aNewSettingTxt->downloadSettingTxt(); return true; } } if (!($code == 200 || $code == 206 || $code == 304)) { //var_dump($req->getResponseHeader()); $error_msg = $code; } } // DLエラー if (isset($error_msg) && strlen($error_msg) > 0) { $url_t = P2Util::throughIme($this->_url); $info_msg_ht = "<p class=\"info-msg\">Error: {$error_msg}<br>"; $info_msg_ht .= "rep2 info: <a href=\"{$url_t}\"{$_conf['ext_win_target_at']}>{$this->_url}</a> に接続できませんでした。</p>"; P2Util::pushInfoHtml($info_msg_ht); touch($this->_setting_txt); // DL失敗した場合も touch return false; } $body = $req->getResponseBody(); // DL成功して かつ 更新されていたら保存 if ($body && $code != '304') { // したらば or be.2ch.net ならEUCをSJISに変換 if (P2Util::isHostJbbsShitaraba($this->_host) || P2Util::isHostBe2chNet($this->_host)) { $body = mb_convert_encoding($body, 'CP932', 'CP51932'); } if (FileCtl::file_write_contents($this->_setting_txt, $body) === false) { p2die('cannot write file'); } // パースしてキャッシュを保存する if (!$this->cacheParsedSettingTxt()) { return false; } } else { // touchすることで更新インターバルが効くので、しばらく再チェックされなくなる touch($this->_setting_txt); // 同時にキャッシュもtouchしないと、_setting_txtと_setting_srdで更新時間がずれ、 // 毎回ここまで処理が来る(サーバへのヘッダリクエストが飛ぶ)場合がある。 touch($this->_setting_srd); } return true; }
/** * subject.txt を読み込み、セットし、調整する * 成功すれば、$this->subject_lines がセットされる * * @access private * @param string $lines eaccelerator, apc用 * @return boolean 実行成否 */ function loadSubjectLines($lines = null) { if (!$lines) { if ($this->storage == 'eaccelerator') { $this->subject_lines = eaccelerator_get("{$this->host}/{$this->bbs}"); } elseif ($this->storage == 'apc') { $this->subject_lines = apc_fetch("{$this->host}/{$this->bbs}"); } elseif ($this->storage == 'file') { $this->subject_lines = file($this->subject_file); } else { return false; } } else { $this->subject_lines = $lines; } // JBBS@したらばなら重複スレタイを削除する if (P2Util::isHostJbbsShitaraba($this->host)) { $this->subject_lines = array_unique($this->subject_lines); } return $this->subject_lines ? true : false; }
/** * host が 信頼できる掲示板サイトなら true を返す * * @access public * @return boolean */ function isTrustedHost($host) { return P2Util::isHost2chs($host) || P2Util::isHostBbsPink($host) || P2Util::isHostMachiBbs($host) || P2Util::isHostJbbsShitaraba($host); }
/** * レスを書き込む 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; } }
/** * subject.txt を読み込む * * 成功すれば、$this->subject_lines がセットされる * * @param string $cont これは eashm 用に渡している。 * @return boolean 実行成否 */ public function setSubjectLines($cont = '') { $this->subject_lines = FileCtl::file_read_lines($this->subject_file); // JBBS@したらばなら重複スレタイを削除する if (P2Util::isHostJbbsShitaraba($this->host)) { $this->subject_lines = array_unique($this->subject_lines); } if ($this->subject_lines) { return true; } else { return false; } }
/** * レスを書き込む * * @return boolean 書き込み成功なら true、失敗なら false */ function postIt($host, $bbs, $key, $post) { global $_conf, $post_result, $post_error2ch, $p2cookies, $popup, $rescount, $ttitle_en; global $bbs_cgi; $method = 'POST'; $bbs_cgi_url = 'http://' . $host . $bbs_cgi; $URL = parse_url($bbs_cgi_url); // URL分解 if (isset($URL['query'])) { // クエリー $URL['query'] = '?' . $URL['query']; } else { $URL['query'] = ''; } // プロキシ if ($_conf['proxy_use']) { $send_host = $_conf['proxy_host']; $send_port = $_conf['proxy_port']; $send_path = $bbs_cgi_url; } else { $send_host = $URL['host']; $send_port = isset($URL['port']) ? $URL['port'] : 80; $send_path = $URL['path'] . $URL['query']; } if (!$send_port) { $send_port = 80; } // デフォルトを80 $request = "{$method} {$send_path} HTTP/1.0\r\n"; $request .= "Host: {$URL['host']}\r\n"; $request .= "User-Agent: Monazilla/1.00 ({$_conf['p2ua']})\r\n"; $request .= "Referer: http://{$URL['host']}/\r\n"; // クッキー $cookies_to_send = ''; if ($p2cookies) { foreach ($p2cookies as $cname => $cvalue) { if ($cname != 'expires') { $cookies_to_send .= " {$cname}={$cvalue};"; } } } // be.2ch.net 認証クッキー if (P2Util::isHostBe2chNet($host) || !empty($_REQUEST['beres'])) { $cookies_to_send .= ' MDMD=' . $_conf['be_2ch_code'] . ';'; // be.2ch.netの認証コード(パスワードではない) $cookies_to_send .= ' DMDM=' . $_conf['be_2ch_mail'] . ';'; // be.2ch.netの登録メールアドレス } if (!$cookies_to_send) { $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 (strcasecmp($method, 'POST') == 0) { $post_enc = array(); while (list($name, $value) = each($post)) { // したらば or be.2ch.netなら、EUCに変換 if (P2Util::isHostJbbsShitaraba($host) || P2Util::isHostBe2chNet($host)) { $value = mb_convert_encoding($value, 'CP51932', 'CP932'); } $post_enc[] = $name . '=' . rawurlencode($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"; } // }}} // WEBサーバへ接続 $fp = fsockopen($send_host, $send_port, $errno, $errstr, $_conf['http_conn_timeout']); if (!$fp) { $errstr = htmlspecialchars($errstr, ENT_QUOTES); showPostMsg(false, "サーバ接続エラー: {$errstr} ({$errno})<br>p2 Error: 板サーバへの接続に失敗しました", false); return false; } stream_set_timeout($fp, $_conf['http_read_timeout'], 0); //echo '<h4>$request</h4><p>' . $request . "</p>"; //for debug fputs($fp, $request); $start_here = false; $post_seikou = false; while (!p2_stream_eof($fp, $timed_out)) { if ($start_here) { $wr = ''; while (!p2_stream_eof($fp, $timed_out)) { $wr .= fread($fp, 164000); } $response = $wr; break; } else { $l = fgets($fp, 164000); //echo $l .'<br>'; // for debug // クッキーキタ 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') { if (!$p2cookies) { $p2cookies = array(); } $p2cookies[$k] = $m[2]; } } } } if ($p2cookies) { $cookies_to_send = ''; foreach ($p2cookies as $cname => $cvalue) { if ($cname != 'expires') { $cookies_to_send .= " {$cname}={$cvalue};"; } } $newcookies = "Cookie:{$cookies_to_send}\r\n"; $request = preg_replace('/Cookie: .*?\\r\\n/', $newcookies, $request); } // 転送は書き込み成功と判断 } elseif (preg_match('/^Location: /', $l, $matches)) { $post_seikou = true; } if ($l == "\r\n") { $start_here = true; } } } fclose($fp); // be.2ch.net or JBBSしたらば 文字コード変換 EUC→SJIS if (P2Util::isHostBe2chNet($host) || P2Util::isHostJbbsShitaraba($host)) { $response = mb_convert_encoding($response, 'CP932', 'CP51932'); //<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', '<head><meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">$1$2</head>', $response); } $kakikonda_match = '{<title>.*(?:書きこみました|■ 書き込みました ■|書き込み終了 - SubAll BBS).*</title>}is'; $cookie_kakunin_match = '{<!-- 2ch_X:cookie -->|<title>■ 書き込み確認 ■</title>|>書き込み確認。<}'; if (preg_match('/<.+>/s', $response, $matches)) { $response = $matches[0]; } // カキコミ成功 if ($post_seikou || preg_match($kakikonda_match, $response)) { $reload = empty($_POST['from_read_new']); showPostMsg(true, '書きこみが終わりました。', $reload); return true; //$response_ht = htmlspecialchars($response, ENT_QUOTES); //echo "<pre>{$response_ht}</pre>"; // cookie確認(post再チャレンジ) } elseif (preg_match($cookie_kakunin_match, $response)) { showCookieConfirmation($host, $response); return false; // その他はレスポンスをそのまま表示 } else { echo preg_replace('@こちらでリロードしてください。<a href="\\.\\./[a-z]+/index\\.html"> GO! </a><br>@', '', $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; } }
/** * SETTING.TXT をダウンロードして、パースして、キャッシュする * * @access public * @return true|null|false 成功|更新なし(キャッシュ)|失敗 */ function downloadSettingTxt() { global $_conf; $perm = $_conf['dl_perm'] ? $_conf['dl_perm'] : 0606; FileCtl::mkdirFor($this->setting_txt); // 板ディレクトリが無ければ作る $modified = null; if (file_exists($this->setting_srd) && file_exists($this->setting_txt)) { // 更新しない場合は、その場で抜けてしまう if (!empty($_GET['norefresh']) || isset($_REQUEST['word'])) { return null; // キャッシュが新しい場合も抜ける } elseif ($this->isSettingSrdCacheFresh()) { return null; } $modified = gmdate('D, d M Y H:i:s', filemtime($this->setting_txt)) . ' GMT'; } // DL /* // PHP5 if (!class_exists('HTTP_Request', false)) { require 'HTTP/Request.php'; } */ require_once 'HTTP/Request.php'; $params = array(); $params['timeout'] = $_conf['fsockopen_time_limit']; if ($_conf['proxy_use']) { $params['proxy_host'] = $_conf['proxy_host']; $params['proxy_port'] = $_conf['proxy_port']; } $req = new HTTP_Request($this->url, $params); $modified && $req->addHeader('If-Modified-Since', $modified); $req->addHeader('User-Agent', 'Monazilla/1.00 (' . $_conf['p2uaname'] . '/' . $_conf['p2version'] . ')'); $response = $req->sendRequest(); $error_msg = null; if (PEAR::isError($response)) { $error_msg = $response->getMessage(); } else { $code = $req->getResponseCode(); if ($code == 302) { // ホストの移転を追跡 require_once P2_LIB_DIR . '/BbsMap.php'; $new_host = BbsMap::getCurrentHost($this->host, $this->bbs); if ($new_host != $this->host) { $aNewSettingTxt = new SettingTxt($new_host, $this->bbs); return $aNewSettingTxt->downloadSettingTxt(); } } if (!($code == 200 || $code == 206 || $code == 304)) { //var_dump($req->getResponseHeader()); $error_msg = $code; } } // DLエラー if (strlen($error_msg)) { P2Util::pushInfoHtml(sprintf('<div>Error: %s<br>p2 info - %s に接続できませんでした。</div>', hs($error_msg), P2View::tagA(P2Util::throughIme($this->url), hs($this->url), array('target' => $_conf['ext_win_target'])))); touch($this->setting_txt); // DL失敗した場合(404)も touch する touch($this->setting_srd); return false; } $body = $req->getResponseBody(); // DL成功して かつ 更新されていたら保存 if ($body && $code != 304) { // したらば or be.2ch.net ならEUCをSJISに変換 if (P2Util::isHostJbbsShitaraba($this->host) || P2Util::isHostBe2chNet($this->host)) { $body = mb_convert_encoding($body, 'SJIS-win', 'eucJP-win'); } if (false === FileCtl::filePutRename($this->setting_txt, $body)) { die('Error: cannot write file'); } chmod($this->setting_txt, $perm); // パースして if (!$this->setSettingArrayFromSettingTxt()) { return false; } // srd保存する if (!$this->saveSettingSrd($this->setting_array)) { return false; } } else { // touchすることで更新インターバルが効くので、しばらく再チェックされなくなる touch($this->setting_txt); // 同時にキャッシュもtouchしないと、setting_txtとsetting_srdで更新時間がずれて、 // 毎回ここまで処理が来る(サーバへのヘッダリクエストが飛ぶ)場合がある。 touch($this->setting_srd); } return true; }
/** * ホストの種類を判定する * * @param string $host ホスト名 * @return string ホストの種類 */ private static function _detectHostType($host) { if (P2Util::isHostBbsPink($host)) { $type = 'bbspink'; } elseif (P2Util::isHost2chs($host)) { $type = '2channel'; } elseif (P2Util::isHostMachiBbs($host)) { $type = 'machibbs'; } elseif (P2Util::isHostJbbsShitaraba($host)) { $type = 'jbbs'; } else { $type = $host; } return $type; }
P2Util::header_nocache(); header('Content-Type: text/plain; charset=UTF-8'); // }}} // {{{ 初期化 $post_param_keys = array('bbs', 'key', 'time', 'FROM', 'mail', 'MESSAGE', 'subject', 'submit'); $post_internal_keys = array('host', 'sub', 'popup', 'rescount', 'ttitle_en'); foreach ($post_param_keys as $pk) { ${$pk} = isset($_POST[$pk]) ? mb_convert_encoding($_POST[$pk], 'CP932', 'UTF-8') : ''; } foreach ($post_internal_keys as $pk) { ${$pk} = isset($_POST[$pk]) ? $_POST[$pk] : ''; } // したらばのlivedoor移転に対応。post先をlivedoorとする。 $host = P2Util::adjustHostJbbs($host); // machibbs、JBBS@したらば なら if (P2Util::isHostMachiBbs($host) or P2Util::isHostJbbsShitaraba($host)) { /* compact() と array_combine() でPOSTする値の配列を作るので、 $post_param_keys と $post_send_keys の値の順序は揃える! */ //$post_param_keys = array('bbs', 'key', 'time', 'FROM', 'mail', 'MESSAGE', 'subject', 'submit'); $post_send_keys = array('BBS', 'KEY', 'TIME', 'NAME', 'MAIL', 'MESSAGE', 'SUBJECT', 'submit'); // 2ch } else { $post_send_keys = $post_param_keys; } $post = array_combine($post_send_keys, compact($post_param_keys)); unset($post['submit']); // }}} // {{{ execute $post_backup_key = PostDataStore::getKeyForBackup($host, $bbs, $key, !empty($_REQUEST['newthread'])); PostDataStore::set($post_backup_key, $post); echo '1';
/** * したらばJBBSの rawmode.cgi を読んで、datに保存する(2ch風に整形) */ function shitarabaDownload(ThreadRead $aThread) { $GLOBALS['machi_latest_num'] = ''; // {{{ 既得datの取得レス数が適性かどうかを念のためチェック if (file_exists($aThread->keydat)) { $dls = FileCtl::file_read_lines($aThread->keydat); if (!$dls || sizeof($dls) != $aThread->gotnum) { // echo 'bad size!<br>'; unlink($aThread->keydat); $aThread->gotnum = 0; } } else { $aThread->gotnum = 0; } // }}} if ($aThread->gotnum == 0) { $file_append = false; $START = 1; } else { $file_append = true; $START = $aThread->gotnum + 1; } // JBBS@したらば if (P2Util::isHostJbbsShitaraba($aThread->host)) { // したらばのlivedoor移転に対応。読込先をlivedoorとする。 $host = P2Util::adjustHostJbbs($aThread->host); list($host, $category, ) = explode('/', $host); $machiurl = "http://{$host}/bbs/rawmode.cgi/{$category}/{$aThread->bbs}/{$aThread->key}/{$START}-"; } $tempfile = $aThread->keydat . '.dat.temp'; FileCtl::mkdirFor($tempfile); $machiurl_res = P2Util::fileDownload($machiurl, $tempfile); if ($machiurl_res->isError()) { $aThread->diedat = true; return false; } // {{{ したらばならEUCをSJISに変換 if (P2Util::isHostJbbsShitaraba($aThread->host)) { $temp_data = FileCtl::file_read_contents($tempfile); $temp_data = mb_convert_encoding($temp_data, 'CP932', 'CP51932'); if (FileCtl::file_write_contents($tempfile, $temp_data) === false) { p2die('cannot write file.'); } } // }}} $mlines = FileCtl::file_read_lines($tempfile); // 一時ファイルを削除する unlink($tempfile); // ↓rawmode.cgiではこれは出ないだろう /* // (JBBS)ERROR!: スレッドがありません。過去ログ倉庫にもありません。 if (stripos($mlines[0], 'ERROR') === 0) { $aThread->getdat_error_msg_ht .= $mlines[0]; $aThread->diedat = true; return false; } */ // {{{ DATを書き込む if ($mdatlines = shitarabaDatTo2chDatLines($mlines)) { $file_append = $file_append ? FILE_APPEND : 0; $cont = ''; for ($i = $START; $i <= $GLOBALS['machi_latest_num']; $i++) { if ($mdatlines[$i]) { $cont .= $mdatlines[$i]; } else { $cont .= "あぼーん<>あぼーん<>あぼーん<>あぼーん<>\n"; } } if (FileCtl::file_write_contents($aThread->keydat, $cont, $file_append) === false) { p2die('cannot write file.'); } } // }}} $aThread->isonline = true; return true; }