/** * Test Http functions. */ function test_functions() { http_cache_last_modified(); http_chunked_decode(); http_deflate(); http_inflate(); http_build_cookie(); http_date(); http_get_request_body_stream(); http_get_request_body(); http_get_request_headers(); http_match_etag(); http_match_modified(); http_match_request_header(); http_support(); http_negotiate_charset(); http_negotiate_content_type(); http_negotiate_language(); ob_deflatehandler(); ob_etaghandler(); ob_inflatehandler(); http_parse_cookie(); http_parse_headers(); http_parse_message(); http_parse_params(); http_persistent_handles_clean(); http_persistent_handles_count(); http_persistent_handles_ident(); http_get(); http_head(); http_post_data(); http_post_fields(); http_put_data(); http_put_file(); http_put_stream(); http_request_body_encode(); http_request_method_exists(); http_request_method_name(); http_request_method_register(); http_request_method_unregister(); http_request(); http_redirect(); http_send_content_disposition(); http_send_content_type(); http_send_data(); http_send_file(); http_send_last_modified(); http_send_status(); http_send_stream(); http_throttle(); http_build_str(); http_build_url(); }
} } // }}} // {{{ init http-client // 設定を確認 $conn_timeout = isset($ini['Getter']['conn_timeout']) && $ini['Getter']['conn_timeout'] > 0 ? (double) $ini['Getter']['conn_timeout'] : 60.0; $read_timeout = isset($ini['Getter']['read_timeout']) && $ini['Getter']['read_timeout'] > 0 ? (int) $ini['Getter']['read_timeout'] : 60; $ic2_ua = !empty($_conf['expack.user_agent']) ? $_conf['expack.user_agent'] : $_SERVER['HTTP_USER_AGENT']; // キャッシュされていなければ、取得を試みる $client = new HTTP_Client(); $client->setRequestParameter('timeout', $conn_timeout); $client->setRequestParameter('readTimeout', array($read_timeout, 0)); $client->setMaxRedirects(3); $client->setDefaultHeader('User-Agent', $ic2_ua); if ($force && $time) { $client->setDefaultHeader('If-Modified-Since', http_date($time)); } // プロキシ設定 if ($ini['Proxy']['enabled'] && $ini['Proxy']['host'] && $ini['Proxy']['port']) { $client->setRequestParameter('proxy_host', $ini['Proxy']['host']); $client->setRequestParameter('proxy_port', $ini['Proxy']['port']); if ($ini['Proxy']['user']) { $client->setRequestParameter('proxy_user', $ini['Proxy']['user']); $client->setRequestParameter('proxy_pass', $ini['Proxy']['pass']); $proxy_auth_data = base64_encode($ini['Proxy']['user'] . ':' . $ini['Proxy']['pass']); $client->setDefaultHeader('Proxy-Authorization', 'Basic ' . $proxy_auth_data); } } // リファラ設定 if (is_null($referer)) { $send_referer = (bool) $ini['Getter']['sendreferer'];
/** * set modified * * @param string|int $modified * @return void */ public function setModified($modified) { if (is_numeric($modified)) { $this->modified = http_date((int) $modified); } else { $this->modified = $modified; } }
/** * Sets the current date in the request header if not present. * * @param RequestInterface $request Request to write header to. * * @return null */ protected function setDateHeaderOnRequest($request) { if (!($date = $request->getHeader('Date'))) { $request->setHeader('Date', http_date()); } }
/** * http header no cache を出力 * * @return void */ public static function header_nocache() { header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // 日付が過去 header("Last-Modified: " . http_date()); // 常に修正されている header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); // HTTP/1.0 }
// {{{ 妥当なファイルか検証 if (isset($_GET['css']) && preg_match('/^\\w+$/', $_GET['css'])) { $cssName = $_GET['css']; $cssFilePath = P2_STYLE_DIR . DIRECTORY_SEPARATOR . $cssName . '_css.inc'; if (!file_exists($cssFilePath)) { exit; } } else { exit; } // }}} // {{{ 出力 // クエリにユニークキーを埋め込んでいるいるので、キャッシュさせてよい $now = time(); header('Expires: ' . http_date($now + 3600)); header('Last-Modified: ' . http_date($now)); header('Pragma: cache'); header('Content-Type: text/css; charset=Shift_JIS'); echo "@charset \"Shift_JIS\";\n\n"; ob_start(); include $cssFilePath; disp_mystyle($cssName); // 空スタイルを除去 echo preg_replace('/[a-z\\-]+[ \\t]*:[ \\t]*;/', '', ob_get_clean()); // }}} /* * Local Variables: * mode: php * coding: cp932 * tab-width: 4 * c-basic-offset: 4
/** * 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; }
public function testMD5HeaderShouldCalculateForRealContent() { $request = RequestFactory::getInstance()->create('PUT', 'http://test.co/resource.xml?foo=bar&bar=foo', array('Content-type' => "text/plain", 'Date' => http_date()), "helo\nworld"); $event = $this->mockBeforeSendFor($request); $this->assertEquals((string) $event['request']->getHeader('Content-MD5'), 'MATnNnvfHYuh9MbanV26yg=='); }
/** * 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; }
/** * メッセージを表示して終了 * ヘッダが出力されている場合、<body>までは出力済と見なす * * 終了ステータスコード2はP2CommandRunnerにエラーメッセージが * HTMLであることを通知するため * * @param string $err エラー概要 * @param string $msg 詳細な説明 * @param bool $raw 詳細な説明をエスケープするか否か * @return void */ function p2die($err = null, $msg = null, $raw = false) { if (!defined('P2_CLI_RUN') && !headers_sent()) { header('Expires: ' . http_date(0)); // 日付が過去 header('Last-Modified: ' . http_date()); // 常に修正されている header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1 header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); // HTTP/1.0 echo <<<EOH <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <meta name="ROBOTS" content="NOINDEX, NOFOLLOW"> {$GLOBALS['_conf']['extra_headers_ht']} <title>rep2 error</title> </head> <body> EOH; } echo '<h3>rep2 error</h3>'; if ($err !== null) { echo '<p><strong>', p2h($err), '</strong></p>'; } if ($msg !== null) { if ($raw) { echo $msg; } else { echo '<p>', nl2br(p2h($msg)), '</p>'; } } if (true) { echo '<pre><em>backtrace:</em>'; $p2_file_prefix = P2_BASE_DIR . DIRECTORY_SEPARATOR; $p2_base_dir_len = strlen(P2_BASE_DIR); $backtrace = debug_backtrace(); $c = count($backtrace); foreach ($backtrace as $bt) { echo "\n"; if (strpos($bt['file'], $p2_file_prefix) === 0) { $filename = '.' . substr($bt['file'], $p2_base_dir_len); } else { $filename = '(external)' . DIRECTORY_SEPARATOR . basename($bt['file']); } printf(' % 2d. %s (line %d)', $c--, $filename, $bt['line']); if (array_key_exists('function', $bt) && $bt['function'] !== '' && $bt['function'] !== 'p2die') { if (array_key_exists('class', $bt) && $bt['class'] !== '') { printf(': %s%s%s()', $bt['class'], str_replace('>', '>', $bt['type']), $bt['function']); } else { printf(': %s()', $bt['function']); } } } echo '</pre>'; } if (!defined('P2_CLI_RUN')) { echo '</body></html>'; } exit(2); }
/** * 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; }