From 3c0aaebce924addcb1b3b2426eae6a3a85cf2dc0 Mon Sep 17 00:00:00 2001 From: Abdulrahman Date: Sun, 19 May 2019 02:40:43 +0300 Subject: [PATCH] fetch file --- includes/FetchFile.php | 330 ++++++++++++++++++++++++++++++ includes/adm/j_plugins.php | 9 +- includes/adm/m_styles.php | 9 +- includes/adm/p_check_update.php | 7 +- includes/adm/start.php | 2 +- includes/auth_integration/api.php | 10 +- includes/common.php | 1 + includes/functions.php | 242 +--------------------- includes/plugins.php | 1 + 9 files changed, 357 insertions(+), 254 deletions(-) create mode 100644 includes/FetchFile.php diff --git a/includes/FetchFile.php b/includes/FetchFile.php new file mode 100644 index 0000000..d3085e5 --- /dev/null +++ b/includes/FetchFile.php @@ -0,0 +1,330 @@ +url = $url; + } + + public static function make($url) + { + return new static($url); + } + + public function isHeadOnly($val) + { + $this->headOnly = $val; + return $this; + } + + public function setTimeOut($seconds) + { + $this->timeout = $seconds; + return $this; + } + + public function setDestinationPath($path) + { + $this->destinationPath = $path; + return $this; + } + + public function setMaxRedirects($limit) + { + $this->maxRedirects = $limit; + return $this; + } + + public function isBinaryFile($val) + { + $this->binary = $val; + return $this; + } + + public function get() + { + $fetchType = ''; + + $allow_url_fopen = function_exists('ini_get') + ? strtolower(@ini_get('allow_url_fopen')) + : strtolower(@get_cfg_var('allow_url_fopen')); + + if (function_exists('curl_init')) + { + $fetchType = 'curl'; + } + // fsockopen() is the second best thing + elseif (function_exists('fsockopen')) + { + $fetchType = 'fsocket'; + } + // Last case scenario, we use file_get_contents provided allow_url_fopen is enabled (any non 200 response results in a failure) + elseif (in_array($allow_url_fopen, ['on', 'true', '1'])) + { + $fetchType = 'fopen'; + } + + session_write_close(); + + $result = null; + + is_array($plugin_run_result = Plugins::getInstance()->run('kleeja_fetch_file_start', get_defined_vars())) ? extract($plugin_run_result) : null; //run hook + + if (! empty($fetchType)) + { + $result = $this->{$fetchType}(); + } + + $this->finishUp(); + + return $result; + } + + protected function finishUp() + { + global $klj_session; + + session_id($klj_session); + + session_start(); + } + + protected function curl() + { + $ch = curl_init($this->url); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + @curl_setopt($ch, CURLOPT_AUTOREFERER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_HEADER, $this->headOnly); + curl_setopt($ch, CURLOPT_NOBODY, $this->headOnly); + curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)'); + curl_setopt($ch, CURLOPT_FAILONERROR, true); + + if ($this->binary) + { + curl_setopt($ch, CURLOPT_ENCODING, ''); + } + + //let's open new file to save it in. + if (! empty($this->destinationPath)) + { + $out = @fopen($this->destinationPath, 'w'); + curl_setopt($ch, CURLOPT_FILE, $out); + @curl_exec($ch); + curl_close($ch); + fclose($out); + } + + if ($this->headOnly) + { + // Grab the page + $data = @curl_exec($ch); + $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($data !== false && $response_code == '200') + { + return explode("\r\n", str_replace("\r\n\r\n", "\r\n", trim($data))); + } + + return false; + } + else + { + if (! empty($this->destinationPath)) + { + $data = @curl_exec($ch); + curl_close($ch); + } + + return ! empty($this->destinationPath) ? true : $data; + } + } + + protected function fsocket() + { + $url_parsed = parse_url($this->url); + $host = $url_parsed['host']; + $port = empty($url_parsed['port']) || $url_parsed['port'] == 0 ? 80 : $url_parsed['port']; + $path = $url_parsed['path']; + + if (isset($url_parsed['query']) && $url_parsed['query'] != '') + { + $path .= '?' . $url_parsed['query']; + } + + if (! $fp = @fsockopen($host, $port, $_, $_, $this->timeout)) + { + return false; + } + + // Send a standard HTTP 1.0 request for the page + fwrite($fp, ($this->headOnly ? 'HEAD' : 'GET') . " $path HTTP/1.0\r\n"); + fwrite($fp, "Host: $host\r\n"); + fwrite($fp, 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)' . "\r\n"); + fwrite($fp, 'Connection: Close' . "\r\n\r\n"); + + stream_set_timeout($fp, $this->timeout); + $stream_meta = stream_get_meta_data($fp); + + $fp2 = null; + + //let's open new file to save it in. + if (! empty($this->destinationPath)) + { + $fp2 = @fopen($this->destinationPath, 'w' . ($this->binary ? '' : '')); + } + + // Fetch the response 1024 bytes at a time and watch out for a timeout + $in = false; + $h = false; + + while (! feof($fp) && ! $stream_meta['timed_out']) + { + $s = fgets($fp, 1024); + + if (! empty($this->destinationPath)) + { + if ($s == "\r\n") + { //|| $s == "\n") + $h = true; + + continue; + } + + if ($h) + { + @fwrite($fp2, $s); + } + } + + $in .= $s; + $stream_meta = stream_get_meta_data($fp); + } + + fclose($fp); + + if (! empty($this->destinationPath)) + { + unset($in); + @fclose($fp2); + return true; + } + + // Process 301/302 redirect + if ($in !== false && $this->maxRedirects > 0 && preg_match('#^HTTP/1.[01] 30[12]#', $in)) + { + $headers = explode("\r\n", trim($in)); + + foreach ($headers as $header) + { + if (substr($header, 0, 10) == 'Location: ') + { + $response = static::make(substr($header, 10)) + ->setDestinationPath($this->destinationPath) + ->setTimeOut($this->timeout) + ->isHeadOnly($this->headOnly) + ->setMaxRedirects($this->maxRedirects - 1) + ->get(); + + if ($response != false) + { + $headers[] = $response; + } + return $headers; + } + } + } + + // Ignore everything except a 200 response code + if ($in !== false && preg_match('#^HTTP/1.[01] 200 OK#', $in)) + { + if ($this->headOnly) + { + return explode("\r\n", trim($in)); + } + else + { + $content_start = strpos($in, "\r\n\r\n"); + + if ($content_start !== false) + { + return substr($in, $content_start + 4); + } + } + } + + return $in; + } + + protected function fopen() + { + // PHP5's version of file_get_contents() supports stream options + if (version_compare(PHP_VERSION, '5.0.0', '>=')) + { + // Setup a stream context + $stream_context = stream_context_create( + [ + 'http' => [ + 'method' => $this->headOnly ? 'HEAD' : 'GET', + 'user_agent' => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)', + 'max_redirects' => $this->maxRedirects + 1, // PHP >=5.1.0 only + 'timeout' => $this->timeout // PHP >=5.2.1 only + ] + ] + ); + + $content = @file_get_contents($this->url, false, $stream_context); + } + else + { + $content = @file_get_contents($this->url); + } + + // Did we get anything? + if ($content !== false) + { + // Gotta love the fact that $http_response_header just appears in the global scope (*cough* hack! *cough*) + if ($this->headOnly) + { + return $http_response_header; + } + + if (! empty($this->destinationPath)) + { + $fp2 = fopen($this->destinationPath, 'w' . ($this->binary ? 'b' : '')); + @fwrite($fp2, $content); + @fclose($fp2); + unset($content); + return true; + } + } + + return false; + } +} diff --git a/includes/adm/j_plugins.php b/includes/adm/j_plugins.php index 6936868..b36a071 100755 --- a/includes/adm/j_plugins.php +++ b/includes/adm/j_plugins.php @@ -144,7 +144,7 @@ switch ($case): { $store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json'; - $store_catalog = fetch_remote_file($store_link); + $store_catalog = FetchFile::make($store_link)->get(); $store_catalog = json_decode($store_catalog, true); if (json_last_error() == JSON_ERROR_NONE) @@ -552,7 +552,7 @@ switch ($case): // plugins avilable in kleeja store $store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json'; - $catalog_plugins = fetch_remote_file($store_link); + $catalog_plugins = FetchFile::make($store_link)->get(); if ($catalog_plugins) { @@ -587,7 +587,10 @@ switch ($case): ) { $plugin_name_link = $store_plugins[$plugin_name]['url']; - $plugin_archive = fetch_remote_file($plugin_name_link, PATH . 'cache/' . $plugin_name . '.zip', 60, false, 10, true); + $plugin_archive = FetchFile::make($plugin_name_link) + ->setDestinationPath(PATH . 'cache/' . $plugin_name . '.zip') + ->isBinaryFile(true) + ->get(); if ($plugin_archive) { diff --git a/includes/adm/m_styles.php b/includes/adm/m_styles.php index fba81b5..deeec1c 100755 --- a/includes/adm/m_styles.php +++ b/includes/adm/m_styles.php @@ -117,7 +117,7 @@ case 'store': { $store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json'; - $store_catalog = fetch_remote_file($store_link); + $store_catalog = FetchFile::make($store_link)->get(); $store_catalog = json_decode($store_catalog, true); if (json_last_error() == JSON_ERROR_NONE) @@ -382,7 +382,7 @@ case 'download': // plugins avilable in kleeja store $store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json'; - $catalog_styles = fetch_remote_file($store_link); + $catalog_styles = FetchFile::make($store_link)->get(); if ($catalog_styles) { @@ -417,7 +417,10 @@ case 'download': ) { $style_name_link = $store_styles[$style_name]['url']; - $style_archive = fetch_remote_file($style_name_link, PATH . 'cache/' . $style_name . '.zip', 60, false, 10, true); + $style_archive = FetchFile::make($style_name_link) + ->setDestinationPath(PATH . 'cache/' . $style_name . '.zip') + ->isBinaryFile(true) + ->get(); if ($style_archive) { diff --git a/includes/adm/p_check_update.php b/includes/adm/p_check_update.php index f8b5680..a9a44e5 100755 --- a/includes/adm/p_check_update.php +++ b/includes/adm/p_check_update.php @@ -54,7 +54,7 @@ if ($current_smt == 'check') //get data from kleeja github repo if (! ($version_data = $cache->get('kleeja_repo_version'))) { - $github_data = fetch_remote_file(KLEEJA_VERSION_CHECK_LINK, false, 100); + $github_data = FetchFile::make(KLEEJA_VERSION_CHECK_LINK)->setTimeOut(100)->get(); if (! empty($github_data)) { @@ -151,7 +151,10 @@ elseif ($current_smt == 'update1') else { // downloaded the last package to cache folder - fetch_remote_file(KLEEJA_LATEST_PACKAGE_LINK . $new_version, PATH . "cache/kleeja-{$new_version}.zip", 60, false, 10, true); + FetchFile::make(KLEEJA_LATEST_PACKAGE_LINK . $new_version) + ->setDestinationPath(PATH . "cache/kleeja-{$new_version}.zip") + ->isBinaryFile(true) + ->get(); if (file_exists(PATH . "cache/kleeja-{$new_version}.zip")) { diff --git a/includes/adm/start.php b/includes/adm/start.php index 2f72e14..793dc04 100755 --- a/includes/adm/start.php +++ b/includes/adm/start.php @@ -177,7 +177,7 @@ if (! empty($d_groups) && is_array($d_groups)) // rev: let's say cache is not refreshed, so we will redirect alots of time, // so update_done will be good solution // -if (empty($v['last_check']) || ((time() - $v['last_check']) > 3600 * 24 * 10 && $_SERVER['SERVER_NAME'] != 'localhost' && ! ig('update_done'))) +if ((empty($v['last_check']) || time() - $v['last_check'] > 3600 * 24 * 10) && ! ig('update_done')) { redirect(basename(ADMIN_PATH) . '?cp=p_check_update&show_msg=1'); $SQL->close(); diff --git a/includes/auth_integration/api.php b/includes/auth_integration/api.php index f703d20..5122521 100755 --- a/includes/auth_integration/api.php +++ b/includes/auth_integration/api.php @@ -26,7 +26,7 @@ function kleeja_auth_login ($name, $pass, $hashed = false, $expire, $loginadm = } //api key is the key to make the query between the remote script and kleeja more secure ! - //this must be changed in the real use + //this must be changed in the real use if (empty($script_api_key)) { big_error('api key', 'To connect to the remote script you have to write the API key ...'); @@ -43,7 +43,7 @@ function kleeja_auth_login ($name, $pass, $hashed = false, $expire, $loginadm = //get it - $remote_data = fetch_remote_file($script_path . '?' . $api_http_query); + $remote_data = FetchFile::make($script_path . '?' . $api_http_query)->get(); //no responde //empty or can not connect @@ -53,7 +53,7 @@ function kleeja_auth_login ($name, $pass, $hashed = false, $expire, $loginadm = } //see kleeja_api.php file - //split the data , the first one is always 0 or 1 + //split the data , the first one is always 0 or 1 //0 : error //1: ok $user_info = explode('%|%', kleeja_base64_decode($remote_data)); @@ -105,11 +105,11 @@ function kleeja_auth_login ($name, $pass, $hashed = false, $expire, $loginadm = } // -//return username +//return username // function kleeja_auth_username ($user_id) { return kleeja_auth_login($user_id, false, false, false, false, true); -} +} //<-- EOF diff --git a/includes/common.php b/includes/common.php index b9b66fa..ef33469 100755 --- a/includes/common.php +++ b/includes/common.php @@ -146,6 +146,7 @@ include PATH . 'includes/pager.php'; include PATH . 'includes/functions.php'; include PATH . 'includes/functions_display.php'; include PATH . 'includes/plugins.php'; +include PATH . 'includes/FetchFile.php'; if (defined('IN_ADMIN')) diff --git a/includes/functions.php b/includes/functions.php index 8558958..d74824a 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -264,244 +264,6 @@ function send_mail($to, $body, $subject, $fromAddress, $fromName, $bcc = '') return $mail_sent; } - -/** - * Get remote files - * (c) punbb + Kleeja team - * @param $url - * @param bool $save_in - * @param int $timeout - * @param bool $head_only - * @param int $max_redirects - * @param bool $binary - * @return bool|string|array - */ -function fetch_remote_file($url, $save_in = false, $timeout = 20, $head_only = false, $max_redirects = 10, $binary = false) -{ - is_array($plugin_run_result = Plugins::getInstance()->run('kleeja_fetch_remote_file_func', get_defined_vars())) ? extract($plugin_run_result) : null; //run hook - - // Quite unlikely that this will be allowed on a shared host, but it can't hurt - if (function_exists('ini_set')) - { - @ini_set('default_socket_timeout', $timeout); - } - $allow_url_fopen = function_exists('ini_get') - ? strtolower(@ini_get('allow_url_fopen')) - : strtolower(@get_cfg_var('allow_url_fopen')); - - if (function_exists('curl_init')) - { - $ch = curl_init($url); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - @curl_setopt($ch, CURLOPT_AUTOREFERER, true); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch, CURLOPT_HEADER, $head_only); - curl_setopt($ch, CURLOPT_NOBODY, $head_only); - curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); - curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)'); - curl_setopt($ch, CURLOPT_FAILONERROR, true); - - if ($binary) - { - curl_setopt($ch, CURLOPT_ENCODING, ''); - } - - //let's open new file to save it in. - if ($save_in) - { - $out = @fopen($save_in, 'w'); - curl_setopt($ch, CURLOPT_FILE, $out); - @curl_exec($ch); - curl_close($ch); - fclose($out); - } - - if ($head_only) - { - // Grab the page - $data = @curl_exec($ch); - $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close(); - - if ($data !== false && $response_code == '200') - { - return explode("\r\n", str_replace("\r\n\r\n", "\r\n", trim($data))); - } - } - else - { - if (! $save_in) - { - $data = @curl_exec($ch); - curl_close(); - } - - return $save_in ? true : $data; - } - } - // fsockopen() is the second best thing - elseif (function_exists('fsockopen')) - { - $url_parsed = parse_url($url); - $host = $url_parsed['host']; - $port = empty($url_parsed['port']) || $url_parsed['port'] == 0 ? 80 : $url_parsed['port']; - $path = $url_parsed['path']; - - if (isset($url_parsed['query']) && $url_parsed['query'] != '') - { - $path .= '?' . $url_parsed['query']; - } - - if (! $fp = @fsockopen($host, $port, $errno, $errstr, $timeout)) - { - return false; - } - - // Send a standard HTTP 1.0 request for the page - fwrite($fp, ($head_only ? 'HEAD' : 'GET') . " $path HTTP/1.0\r\n"); - fwrite($fp, "Host: $host\r\n"); - fwrite($fp, 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)' . "\r\n"); - fwrite($fp, 'Connection: Close' . "\r\n\r\n"); - - stream_set_timeout($fp, $timeout); - $stream_meta = stream_get_meta_data($fp); - - $fp2 = null; - - //let's open new file to save it in. - if ($save_in) - { - $fp2 = @fopen($save_in, 'w' . ($binary ? '' : '')); - } - - // Fetch the response 1024 bytes at a time and watch out for a timeout - $in = false; - $h = false; - - while (! feof($fp) && ! $stream_meta['timed_out']) - { - $s = fgets($fp, 1024); - - if ($save_in) - { - if ($s == "\r\n") - { //|| $s == "\n") - $h = true; - - continue; - } - - if ($h) - { - @fwrite($fp2, $s); - } - } - - $in .= $s; - $stream_meta = stream_get_meta_data($fp); - } - - fclose($fp); - - if ($save_in) - { - unset($in); - @fclose($fp2); - return true; - } - - // Process 301/302 redirect - if ($in !== false && $max_redirects > 0 && preg_match('#^HTTP/1.[01] 30[12]#', $in)) - { - $headers = explode("\r\n", trim($in)); - - foreach ($headers as $header) - { - if (substr($header, 0, 10) == 'Location: ') - { - $response = fetch_remote_file(substr($header, 10), $save_in, $timeout, $head_only, $max_redirects - 1); - - if ($response != false) - { - $headers[] = $response; - } - return $headers; - } - } - } - - // Ignore everything except a 200 response code - if ($in !== false && preg_match('#^HTTP/1.[01] 200 OK#', $in)) - { - if ($head_only) - { - return explode("\r\n", trim($in)); - } - else - { - $content_start = strpos($in, "\r\n\r\n"); - - if ($content_start !== false) - { - return substr($in, $content_start + 4); - } - } - } - return $in; - } - // Last case scenario, we use file_get_contents provided allow_url_fopen is enabled (any non 200 response results in a failure) - elseif (in_array($allow_url_fopen, ['on', 'true', '1'])) - { - // PHP5's version of file_get_contents() supports stream options - if (version_compare(PHP_VERSION, '5.0.0', '>=')) - { - // Setup a stream context - $stream_context = stream_context_create( - [ - 'http' => [ - 'method' => $head_only ? 'HEAD' : 'GET', - 'user_agent' => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Kleeja)', - 'max_redirects' => $max_redirects + 1, // PHP >=5.1.0 only - 'timeout' => $timeout // PHP >=5.2.1 only - ] - ] - ); - - $content = @file_get_contents($url, false, $stream_context); - } - else - { - $content = @file_get_contents($url); - } - - // Did we get anything? - if ($content !== false) - { - // Gotta love the fact that $http_response_header just appears in the global scope (*cough* hack! *cough*) - if ($head_only) - { - return $http_response_header; - } - - if ($save_in) - { - $fp2 = fopen($save_in, 'w' . ($binary ? 'b' : '')); - @fwrite($fp2, $content); - @fclose($fp2); - unset($content); - return true; - } - - return $content; - } - } - - return false; -} - - /** * Delete cache * @param string $name @@ -1617,12 +1379,12 @@ function user_can($acl_name, $group_id = 0) function ig($name) { - return isset($_GET[$name]) ? true : false; + return isset($_GET[$name]); } function ip($name) { - return isset($_POST[$name]) ? true : false; + return isset($_POST[$name]); } function g($name, $type = 'str', $default = '') diff --git a/includes/plugins.php b/includes/plugins.php index df71027..34e6684 100755 --- a/includes/plugins.php +++ b/includes/plugins.php @@ -6,6 +6,7 @@ * @license http://www.kleeja.com/license * */ + //no for directly open if (! defined('IN_COMMON')) {