EVOLUTION-MANAGER
Edit File: CurlX.php
<?php /** * CurlX Lib - v0.0.4 * @author devblack */ class CurlX { const VERSION = '0.0.4'; private static array $default = [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false, CURLINFO_HEADER_OUT => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_AUTOREFERER => true, CURLOPT_CONNECTTIMEOUT => 30, CURLOPT_TIMEOUT => 60, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0 ]; private static string $current_dir = ''; private static $ch; private static array $info; private static $headersCallBack; private static string $cookie_file = ''; private static string $ua = ''; private static int $error_code; private static string $error_string; private static $response; /** * Basic curl_init for request structure * * @access private * @param string $url * * @return void */ private static function Prepare(string $url) : void { self::$ch = curl_init($url); self::SetOpt(self::$default); } /** * Add options to current curl structure * * @access public * @param array $args * * @return void */ public static function SetOpt(array $option) : void { curl_setopt_array(self::$ch, $option); } /** * Add an header to current curl structure * * @access private * @param header * * @return void */ private static function Header(array $header) : void { self::SetOpt([CURLOPT_HTTPHEADER => $header]); } /** * Set a proxy tunnel configuration to current curl structure, support: HTTP/S, SOCKS4, SOCKS5 * * @access private * @param array $args * * @return void */ private static function Tunnel(array $args) : void { self::SetOpt([ CURLOPT_PROXY => $args['SERVER'], CURLOPT_HTTPPROXYTUNNEL => true ]); } /** * Proxy Auth * * @access private * @param array $args * * @return void */ private static function proxyAuth(array $args) : void { self::SetOpt([ CURLOPT_PROXY => $args['SERVER'], CURLOPT_PROXYUSERPWD => $args['AUTH'] ]); } /** * Detect the tunnel configuration * * @access private * @param array $args * * @return void */ private static function AutoRouter($args) : void { switch (strtoupper($args['METHOD'])) { case 'TUNNEL': self::Tunnel($args); break; case 'CUSTOM': self::proxyAuth($args); break; } } /** * Created a file in the temporal DIRECTORY and import to current curl structure * * @access private * @param string $file * * @return void */ private static function SetCookie(string $file) : void { // set the current dir self::$current_dir = dirname(__FILE__); # check if the dir exits, if not create it if(!is_dir(self::$current_dir.'/Cache/')) mkdir(self::$current_dir.'/Cache/', 0755); // PHP7.4+ self::$cookie_file = sprintf("%s/Cache/curlX_%s.txt", self::$current_dir, $file); // check if the dir is writable if (!is_writable(self::$current_dir)) { trigger_error("The current directory is not writable, please add permissions 0755 to Cache dir and 0644 to CurlX.php", E_USER_ERROR); return; } self::SetOpt([ CURLOPT_COOKIEJAR => self::$cookie_file, CURLOPT_COOKIEFILE => self::$cookie_file ]); } /** * Delete the current cookie file in curl structure * * @access public * * @return void */ public static function DeleteCookie() : void { if (empty(self::$current_dir) || !is_file(self::$cookie_file)) return; chmod(self::$cookie_file, 0755); unlink(self::$cookie_file); } /** * Add an header to current curl structure * * @access private * @param header * * @return void */ private static function SetUSERPWD(string $userpwd) : void { self::SetOpt([CURLOPT_USERPWD => $userpwd]); } /** * Check parameters for curl structure * * @access private * @param array $headers * @param string $cookie * @param array $server * * @return void */ private static function CheckParam(array $headers=NULL, string $cookie=NULL, array $server=NULL, $userpwd=NULL) : void { if (!empty($headers) && (is_array($headers) || is_object($headers))) self::Header($headers); if (!empty($cookie)) self::SetCookie($cookie); if (!empty($server) && (is_array($server) || is_object($server))) self::AutoRouter($server); if (!empty($userpwd)) self::SetUSERPWD($userpwd); } /** * Send a GET request method with headers, cookies and server tunnel * * @access public * @param string $url * @param array $headers * @param string $cookie * @param array %server * * @return object */ public static function Get(string $url, array $headers=NULL, string $cookie=NULL, array $server=NULL, $userpwd=NULL) : object { self::Prepare($url); self::SetOpt([CURLOPT_USERAGENT => self::userAgent()]); self::CheckParam($headers, $cookie, $server, $userpwd); return self::Run(); } /** * Send a POST request method with custom post data, headers, cookies and server tunnel * * @access public * @param string $url * @param string|array $data * @param array $headers * @param string $cookie * @param array $server * * @return object */ public static function Post(string $url, $data=NULL, array $headers=NULL, string $cookie=NULL, array $server=NULL, $userpwd=NULL) : object { self::Prepare($url); self::SetOpt([ CURLOPT_USERAGENT => self::userAgent(), CURLOPT_POST => true, CURLOPT_POSTFIELDS => self::DataType($data) ]); self::CheckParam($headers, $cookie, $server, $userpwd); return self::Run(); } /** * Send a CUSTOM request method with data, headers, cookies and server tunnel * * @access public * @param string $url * @param string $method * @param string|array $data * @param array $headers * @param string $cookie * @param array $server * * @return void */ public static function Custom(string $url, string $method='GET', $data=NULL, array $headers=NULL, string $cookie=NULL, array $server=NULL, $userpwd=NULL) : object { self::Prepare($url); self::SetOpt([ CURLOPT_USERAGENT => self::userAgent(), CURLOPT_CUSTOMREQUEST => $method, CURLOPT_POSTFIELDS => self::DataType($data) ]); self::CheckParam($headers, $cookie, $server, $userpwd); return self::Run(); } /** * Send the request structure * * @access public * * @return object */ public static function Run() : object { self::MakeStdClass(); self::SetOpt([CURLOPT_HEADERFUNCTION => createHeaderCallback(self::$headersCallBack)]); self::$response = curl_exec(self::$ch); self::$info = curl_getinfo(self::$ch); // Request failed if (self::$response === FALSE) { self::$error_code = curl_errno(self::$ch); self::$error_string = preg_replace('/(?!\-)(?:(?:[a-zA-Z\d][a-zA-Z\d\-]{0,61})?[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}/', 'unknown.unk', curl_error(self::$ch)); curl_close(self::$ch); return (object) [ 'success' => false, 'code' => self::$info['http_code'], 'headers' => (object) [ 'request' => key_exists('request_header', self::$info) ? self::parseHeadersHandle(self::$info['request_header']) : [], 'response' => self::parseHeadersHandle(self::$headersCallBack->rawResponseHeaders) ], 'errno' => self::$error_code, 'error' => self::$error_string, 'body' => 'Error, ' . self::$error_string ]; } else { curl_close(self::$ch); return (object) [ 'success' => true, 'code' => self::$info['http_code'], 'url' => self::$info['url'], 'headers' => (object) [ 'request' => self::parseHeadersHandle(self::$info['request_header']), 'response' => self::parseHeadersHandle(self::$headersCallBack->rawResponseHeaders) ], 'body' => self::$response ]; } } /** * Show all data process|errors of the request * * @access public * @param bool $pretty * * @return string */ public static function Debug(bool $pretty=false) { if ($pretty) { header('Content-Type: application/json'); echo json_encode([ 'curlx_debug' => [ 'information' => [ 'request_headers' => self::parseArray(self::$info), 'response_headers' => self::parseHeadersHandle(self::$headersCallBack->rawResponseHeaders) ], 'errors' => [ 'errnum' => self::$error_code ?? '', 'errstr' => self::$error_string ?? '' ], 'response' => self::$response ] ]); } else { echo sprintf("=============================================<br/>\n<h2>CURLX DEBUG</h2>\n=============================================<br/>\n<h3>Response</h3>\n<code>%s</code><br/>\n\n", nl2br(htmlentities(self::$response))); echo sprintf("=============================================<br/>\n<h3>Information</h3><pre>%s</pre>", print_r(['request_headers' => self::parseArray(self::$info), 'response_headers' => self::parseHeadersHandle(self::$headersCallBack->rawResponseHeaders)], true)); if (isset(self::$error_string)) { echo sprintf("=============================================<br/>\n<h3>Errors</h3>\n<strong>Code: </strong>%d<br/>\n<strong>Message: </strong>%d<br/>\n", self::$error_code, self::$error_string); } } } /** * Create a placeholder to temporarily store the header callback data. * * @access private * * @return void * */ private static function MakeStdClass() : void { $hcd = new \stdClass(); $hcd->rawResponseHeaders = ''; self::$headersCallBack = $hcd; } /** * Detect data type * * @access private * @param string|array|object|null $data * * @return string */ private static function DataType($data) { if (empty($data)) { return false; } elseif (is_array($data) || is_object($data)) { return json_encode($data); } else { return $data; } } /** * Can split a string by two specify strings * * @access public * @param string $str * @param string $start * @param string $end * @param bool $decode * * @return string */ public static function ParseString(string $str, string $start, string $end, bool $decode=false) : string { return $decode ? base64_decode(explode($end, explode($start, $str)[1])[0]) : explode($end, explode($start, $str)[1])[0]; } /** * Remove all spaces from a string * * @access public * @param string $str * * @return string */ public static function CleanString(string $str) : string { return preg_replace('/\s+/', '', $str); } /** * Get a rand value from specify file.txt * * @access public * @param string $file * * @return string */ public static function GetRandVal(string $file) : string { $_ = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); return $_[array_rand($_)]; } /** * Parse Headers * * @access private * @param string $raw * * @return array */ private static function parseHeaders(string $raw) : array { $raw = preg_split('/\r\n/', $raw, -1, PREG_SPLIT_NO_EMPTY); $http_headers = []; for($i = 1; $i < count($raw); $i++) { if (strpos($raw[$i], ':') !== false) { list($key, $value) = explode(':', $raw[$i], 2); $key = trim($key); $value = trim($value); isset($http_headers[$key]) ? $http_headers[$key] .= ',' . $value : $http_headers[$key] = $value; } } return [$raw['0'] ??= $raw['0'], $http_headers]; } /** * * @access private * @param array $raw * * @return array */ private static function parseArray(array $raw) : array { if (array_key_exists('request_header', $raw)) { list($scheme, $headers) = self::parseHeaders($raw['request_header']); $nh['scheme'] = $scheme; $nh += $headers; $raw['request_header'] = $nh; } return $raw; } /** * Parse Headers Handle * * @access private * @param string $raw * * @return array */ private static function parseHeadersHandle($raw) : array { if (empty($raw)) return []; list($scheme, $headers) = self::parseHeaders($raw); $request_headers['scheme'] = $scheme; unset($headers['request_header']); foreach ($headers as $key => $value) { $request_headers[$key] = $value; } return $request_headers; } /** * return a random user agent * * @access private * * @return string */ public static function UserAgent() : string { $uas = [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:83.0) Gecko/20100101 Firefox/83.0", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0", "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:81.0) Gecko/20100101 Firefox/81.0", "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0", "Mozilla/5.0 (X11; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0", "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8) Gecko/20060110 Debian/1.5.dfsg-4 Firefox/1.5", "Mozilla/5.0 (Android 10; Mobile; rv:79.0) Gecko/79.0 Firefox/79.0", "Mozilla/5.0 (Android 9; Mobile; rv:68.6.0) Gecko/68.6.0 Firefox/68.6.0", "Mozilla/5.0 (Android 7.1.1; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) FxiOS/7.5b3349 Mobile/14F89 Safari/603.2.4", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Snapchat/10.77.5.59 (like Safari/604.1)", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/80.0.3987.95 Mobile/15E148 Safari/604.1" ]; if (empty(self::$ua)) { self::$ua = $uas[array_rand($uas)]; return self::$ua; } else { return self::$ua; } } } /** * Local createHeaderCallback */ function createHeaderCallback($headersCallBack) { return function ($_, $header) use ($headersCallBack) { $headersCallBack->rawResponseHeaders .= $header; return strlen($header); }; } /*** * COD3D BY D3VBL4CK */