*/ if ( ! defined( 'ABSPATH' ) ) { die( 'These aren\'t the droids you\'re looking for.' ); } if ( ! class_exists( 'SuextYourls' ) ) { class SuextYourls { /** * Available actions */ const ACTION_SHORTURL = 'shorturl'; const ACTION_URL_STATS = 'url-stats'; const ACTION_EXPAND = 'expand'; /** * @var string */ protected $apiUrl; /** * @var null|string */ protected $username; /** * @var null|string */ protected $password; /** * @var null|string */ protected $token; /** * @var string */ private $lastResponse; /** * Class constructor * * @param string $apiUrl * @param null|string $username * @param null|string $password * @param null|string $token */ public function __construct( $apiUrl, $username = null, $password = null, $token = null ) { $this->apiUrl = $apiUrl; $this->username = $username; $this->password = $password; $this->token = $token; } /** * Get short URL for a URL * * @param string $url * @param null|string $keyword * * @return string */ public function shorten( $url, $keyword = null ) { $resp_data = $this->call( self::ACTION_SHORTURL, array( 'url' => $url, 'keyword' => $keyword ) ); return isset( $resp_data[ 'shorturl' ] ) ? $resp_data[ 'shorturl' ] : false; } /** * Get stats about short URL * * @param string $shortUrl * * @return array */ public function getUrlStats( $shortUrl ) { return $this->call( self::ACTION_URL_STATS, array( 'shorturl' => $shortUrl ) ); } /** * Get long URL of a short URL * * @param string $shortUrl * * @return string */ public function expand( $shortUrl ) { $resp_data = $this->call( self::ACTION_EXPAND, array( 'shorturl' => $shortUrl ) ); return isset( $resp_data[ 'longurl' ] ) ? $resp_data[ 'longurl' ] : false; } /** * Returns last raw response from API * * @return string */ public function getLastResponse() { return $this->lastResponse; } /** * Calls API action with specified params * * @param string $action * @param array $params * * @return array */ protected function call( $action, $params = array() ) { $params['action'] = $action; if ( $this->username ) { $params[ 'username' ] = $this->username; $params[ 'password' ] = $this->password; } else { $params[ 'timestamp' ] = time(); $params[ 'signature' ] = md5( $this->token.$params['timestamp'] ); } $params[ 'format' ] = 'json'; $url = $this->apiUrl . ( strpos( $this->apiUrl, '?' ) === false ? '?' : '&' ) . http_build_query( $params ); $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 5 ); curl_setopt( $ch, CURLOPT_TIMEOUT, 15 ); /** * When negotiating a TLS or SSL connection, the server sends a * certificate indicating its identity. Curl verifies whether the * certificate is authentic, i.e. that you can trust that the server is * who the certificate says it is. This trust is based on a chain of * digital signatures, rooted in certification authority (CA) * certificates you supply. curl uses a default bundle of CA * certificates (the path for that is determined at build time) and you * can specify alternate certificates with the CURLOPT_CAINFO option or * the CURLOPT_CAPATH option. * * See https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html */ curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 1 ); /** * When CURLOPT_SSL_VERIFYHOST is 2, that certificate must indicate * that the server is the server to which you meant to connect, or the * connection fails. Simply put, it means it has to have the same name * in the certificate as is in the URL you operate against. * * See https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html */ curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 ); /** * Define and disable the "Expect: 100-continue" header. */ curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Expect:' ) ); if ( ! ini_get('safe_mode') && ! ini_get('open_basedir') ) { curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 ); curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 ); } $response = $this->lastResponse = curl_exec( $ch ); $curl_errnum = curl_errno( $ch ); $curl_errmsg = curl_error( $ch ); // See https://curl.se/libcurl/c/libcurl-errors.html. $ssl_verify = (int) curl_getinfo( $ch, CURLINFO_SSL_VERIFYRESULT ); // See https://www.php.net/manual/en/function.curl-getinfo.php. $http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE ); curl_close( $ch ); $http_success_codes = array( 200, 201 ); try { if ( ! empty( $curl_errnum ) ) { $except_msg = sprintf( __( '%1$s shortener API error: %2$s', 'wpsso' ), 'YOURLS', $curl_errnum . ' ' . $curl_errmsg ); throw new WpssoErrorException( $except_msg ); } elseif ( ! in_array( $http_code, $http_success_codes ) ) { $except_msg = sprintf( __( '%1$s shortener API error: %2$s', 'wpsso' ), 'YOURLS', '' ); throw new WpssoErrorException( $except_msg, $http_code ); } else { $resp_data = json_decode( $response, $assoc = true ); if ( null === $resp_data ) { $json_msg = sprintf( __( 'JSON response decode error code %d.', 'wpsso' ), json_last_error() ); $except_msg = sprintf( __( '%1$s shortener API error: %2$s', 'wpsso' ), 'YOURLS', $json_msg ); throw new WpssoErrorException( $except_msg ); } else { return $resp_data; } } } catch ( WpssoErrorException $e ) { return $e->errorMessage(); } return false; } } }