diff --git a/README.md b/README.md index 36c988f1f..d797e4e54 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ TorrentPier - движок торрент-трекера, написанный > ***'db1' => array('localhost', 'tp_216', 'user', 'pass', $charset, $pconnect)*** В данной строке изменяем данные входа в базу данных ***$domain_name = 'torrentpier.me';*** -В данной строке указываем ваше доменное имя. Остальные правки в файле вносятся по усмотрению, исходя из необходимости из внесения (ориентируйтесь на описания, указанные у полей). +В данной строке указываем ваше доменное имя. Остальные правки в файле вносятся по усмотрению, исходя из необходимости из внесения (ориентируйтесь на описания, указанные у полей). Также вы можете создать файл **library/config.local.php** в который продублировать все изменяемые значения, чтобы была возможность обновления основного файла конфигурации через git. Значения из этого файла будут иметь приоритет перед всеми остальными. 4. Редактируем указанные файлы: + **favicon.ico** (меняем на свою иконку, если есть) diff --git a/ajax.php b/ajax.php index d98d2804e..3c154750d 100644 --- a/ajax.php +++ b/ajax.php @@ -76,35 +76,35 @@ $ajax->exec(); // class ajax_common { - var $request = array(); - var $response = array(); + var $request = []; + var $response = []; - var $valid_actions = array( + var $valid_actions = [ // ACTION NAME AJAX_AUTH - 'edit_user_profile' => array('admin'), - 'change_user_rank' => array('admin'), - 'change_user_opt' => array('admin'), - 'manage_user' => array('admin'), - 'manage_admin' => array('admin'), - 'sitemap' => array('admin'), + 'edit_user_profile' => ['admin'], + 'change_user_rank' => ['admin'], + 'change_user_opt' => ['admin'], + 'manage_user' => ['admin'], + 'manage_admin' => ['admin'], + 'sitemap' => ['admin'], - 'mod_action' => array('mod'), - 'topic_tpl' => array('mod'), - 'group_membership' => array('mod'), - 'post_mod_comment' => array('mod'), + 'mod_action' => ['mod'], + 'topic_tpl' => ['mod'], + 'group_membership' => ['mod'], + 'post_mod_comment' => ['mod'], - 'avatar' => array('user'), - 'gen_passkey' => array('user'), - 'change_torrent' => array('user'), - 'change_tor_status' => array('user'), - 'manage_group' => array('user'), + 'avatar' => ['user'], + 'gen_passkey' => ['user'], + 'change_torrent' => ['user'], + 'change_tor_status' => ['user'], + 'manage_group' => ['user'], - 'view_post' => array('guest'), - 'view_torrent' => array('guest'), - 'user_register' => array('guest'), - 'posts' => array('guest'), - 'index_data' => array('guest'), - ); + 'view_post' => ['guest'], + 'view_torrent' => ['guest'], + 'user_register' => ['guest'], + 'posts' => ['guest'], + 'index_data' => ['guest'], + ]; var $action = null; @@ -113,7 +113,7 @@ class ajax_common */ function ajax_common() { - ob_start(array(&$this, 'ob_handler')); + ob_start([&$this, 'ob_handler']); header('Content-Type: text/plain'); } @@ -273,10 +273,10 @@ class ajax_common } else { - $login_args = array( + $login_args = [ 'login_username' => $user->data['username'], 'login_password' => $_POST['user_password'], - ); + ]; if (!$user->login($login_args, true)) { $this->ajax_die('Wrong password'); diff --git a/callseed.php b/callseed.php index 33786bc7d..dd7fec431 100644 --- a/callseed.php +++ b/callseed.php @@ -5,7 +5,7 @@ define('BB_ROOT', './'); require(BB_ROOT . 'common.php'); // Init userdata -$user->session_start(array('req_login' => true)); +$user->session_start(['req_login' => true]); $topic_id = (int) request_var('t', 0); $t_data = topic_info($topic_id); @@ -23,7 +23,7 @@ elseif ($t_data['call_seed_time'] > (TIMENOW - 86400)) bb_die(sprintf($lang['CALLSEED_MSG_SPAM'], $time_left)); } -$ban_user_id = array(); +$ban_user_id = []; $sql = DB()->fetch_rowset("SELECT ban_userid FROM ". BB_BANLIST ." WHERE ban_userid != 0"); diff --git a/library/TorrentPier/ReCaptcha/ReCaptcha.php b/library/TorrentPier/ReCaptcha/ReCaptcha.php new file mode 100755 index 000000000..b97a2ae25 --- /dev/null +++ b/library/TorrentPier/ReCaptcha/ReCaptcha.php @@ -0,0 +1,97 @@ +secret = $secret; + + if (!is_null($requestMethod)) { + $this->requestMethod = $requestMethod; + } else { + $this->requestMethod = new RequestMethod\Post(); + } + } + + /** + * Calls the reCAPTCHA siteverify API to verify whether the user passes + * CAPTCHA test. + * + * @param string $response The value of 'g-recaptcha-response' in the submitted form. + * @param string $remoteIp The end user's IP address. + * @return Response Response from the service. + */ + public function verify($response, $remoteIp = null) + { + // Discard empty solution submissions + if (empty($response)) { + $recaptchaResponse = new Response(false, array('missing-input-response')); + return $recaptchaResponse; + } + + $params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION); + $rawResponse = $this->requestMethod->submit($params); + return Response::fromJson($rawResponse); + } +} \ No newline at end of file diff --git a/library/TorrentPier/ReCaptcha/RequestMethod.php b/library/TorrentPier/ReCaptcha/RequestMethod.php new file mode 100755 index 000000000..58015cb62 --- /dev/null +++ b/library/TorrentPier/ReCaptcha/RequestMethod.php @@ -0,0 +1,42 @@ + array( + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => $params->toQueryString(), + // Force the peer to validate (not needed in 5.6.0+, but still works + 'verify_peer' => true, + // Force the peer validation to use www.google.com + $peer_key => 'www.google.com', + ), + ); + $context = stream_context_create($options); + return file_get_contents(self::SITE_VERIFY_URL, false, $context); + } +} \ No newline at end of file diff --git a/library/TorrentPier/ReCaptcha/RequestMethod/Socket.php b/library/TorrentPier/ReCaptcha/RequestMethod/Socket.php new file mode 100755 index 000000000..dd2091c06 --- /dev/null +++ b/library/TorrentPier/ReCaptcha/RequestMethod/Socket.php @@ -0,0 +1,104 @@ +handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout)); + + if ($this->handle != false && $errno === 0 && $errstr === '') { + return $this->handle; + } else { + return false; + } + } + + /** + * fwrite + * + * @see http://php.net/fwrite + * @param string $string + * @param int $length + * @return int | bool + */ + public function fwrite($string, $length = null) + { + return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length)); + } + + /** + * fgets + * + * @see http://php.net/fgets + * @param int $length + */ + public function fgets($length = null) + { + return fgets($this->handle, $length); + } + + /** + * feof + * + * @see http://php.net/feof + * @return bool + */ + public function feof() + { + return feof($this->handle); + } + + /** + * fclose + * + * @see http://php.net/fclose + * @return bool + */ + public function fclose() + { + return fclose($this->handle); + } +} \ No newline at end of file diff --git a/library/TorrentPier/ReCaptcha/RequestMethod/SocketPost.php b/library/TorrentPier/ReCaptcha/RequestMethod/SocketPost.php new file mode 100755 index 000000000..a09430ac5 --- /dev/null +++ b/library/TorrentPier/ReCaptcha/RequestMethod/SocketPost.php @@ -0,0 +1,120 @@ +socket = $socket; + } else { + $this->socket = new Socket(); + } + } + + /** + * Submit the POST request with the specified parameters. + * + * @param RequestParameters $params Request parameters + * @return string Body of the reCAPTCHA response + */ + public function submit(RequestParameters $params) + { + $errno = 0; + $errstr = ''; + + if ($this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30) !== false) { + $content = $params->toQueryString(); + + $request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n"; + $request .= "Host: " . self::RECAPTCHA_HOST . "\r\n"; + $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $request .= "Content-length: " . strlen($content) . "\r\n"; + $request .= "Connection: close\r\n\r\n"; + $request .= $content . "\r\n\r\n"; + + $this->socket->fwrite($request); + $response = ''; + + while (!$this->socket->feof()) { + $response .= $this->socket->fgets(4096); + } + + $this->socket->fclose(); + + if (0 === strpos($response, 'HTTP/1.1 200 OK')) { + $parts = preg_split("#\n\s*\n#Uis", $response); + return $parts[1]; + } + + return self::BAD_RESPONSE; + } + + return self::BAD_REQUEST; + } +} \ No newline at end of file diff --git a/library/TorrentPier/ReCaptcha/RequestParameters.php b/library/TorrentPier/ReCaptcha/RequestParameters.php new file mode 100755 index 000000000..d3d46f461 --- /dev/null +++ b/library/TorrentPier/ReCaptcha/RequestParameters.php @@ -0,0 +1,103 @@ +secret = $secret; + $this->response = $response; + $this->remoteIp = $remoteIp; + $this->version = $version; + } + + /** + * Array representation. + * + * @return array Array formatted parameters. + */ + public function toArray() + { + $params = array('secret' => $this->secret, 'response' => $this->response); + + if (!is_null($this->remoteIp)) { + $params['remoteip'] = $this->remoteIp; + } + + if (!is_null($this->version)) { + $params['version'] = $this->version; + } + + return $params; + } + + /** + * Query string representation for HTTP request. + * + * @return string Query string formatted parameters. + */ + public function toQueryString() + { + return http_build_query($this->toArray(), '', '&'); + } +} \ No newline at end of file diff --git a/library/TorrentPier/ReCaptcha/Response.php b/library/TorrentPier/ReCaptcha/Response.php new file mode 100755 index 000000000..c1c77aa4d --- /dev/null +++ b/library/TorrentPier/ReCaptcha/Response.php @@ -0,0 +1,102 @@ +success = $success; + $this->errorCodes = $errorCodes; + } + + /** + * Is success? + * + * @return boolean + */ + public function isSuccess() + { + return $this->success; + } + + /** + * Get error codes. + * + * @return array + */ + public function getErrorCodes() + { + return $this->errorCodes; + } +} \ No newline at end of file diff --git a/library/config.php b/library/config.php index eca52e2a6..51bc9ee30 100644 --- a/library/config.php +++ b/library/config.php @@ -262,6 +262,7 @@ define('CLASS_DIR', BB_PATH .'/library/includes/classes/'); define('CORE_DIR', BB_PATH .'/library/includes/core/' ); define('UCP_DIR', BB_PATH .'/library/includes/ucp/' ); define('LANG_ROOT_DIR', BB_PATH .'/library/language/' ); +define('TP_AUTO_DIR', BB_PATH .'/library/TorrentPier/' ); define('IMAGES_DIR', BB_PATH .'/styles/images/' ); define('TEMPLATES_DIR', BB_PATH .'/styles/templates/' ); @@ -347,7 +348,7 @@ $page_cfg['show_sidebar2'] = array( // Cookie $bb_cfg['cookie_domain'] = in_array($domain_name, array(getenv('SERVER_ADDR'), 'localhost')) ? '' : ".$domain_name"; -$bb_cfg['cookie_secure'] = (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') ? 1 : 0); +$bb_cfg['cookie_secure'] = (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') ? 1 : 0; $bb_cfg['cookie_prefix'] = 'bb_'; // 'bb_' // Sessions diff --git a/library/includes/classes/recaptcha.php b/library/includes/classes/recaptcha.php deleted file mode 100644 index 43dbbd6e8..000000000 --- a/library/includes/classes/recaptcha.php +++ /dev/null @@ -1,153 +0,0 @@ -getMessage(); - } -} - -class Client -{ - private $_secret; - private $_curl_opts; - - /** - * Constructor - * - * @param string $secret shared secret between site and ReCAPTCHA server - * @param array $curl_opts array of curl parameters - * - * @throws Exception - */ - public function __construct($secret, array $curl_opts = array()) - { - if (is_null($secret) || $secret == '') { - throw new Exception('To use reCAPTCHA you must get an API key from ' . SIGNUP_URL . ''); - } - $this->_secret = $secret; - if (!empty($curl_opts)) { - $this->_curl_opts = $curl_opts; - } - } - - /** - * Encodes the given data into a query string format - * - * @param array $data array of string elements to be encoded - * - * @return string - encoded request - */ - private function _encodeQS($data) - { - $req = array(); - foreach ($data as $key => $value) { - $req[] = $key . '=' . urlencode(stripslashes(trim($value))); - } - return implode('&', $req); - } - - /** - * Submits an HTTP GET to a reCAPTCHA server - * - * @param string $path url path to reCAPTCHA server - * @param array $data array of parameters to be sent - * - * @throws Exception - * @return array response - */ - private function _submitHTTPGet($path, $data) - { - $req = $this->_encodeQS($data); - // Prefer curl - if (function_exists('curl_version')) { - $opts = array( - CURLOPT_HEADER => false, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_USERAGENT => 'ReCaptcha ' . VERSION, - CURLOPT_AUTOREFERER => true, - CURLOPT_CONNECTTIMEOUT => 60, - CURLOPT_TIMEOUT => 60, - CURLOPT_MAXREDIRS => 5, - CURLOPT_ENCODING => '', - ); - // Check if we got overrides, or extra options (eg. proxy configuration) - if (is_array($this->_curl_opts) && !empty($this->_curl_opts)) { - $opts = array_merge($opts, $this->_curl_opts); - } - $conn = curl_init($path . $req); - curl_setopt_array($conn, $opts); - $response = curl_exec($conn); - // Handle a connection error - $errno = curl_errno($conn); - if ($errno !== 0) { - throw new Exception('Fatal error while contacting reCAPTCHA. ' . $errno . ': ' . curl_error($conn)); - } - curl_close($conn); - } else { - $response = file_get_contents($path . $req); - } - return $response; - } - - /** - * Calls the reCAPTCHA siteverify API to verify whether the user passes test - * - * @param string $remoteIp IP address of end user - * @param string $response response string from reCAPTCHA verification - * - * @return ReCaptcha\Response - */ - public function verifyResponse($remoteIp, $response) - { - // Discard empty solution submissions - if (is_null($response) || strlen($response) == 0) { - $recaptchaResponse = new Response(); - $recaptchaResponse->success = false; - $recaptchaResponse->errorCodes = 'missing-input'; - return $recaptchaResponse; - } - - // Send request - $getResponse = $this->_submitHttpGet( - VERIFY_URL, - array( - 'secret' => $this->_secret, - 'remoteip' => $remoteIp, - 'v' => VERSION, - 'response' => $response - ) - ); - $answers = json_decode($getResponse, true); - $recaptchaResponse = new Response(); - - // Parse answer - if (trim($answers['success']) == true) { - $recaptchaResponse->success = true; - } else { - $recaptchaResponse->success = false; - $recaptchaResponse->errorCodes = $answers['error-codes']; - } - - return $recaptchaResponse; - } -} \ No newline at end of file diff --git a/library/includes/functions.php b/library/includes/functions.php index cd1e9454d..b66893387 100644 --- a/library/includes/functions.php +++ b/library/includes/functions.php @@ -2566,16 +2566,21 @@ function hash_search ($hash) function bb_captcha ($mode, $callback = '') { - global $bb_cfg, $userdata; + global $bb_cfg, $lang, $userdata; - require_once(CLASS_DIR . 'recaptcha.php'); + require_once(TP_AUTO_DIR . 'ReCaptcha/ReCaptcha.php'); $secret = $bb_cfg['captcha']['secret_key']; $public = $bb_cfg['captcha']['public_key']; $theme = $bb_cfg['captcha']['theme']; $lang = $bb_cfg['lang'][$userdata['user_lang']]['captcha']; - $reCaptcha = new Google\ReCaptcha\Client($secret); + if (!$public || !$secret) + { + bb_die($lang['CAPTCHA_SETTINGS']); + } + + $reCaptcha = new \ReCaptcha\ReCaptcha($secret); switch ($mode) { @@ -2595,19 +2600,11 @@ function bb_captcha ($mode, $callback = '') break; case 'check': - $resp = null; $g_resp = request_var('g-recaptcha-response', ''); - if ($g_resp) { - try { - $resp = $reCaptcha->verifyResponse($_SERVER["REMOTE_ADDR"], $g_resp); - } catch (Google\ReCaptcha\Exception $e) { - $e->getError(); - } - } - if (is_object($resp) && $resp->success === true) { + $resp = $reCaptcha->verify($g_resp, $_SERVER['REMOTE_ADDR']); + if ($resp->isSuccess()) + { return true; - } else { - return false; } break; diff --git a/library/includes/functions_selects.php b/library/includes/functions_selects.php index e6fb9cec4..8cf43a765 100644 --- a/library/includes/functions_selects.php +++ b/library/includes/functions_selects.php @@ -9,7 +9,6 @@ function language_select ($default_lang, $select_name = 'language') { global $bb_cfg; - $lang_default = reset($bb_cfg['lang']); $lang_select = ''; - return ($x > 1) ? $lang_select : $lang_default['name']; + return ($x > 1) ? $lang_select : reset($bb_cfg['lang'])['name']; } // diff --git a/library/includes/init_bb.php b/library/includes/init_bb.php index bdf5b1012..af91a1667 100644 --- a/library/includes/init_bb.php +++ b/library/includes/init_bb.php @@ -1,7 +1,7 @@ ReCaptcha not being fully configured

If you haven\'t already generated the keys, you can do it on https://www.google.com/recaptcha/admin.
After you generate the keys, you need to put them at the file library/config.php.

'; \ No newline at end of file diff --git a/library/language/ru/main.php b/library/language/ru/main.php index ad1cc05e3..274a7894e 100644 --- a/library/language/ru/main.php +++ b/library/language/ru/main.php @@ -2704,4 +2704,5 @@ $lang['UPLOAD_ERRORS'] = array( // Captcha $lang['CAPTCHA'] = 'Проверка, что вы не робот'; -$lang['CAPTCHA_WRONG'] = 'Вы не смогли подтвердить, что вы не робот'; \ No newline at end of file +$lang['CAPTCHA_WRONG'] = 'Вы не смогли подтвердить, что вы не робот'; +$lang['CAPTCHA_SETTINGS'] = '

ReCaptcha настроена не полностью

Если вы еще не сгенерировали ключи, вы можете это сделать на странице https://www.google.com/recaptcha/admin.
После того, как вы сгенерируете ключи, нужно прописать их в файл library/config.php.

'; \ No newline at end of file diff --git a/library/language/uk/main.php b/library/language/uk/main.php index 97ce7d188..d4d6a2e65 100644 --- a/library/language/uk/main.php +++ b/library/language/uk/main.php @@ -2704,4 +2704,5 @@ $lang['UPLOAD_ERRORS'] = array( // Captcha $lang['CAPTCHA'] = 'Перевірка, що ви не робот'; -$lang['CAPTCHA_WRONG'] = 'Ви не змогли підтвердити, що ви не робот'; \ No newline at end of file +$lang['CAPTCHA_WRONG'] = 'Ви не змогли підтвердити, що ви не робот'; +$lang['CAPTCHA_SETTINGS'] = '

ReCaptcha налаштована не повністю

Якщо ви ще не згенерували ключі, ви можете це зробити на сторінці https://www.google.com/recaptcha/admin.
Після того, як ви сгенеріруете ключі, потрібно прописати їх у файл library/config.php.

'; \ No newline at end of file