/** * >>1のみをプレビューする */ public function previewOne() { global $_conf; if (!($this->host && $this->bbs && $this->key)) { return false; } // ローカルdatから取得 if (is_readable($this->keydat)) { $fd = fopen($this->keydat, "rb"); $first_line = fgets($fd, 32800); fclose($fd); // be.2ch.net ならEUC→SJIS変換 if (P2Util::isHostBe2chNet($this->host)) { $first_line = mb_convert_encoding($first_line, 'CP932', 'CP51932'); } $first_datline = rtrim($first_line); if (strpos($first_datline, '<>') !== false) { $datline_sepa = "<>"; } else { $datline_sepa = ","; $this->dat_type = "2ch_old"; } $d = explode($datline_sepa, $first_datline); $this->setTtitle($d[4]); } // ローカルdatなければオンラインから if (!$first_line) { $method = 'GET'; $url = "http://{$this->host}/{$this->bbs}/dat/{$this->key}.dat"; $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 = $purl['port']; $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 .= "User-Agent: Monazilla/1.00 ({$_conf['p2ua']})\r\n"; // $request .= "Range: bytes={$from_bytes}-\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); fputs($fp, $request); $start_here = false; while (!p2_stream_eof($fp, $timed_out)) { if ($start_here) { if ($code == "200") { $first_line = fgets($fp, 32800); break; } else { fclose($fp); return $this->previewOneNotFound($code); } } else { $l = fgets($fp, 32800); //echo $l."<br>";// for debug if (preg_match("/^HTTP\\/1\\.\\d (\\d+) (.+)\r\n/", $l, $matches)) { // ex) HTTP/1.1 304 Not Modified $code = $matches[1]; if ($code == "200") { } else { fclose($fp); return $this->previewOneNotFound($code); } } elseif (preg_match("/^Content-Length: ([0-9]+)/", $l, $matches)) { $onbytes = $matches[1]; } elseif ($l == "\r\n") { $start_here = true; } } } fclose($fp); // be.2ch.net ならEUC→SJIS変換 if (P2Util::isHostBe2chNet($this->host)) { $first_line = mb_convert_encoding($first_line, 'CP932', 'CP51932'); } $first_datline = rtrim($first_line); if (strpos($first_datline, '<>') !== false) { $datline_sepa = "<>"; } else { $datline_sepa = ","; $this->dat_type = "2ch_old"; } $d = explode($datline_sepa, $first_datline); $this->setTtitle($d[4]); $this->onthefly = true; } else { // 便宜上 if (!$this->readnum) { $this->readnum = 1; } } if ($_conf['ktai']) { $aShowThread = new ShowThreadK($this); $aShowThread->am_autong = false; } else { $aShowThread = new ShowThreadPc($this); } $body = ''; if ($this->onthefly) { $body .= "<div><span class=\"onthefly\">on the fly</span></div>\n"; } $body .= "<div class=\"thread\">\n"; $res = $aShowThread->transRes($first_line, 1); // 1を表示 $body .= is_array($res) ? $res['body'] . $res['q'] : $res; $body .= "</div>\n"; return $body; }
/** * HTTPリクエストをサーバに送信して、レスポンス(WapResponseオブジェクト)を取得する * * @thanks http://www.spencernetwork.org/memo/tips-3.php * * @param WapRequest $req * @param array $options * @return WapResponse */ public function request(WapRequest $req, array $options = array()) { if (!empty($options['onlyHeader'])) { $req->setOnlyHeader($options['onlyHeader']); } if (!($purl = parse_url($req->url))) { $res = new WapResponse(); $res->message = 'parse_url() failed'; return $res; } if (isset($purl['query'])) { $purl['query'] = '?' . $purl['query']; } else { $purl['query'] = ''; } $default_port = $purl['scheme'] == 'https' ? 443 : 80; // プロキシ if ($req->proxy) { $send_host = $req->proxy['host']; $send_port = isset($req->proxy['port']) ? $req->proxy['port'] : $default_port; $send_path = $req->url; } else { $send_host = $purl['host']; $send_port = isset($purl['port']) ? $purl['port'] : $default_port; $send_path = $purl['path'] . $purl['query']; } // SSL if ($purl['scheme'] == 'https') { $send_host = 'ssl://' . $send_host; } $request = $req->method . ' ' . $send_path . ' HTTP/1.0' . self::CRLF; $request .= 'Host: ' . $purl['host'] . self::CRLF; if ($this->_agent) { $request .= 'User-Agent: ' . $this->_agent . self::CRLF; } $request .= 'Connection: Close' . self::CRLF; //$request .= 'Accept-Encoding: gzip' . self::CRLF; if ($req->modified) { $request .= 'If-Modified-Since: ' . $req->modified . self::CRLF; } // Basic認証用のヘッダ if (isset($purl['user']) && isset($purl['pass'])) { $request .= 'Authorization: Basic ' . base64_encode($purl['user'] . ':' . $purl['pass']) . self::CRLF; } // 追加ヘッダ if ($req->headers) { $request .= $req->headers; } // POSTの時はヘッダを追加して末尾にURLエンコードしたデータを添付 if (strtoupper($req->method) == 'POST') { // 通常はURLエンコードする if (empty($req->noUrlencodePost)) { foreach ($req->post as $name => $value) { $POST[] = $name . '=' . rawurlencode($value); } $postdata_content_type = 'application/x-www-form-urlencoded'; // ●ログインのときなどはURLエンコードしない } else { foreach ($req->post as $name => $value) { $POST[] = $name . '=' . $value; } $postdata_content_type = 'text/plain'; } $postdata = implode('&', $POST); $request .= 'Content-Type: ' . $postdata_content_type . self::CRLF; $request .= 'Content-Length: ' . strlen($postdata) . self::CRLF; $request .= self::CRLF; $request .= $postdata; } else { $request .= self::CRLF; } $res = new WapResponse(); // WEBサーバへ接続 if ($this->_timeout > 0) { if ($this->_atFsockopen) { $fp = @fsockopen($send_host, $send_port, $errno, $errstr, $this->_timeout); } else { $fp = fsockopen($send_host, $send_port, $errno, $errstr, $this->_timeout); } } else { if ($this->_atFsockopen) { $fp = @fsockopen($send_host, $send_port, $errno, $errstr); } else { $fp = fsockopen($send_host, $send_port, $errno, $errstr); } } if (!$fp) { $res->code = $errno; // ex) 602 $res->message = $errstr; // ex) "Connection Failed" return $res; } if ($this->_readTimeout > 0) { stream_set_timeout($fp, $this->_readTimeout, 0); } fputs($fp, $request); $body = ''; // header response while (!p2_stream_eof($fp, $timed_out)) { $l = fgets($fp, 128000); //echo $l."<br>"; // // ex) HTTP/1.1 304 Not Modified if (preg_match('/^(.+?): (.+)\\r\\n/', $l, $matches)) { $res->headers[$matches[1]] = $matches[2]; } elseif (preg_match('/HTTP\\/1\\.\\d (\\d+) (.+)\\r\\n/', $l, $matches)) { $res->code = (int) $matches[1]; $res->message = $matches[2]; $res->headers['HTTP'] = rtrim($l); } elseif ($l == self::CRLF) { break; } } // body response if (!$req->onlyHeader) { while (!p2_stream_eof($fp, $timed_out)) { $body .= fread($fp, 4096); } $res->setContent($body); } fclose($fp); // リダイレクト(301 Moved, 302 Found)を追跡 // RFC2616 - Section 10.3 /*if ($GLOBALS['trace_http_redirect']) { if ($res->code == 301 || ($res->code == 302 && $req->isSafeMethod())) { if (!$this->_redirectCache) { $this->_maxRedirect = 5; $this->_redirectCount = 0; $this->_redirectCache = array(); } while ($res->isRedirect() && isset($res->headers['Location']) && $this->_redirectCount < $this->_maxRedirect) { $this->_redirectCache[] = $res; $req->setUrl($res->headers['Location']); $res = $this->request($req); $this->_redirectCount++; } } } elseif ($res->isRedirect() && isset($res->headers['Location'])) { $res->message .= " (Location: <a href=\"{$res->headers['Location']}\">{$res->headers['Location']}</a>)"; }*/ return $res; }
/** * レスを書き込む * * @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; } }