Guest User

Untitled

a guest
Mar 3rd, 2015
523
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 18.47 KB | None | 0 0
  1.  conf/conf.inc.php          |   1 +
  2.  conf/conf_user_def.inc.php |  17 +++
  3.  lib/ThreadRead.php         | 275 ++++++++++++++++++++++++++++++++++++++++++++-
  4.  lib/auth2chapi.inc.php     |  92 +++++++++++++++
  5.  rep2/edit_conf_user.php    |  18 +++
  6.  5 files changed, 402 insertions(+), 1 deletion(-)
  7.  
  8. diff --git a/conf/conf.inc.php b/conf/conf.inc.php
  9. index 84e50e2..2fec7ae 100644
  10. --- a/conf/conf.inc.php
  11. +++ b/conf/conf.inc.php
  12. @@ -262,6 +262,7 @@ function p2_init()
  13.          'auth_user_file'    => 'p2_auth_user.php',      // 認証ユーザ設定ファイル(データPHP)
  14.          'login_log_file'    => 'p2_login.log.php',      // ログイン履歴 (データPHP)
  15.          'login_failed_log_file' => 'p2_login_failed.dat.php',   // ログイン失敗履歴 (データPHP)
  16. +        'sid2chapi_php'        => 'p2_sid2chapi.php',         // 2ch APIセッションID記録ファイル (データPHP)
  17.      );
  18.      foreach ($preferences as $k => $v) {
  19.          $_conf[$k] = $_conf['pref_dir'] . '/' . $v;
  20. diff --git a/conf/conf_user_def.inc.php b/conf/conf_user_def.inc.php
  21. index 644e4fe..7ba4dae 100644
  22. --- a/conf/conf_user_def.inc.php
  23. +++ b/conf/conf_user_def.inc.php
  24. @@ -374,6 +374,23 @@ $conf_user_def['ngaborn_purge_aborn'] = 0;  // (0)
  25.  $conf_user_rad['ngaborn_purge_aborn'] = array('1' => 'はい', '0' => 'いいえ');
  26.  
  27.  // }}}
  28. +// {{{ 2ch API
  29. +
  30. +// 2ch API を使用する
  31. +$conf_user_def['2chapi_use'] = 1; // (1)
  32. +$conf_user_rad['2chapi_use'] = array('1' => 'する', '0' => 'しない');
  33. +
  34. +// 2ch API 認証時に●(浪人)IDを送信する
  35. +$conf_user_def['2chapi_rounin'] = 0; // (0)
  36. +$conf_user_rad['2chapi_rounin'] = array('1' => 'する', '0' => 'しない');
  37. +
  38. +// APPKey
  39. +$conf_user_def['2chapi_appkey'] = ""; // ("")
  40. +
  41. +// HMKey
  42. +$conf_user_def['2chapi_hmkey'] = ""; // ("")
  43. +
  44. +// }}}
  45.  // {{{ ETC
  46.  
  47.  // レス書き込み時のデフォルトの名前
  48. diff --git a/lib/ThreadRead.php b/lib/ThreadRead.php
  49. index 04680be..e6e13f5 100644
  50. --- a/lib/ThreadRead.php
  51. +++ b/lib/ThreadRead.php
  52. @@ -113,12 +113,282 @@ class ThreadRead extends Thread
  53.  
  54.              // 2ch or 2ch互換
  55.              } elseif (P2Util::isHost2chs($this->host) && !empty($_GET['shirokuma'])) {
  56. -               $this->_downloadDat2chMaru($uaMona, $SID2ch, 'shirokuma');
  57. +                $this->_downloadDat2chMaru($uaMona, $SID2ch, 'shirokuma');
  58. +            //2ch はAPI経由で落とす
  59. +            } elseif (P2Util::isHost2chs($this->host) && $_conf['2chapi_use'] == 1 && empty($_GET['olddat'])) {
  60. +                $AppKey = $_conf['2chapi_appkey'];
  61. +                $HMKey  = $_conf['2chapi_hmkey'];
  62. +                
  63. +                // ログインしてなければ or ログイン後、55分以上経過していたら自動再ログイン
  64. +                if (!file_exists($_conf['sid2chapi_php']) ||
  65. +                    !empty($_REQUEST['relogin2chapi']) ||
  66. +                    (filemtime($_conf['sid2chapi_php']) < time() - 60*55))
  67. +                {
  68. +                    if (!function_exists('authenticate_2chapi')) {
  69. +                        include P2_LIB_DIR . '/auth2chapi.inc.php';
  70. +                    }
  71. +                    if (!authenticate_2chapi($AppKey,$HMKey)) {
  72. +                        $this->getdat_error_msg_ht .= $this->get2chDatError();
  73. +                        $this->diedat = true;
  74. +                        return false;
  75. +                    }
  76. +                }
  77. +
  78. +                include $_conf['sid2chapi_php'];
  79. +                $this->_downloadDat2chAPI($AppKey,$HMKey,$SID2chAPI,$this->length);
  80.              } else {
  81. +                //2ch 以外の外部板
  82.                  // DATを差分DLする
  83.                  $this->_downloadDat2ch($this->length);
  84.              }
  85. +        }
  86. +    }
  87. +
  88. +    // }}}
  89. +    // {{{ _downloadDat2chAPI()
  90. +    
  91. +    /**
  92. +     * 2chAPIで DAT を差分ダウンロードする
  93. +     *
  94. +     * @return mix 取得できたか、更新がなかった場合はtrueを返す
  95. +     */
  96. +    protected function _downloadDat2chAPI($AppKey,$HMKey,$sid,$from_bytes)
  97. +    {
  98. +        global $_conf;
  99. +        global $debug;
  100. +
  101. +        if (!($this->host && $this->bbs && $this->key)) {
  102. +            return false;
  103. +        }
  104. +        
  105. +        if ($sid == '') {
  106. +            return false;
  107. +        }
  108. +
  109. +        $from_bytes = intval($from_bytes);
  110. +
  111. +        if ($from_bytes == 0) {
  112. +            $zero_read = true;
  113. +        } else {
  114. +            $zero_read = false;
  115. +            $from_bytes = $from_bytes - 1;
  116. +        }
  117. +
  118. +        $serverName = explode('.', $this->host);
  119. +        //$url = "http://{$this->host}/{$this->bbs}/dat/{$this->key}.dat";
  120. +        //$url="http://news2.2ch.net/test/read.cgi?bbs=newsplus&key=1038486598";
  121. +        $url = 'https://api.2ch.net/v1/'.$serverName[0].'/'.$this->bbs.'/'.$this->key;
  122. +        $message = '/v1/'.$serverName[0].'/'.$this->bbs.'/'.$this->key.$sid.$AppKey;
  123. +        $HB = hash_hmac("sha256", $message, $HMKey);
  124. +
  125. +        $headers = "User-Agent: Mozilla/3.0 (compatible; JaneStyle/3.80β)\r\n";
  126. +        $headers .= "Connection: close\r\n";
  127. +        $headers .= "Content-Type: application/x-www-form-urlencoded\r\n";
  128. +        
  129. +        $purl = parse_url($url); // URL分解
  130. +
  131. +        if (!$zero_read) {
  132. +            $headers .= "Range: bytes={$from_bytes}-\r\n";
  133. +        }
  134. +
  135. +        if ($this->modified) {
  136. +            $headers .= "If-Modified-Since: {$this->modified}\r\n";
  137. +        }
  138. +
  139. +        // Basic認証用のヘッダ
  140. +        if (isset($purl['user']) && isset($purl['pass'])) {
  141. +            $headers .= "Authorization: Basic ".base64_encode($purl['user'].":".$purl['pass'])."\r\n";
  142. +        }
  143. +        
  144. +        $post_values = array(
  145. +            'sid' => $sid,
  146. +            'hobo' => $HB,
  147. +            'appkey' => $AppKey,
  148. +        );
  149. +        
  150. +        $http = array(
  151. +            'method' => 'POST',
  152. +            'header' => $headers,
  153. +            'ignore_errors'=> true,
  154. +            'content' => http_build_query($post_values),
  155. +        );
  156. +        
  157. +        // プロキシ
  158. +        if ($_conf['proxy_use']) {
  159. +            $http += array('proxy' => 'tcp://'.$_conf['proxy_host'].":".$_conf['proxy_port']);
  160. +            $http += array('request_fulluri' => true);
  161. +        }
  162. +
  163. +        $options = array('http' => $http);
  164. +        
  165. +        // WEBサーバへ接続
  166. +        $fp = @fopen($url, 'r', false, stream_context_create($options));
  167. +        if (!$fp) {
  168. +            self::_pushInfoConnectFailed($url, $errno, $errstr);
  169. +            $this->diedat = true;
  170. +            return false;
  171. +        }
  172. +        stream_set_timeout($fp, $_conf['http_read_timeout'], 0);
  173. +
  174. +        $body = '';
  175. +        $code = null;
  176. +        $start_here = false;
  177.  
  178. +        while (!p2_stream_eof($fp, $timed_out)) {
  179. +
  180. +            if ($start_here) {
  181. +
  182. +                if ($code == '200' || $code == '206') {
  183. +
  184. +                    while (!p2_stream_eof($fp, $timed_out)) {
  185. +                        $body .= fread($fp, 4096);
  186. +                    }
  187. +
  188. +                    if ($timed_out) {
  189. +                        self::_pushInfoReadTimedOut($url);
  190. +                        $this->diedat = true;
  191. +                        fclose($fp);
  192. +                        return false;
  193. +                    }
  194. +                    //1行目を少し切り出す
  195. +                    $firstmsg = substr($body, 0, 50);
  196. +                    if(strstr($firstmsg, 'ng')) {
  197. +                        //ngで始まってたらapiのエラー
  198. +                        fclose($fp);
  199. +                        if (strstr($firstmsg, "not valid")) {
  200. +                            //sidが無効になった可能性。もう一回認証するため最初からやり直し。
  201. +                            if (empty($_REQUEST['relogin2chapi'])) {
  202. +                                $_REQUEST['relogin2chapi'] = true;
  203. +                                return $this->downloadDat();
  204. +                            }
  205. +                        }
  206. +                        $this->getdat_error_msg_ht .= "<p>rep2 error: API経由でのスレッド取得に失敗しました。".trim($firstmsg)."</p>";
  207. +                        $this->getdat_error_msg_ht .= " [<a href=\"{$_conf['read_php']}?host={$this->host}&amp;bbs={$this->bbs}&amp;key={$this->key}&amp;ls={$this->ls}&amp;relogin2chapi=true\">APIで再取得を試みる</a>]";
  208. +                        $this->getdat_error_msg_ht .= " [<a href=\"{$_conf['read_php']}?host={$this->host}&amp;bbs={$this->bbs}&amp;key={$this->key}&amp;ls={$this->ls}&amp;olddat=true\">旧datで再取得を試みる</a>]";
  209. +                        $this->diedat = true;
  210. +                        return false;
  211. +                        
  212. +                    }
  213. +                    unset($firstmsg);
  214. +
  215. +                    // 末尾の改行であぼーんチェック
  216. +                    if (!$zero_read) {
  217. +                        if (substr($body, 0, 1) != "\n") {
  218. +                            //echo "あぼーん検出";
  219. +                            fclose($fp);
  220. +                            $this->onbytes = 0;
  221. +                            $this->modified = null;
  222. +                            return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,0); // あぼーん検出。全部取り直し。
  223. +                        }
  224. +                        $body = substr($body, 1);
  225. +                    }
  226. +
  227. +                    $file_append = ($zero_read) ? 0 : FILE_APPEND;
  228. +
  229. +                    if (FileCtl::file_write_contents($this->keydat, $body, $file_append) === false) {
  230. +                        p2die('cannot write file.');
  231. +                    }
  232. +
  233. +                    //$GLOBALS['debug'] && $GLOBALS['profiler']->enterSection("dat_size_check");
  234. +                    // 取得後サイズチェック
  235. +                    if ($zero_read == false && $this->onbytes) {
  236. +                        $this->getDatBytesFromLocalDat(); // $aThread->length をset
  237. +                        if ($this->onbytes != $this->length) {
  238. +                            fclose($fp);
  239. +                            $this->onbytes = 0;
  240. +                            $this->modified = null;
  241. +                            P2Util::pushInfoHtml("<p>rep2 info: {$this->onbytes}/{$this->length} ファイルサイズが変なので、datを再取得</p>");
  242. +                            //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection("dat_size_check");
  243. +                            return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,0); //datサイズは不正。全部取り直し。
  244. +
  245. +                        // サイズが同じならそのまま
  246. +                        } elseif ($this->onbytes == $this->length) {
  247. +                            fclose($fp);
  248. +                            $this->isonline = true;
  249. +                            //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection('dat_size_check');
  250. +                            return true;
  251. +                        }
  252. +                    }
  253. +                    //$GLOBALS['debug'] && $GLOBALS['profiler']->leaveSection('dat_size_check');
  254. +
  255. +                // スレッドがないと判断
  256. +                } else {
  257. +                    fclose($fp);
  258. +                    return $this->_downloadDat2chNotFound($code);
  259. +                }
  260. +
  261. +            } else {
  262. +                $meta = stream_get_meta_data($fp);
  263. +                foreach($meta['wrapper_data'] as $l)
  264. +                {
  265. +                    // ex) HTTP/1.1 304 Not Modified
  266. +                    if (preg_match('@^HTTP/1\\.\\d (\\d+) (.+)@i', $l, $matches)) {
  267. +                        $code = $matches[1];
  268. +
  269. +                        if ($code == '200' || $code == '206') { // Partial Content
  270. +                            ;
  271. +
  272. +                        } elseif ($code == '302') { // Found
  273. +
  274. +                            // ホストの移転を追跡
  275. +                            $new_host = BbsMap::getCurrentHost($this->host, $this->bbs);
  276. +                            if ($new_host != $this->host) {
  277. +                                fclose($fp);
  278. +                                $this->old_host = $this->host;
  279. +                                $this->host = $new_host;
  280. +                                return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,$from_bytes);
  281. +                            } else {
  282. +                                fclose($fp);
  283. +                                return $this->_downloadDat2chNotFound($code);
  284. +                            }
  285. +
  286. +                        } elseif ($code == '304') { // Not Modified
  287. +                            fclose($fp);
  288. +                            $this->isonline = true;
  289. +                            return '304 Not Modified';
  290. +
  291. +                        } elseif ($code == '416') { // Requested Range Not Satisfiable
  292. +                            //echo "あぼーん検出";
  293. +                            fclose($fp);
  294. +                            $this->onbytes = 0;
  295. +                            $this->modified = null;
  296. +                            return $this->_downloadDat2chAPI($AppKey,$HMKey,$sid,0); // あぼーん検出。全部取り直し。
  297. +
  298. +                        } else {
  299. +                            fclose($fp);
  300. +                            return $this->_downloadDat2chNotFound($code);
  301. +                        }
  302. +                    }
  303. +
  304. +                    if ($zero_read) {
  305. +                        if (preg_match('/^Content-Length: ([0-9]+)/i', $l, $matches)) {
  306. +                            $this->onbytes = intval($matches[1]);
  307. +                        }
  308. +                    } else {
  309. +
  310. +                        if (preg_match('@^Content-Range: bytes ([^/]+)/([0-9]+)@i', $l, $matches)) {
  311. +                            $this->onbytes = intval($matches[2]);
  312. +                        }
  313. +
  314. +                    }
  315. +
  316. +                    if (preg_match('/^Last-Modified: (.+)/i', $l, $matches)) {
  317. +                        //echo $matches[1] . '<br />'; //debug
  318. +                        $this->modified = $matches[1];
  319. +                    }
  320. +                }
  321. +                $start_here = true;
  322. +            }
  323. +        }
  324. +
  325. +        fclose($fp);
  326. +        if ($timed_out) {
  327. +            self::_pushInfoReadTimedOut($url);
  328. +            $this->diedat = true;
  329. +            return false;
  330. +        } else {
  331. +            $this->isonline = true;
  332. +            return true;
  333.          }
  334.      }
  335.  
  336. @@ -760,6 +1030,9 @@ class ThreadRead extends Thread
  337.                      $reason = 'kakohtml';
  338.                  }
  339.              }
  340. +        } elseif (P2Util::isHost2chs($this->host) && $code == '404') {
  341. +            //APIの為404だったら過去ログと決めつけとく(fix Here)
  342. +            $reason = 'datochi';
  343.          }
  344.  
  345.          $read_url = "http://{$this->host}/test/read.cgi/{$this->bbs}/{$this->key}/";
  346. diff --git a/lib/auth2chapi.inc.php b/lib/auth2chapi.inc.php
  347. new file mode 100644
  348. index 0000000..dc697b8
  349. --- /dev/null
  350. +++ b/lib/auth2chapi.inc.php
  351. @@ -0,0 +1,92 @@
  352. +<?php
  353. +/**
  354. + * rep2 - 2chログイン
  355. + */
  356. +
  357. +// {{{ authenticate_2chapi()
  358. +
  359. +
  360. +/**
  361. +* 2chAPIの SID を取得する
  362. +*
  363. +* @return mix 取得できた場合はSIDを返す
  364. +*/
  365. +    function authenticate_2chapi($AppKey, $HMKey)
  366. +    {
  367. +       global $_conf;
  368. +        $url = 'https://api.2ch.net/v1/auth/';
  369. +        $CT = time();
  370. +        $login2chID = "";
  371. +        $login2chPW = "";
  372. +        $message = $AppKey.$CT;
  373. +        $HB = hash_hmac("sha256", $message, $HMKey);
  374. +        
  375. +        if ($_conf['2chapi_rounin'] == 1&& $array = P2Util::readIdPw2ch()) {
  376. +            list($login2chID, $login2chPW, $autoLogin2ch) = $array;
  377. +        }
  378. +        
  379. +        $values = array(
  380. +            'ID' => $login2chID,
  381. +            'PW' => $login2chPW,
  382. +            'KY' => $AppKey,
  383. +            'CT' => $CT,
  384. +            'HB' => $HB,
  385. +        );
  386. +        $options = array('http' => array(
  387. +            'ignore_errors' => true,
  388. +            'method' => 'POST',
  389. +            'header' => implode("\r\n", array(
  390. +                'User-Agent: Monazilla/1.3',
  391. +                'X-2ch-UA: JaneStyle/3.80',
  392. +                'Content-Type: application/x-www-form-urlencoded',
  393. +            )),
  394. +            'content' => http_build_query($values),
  395. +        ));
  396. +        
  397. +        // プロキシ
  398. +        if ($_conf['proxy_use']) {
  399. +            $options['http'] += array('proxy' => 'tcp://'.$_conf['proxy_host'].":".$_conf['proxy_port']);
  400. +            $options['http'] += array('request_fulluri' => true);
  401. +        }
  402. +        
  403. +        $response = '';
  404. +        $response = file_get_contents($url, false, stream_context_create($options));
  405. +        
  406. +        if(file_exists($_conf['sid2chapi_php'])) {
  407. +            unlink($_conf['sid2chapi_php']);
  408. +        }
  409. +        
  410. +        if (strpos($response, ':') != false)
  411. +        {
  412. +            $sid = explode(':', $response);
  413. +            
  414. +            P2Util::pushInfoHtml($response);
  415. +            
  416. +            if($sid[0]!='SESSION-ID=Monazilla/1.00') {
  417. +                P2Util::pushInfoHtml("<p>p2 Error: 2ch API のSessionIDを取得出来ませんでした。</p>");
  418. +                return '';
  419. +            }
  420. +            
  421. +            $cont = sprintf('<?php $SID2chAPI = %s;', var_export($sid[1], true));
  422. +            if (false === file_put_contents($_conf['sid2chapi_php'], $cont, LOCK_EX)) {
  423. +                P2Util::pushInfoHtml("<p>p2 Error: {$_conf['sid2chapi_php']} を保存できませんでした。ログイン登録失敗。</p>");
  424. +                return '';
  425. +            }
  426. +            
  427. +            return $sid[1];
  428. +        }
  429. +        
  430. +        return '';
  431. +    }
  432. +// }}}
  433. +
  434. +/*
  435. + * Local Variables:
  436. + * mode: php
  437. + * coding: cp932
  438. + * tab-width: 4
  439. + * c-basic-offset: 4
  440. + * indent-tabs-mode: nil
  441. + * End:
  442. + */
  443. +// vim: set syn=php fenc=cp932 ai et ts=4 sw=4 sts=4 fdm=marker:
  444. diff --git a/rep2/edit_conf_user.php b/rep2/edit_conf_user.php
  445. index 1dcc97f..11a52d7 100644
  446. --- a/rep2/edit_conf_user.php
  447. +++ b/rep2/edit_conf_user.php
  448. @@ -360,6 +360,24 @@ if ($flags & P2_EDIT_CONF_USER_SKIPPED) {
  449.  }
  450.  
  451.  // }}}
  452. +// {{{ '2ch API'
  453. +
  454. +$groupname = '2ch API';
  455. +$groups[] = $groupname;
  456. +$flags = getGroupShowFlags($groupname);
  457. +if ($flags & P2_EDIT_CONF_USER_SKIPPED) {
  458. +    $keep_old = true;
  459. +} else {
  460. +    $conflist = array(
  461. +        array('2chapi_use','2ch API を使用する'),
  462. +        array('2chapi_rounin','2ch API 認証時に●(浪人)IDを送信する(人柱機能)'),
  463. +        array('2chapi_appkey','AppKey'),
  464. +        array('2chapi_hmkey','HMkey'),
  465. +    );
  466. +    printEditConfGroupHtml($groupname, $conflist, $flags);
  467. +}
  468. +
  469. +// }}}
  470.  // {{{ ETC
  471.  
  472.  $groupname = 'ETC';
Add Comment
Please, Sign In to add comment