Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- conf/conf.inc.php | 1 +
- lib/ThreadRead.php | 247 +++++++++++++++++++++++++++++++++++++++++++++++++
- lib/auth2chapi.inc.php | 74 +++++++++++++++
- 3 files changed, 322 insertions(+)
- diff --git a/conf/conf.inc.php b/conf/conf.inc.php
- index 62ff466..feec1bd 100644
- --- a/conf/conf.inc.php
- +++ b/conf/conf.inc.php
- @@ -261,6 +261,7 @@ function p2_init()
- 'auth_user_file' => 'p2_auth_user.php', // 認証ユーザ設定ファイル(データPHP)
- 'login_log_file' => 'p2_login.log.php', // ログイン履歴 (データPHP)
- 'login_failed_log_file' => 'p2_login_failed.dat.php', // ログイン失敗履歴 (データPHP)
- + 'sid2chapi_php' => 'p2_sid2chapi.php', // 2ch APIセッションID記録ファイル (データPHP)
- );
- foreach ($preferences as $k => $v) {
- $_conf[$k] = $_conf['pref_dir'] . '/' . $v;
- diff --git a/lib/ThreadRead.php b/lib/ThreadRead.php
- index 1d76626..52d200b 100644
- --- a/lib/ThreadRead.php
- +++ b/lib/ThreadRead.php
- @@ -110,6 +110,26 @@ class ThreadRead extends Thread
- }
- $this->_downloadDat2chKako($_GET['kakolog'], $ext);
- + //2ch はAPI経由で落とす
- + } elseif (P2Util::isHost2chs($this->host)) {
- + $AppKey = 'xxfvFQcOzpTBvwuwPMwwzLZxiCSaGb';
- + $HMKey = 'DgQ3aNpoluV1cl3GFJAqitBg5xKiXZ';
- + // ログインしてなければ or ログイン後、55分以上経過していたら自動再ログイン
- + if (!file_exists($_conf['sid2chapi_php']) ||
- + (filemtime($_conf['sid2chapi_php']) < time() - 60*55))
- + {
- + if (!function_exists('authenticate_2chapi')) {
- + include P2_LIB_DIR . '/auth2chapi.inc.php';
- + }
- + if (!authenticate_2chapi($AppKey,$HMKey)) {
- + $this->getdat_error_msg_ht .= $this->get2chDatError();
- + $this->diedat = true;
- + return false;
- + }
- + }
- +
- + include $_conf['sid2chapi_php'];
- + $this->_downloadDat2chAPI($AppKey,$HMKey,$SID2chAPI,$this->length);
- // 2ch or 2ch互換
- } else {
- // DATを差分DLする
- @@ -120,6 +140,233 @@ class ThreadRead extends Thread
- }
- // }}}
- + // {{{ _downloadDat2chAPI()
- +
- + /**
- + * 2chAPIで DAT を差分ダウンロードする
- + *
- + * @return mix 取得できたか、更新がなかった場合はtrueを返す
- + */
- + protected function _downloadDat2chAPI($AppKey,$HMKey,$sid,$from_bytes)
- + {
- + global $_conf;
- + global $debug;
- +
- + if (!($this->host && $this->bbs && $this->key)) {
- + return false;
- + }
- +
- + if ($sid == '') {
- + return false;
- + }
- +
- + $from_bytes = intval($from_bytes);
- +
- + if ($from_bytes == 0) {
- + $zero_read = true;
- + } else {
- + $zero_read = false;
- + $from_bytes = $from_bytes - 1;
- + }
- +
- + $serverName = explode('.', $this->host);
- + //$url = "http://{$this->host}/{$this->bbs}/dat/{$this->key}.dat";
- + //$url="http://news2.2ch.net/test/read.cgi?bbs=newsplus&key=1038486598";
- + $url = 'https://api.2ch.net/v1/'.$serverName[0].'/'.$this->bbs.'/'.$this->key;
- + $message = '/v1/'.$serverName[0].'/'.$this->bbs.'/'.$this->key.$sid.$AppKey;
- + $HB = hash_hmac("sha256", $message, $HMKey);
- +
- + $headers = "User-Agent: Mozilla/3.0 (compatible; JaneStyle/3.80..)\r\n";
- + $headers .= "Connection: close\r\n";
- + $headers .= "Content-Type: application/x-www-form-urlencoded\r\n";
- +
- + $purl = parse_url($url); // URL分解
- +
- + if (!$zero_read) {
- + $headers .= "Range: bytes={$from_bytes}-\r\n";
- + }
- +
- + if ($this->modified) {
- + $headers .= "If-Modified-Since: {$this->modified}\r\n";
- + }
- +
- + // Basic認証用のヘッダ
- + if (isset($purl['user']) && isset($purl['pass'])) {
- + $headers .= "Authorization: Basic ".base64_encode($purl['user'].":".$purl['pass'])."\r\n";
- + }
- +
- + $post_values = array(
- + 'sid' => $sid,
- + 'hobo' => $HB,
- + 'appkey' => $AppKey,
- + );
- +
- + $http = array(
- + 'method' => 'POST',
- + 'header' => $headers,
- + 'content' => http_build_query($post_values),
- + );
- +
- + // プロキシ
- + if ($_conf['proxy_use']) {
- + $http += array('proxy' => 'tcp://'.$_conf['proxy_host'].":".$_conf['proxy_port']);
- + $http += array('request_fulluri' => true);
- + }
- +
- + $options = array('http' => $http);
- +
- + // WEBサーバへ接続
- + $fp = @fopen($url, 'r', false, stream_context_create($options));
- + if (!$fp) {
- + self::_pushInfoConnectFailed($url, $errno, $errstr);
- + $this->diedat = true;
- + return false;
- + }
- + stream_set_timeout($fp, $_conf['http_read_timeout'], 0);
- +
- + $body = '';
- + $code = null;
- + $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)) {
- + $body .= fread($fp, 4096);
- + }
- +
- + if ($timed_out) {
- + self::_pushInfoReadTimedOut($url);
- + $this->diedat = true;
- + fclose($fp);
- + return false;
- + }
- +
- + // 末尾の改行であぼーんチェック
- + if (!$zero_read) {
- + if (substr($body, 0, 1) != "\n") {
- + //echo "あぼーん検出";
- + fclose($fp);
- + $this->onbytes = 0;
- + $this->modified = null;
- + return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,0); // あぼーん検出。全部取り直し。
- + }
- + $body = substr($body, 1);
- + }
- +
- + $file_append = ($zero_read) ? 0 : FILE_APPEND;
- +
- + if (FileCtl::file_write_contents($this->keydat, $body, $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);
- + $this->onbytes = 0;
- + $this->modified = null;
- + P2Util::pushInfoHtml("<p>rep2 info: {$this->onbytes}/{$this->length} ファイルサイズが変なので、datを再取得</p>");
- + //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection("dat_size_check");
- + return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,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($code);
- + }
- +
- + } else {
- + $meta = stream_get_meta_data($fp);
- + foreach($meta['wrapper_data'] as $l)
- + {
- + // ex) HTTP/1.1 304 Not Modified
- + if (preg_match('@^HTTP/1\\.\\d (\\d+) (.+)@i', $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->_downloadDat2chAPI($AppKey,$HMKey,$sid,$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);
- + $this->onbytes = 0;
- + $this->modified = null;
- + return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,0); // あぼーん検出。全部取り直し。
- +
- + } else {
- + fclose($fp);
- + return $this->_downloadDat2chNotFound($code);
- + }
- + }
- +
- + if ($zero_read) {
- + if (preg_match('/^Content-Length: ([0-9]+)/i', $l, $matches)) {
- + $this->onbytes = intval($matches[1]);
- + }
- + } else {
- +
- + if (preg_match('@^Content-Range: bytes ([^/]+)/([0-9]+)@i', $l, $matches)) {
- + $this->onbytes = intval($matches[2]);
- + }
- +
- + }
- +
- + if (preg_match('/^Last-Modified: (.+)/i', $l, $matches)) {
- + //echo $matches[1] . '<br />'; //debug
- + $this->modified = $matches[1];
- + }
- + }
- + $start_here = true;
- + }
- + }
- +
- + fclose($fp);
- + if ($timed_out) {
- + self::_pushInfoReadTimedOut($url);
- + $this->diedat = true;
- + return false;
- + } else {
- + $this->isonline = true;
- + return true;
- + }
- + }
- +
- + // }}}
- // {{{ _downloadDat2ch()
- /**
- diff --git a/lib/auth2chapi.inc.php b/lib/auth2chapi.inc.php
- new file mode 100644
- index 0000000..cf342f4
- --- /dev/null
- +++ b/lib/auth2chapi.inc.php
- @@ -0,0 +1,74 @@
- +<?php
- +/**
- + * rep2 - 2chログイン
- + */
- +
- +// {{{ authenticate_2chapi()
- +
- +/**
- + * 2ch IDにログインする
- + *
- + * @return string|false 成功したら2chAPI SIDを返す
- + */
- +
- +
- +/**
- + * 2chAPIの SID を取得する
- + *
- + * @return mix 取得できた場合はSIDを返す
- + */
- + function authenticate_2chapi($AppKey, $HMKey)
- + {
- + global $_conf;
- + $url = 'https://api.2ch.net/v1/auth/';
- + $CT = time();
- + $message = $AppKey.$CT;
- + $HB = hash_hmac("sha256", $message, $HMKey);
- + $values = array(
- + 'ID' => '',
- + 'PW' => '',
- + 'KY' => $AppKey,
- + 'CT' => $CT,
- + 'HB' => $HB,
- + );
- + $options = array('http' => array(
- + 'ignore_errors' => true,
- + 'method' => 'POST',
- + 'header' => implode("\r\n", array(
- + 'User-Agent: ',
- + 'X-2ch-UA: JaneStyle/3.80',
- + 'Content-Type: application/x-www-form-urlencoded',
- + )),
- + 'content' => http_build_query($values),
- + ));
- +
- + $response = '';
- + $response = file_get_contents($url, false, stream_context_create($options));
- +
- + if (strpos($response, ':') != false)
- + {
- + $sid = explode(':', $response);
- +
- + $cont = sprintf('<?php $SID2chAPI = %s;', var_export($sid[1], true));
- + if (false === file_put_contents($_conf['sid2chapi_php'], $cont, LOCK_EX)) {
- + P2Util::pushInfoHtml("<p>p2 Error: {$_conf['sid2chapi_php']} を保存できませんでした。ログイン登録失敗。</p>");
- + return '';
- + }
- +
- + return $sid[1];
- + }
- +
- + return '';
- + }
- +// }}}
- +
- +/*
- + * Local Variables:
- + * mode: php
- + * coding: cp932
- + * tab-width: 4
- + * c-basic-offset: 4
- + * indent-tabs-mode: nil
- + * End:
- + */
- +// vim: set syn=php fenc=cp932 ai et ts=4 sw=4 sts=4 fdm=marker:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement