Server : Apache System : Linux pod-100823:apache2_74:v0.5.7 5.4.0-1138-gcp #147~18.04.1-Ubuntu SMP Mon Oct 7 21:46:26 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33.7 Disable Function : apache_child_terminate,apache_get_modules,apache_get_version,apache_getenv,apache_note,apache_setenv,disk_free_space,disk_total_space,diskfreespace,dl,exec,fastcgi_finish_request,link,opcache_compile_file,opcache_get_configuration,opcache_invalidate,opcache_is_script_cached,opcache_reset,passthru,pclose,pcntl_exec,popen,posix_getpid,posix_getppid,posix_getpwuid,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_uname,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,realpath_cache_get,shell_exec,show_source,symlink,system Directory : /nas/content/live/attorneyexperi/wp-content/plugins/imagify/inc/classes/ |
<?php use Imagify\Traits\InstanceGetterTrait; /** * Imagify.io API for WordPress. */ class Imagify { use InstanceGetterTrait; /** * The Imagify API endpoint. * * @var string */ const API_ENDPOINT = IMAGIFY_APP_API_URL; /** * The Imagify API key. * * @var string */ private $api_key = ''; /** * Random key used to store the API key in the request args. * * @var string */ private $secure_key = ''; /** * HTTP headers. Each http call must fill it (even if it's with an empty array). * * @var array */ private $headers = []; /** * All (default) HTTP headers. They must not be modified once the class is instanciated, or it will affect any following HTTP calls. * * @var array */ private $all_headers = []; /** * Filesystem object. * * @var object Imagify_Filesystem * @since 1.7.1 * @author Grégory Viguier */ protected $filesystem; /** * Use data fetched from the API. * * @var \stdClass|\WP_Error * @since 1.9.9 * @author Grégory Viguier */ protected static $user; /** * The constructor. */ protected function __construct() { if ( ! class_exists( 'Imagify_Filesystem' ) ) { // Dirty patch used when updating from 1.7. include_once IMAGIFY_PATH . 'inc/classes/class-imagify-filesystem.php'; } $this->api_key = get_imagify_option( 'api_key' ); $this->secure_key = $this->generate_secure_key(); $this->filesystem = Imagify_Filesystem::get_instance(); $this->all_headers['Accept'] = 'Accept: application/json'; $this->all_headers['Content-Type'] = 'Content-Type: application/json'; $this->all_headers['Authorization'] = 'Authorization: token ' . $this->api_key; } /** * Get your Imagify account infos. * * @since 1.6.5 * * @return object */ public function get_user() { global $wp_current_filter; if ( isset( static::$user ) ) { return static::$user; } if ( in_array( 'upgrader_post_install', (array) $wp_current_filter, true ) ) { // Dirty patch used when updating from 1.7. static::$user = new WP_Error(); return static::$user; } $this->headers = $this->all_headers; static::$user = $this->http_call( 'users/me/', [ 'timeout' => 10 ] ); if ( is_wp_error( static::$user ) ) { return static::$user; } $maybe_missing = [ 'account_type' => 'free', 'quota' => 0, 'extra_quota' => 0, 'extra_quota_consumed' => 0, 'consumed_current_month_quota' => 0, ]; foreach ( $maybe_missing as $name => $value ) { if ( ! isset( static::$user->$name ) ) { static::$user->$name = $value; } } return static::$user; } /** * Create a user on your Imagify account. * * @since 1.6.5 * * @param array $data All user data. * @return object */ public function create_user( $data ) { $this->headers = []; $data = array_merge( $data, [ 'from_plugin' => true, 'partner' => imagify_get_partner(), ] ); if ( ! $data['partner'] ) { unset( $data['partner'] ); } $response = $this->http_call( 'users/', [ 'method' => 'POST', 'post_data' => $data, ] ); if ( ! is_wp_error( $response ) ) { imagify_delete_partner(); } return $response; } /** * Update an existing user on your Imagify account. * * @since 1.6.5 * * @param string $data All user data. * @return object */ public function update_user( $data ) { $this->headers = $this->all_headers; return $this->http_call( 'users/me/', [ 'method' => 'PUT', 'post_data' => $data, 'timeout' => 10, ] ); } /** * Check your Imagify API key status. * * @since 1.6.5 * * @param string $data The license key. * @return object */ public function get_status( $data ) { static $status = []; if ( isset( $status[ $data ] ) ) { return $status[ $data ]; } $this->headers = [ 'Authorization' => 'Authorization: token ' . $data, ]; $uri = 'status/'; $partner = imagify_get_partner(); if ( $partner ) { $uri .= '?partner=' . $partner; } $status[ $data ] = $this->http_call( $uri, [ 'timeout' => 10 ] ); return $status[ $data ]; } /** * Get the Imagify API version. * * @since 1.6.5 * * @return object */ public function get_api_version() { static $api_version; if ( ! isset( $api_version ) ) { $this->headers = [ 'Authorization' => $this->all_headers['Authorization'], ]; $api_version = $this->http_call( 'version/', [ 'timeout' => 5 ] ); } return $api_version; } /** * Get Public Info. * * @since 1.6.5 * * @return object */ public function get_public_info() { $this->headers = $this->all_headers; return $this->http_call( 'public-info' ); } /** * Optimize an image from its binary content. * * @since 1.6.5 * @since 1.6.7 $data['image'] can contain the file path (prefered) or the result of `curl_file_create()`. * * @param string $data All options. * @return object */ public function upload_image( $data ) { $this->headers = [ 'Authorization' => $this->all_headers['Authorization'], ]; return $this->http_call( 'upload/', [ 'method' => 'POST', 'post_data' => $data, ] ); } /** * Optimize an image from its URL. * * @since 1.6.5 * * @param string $data All options. Details here: --. * @return object */ public function fetch_image( $data ) { $this->headers = $this->all_headers; return $this->http_call( 'fetch/', [ 'method' => 'POST', 'post_data' => wp_json_encode( $data ), ] ); } /** * Get prices for plans. * * @since 1.6.5 * * @return object */ public function get_plans_prices() { $this->headers = $this->all_headers; return $this->http_call( 'pricing/plan/' ); } /** * Get all prices (Plans included). * * @since 1.6.5 * * @return object */ public function get_all_prices() { $this->headers = $this->all_headers; return $this->http_call( 'pricing/all/' ); } /** * Get coupon code data. * * @since 1.6.5 * * @param string $coupon A coupon code. * @return object */ public function check_coupon_code( $coupon ) { $this->headers = $this->all_headers; return $this->http_call( 'coupons/' . $coupon . '/' ); } /** * Get information about current discount. * * @since 1.6.5 * * @return object */ public function check_discount() { $this->headers = $this->all_headers; return $this->http_call( 'pricing/discount/' ); } /** * Make an HTTP call using curl. * * @since 1.6.5 * @since 1.6.7 Use `wp_remote_request()` when possible (when we don't need to send an image). * * @param string $url The URL to call. * @param array $args The request args. * @return object */ private function http_call( $url, $args = [] ) { $args = array_merge( [ 'method' => 'GET', 'post_data' => null, 'timeout' => 45, ], $args ); $endpoint = trim( $url, '/' ); /** * Filter the timeout value for any request to the API. * * @since 1.6.7 * @author Grégory Viguier * * @param int $timeout Timeout value in seconds. * @param string $endpoint The targetted endpoint. It's basically URI without heading nor trailing slash. */ $args['timeout'] = apply_filters( 'imagify_api_http_request_timeout', $args['timeout'], $endpoint ); // We need to send an image: we must use cURL directly. if ( isset( $args['post_data']['image'] ) ) { return $this->curl_http_call( $url, $args ); } $args = array_merge( [ 'headers' => [], 'body' => $args['post_data'], 'sslverify' => apply_filters( 'https_ssl_verify', false ), ], $args ); unset( $args['post_data'] ); if ( $this->headers ) { foreach ( $this->headers as $name => $value ) { $value = explode( ':', $value, 2 ); $value = end( $value ); $args['headers'][ $name ] = trim( $value ); } } if ( ! empty( $args['headers']['Authorization'] ) ) { // Make sure our API has not overwritten by some other plugin. $args[ $this->secure_key ] = preg_replace( '/^token /', '', $args['headers']['Authorization'] ); if ( ! has_filter( 'http_request_args', [ $this, 'force_api_key_header' ] ) ) { add_filter( 'http_request_args', [ $this, 'force_api_key_header' ], IMAGIFY_INT_MAX + 25, 2 ); } } $response = wp_remote_request( self::API_ENDPOINT . $url, $args ); if ( is_wp_error( $response ) ) { return $response; } $http_code = wp_remote_retrieve_response_code( $response ); $response = wp_remote_retrieve_body( $response ); return $this->handle_response( $response, $http_code ); } /** * Make an HTTP call using curl. * * @since 1.6.7 * @throws Exception When curl_init() fails. * @author Grégory Viguier * * @param string $url The URL to call. * @param array $args The request arguments. * @return object */ private function curl_http_call( $url, $args = [] ) { // Check if curl is available. if ( ! Imagify_Requirements::supports_curl() ) { return new WP_Error( 'curl', 'cURL isn\'t installed on the server.' ); } /** * Allows to mock Imagify calls to the API. * * @param stdClass|null $response Response from the call. * @param string $url URL from the call. * @param array $args Arguments from the call. */ $response = apply_filters( 'pre_imagify_request', null, $url, $args ); if ( $response ) { return $response; } try { $url = self::API_ENDPOINT . $url; $ch = curl_init(); if ( false === $ch ) { throw new Exception( 'Could not initialize a new cURL handle' ); } if ( isset( $args['post_data']['image'] ) && is_string( $args['post_data']['image'] ) && $this->filesystem->exists( $args['post_data']['image'] ) ) { $args['post_data']['image'] = curl_file_create( $args['post_data']['image'] ); } // Handle proxies. $proxy = new WP_HTTP_Proxy(); if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() ); curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() ); if ( $proxy->use_authentication() ) { curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY ); curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() ); } } if ( 'POST' === $args['method'] ) { curl_setopt( $ch, CURLOPT_POST, true ); curl_setopt( $ch, CURLOPT_POSTFIELDS, $args['post_data'] ); } elseif ( 'PUT' === $args['method'] ) { curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'PUT' ); curl_setopt( $ch, CURLOPT_POSTFIELDS, $args['post_data'] ); } if ( defined( 'CURLOPT_PROTOCOLS' ) ) { curl_setopt( $ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); } $user_agent = apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ), $url ); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_HEADER, false ); curl_setopt( $ch, CURLOPT_HTTPHEADER, $this->headers ); curl_setopt( $ch, CURLOPT_TIMEOUT, $args['timeout'] ); curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $args['timeout'] ); curl_setopt( $ch, CURLOPT_USERAGENT, $user_agent ); @curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, false ); curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false ); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); /** * Tell which http version to use with cURL during image optimization. * * @since 1.8.4.1 * @since 1.9.9 Default value is `false`. * @author Grégory Viguier * * @param $use_version_1_0 bool True to use version 1.0. False for 1.1. Default is false. */ if ( apply_filters( 'imagify_curl_http_version_1_0', false ) ) { curl_setopt( $ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); } else { curl_setopt( $ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); } $response = curl_exec( $ch ); $error = curl_error( $ch ); $http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE ); if ( is_resource( $ch ) ) { curl_close( $ch ); } else { unset( $ch ); } } catch ( Exception $e ) { $args['headers'] = $this->headers; /** * Fires after a failed curl request. * * @since 1.6.9 * @author Grégory Viguier * * @param string $url The requested URL. * @param array $args The request arguments. * @param object $e The raised Exception. */ do_action( 'imagify_curl_http_response', $url, $args, $e ); return new WP_Error( 'curl', 'An error occurred (' . $e->getMessage() . ')' ); } // End try(). $args['headers'] = $this->headers; /** * Fires after a successful curl request. * * @since 1.6.9 * @author Grégory Viguier * * @param string $url The requested URL. * @param array $args The request arguments. * @param string $response The request response. * @param int $http_code The request HTTP code. * @param string $error An error message. */ do_action( 'imagify_curl_http_response', $url, $args, $response, $http_code, $error ); return $this->handle_response( $response, $http_code, $error ); } /** * Handle the request response and maybe trigger an error. * * @since 1.6.7 * @author Grégory Viguier * * @param string $response The request response. * @param int $http_code The request HTTP code. * @param string $error An error message. * @return object */ private function handle_response( $response, $http_code, $error = '' ) { $response = json_decode( $response ); if ( 401 === $http_code ) { // Reset the API validity cache if the API key is not valid. Imagify_Requirements::reset_cache( 'api_key_valid' ); } if ( 200 !== $http_code && ! empty( $response->code ) ) { if ( ! empty( $response->detail ) ) { return new WP_Error( 'error ' . $http_code, $response->detail ); } if ( ! empty( $response->image ) ) { $error = (array) $response->image; $error = reset( $error ); return new WP_Error( 'error ' . $http_code, $error ); } } if ( 413 === $http_code ) { return new WP_Error( 'error ' . $http_code, 'Your image is too big to be uploaded on our server.' ); } if ( 200 !== $http_code ) { $error = trim( (string) $error ); $error = '' !== $error ? ' - ' . htmlentities( $error ) : ''; return new WP_Error( 'error ' . $http_code, "Our server returned an error ({$http_code}{$error})" ); } if ( ! is_object( $response ) ) { return new WP_Error( 'invalid response', 'Our server returned an invalid response.', $response ); } return $response; } /** * Generate a random key. * Similar to wp_generate_password() but without filter. * * @since 1.8.4 * @see wp_generate_password() * @author Grégory Viguier * * @return string */ private function generate_secure_key() { $length = wp_rand( 12, 20 ); $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|'; $password = ''; for ( $i = 0; $i < $length; $i++ ) { $password .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 ); } return $password; } /** * Filter the arguments used in an HTTP request, to make sure our API key has not been overwritten by some other plugin. * * @since 1.8.4 * @author Grégory Viguier * * @param array $args An array of HTTP request arguments. * @param string $url The request URL. * @return array */ public function force_api_key_header( $args, $url ) { if ( strpos( $url, self::API_ENDPOINT ) === false ) { return $args; } if ( ! empty( $args['headers']['Authorization'] ) || ! empty( $args[ $this->secure_key ] ) ) { if ( ! empty( $args[ $this->secure_key ] ) ) { $args['headers']['Authorization'] = 'token ' . $args[ $this->secure_key ]; } else { $args['headers']['Authorization'] = 'token ' . $this->api_key; } } return $args; } }