Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- conf/conf.inc.php | 1 +
- conf/conf_user_def.inc.php | 17 +++
- lib/ThreadRead.php | 275 ++++++++++++++++++++++++++++++++++++++++++++-
- lib/auth2chapi.inc.php | 92 +++++++++++++++
- rep2/edit_conf_user.php | 18 +++
- 5 files changed, 402 insertions(+), 1 deletion(-)
- diff --git a/conf/conf.inc.php b/conf/conf.inc.php
- index 84e50e2..2fec7ae 100644
- --- a/conf/conf.inc.php
- +++ b/conf/conf.inc.php
- @@ -262,6 +262,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/conf/conf_user_def.inc.php b/conf/conf_user_def.inc.php
- index 644e4fe..7ba4dae 100644
- --- a/conf/conf_user_def.inc.php
- +++ b/conf/conf_user_def.inc.php
- @@ -374,6 +374,23 @@ $conf_user_def['ngaborn_purge_aborn'] = 0; // (0)
- $conf_user_rad['ngaborn_purge_aborn'] = array('1' => 'はい', '0' => 'いいえ');
- // }}}
- +// {{{ 2ch API
- +
- +// 2ch API を使用する
- +$conf_user_def['2chapi_use'] = 1; // (1)
- +$conf_user_rad['2chapi_use'] = array('1' => 'する', '0' => 'しない');
- +
- +// 2ch API 認証時に●(浪人)IDを送信する
- +$conf_user_def['2chapi_rounin'] = 0; // (0)
- +$conf_user_rad['2chapi_rounin'] = array('1' => 'する', '0' => 'しない');
- +
- +// APPKey
- +$conf_user_def['2chapi_appkey'] = ""; // ("")
- +
- +// HMKey
- +$conf_user_def['2chapi_hmkey'] = ""; // ("")
- +
- +// }}}
- // {{{ ETC
- // レス書き込み時のデフォルトの名前
- diff --git a/lib/ThreadRead.php b/lib/ThreadRead.php
- index 04680be..e6e13f5 100644
- --- a/lib/ThreadRead.php
- +++ b/lib/ThreadRead.php
- @@ -113,12 +113,282 @@ class ThreadRead extends Thread
- // 2ch or 2ch互換
- } elseif (P2Util::isHost2chs($this->host) && !empty($_GET['shirokuma'])) {
- - $this->_downloadDat2chMaru($uaMona, $SID2ch, 'shirokuma');
- + $this->_downloadDat2chMaru($uaMona, $SID2ch, 'shirokuma');
- + //2ch はAPI経由で落とす
- + } elseif (P2Util::isHost2chs($this->host) && $_conf['2chapi_use'] == 1 && empty($_GET['olddat'])) {
- + $AppKey = $_conf['2chapi_appkey'];
- + $HMKey = $_conf['2chapi_hmkey'];
- +
- + // ログインしてなければ or ログイン後、55分以上経過していたら自動再ログイン
- + if (!file_exists($_conf['sid2chapi_php']) ||
- + !empty($_REQUEST['relogin2chapi']) ||
- + (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);
- } else {
- + //2ch 以外の外部板
- // DATを差分DLする
- $this->_downloadDat2ch($this->length);
- }
- + }
- + }
- +
- + // }}}
- + // {{{ _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,
- + 'ignore_errors'=> true,
- + '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;
- + }
- + //1行目を少し切り出す
- + $firstmsg = substr($body, 0, 50);
- + if(strstr($firstmsg, 'ng')) {
- + //ngで始まってたらapiのエラー
- + fclose($fp);
- + if (strstr($firstmsg, "not valid")) {
- + //sidが無効になった可能性。もう一回認証するため最初からやり直し。
- + if (empty($_REQUEST['relogin2chapi'])) {
- + $_REQUEST['relogin2chapi'] = true;
- + return $this->downloadDat();
- + }
- + }
- + $this->getdat_error_msg_ht .= "<p>rep2 error: API経由でのスレッド取得に失敗しました。".trim($firstmsg)."</p>";
- + $this->getdat_error_msg_ht .= " [<a href=\"{$_conf['read_php']}?host={$this->host}&bbs={$this->bbs}&key={$this->key}&ls={$this->ls}&relogin2chapi=true\">APIで再取得を試みる</a>]";
- + $this->getdat_error_msg_ht .= " [<a href=\"{$_conf['read_php']}?host={$this->host}&bbs={$this->bbs}&key={$this->key}&ls={$this->ls}&olddat=true\">旧datで再取得を試みる</a>]";
- + $this->diedat = true;
- + return false;
- +
- + }
- + unset($firstmsg);
- +
- + // 末尾の改行であぼーんチェック
- + 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;
- }
- }
- @@ -760,6 +1030,9 @@ class ThreadRead extends Thread
- $reason = 'kakohtml';
- }
- }
- + } elseif (P2Util::isHost2chs($this->host) && $code == '404') {
- + //APIの為404だったら過去ログと決めつけとく(fix Here)
- + $reason = 'datochi';
- }
- $read_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/";
- diff --git a/lib/auth2chapi.inc.php b/lib/auth2chapi.inc.php
- new file mode 100644
- index 0000000..dc697b8
- --- /dev/null
- +++ b/lib/auth2chapi.inc.php
- @@ -0,0 +1,92 @@
- +<?php
- +/**
- + * rep2 - 2chログイン
- + */
- +
- +// {{{ authenticate_2chapi()
- +
- +
- +/**
- +* 2chAPIの SID を取得する
- +*
- +* @return mix 取得できた場合はSIDを返す
- +*/
- + function authenticate_2chapi($AppKey, $HMKey)
- + {
- + global $_conf;
- + $url = 'https://api.2ch.net/v1/auth/';
- + $CT = time();
- + $login2chID = "";
- + $login2chPW = "";
- + $message = $AppKey.$CT;
- + $HB = hash_hmac("sha256", $message, $HMKey);
- +
- + if ($_conf['2chapi_rounin'] == 1&& $array = P2Util::readIdPw2ch()) {
- + list($login2chID, $login2chPW, $autoLogin2ch) = $array;
- + }
- +
- + $values = array(
- + 'ID' => $login2chID,
- + 'PW' => $login2chPW,
- + 'KY' => $AppKey,
- + 'CT' => $CT,
- + 'HB' => $HB,
- + );
- + $options = array('http' => array(
- + 'ignore_errors' => true,
- + 'method' => 'POST',
- + 'header' => implode("\r\n", array(
- + 'User-Agent: Monazilla/1.3',
- + 'X-2ch-UA: JaneStyle/3.80',
- + 'Content-Type: application/x-www-form-urlencoded',
- + )),
- + 'content' => http_build_query($values),
- + ));
- +
- + // プロキシ
- + if ($_conf['proxy_use']) {
- + $options['http'] += array('proxy' => 'tcp://'.$_conf['proxy_host'].":".$_conf['proxy_port']);
- + $options['http'] += array('request_fulluri' => true);
- + }
- +
- + $response = '';
- + $response = file_get_contents($url, false, stream_context_create($options));
- +
- + if(file_exists($_conf['sid2chapi_php'])) {
- + unlink($_conf['sid2chapi_php']);
- + }
- +
- + if (strpos($response, ':') != false)
- + {
- + $sid = explode(':', $response);
- +
- + P2Util::pushInfoHtml($response);
- +
- + if($sid[0]!='SESSION-ID=Monazilla/1.00') {
- + P2Util::pushInfoHtml("<p>p2 Error: 2ch API のSessionIDを取得出来ませんでした。</p>");
- + return '';
- + }
- +
- + $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:
- diff --git a/rep2/edit_conf_user.php b/rep2/edit_conf_user.php
- index 1dcc97f..11a52d7 100644
- --- a/rep2/edit_conf_user.php
- +++ b/rep2/edit_conf_user.php
- @@ -360,6 +360,24 @@ if ($flags & P2_EDIT_CONF_USER_SKIPPED) {
- }
- // }}}
- +// {{{ '2ch API'
- +
- +$groupname = '2ch API';
- +$groups[] = $groupname;
- +$flags = getGroupShowFlags($groupname);
- +if ($flags & P2_EDIT_CONF_USER_SKIPPED) {
- + $keep_old = true;
- +} else {
- + $conflist = array(
- + array('2chapi_use','2ch API を使用する'),
- + array('2chapi_rounin','2ch API 認証時に●(浪人)IDを送信する(人柱機能)'),
- + array('2chapi_appkey','AppKey'),
- + array('2chapi_hmkey','HMkey'),
- + );
- + printEditConfGroupHtml($groupname, $conflist, $flags);
- +}
- +
- +// }}}
- // {{{ ETC
- $groupname = 'ETC';
Add Comment
Please, Sign In to add comment