/** * hostとbbsから板名を返す */ public static function getItaName($host, $bbs) { global $_conf; $id = $host . '/' . $bbs; if (array_key_exists($id, self::$_itaNames)) { return self::$_itaNames[$id]; } $p2_setting_txt = self::idxDirOfHostBbs($host, $bbs) . 'p2_setting.txt'; if (file_exists($p2_setting_txt)) { $p2_setting_cont = FileCtl::file_read_contents($p2_setting_txt); if ($p2_setting_cont) { $p2_setting = unserialize($p2_setting_cont); if (isset($p2_setting['itaj'])) { self::$_itaNames[$id] = $p2_setting['itaj']; return self::$_itaNames[$id]; } } } // 板名Longの取得 if (!isset($p2_setting['itaj'])) { $itaj = BbsMap::getBbsName($host, $bbs); if ($itaj != $bbs) { self::$_itaNames[$id] = $p2_setting['itaj'] = $itaj; FileCtl::make_datafile($p2_setting_txt, $_conf['p2_perm']); $p2_setting_cont = serialize($p2_setting); if (FileCtl::file_write_contents($p2_setting_txt, $p2_setting_cont) === false) { p2die("{$p2_setting_txt} を更新できませんでした"); } return self::$_itaNames[$id]; } } return null; }
} $synctitle = array(basename($_conf['favita_path']) => 'お気に板', basename($_conf['favlist_file']) => 'お気にスレ', basename($_conf['recent_file']) => '最近読んだスレ', basename($rh_idx) => '書き込み履歴', basename($palace_idx) => 'スレの殿堂'); // }}} // {{{ 設定変更処理 // スキン変更があれば、設定ファイルを書き換えてリロード if (isset($_POST['skin'])) { _updateSkinSetting($_POST['skin']); // ホストを同期する } elseif (isset($_POST['sync'])) { require_once P2_LIB_DIR . '/BbsMap.php'; $syncfile = $_conf['pref_dir'] . '/' . $_POST['sync']; $sync_name = $_POST['sync']; if ($syncfile == $_conf['favita_path']) { BbsMap::syncBrd($syncfile); } elseif (in_array($syncfile, array($_conf['favlist_file'], $_conf['recent_file'], $rh_idx, $palace_idx))) { BbsMap::syncIdx($syncfile); } } $parent_reload = ''; if (isset($_GET['reload_skin'])) { $parent_reload = " onload=\"parent.menu.location.href='./{$_conf['menu_php']}'; parent.read.location.href='./first_cont.php';\""; } // }}} // {{{ 書き出し用変数 $ptitle = '設定管理'; if ($_conf['ktai']) { $status_st = 'ステータス'; $autho_user_st = '認証ユーザ'; $client_host_st = '端末ホスト'; $client_ip_st = '端末IPアドレス'; $browser_ua_st = 'ブラウザUA';
$sync_boards[] = $_conf['favita_brd']; $sync_indexes[] = $_conf['favlist_idx']; } $sync_indexes[] = $_conf['recent_idx']; $sync_indexes[] = $_conf['res_hist_idx']; $sync_indexes[] = $_conf['palace_idx']; break; } foreach ($sync_boards as $brd) { if (file_exists($brd)) { BbsMap::syncBrd($brd); } } foreach ($sync_indexes as $idx) { if (file_exists($idx)) { BbsMap::syncIdx($idx); } } // お気に入りセット変更があれば、設定ファイルを書き換える } elseif ($_conf['expack.misc.multi_favs'] && isset($_POST['favsetlist'])) { updateFavSetList(); } // }}} // {{{ 書き出し用変数 $ptitle = '設定管理'; if ($_conf['ktai']) { $status_st = 'ステータス'; $autho_user_st = '認証ユーザ'; $client_host_st = '端末ホスト'; $client_ip_st = '端末IPアドレス'; $browser_ua_st = 'ブラウザUA';
/** * スレッドを指定する * * @return array|false */ function _detectThread() { global $_conf; $ls = null; $url = null; // スレURLの直接指定 if (($url = geti($_GET['nama_url'])) || ($url = geti($_GET['url']))) { $url = trim($url); // 2ch or pink http://choco.2ch.net/test/read.cgi/event/1027770702/ if (preg_match('{http://([^/]+\\.(2ch\\.net|bbspink\\.com|machibbs\\.com|machi\\.to))/test/read\\.cgi/([^/]+)/([0-9]+)/?([^/]+)?}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[3]; $key = $matches[4]; $ls = geti($matches[5]); // c-docomo c-au c-other http://c-au.2ch.net/test/--3!mail=sage/operate/1159594301/519-n } elseif (preg_match('{http://((c-docomo|c-au|c-other)\\.2ch\\.net)/test/([^/]+)/([^/]+)/([0-9]+)/?([^/]+)?}', $url, $m)) { require_once P2_LIB_DIR . '/BbsMap.php'; if ($mapped_host = BbsMap::get2chHostByBbs($m[4])) { $host = $mapped_host; $bbs = $m[4]; $key = $m[5]; $ls = geti($m[6]); } // 2ch, pink, vip2ch.com 過去ログhtml - http://pc.2ch.net/mac/kako/1015/10153/1015358199.html } elseif (preg_match('{(http://([^/]+\\.(2ch\\.net|bbspink\\.com|vip2ch\\.com))(/[^/]+)?/([^/]+)/kako/\\d+(/\\d+)?/(\\d+)).html}', $url, $matches)) { $host = $matches[2]; $bbs = $matches[5]; $key = $matches[7]; $kakolog_uri = $matches[1]; $_GET['kakolog'] = $kakolog_uri; // 新まちBBS http://tohoku.machi.to/bbs/read.cgi/touhoku/1179407635/l50 } elseif (preg_match('{http://([^/]+\\.(2ch\\.net|bbspink\\.com|machibbs\\.com|machi\\.to))/bbs/read\\.cgi/([^/]+)/([0-9]+)/?([^/]+)?}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[3]; $key = $matches[4]; $ls = geti($matches[5]); // (旧)まちBBS http://kanto.machibbs.com/bbs/read.pl?BBS=kana&KEY=1034515019 } elseif (preg_match('{http://([^/]+\\.machibbs\\.com|[^/]+\\.machi\\.to)/bbs/read\\.(pl|cgi)\\?BBS=([^&]+)&KEY=([0-9]+)(&START=([0-9]+))?(&END=([0-9]+))?[^\\"]*}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[3]; $key = $matches[4]; $ls = geti($matches[6]) . '-' . geti($matches[8]); // したらばJBBS(旧まちBBSと類似形式) } elseif (preg_match('{http://((jbbs\\.livedoor\\.jp|jbbs\\.livedoor.com|jbbs\\.shitaraba\\.com)(/[^/]+)?)/bbs/read\\.(pl|cgi)\\?BBS=([^&]+)&KEY=([0-9]+)(&START=([0-9]+))?(&END=([0-9]+))?[^"]*}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[5]; $key = $matches[6]; $ls = geti($matches[8]) . '-' . geti($matches[10]); // したらばJBBS(2ch類似形式) http://jbbs.livedoor.com/bbs/read.cgi/computer/2999/1081177036/-100 } elseif (preg_match('{http://(jbbs\\.livedoor\\.jp|jbbs\\.livedoor.com|jbbs\\.shitaraba\\.com)/bbs/read\\.cgi/(\\w+)/(\\d+)/(\\d+)/((\\d+)?-(\\d+)?)?[^"]*}', $url, $matches)) { $host = $matches[1] . '/' . $matches[2]; $bbs = $matches[3]; $key = $matches[4]; $ls = geti($matches[5]); // チャットちゃんねる http://cha2.net/cgi-bin/test/read.cgi/anitoku/1241688251/l50 } elseif (preg_match('{http://(cha2\\.net)/cgi-bin/test/read\\.cgi/(\\w+)/(\\d+)/?([^/]+)?}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[2]; $key = $matches[3]; $ls = geti($matches[4]); // 外部板 read.cgi 形式 http://ex14.vip2ch.com/test/read.cgi/operate/1161701941/ } elseif (preg_match('{http://([^/]+)/test/read\\.cgi/(\\w+)/(\\d+)/?([^/]+)?}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[2]; $key = $matches[3]; $ls = geti($matches[4]); } } else { !empty($_GET['host']) and $host = $_GET['host']; // "pc.2ch.net" !empty($_POST['host']) and $host = $_POST['host']; isset($_GET['bbs']) and $bbs = $_GET['bbs']; // "php" isset($_POST['bbs']) and $bbs = $_POST['bbs']; isset($_GET['key']) and $key = $_GET['key']; // "1022999539" isset($_POST['key']) and $key = $_POST['key']; !empty($_GET['ls']) and $ls = $_GET['ls']; // "all" !empty($_POST['ls']) and $ls = $_POST['ls']; } if (empty($host) || !isset($bbs) || !isset($key)) { $err = $_conf['read_php'] . ' スレッドの指定が変です。'; $msg = null; if ($url) { if (preg_match('/^http/', $url)) { $msg = sprintf('<a href="%1$s">%1$s</a>', hs($url)); } else { $msg = hs($url); } } p2die($err, $msg); } if (P2Validate::host($host) || P2Validate::bbs($bbs) || P2Validate::key($key)) { p2die('不正な引数です'); } return array($host, $bbs, $key, $ls); }
/** * 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; }
/** * スレッドを指定する * * @return array|false */ function detectThread() { global $_conf; $ls = null; // スレURLの直接指定 if ((isset($_GET['nama_url']) and $url = $_GET['nama_url']) || (isset($_GET['url']) and $url = $_GET['url'])) { $url = trim($url); // 2ch or pink - http://choco.2ch.net/test/read.cgi/event/1027770702/ if (preg_match('{http://([^/]+\\.(2ch\\.net|bbspink\\.com))/test/read\\.cgi/([^/]+)/([0-9]+)/?([^/]+)?}', $url, $matches)) { $host = $matches[1]; $bbs = $matches[3]; $key = $matches[4]; $ls = $matches[5]; // c-docomo c-au c-other http://c-au.2ch.net/test/--3!mail=sage/operate/1159594301/519-n } elseif (preg_match('{http://((c-docomo|c-au|c-other)\\.2ch\\.net)/test/([^/]+)/([^/]+)/([0-9]+)/?([^/]+)?}', $url, $m)) { require_once P2_LIB_DIR . '/BbsMap.class.php'; if ($mapped_host = BbsMap::get2chHostByBbs($m[4])) { $host = $mapped_host; $bbs = $m[4]; $key = $m[5]; $ls = $m[6]; } // 2ch or pink 過去ログhtml - http://pc.2ch.net/mac/kako/1015/10153/1015358199.html } elseif (preg_match("/(http:\\/\\/([^\\/]+\\.(2ch\\.net|bbspink\\.com))(\\/[^\\/]+)?\\/([^\\/]+)\\/kako\\/\\d+(\\/\\d+)?\\/(\\d+)).html/", $url, $matches)) { //2ch pink 過去ログhtml $host = $matches[2]; $bbs = $matches[5]; $key = $matches[7]; $kakolog_uri = $matches[1]; $_GET['kakolog'] = urlencode($kakolog_uri); // まち&したらばJBBS - http://kanto.machibbs.com/bbs/read.pl?BBS=kana&KEY=1034515019 } elseif (preg_match("/http:\\/\\/([^\\/]+\\.machibbs\\.com|[^\\/]+\\.machi\\.to)\\/bbs\\/read\\.(pl|cgi)\\?BBS=([^&]+)&KEY=([0-9]+)(&START=([0-9]+))?(&END=([0-9]+))?[^\"]*/", $url, $matches)) { $host = $matches[1]; $bbs = $matches[3]; $key = $matches[4]; $ls = $matches[6] . "-" . $matches[8]; } elseif (preg_match("{http://((jbbs\\.livedoor\\.jp|jbbs\\.livedoor.com|jbbs\\.shitaraba\\.com)(/[^/]+)?)/bbs/read\\.(pl|cgi)\\?BBS=([^&]+)&KEY=([0-9]+)(&START=([0-9]+))?(&END=([0-9]+))?[^\"]*}", $url, $matches)) { $host = $matches[1]; $bbs = $matches[5]; $key = $matches[6]; $ls = $matches[8] . "-" . $matches[10]; // したらばJBBS http://jbbs.livedoor.com/bbs/read.cgi/computer/2999/1081177036/-100 } elseif (preg_match("{http://(jbbs\\.livedoor\\.jp|jbbs\\.livedoor.com|jbbs\\.shitaraba\\.com)/bbs/read\\.cgi/(\\w+)/(\\d+)/(\\d+)/((\\d+)?-(\\d+)?)?[^\"]*}", $url, $matches)) { $host = $matches[1] . "/" . $matches[2]; $bbs = $matches[3]; $key = $matches[4]; $ls = $matches[5]; } } else { !empty($_GET['host']) and $host = $_GET['host']; // "pc.2ch.net" !empty($_POST['host']) and $host = $_POST['host']; isset($_GET['bbs']) and $bbs = $_GET['bbs']; // "php" isset($_POST['bbs']) and $bbs = $_POST['bbs']; isset($_GET['key']) and $key = $_GET['key']; // "1022999539" isset($_POST['key']) and $key = $_POST['key']; !empty($_GET['ls']) and $ls = $_GET['ls']; // "all" !empty($_POST['ls']) and $ls = $_POST['ls']; } if (empty($host) || !isset($bbs) || !isset($key)) { $htm['url'] = htmlspecialchars($url, ENT_QUOTES); $msg = "p2 - {$_conf['read_php']}: スレッドの指定が変です。<br>" . "<a href=\"{$htm['url']}\">" . $htm['url'] . "</a>"; P2Util::printSimpleHtml($msg); die; return false; } return array($host, $bbs, $key, $ls); }
* rep2 - お気に入り編集 */ require_once __DIR__ . '/../init.php'; $_login->authorize(); // ユーザ認証 //================================================================ // 特殊な前置処理 //================================================================ // お気に板の追加・削除、並び替え if (isset($_GET['setfavita']) || isset($_POST['setfavita']) || isset($_POST['submit_setfavita'])) { require_once P2_LIB_DIR . '/setfavita.inc.php'; setFavIta(); } // お気に板のホストを同期 if (isset($_GET['syncfavita']) || isset($_POST['syncfavita'])) { BbsMap::syncBrd($_conf['favita_brd']); } // プリント用変数 ====================================================== // お気に板追加フォーム $add_favita_form_ht = <<<EOFORM <form method="POST" action="{$_SERVER['SCRIPT_NAME']}" accept-charset="{$_conf['accept_charset']}" target="_self"> <p> 板URL: <input type="text" id="url" name="url" value="http://" size="48"> 板名: <input type="text" id="itaj" name="itaj" value="" size="16"> <input type="hidden" id="setfavita" name="setfavita" value="1"> <input type="submit" name="submit" value="新規追加"> </p> {$_conf['detect_hint_input_ht']}{$_conf['k_input_ht']} </form> EOFORM;
/** * 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; }
/** * 標準方法で 2ch互換 DAT を差分ダウンロードする * * @access private * @return true|string|false 取得できたか、更新がなかった場合はtrue(または"304 Not Modified")を返す */ function downloadDat2ch($from_bytes) { global $_conf; global $debug; if (!($this->host && $this->bbs && $this->key)) { return false; } $range_bytes = intval($from_bytes); if ($range_bytes == 0) { $zero_read = true; } else { $zero_read = false; $range_bytes = $from_bytes - 1; } //$url = 'http://' . $this->host . '/' . $this->bbs . '/dat/' . $this->key . '.dat'; $url = $this->getDatUrl($this->host, $this->bbs, $this->key); $purl = parse_url($url); $purl['query'] = isset($purl['query']) ? '?' . $purl['query'] : ''; // プロキシ if ($_conf['proxy_use']) { $send_host = $_conf['proxy_host']; $send_port = $_conf['proxy_port']; $send_path = $url; } else { $send_host = $purl['host']; $send_port = isset($purl['port']) ? $purl['port'] : null; $send_path = $purl['path'] . $purl['query']; } !$send_port and $send_port = 80; $request = 'GET ' . $send_path . " HTTP/1.0\r\n"; $request .= "Host: " . $purl['host'] . "\r\n"; $request .= "Accept: */*\r\n"; //$request .= "Accept-Charset: Shift_JIS\r\n"; //$request .= "Accept-Encoding: gzip, deflate\r\n"; $request .= "Accept-Language: ja, en\r\n"; $request .= "User-Agent: " . P2Util::getP2UA($withMonazilla = true) . "\r\n"; if (!$zero_read) { $request .= "Range: bytes={$range_bytes}-\r\n"; } $request .= "Referer: http://{$purl['host']}/{$this->bbs}/\r\n"; if ($this->modified) { $request .= "If-Modified-Since: " . $this->modified . "\r\n"; } // Basic認証用のヘッダ if (isset($purl['user']) && isset($purl['pass'])) { $request .= "Authorization: Basic " . base64_encode($purl['user'] . ":" . $purl['pass']) . "\r\n"; } $request .= "Connection: Close\r\n"; $request .= "\r\n"; // WEBサーバへ接続 $fp = @fsockopen($send_host, $send_port, $errno, $errstr, $_conf['fsockopen_time_limit']); if (!$fp) { P2Util::pushInfoHtml(sprintf('<p>サーバ接続エラー: %s (%s)<br>p2 info - %s に接続できませんでした。</div>', hs($errstr), hs($errno), P2View::tagA(P2Util::throughIme($url), hs($url), array('target' => $_conf['ext_win_target'])))); $this->diedat = true; return false; } // HTTPリクエスト送信 fputs($fp, $request); // HTTPヘッダレスポンスを取得する $h = $this->freadHttpHeader($fp); if ($h === false) { fclose($fp); $this->_pushInfoHtmlFreadHttpHeaderError($url); $this->diedat = true; return false; } // {{{ HTTPコードをチェック $code = $h['code']; // 206 Partial Content if ($code == "200" || $code == "206") { // OK。何もしない // Found } elseif ($code == "302") { // ホストの移転を追跡 require_once P2_LIB_DIR . '/BbsMap.php'; $new_host = BbsMap::getCurrentHost($this->host, $this->bbs); if ($new_host != $this->host) { fclose($fp); $this->old_host = $this->host; $this->host = $new_host; return $this->downloadDat2ch($from_bytes); } else { fclose($fp); // 2007/06/11 302の時に、UAをMonazillaにしないでDATアクセスを試みると203が帰ってきて、 // body中に'過去ログ ★'とあれば、●落ち中とみなすことにする。 // 仕様の確証が取れていないので、このような判断でよいのかはっきりしない。 // 203 Non-Authoritative Information // 過去ログ ★ /* 名無し募集中。。。<><>2007/06/10(日) 13:29:51.68 0<> http://mlb.yahoo.co.jp/headlines/?a=2279 <br> くわわ>>>>>>>>>>>>>>>>>>>>>井川 <>★くわわメジャー昇格おめ 売上議論14001★ 1001, 131428 (総レス数, サイズ)<><>1181480550000000 (最終更新)<><div style="color:navy;font-size:smaller;">|<br />| 中略<br />|</div><> 1001<><>Over 1000 Thread<> このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <> 過去ログ ★<><>[過去ログ]<><div style="color:red;text-align:center;">■ このスレッドは過去ログ倉庫に格納されています</div><hr /><br />IE等普通のブラウザで見る場合 http://tubo.80.kg/tubo_and_maru.html<br />専用のブラウザで見る場合 http://www.monazilla.org/<br /><br />2ちゃんねる Viewer を使うと、すぐに読めます。 http://2ch.tora3.net/<br /><div style="color:navy;">この Viewer(通称●) の売上で、2ちゃんねるは設備を増強しています。<br />●が売れたら、新しいサーバを投入できるという事です。</div><br />よくわからない場合はソフトウェア板へGo http://pc11.2ch.net/software/<br /><br />モリタポ ( http://find.2ch.net/faq/faq2.php#c1 ) を持っていれば、50モリタポで表示できます。<br /> こちらから → http://find.2ch.net/index.php?STR=dat:http://ex23.2ch.net/test/read.cgi/morningcoffee/1181449791/<br /><br /><hr /><> */ $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($url, $params); $req->setMethod('GET'); $err = $req->sendRequest(true); if (PEAR::isError($err)) { //var_dump('error'); } else { // レスポンスコードを検証 if ('203' == $req->getResponseCode()) { $body2 = $req->getResponseBody(); $reason = null; // $body2 "過去ログ ★<><>[過去ログ]<>「隊長! 過去ログ倉庫で、スレッド http://qb5.2ch.net/operate/kako/1103/11034/1103495887.html を発見しました。」<>過去ログ発見![改行]" if (preg_match('/<>過去ログ発見!/', $body2)) { //$reason = 'kakologsoko'; } elseif (preg_match('/過去ログ ★<>/', $body2)) { $reason = 'datochi'; } $this->downloadDat2chNotFound($reason); return false; } } $this->downloadDat2chNotFound(); return false; } // Not Modified } elseif ($code == '304') { fclose($fp); $this->isonline = true; return '304 Not Modified'; // Requested Range Not Satisfiable } elseif ($code == '416') { //echo "あぼーん検出"; fclose($fp); $this->clearOnbytesModified(); return $this->downloadDat2ch(0); // あぼーんを検出したので全部取り直し。 // 予期しないHTTPコード。スレッドがないと判断 } else { fclose($fp); $this->downloadDat2chNotFound(); return false; } // }}} $r = $this->getOnbytesFromHeader($h['headers'], $zero_read); if ($r !== false) { $this->onbytes = $r; } if (isset($h['headers']['Last-Modified'])) { $this->modified = $h['headers']['Last-Modified']; } // bodyを読む $body = ''; while (!feof($fp)) { $body .= fread($fp, 8192); } fclose($fp); // 末尾の改行であぼーんをチェックする if (!$zero_read) { if (substr($body, 0, 1) != "\n") { //echo "あぼーん検出"; $this->clearOnbytesModified(); return $this->downloadDat2ch(0); // あぼーんを検出したので全部取り直し。 } $body = substr($body, 1); } FileCtl::make_datafile($this->keydat, $_conf['dat_perm']); $done = false; if ($fp = fopen($this->keydat, 'rb+')) { flock($fp, LOCK_EX); if (0 === fseek($fp, $from_bytes)) { if (false !== fwrite($fp, $body)) { ftruncate($fp, $from_bytes + strlen($body)); $done = true; } } flock($fp, LOCK_UN); fclose($fp); } if (!$done) { trigger_error('cannot write file (' . $this->keydat . ')', E_USER_WARNING); die('Error: cannot write file. downloadDat2ch()'); return false; } // {{{ 取得後サイズチェック $debug && $GLOBALS['profiler']->enterSection('dat_size_check'); if ($zero_read == false && $this->onbytes) { $this->getDatBytesFromLocalDat(); // $aThread->length をset if ($this->onbytes != $this->length) { $onbytes = $this->onbytes; $this->clearOnbytesModified(); P2Util::pushInfoHtml("p2 info: {$onbytes}/{$this->length} ファイルサイズが変なので、datを再取得しました<br>"); $debug && $GLOBALS['profiler']->leaveSection('dat_size_check'); return $this->downloadDat2ch(0); // datサイズは不正。全部取り直し。 } } $debug && $GLOBALS['profiler']->leaveSection('dat_size_check'); // }}} $this->isonline = true; return true; /* あぼーん検出漏れについて 0. p2が読み込む 1. レスがあぼーんされる 2. (あぼーんされたレス-あぼーんテキスト)と全く同サイズのレスが書き込まれる 3. p2が読み込む 0-1-2-3が、完全に連続した時にあぼーん検出漏れはありうる。 */ }
/** * 標準方法で 2ch互換 DAT を差分ダウンロードする * * @return mix 取得できたか、更新がなかった場合はtrueを返す */ protected function _downloadDat2ch($from_bytes) { global $_conf; global $debug; if (!($this->host && $this->bbs && $this->key)) { return false; } $from_bytes = intval($from_bytes); if ($from_bytes == 0) { $zero_read = true; } else { $zero_read = false; $from_bytes = $from_bytes - 1; } $method = 'GET'; $url = "http://{$this->host}/{$this->bbs}/dat/{$this->key}.dat"; //$url="http://news2.2ch.net/test/read.cgi?bbs=newsplus&key=1038486598"; $purl = parse_url($url); // 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 = $url; } else { $send_host = $purl['host']; $send_port = isset($purl['port']) ? $purl['port'] : 80; $send_path = $purl['path'] . $purl['query']; } if (!$send_port) { $send_port = 80; // デフォルトを80 } $request = "{$method} {$send_path} HTTP/1.0\r\n"; $request .= "Host: {$purl['host']}\r\n"; $request .= "Accept: */*\r\n"; //$request .= "Accept-Charset: Shift_JIS\r\n"; //$request .= "Accept-Encoding: gzip, deflate\r\n"; $request .= "Accept-Language: ja, en\r\n"; $request .= "User-Agent: Monazilla/1.00 ({$_conf['p2ua']})\r\n"; if (!$zero_read) { $request .= "Range: bytes={$from_bytes}-\r\n"; } $request .= "Referer: http://{$purl['host']}/{$this->bbs}/\r\n"; if ($this->modified) { $request .= "If-Modified-Since: " . $this->modified . "\r\n"; } // Basic認証用のヘッダ if (isset($purl['user']) && isset($purl['pass'])) { $request .= "Authorization: Basic " . base64_encode($purl['user'] . ":" . $purl['pass']) . "\r\n"; } $request .= "Connection: Close\r\n"; $request .= "\r\n"; // WEBサーバへ接続 $fp = @fsockopen($send_host, $send_port, $errno, $errstr, $_conf['http_conn_timeout']); if (!$fp) { self::_pushInfoConnectFailed($url, $errno, $errstr); $this->diedat = true; return false; } stream_set_timeout($fp, $_conf['http_read_timeout'], 0); $wr = ""; fputs($fp, $request); $start_here = false; while (!p2_stream_eof($fp, $timed_out)) { if ($start_here) { if ($code == "200" || $code == "206") { while (!p2_stream_eof($fp, $timed_out)) { $wr .= fread($fp, 4096); } if ($timed_out) { self::_pushInfoReadTimedOut($url); $this->diedat = true; fclose($fp); return false; } // 末尾の改行であぼーんチェック if (!$zero_read) { if (substr($wr, 0, 1) != "\n") { //echo "あぼーん検出"; fclose($fp); unset($this->onbytes); unset($this->modified); return $this->_downloadDat2ch(0); // あぼーん検出。全部取り直し。 } $wr = substr($wr, 1); } FileCtl::make_datafile($this->keydat, $_conf['dat_perm']); $file_append = $zero_read ? 0 : FILE_APPEND; if (FileCtl::file_write_contents($this->keydat, $wr, $file_append) === false) { p2die('cannot write file.'); } //$GLOBALS['debug'] && $GLOBALS['profiler']->enterSection("dat_size_check"); // 取得後サイズチェック if ($zero_read == false && $this->onbytes) { $this->getDatBytesFromLocalDat(); // $aThread->length をset if ($this->onbytes != $this->length) { fclose($fp); unset($this->onbytes); unset($this->modified); P2Util::pushInfoHtml("<p>rep2 info: {$this->onbytes}/{$this->length} ファイルサイズが変なので、datを再取得</p>"); //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection("dat_size_check"); return $this->_downloadDat2ch(0); //datサイズは不正。全部取り直し。 // サイズが同じならそのまま } elseif ($this->onbytes == $this->length) { fclose($fp); $this->isonline = true; //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection('dat_size_check'); return true; } } //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection('dat_size_check'); // スレッドがないと判断 } else { fclose($fp); return $this->_downloadDat2chNotFound(); } } else { $l = fgets($fp, 32800); // ex) HTTP/1.1 304 Not Modified if (preg_match("/^HTTP\\/1\\.\\d (\\d+) (.+)\r\n/", $l, $matches)) { $code = $matches[1]; if ($code == "200" || $code == "206") { // Partial Content } elseif ($code == "302") { // Found // ホストの移転を追跡 $new_host = BbsMap::getCurrentHost($this->host, $this->bbs); if ($new_host != $this->host) { fclose($fp); $this->old_host = $this->host; $this->host = $new_host; return $this->_downloadDat2ch($from_bytes); } else { fclose($fp); return $this->_downloadDat2chNotFound($code); } } elseif ($code == "304") { // Not Modified fclose($fp); $this->isonline = true; return "304 Not Modified"; } elseif ($code == "416") { // Requested Range Not Satisfiable //echo "あぼーん検出"; fclose($fp); unset($this->onbytes); unset($this->modified); return $this->_downloadDat2ch(0); // あぼーん検出。全部取り直し。 } else { fclose($fp); return $this->_downloadDat2chNotFound(); } } if ($zero_read) { if (preg_match("/^Content-Length: ([0-9]+)/", $l, $matches)) { $this->onbytes = $matches[1]; } } else { if (preg_match("/^Content-Range: bytes ([^\\/]+)\\/([0-9]+)/", $l, $matches)) { $this->onbytes = $matches[2]; } } if (preg_match("/^Last-Modified: (.+)\r\n/", $l, $matches)) { //echo $matches[1]."<br>"; //debug $this->modified = $matches[1]; } elseif ($l == "\r\n") { $start_here = true; } } } fclose($fp); if ($timed_out) { self::_pushInfoReadTimedOut($url); $this->diedat = true; return false; } else { $this->isonline = true; return true; } }
/** * 2ch公式メニューをパースし、板-ホストの対応表を作成する * * @return array site/bbs/(host,itaj) の多次元連想配列 * ダウンロードに失敗したときは false */ private static function _getMapping() { global $_conf; // {{{ 設定 $bbsmenu_url = 'http://menu.2ch.net/bbsmenu.html'; // 公式メニューの URL $altmenu_url = 'http://www.2ch.se/bbsmenu.html'; // 代替メニューの URL $map_cache_path = $_conf['cache_dir'] . '/host_bbs_map.txt'; $map_cache_lifetime = 600; // TTLは少し短めに $err_fmt = '<p>rep2 error: BbsMap: %s - %s をダウンロードできませんでした。</p>'; $use_alt = false; // }}} // {{{ キャッシュ確認 if (!is_null(self::$_map)) { return self::$_map; } elseif (file_exists($map_cache_path)) { $mtime = filemtime($map_cache_path); $expires = $mtime + $map_cache_lifetime; if (time() < $expires) { $map_cahce = file_get_contents($map_cache_path); self::$_map = unserialize($map_cahce); return self::$_map; } } else { FileCtl::mkdirFor($map_cache_path); } touch($map_cache_path); clearstatcache(); // }}} // {{{ メニューをダウンロード if (!class_exists('HTTP_Request', false)) { require 'HTTP/Request.php'; } $params = array(); $params['timeout'] = $_conf['http_conn_timeout']; $params['readTimeout'] = array($_conf['http_read_timeout'], 0); if (isset($mtime)) { $params['requestHeaders'] = array('If-Modified-Since' => http_date($mtime)); } if ($_conf['proxy_use']) { $params['proxy_host'] = $_conf['proxy_host']; $params['proxy_port'] = $_conf['proxy_port']; } $req = new HTTP_Request($bbsmenu_url, $params); $req->setMethod('GET'); $err = $req->sendRequest(true); // エラーのとき、代わりのメニューを使ってみる if (PEAR::isError($err) && $use_alt) { P2Util::pushInfoHtml(sprintf($err_fmt, htmlspecialchars($err->getMessage(), ENT_QUOTES), htmlspecialchars($bbsmenu_url, ENT_QUOTES))); P2Util::pushInfoHtml(sprintf("<p>代わりに %s をダウンロードします。</p>", htmlspecialchars($altmenu_url, ENT_QUOTES))); $bbsmenu_url = $altmenu_url; unset($req, $err); $req = new HTTP_Request($bbsmenu_url, $params); $req->setMethod('GET'); $err = $req->sendRequest(true); } // エラーを検証 if (PEAR::isError($err)) { P2Util::pushInfoHtml(sprintf($err_fmt, htmlspecialchars($err->getMessage(), ENT_QUOTES), htmlspecialchars($bbsmenu_url, ENT_QUOTES))); if (file_exists($map_cache_path)) { return unserialize(file_get_contents($map_cache_path)); } else { return false; } } // レスポンスコードを検証 $code = $req->getResponseCode(); if ($code == 304) { $map_cahce = file_get_contents($map_cache_path); self::$_map = unserialize($map_cahce); return self::$_map; } elseif ($code != 200) { P2Util::pushInfoHtml(sprintf($err_fmt, htmlspecialchars(strval($code), ENT_QUOTES), htmlspecialchars($bbsmenu_url, ENT_QUOTES))); if (file_exists($map_cache_path)) { return unserialize(file_get_contents($map_cache_path)); } else { return false; } } $res_body = $req->getResponseBody(); // }}} // {{{ パース $regex = '!<A HREF=http://(\\w+\\.(?:2ch\\.net|bbspink\\.com|machi\\.to|mathibbs\\.com))/(\\w+)/(?: TARGET=_blank)?>(.+?)</A>!'; preg_match_all($regex, $res_body, $matches, PREG_SET_ORDER); $map = array(); foreach ($matches as $match) { $host = $match[1]; $bbs = $match[2]; $itaj = $match[3]; $type = self::_detectHostType($host); if (!isset($map[$type])) { $map[$type] = array(); } $map[$type][$bbs] = array('host' => $host, 'itaj' => $itaj); } // }}} // {{{ キャッシュする $map_cache = serialize($map); if (FileCtl::file_write_contents($map_cache_path, $map_cache) === false) { p2die("cannot write file. ({$map_cache_path})"); } // }}} return self::$_map = $map; }
/** * 2ch公式メニューをパースし、板-ホストの対応表を作成する * * @return array site/bbs/(host,itaj) の多次元連想配列 * ダウンロードに失敗したときは false * @access private * @static */ function _getMapping() { global $_conf; static $map = null; // {{{ 設定 $bbsmenu_url = 'http://menu.2ch.net/bbsmenu.html'; $map_cache_path = $_conf['cache_dir'] . '/host_bbs_map.txt'; $map_cache_lifetime = 600; // TTLは少し短めに $errfmt = '<p>rep2 error: BbsMap: %s - %s をダウンロードできませんでした。</p>'; // }}} // {{{ キャッシュ確認 if (!is_null($map)) { return $map; } elseif (file_exists($map_cache_path)) { $mtime = filemtime($map_cache_path); $expires = $mtime + $map_cache_lifetime; if (time() < $expires) { $map_cahce = file_get_contents($map_cache_path); $map = unserialize($map_cahce); return $map; } } else { FileCtl::mkdirFor($map_cache_path); } touch($map_cache_path); clearstatcache(); // }}} // {{{ メニューをダウンロード $params = array(); $params['timeout'] = $_conf['fsockopen_time_limit']; //$params['readTimeout'] = array($_conf['fsockopen_time_limit'], 0); if (isset($mtime)) { $params['requestHeaders'] = array('If-Modified-Since' => gmdate('D, d M Y H:i:s', $mtime) . ' GMT'); } if ($_conf['proxy_use']) { $params['proxy_host'] = $_conf['proxy_host']; $params['proxy_port'] = $_conf['proxy_port']; } $req = new HTTP_Request($bbsmenu_url, $params); $req->setMethod('GET'); $err = $req->sendRequest(true); // エラーを検証 if (PEAR::isError($err)) { $errmsg = sprintf($errfmt, htmlspecialchars($err->getMessage()), htmlspecialchars($bbsmenu_url, ENT_QUOTES)); P2Util::pushInfoHtml($errmsg); if (file_exists($map_cache_path)) { return unserialize(file_get_contents($map_cache_path)); } else { return false; } } // レスポンスコードを検証 $code = $req->getResponseCode(); if ($code == 304) { $map_cahce = file_get_contents($map_cache_path); $map = unserialize($map_cahce); return $map; } elseif ($code != 200) { $errmsg = sprintf($errfmt, htmlspecialchars(strval($code)), htmlspecialchars($bbsmenu_url, ENT_QUOTES)); P2Util::pushInfoHtml($errmsg); if (file_exists($map_cache_path)) { return unserialize(file_get_contents($map_cache_path)); } else { return false; } } $res_body = $req->getResponseBody(); // }}} // {{{ パース $regex = '!<A HREF=http://(\\w+\\.(?:2ch\\.net|bbspink\\.com|machi\\.to|mathibbs\\.com))/(\\w+)/(?: TARGET=_blank)?>(.+?)</A>!'; preg_match_all($regex, $res_body, $matches, PREG_SET_ORDER); $map = array(); foreach ($matches as $match) { $host = $match[1]; $bbs = $match[2]; $itaj = $match[3]; $type = BbsMap::_detectHostType($host); !isset($map[$type]) and $map[$type] = array(); $map[$type][$bbs] = array('host' => $host, 'itaj' => $itaj); } // }}} // キャッシュする $map_cache = serialize($map); if (false === FileCtl::filePutRename($map_cache_path, $map_cache)) { $errmsg = sprintf('p2 error: cannot write file. (%s)', htmlspecialchars($map_cache_path, ENT_QUOTES)); P2Util::pushInfoHtml($errmsg); if (file_exists($map_cache_path)) { return unserialize(file_get_contents($map_cache_path)); } else { return false; } } return $map; }
require_once './conf/conf.inc.php'; $_login->authorize(); // ユーザ認証 // {{{ 特殊な前処理 // お気に板の追加・削除、並び替え if (isset($_GET['setfavita']) or isset($_POST['setfavita']) or isset($_POST['submit_listfavita'])) { if (!isset($_REQUEST['csrfid']) or $_REQUEST['csrfid'] != P2Util::getCsrfId()) { p2die('不正なクエリーです(CSRF対策)'); } require_once P2_LIB_DIR . '/setFavIta.func.php'; setFavIta(); } // お気に板のホストを同期 if (isset($_GET['syncfavita']) or isset($_POST['syncfavita'])) { require_once P2_LIB_DIR . '/BbsMap.php'; BbsMap::syncBrd($_conf['favita_path']); } // }}} // 並び替えにJavaScript使うかい? $sortNoJs = false; if (UA::isK() || UA::isNetFront() or !empty($_POST['sortNoJs']) || !empty($_GET['sortNoJs']) or isset($_GET['setfavita'])) { $sortNoJs = true; } $csrfid = P2Util::getCsrfId(); $body_at = P2View::getBodyAttrK(); $hr = P2View::getHrHtmlK(); //================================================================ // ヘッダHTML表示 //================================================================ P2Util::headerNoCache(); P2View::printDoctypeTag();
/** * hostとbbsから板名を取得する * * @access public * @return string|null */ function getItaName($host, $bbs) { global $_conf, $ita_names; $id = $host . '/' . $bbs; if (isset($ita_names[$id])) { return $ita_names[$id]; } $p2_setting_txt = P2Util::idxDirOfHostBbs($host, $bbs) . 'p2_setting.txt'; if (file_exists($p2_setting_txt)) { $p2_setting_cont = file_get_contents($p2_setting_txt); if ($p2_setting_cont) { $p2_setting = unserialize($p2_setting_cont); if (isset($p2_setting['itaj'])) { $ita_names[$id] = $p2_setting['itaj']; return $ita_names[$id]; } } } // 板名Longの取得 if (!isset($p2_setting['itaj'])) { require_once P2_LIB_DIR . '/BbsMap.php'; $itaj = BbsMap::getBbsName($host, $bbs); if ($itaj != $bbs) { $ita_names[$id] = $p2_setting['itaj'] = $itaj; FileCtl::make_datafile($p2_setting_txt, $_conf['p2_perm']); $p2_setting_cont = serialize($p2_setting); if (false === FileCtl::filePutRename($p2_setting_txt, $p2_setting_cont)) { die("Error: {$p2_setting_txt} を更新できませんでした"); } return $ita_names[$id]; } } return null; }
/** * subject.txtをダウンロードする * * @return string subject.txt の中身 */ public function downloadSubject() { global $_conf; if ($this->storage === 'file') { FileCtl::mkdirFor($this->subject_file); // 板ディレクトリが無ければ作る if (file_exists($this->subject_file)) { if (!empty($_REQUEST['norefresh']) || empty($_REQUEST['refresh']) && isset($_REQUEST['word'])) { return; // 更新しない場合は、その場で抜けてしまう } elseif (!empty($GLOBALS['expack.subject.multi-threaded-download.done'])) { return; // 並列ダウンロード済の場合も抜ける } elseif (empty($_POST['newthread']) and $this->isSubjectTxtFresh()) { return; // 新規スレ立て時でなく、更新が新しい場合も抜ける } $modified = http_date(filemtime($this->subject_file)); } 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->subject_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) { $aNewSubjectTxt = new SubjectTxt($new_host, $this->bbs); $body = $aNewSubjectTxt->downloadSubject(); return $body; } } if (!($code == 200 || $code == 206 || $code == 304)) { //var_dump($req->getResponseHeader()); $error_msg = $code; } } if (isset($error_msg) && strlen($error_msg) > 0) { $url_t = P2Util::throughIme($this->subject_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->subject_url}</a> に接続できませんでした。</p>"; P2Util::pushInfoHtml($info_msg_ht); $body = ''; } else { $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->subject_file, $body) === false) { p2die('cannot write file'); } } else { // touchすることで更新インターバルが効くので、しばらく再チェックされなくなる // (変更がないのに修正時間を更新するのは、少し気が進まないが、ここでは特に問題ないだろう) if ($this->storage === 'file') { touch($this->subject_file); } } return $body; }
/** * subject.txtをダウンロードする * * @access public * @return array|null|false subject.txtの配列データ(eaccelerator, apc用)、またはnullを返す。 * 失敗した場合はfalseを返す。 */ function downloadSubject() { global $_conf; static $spentDlTime_ = 0; // DL所要合計時間 $perm = isset($_conf['dl_perm']) ? $_conf['dl_perm'] : 0606; $modified = false; if ($this->storage == 'file') { FileCtl::mkdirFor($this->subject_file); // 板ディレクトリが無ければ作る if (file_exists($this->subject_file)) { // ファイルキャッシュがあれば、DL制限時間をかける if (UA::isK()) { $dlSubjectTotalLimitTime = $_conf['dlSubjectTotalLimitTimeM']; } else { $dlSubjectTotalLimitTime = $_conf['dlSubjectTotalLimitTime']; } if ($dlSubjectTotalLimitTime and $spentDlTime_ > $dlSubjectTotalLimitTime) { return null; } // 条件によって、キャッシュを適用する // subject.php でrefresh指定がある時は、キャッシュを適用しない if (!(basename($_SERVER['SCRIPT_NAME']) == $_conf['subject_php'] && !empty($_REQUEST['refresh']))) { // キャッシュ適用指定時は、その場で抜ける if (!empty($_GET['norefresh']) || isset($_REQUEST['word'])) { return null; // 並列ダウンロード済の場合も抜ける } elseif (!empty($GLOBALS['expack.subject.multi-threaded-download.done'])) { return null; // 新規スレ立て時以外で、キャッシュが新鮮な場合も抜ける } elseif (empty($_POST['newthread']) and $this->isSubjectTxtFresh()) { return null; } } $modified = gmdate("D, d M Y H:i:s", filemtime($this->subject_file)) . " GMT"; } } $dlStartTime = $this->microtimeFloat(); // DL 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->subject_url, $params); $modified && $req->addHeader('If-Modified-Since', $modified); $req->addHeader('User-Agent', sprintf('Monazilla/1.00 (%s/%s)', $_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) { $aNewSubjectTxt = new SubjectTxt($new_host, $this->bbs); return $aNewSubjectTxt->downloadSubject(); } } if (!($code == 200 || $code == 206 || $code == 304)) { //var_dump($req->getResponseHeader()); $error_msg = $code; } } if (!is_null($error_msg) && strlen($error_msg) > 0) { $attrs = array(); if ($_conf['ext_win_target']) { $attrs['target'] = $_conf['ext_win_target']; } $atag = P2View::tagA(P2Util::throughIme($this->subject_url), hs($this->subject_url), $attrs); $msg_ht = sprintf('<div>Error: %s<br>p2 info - %s に接続できませんでした。</div>', hs($error_msg), $atag); P2Util::pushInfoHtml($msg_ht); $body = ''; } else { $body = $req->getResponseBody(); } $dlEndTime = $this->microtimeFloat(); $dlTime = $dlEndTime - $dlStartTime; $spentDlTime_ += $dlTime; // 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'); } // eaccelerator or apcに保存する場合 if ($this->storage == 'eaccelerator' || $this->storage == 'apc') { $cache_key = "{$this->host}/{$this->bbs}"; $cont = rtrim($body); $lines = explode("\n", $cont); if ($this->storage == 'eaccelerator') { eaccelerator_lock($cache_key); eaccelerator_put($cache_key, $lines, $_conf['sb_dl_interval']); eaccelerator_unlock($cache_key); } else { apc_store($cache_key, $lines, $_conf['sb_dl_interval']); } return $lines; // ファイルに保存する場合 } else { if (false === FileCtl::filePutRename($this->subject_file, $body)) { // 保存に失敗はしても、既存のキャッシュが読み込めるならよしとしておく if (is_readable($this->subject_file)) { return null; } else { die("Error: cannot write file"); return false; } } chmod($this->subject_file, $perm); } } else { // touchすることで更新インターバルが効くので、しばらく再チェックされなくなる // (変更がないのに修正時間を更新するのは、少し気が進まないが、ここでは特に問題ないだろう) if ($this->storage == 'file') { touch($this->subject_file); } } return null; }