| @@ -13,8 +13,11 @@ | ||
| 13 | 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 14 | 14 | * License for the specific language governing permissions and limitations |
| 15 | 15 | * under the License. |
| 16 | 16 | */ |
| 17 | + if ( ! defined( 'ABSPATH' ) ) { | |
| 18 | + exit; | |
| 19 | + } | |
| 17 | 20 | |
| 18 | 21 | require_once dirname( __FILE__ ) . '/FreemiusBase.php'; |
| 19 | 22 | |
| 20 | 23 | if ( ! defined( 'FS_SDK__USER_AGENT' ) ) { |
| @@ -58,8 +61,12 @@ | ||
| 58 | 61 | define( 'FS_SDK__HAS_CURL', $has_curl ); |
| 59 | 62 | } |
| 60 | 63 | } |
| 61 | 64 | |
| 65 | + if ( ! defined( 'FS_SDK__SSLVERIFY' ) ) { | |
| 66 | + define( 'FS_SDK__SSLVERIFY', false ); | |
| 67 | + } | |
| 68 | + | |
| 62 | 69 | $curl_version = FS_SDK__HAS_CURL ? |
| 63 | 70 | curl_version() : |
| 64 | 71 | array( 'version' => '7.37' ); |
| 65 | 72 | |
| @@ -77,12 +84,9 @@ | ||
| 77 | 84 | if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) { |
| 78 | 85 | define( 'FS_API__SANDBOX_ADDRESS', '://sandbox-api.freemius.com' ); |
| 79 | 86 | } |
| 80 | 87 | |
| 81 | - if ( class_exists( 'Freemius_Api_WordPress' ) ) { | |
| 82 | - return; | |
| 83 | - } | |
| 84 | - | |
| 88 | + if ( ! class_exists( 'Freemius_Api_WordPress' ) ) { | |
| 85 | 89 | class Freemius_Api_WordPress extends Freemius_Api_Base { |
| 86 | 90 | private static $_logger = array(); |
| 87 | 91 | |
| 88 | 92 | /** |
| @@ -159,8 +163,17 @@ | ||
| 159 | 163 | public static function SetHttp() { |
| 160 | 164 | self::$_protocol = 'http'; |
| 161 | 165 | } |
| 162 | 166 | |
| 167 | + /** | |
| 168 | + * Sets API connection protocol to HTTPS. | |
| 169 | + * | |
| 170 | + * @since 2.5.4 | |
| 171 | + */ | |
| 172 | + public static function SetHttps() { | |
| 173 | + self::$_protocol = 'https'; | |
| 174 | + } | |
| 175 | + | |
| 163 | 176 | /** |
| 164 | 177 | * @since 1.0.4 |
| 165 | 178 | * |
| 166 | 179 | * @return bool |
| @@ -227,13 +240,16 @@ | ||
| 227 | 240 | $content_type = ''; |
| 228 | 241 | $now = ( time() - self::$_clock_diff ); |
| 229 | 242 | $date = date( 'r', $now ); |
| 230 | 243 | |
| 231 | - if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) && ! empty( $pPostParams ) ) { | |
| 232 | - $content_md5 = md5( $pPostParams ); | |
| 233 | - $content_type = 'application/json'; | |
| 234 | - } | |
| 244 | + if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) { | |
| 245 | + $content_type = 'application/json'; | |
| 235 | 246 | |
| 247 | + if ( ! empty( $pPostParams ) ) { | |
| 248 | + $content_md5 = md5( $pPostParams ); | |
| 249 | + } | |
| 250 | + } | |
| 251 | + | |
| 236 | 252 | $string_to_sign = implode( $eol, array( |
| 237 | 253 | $pMethod, |
| 238 | 254 | $content_md5, |
| 239 | 255 | $content_type, |
| @@ -294,11 +310,13 @@ | ||
| 294 | 310 | * |
| 295 | 311 | * @return mixed |
| 296 | 312 | */ |
| 297 | 313 | private static function ExecuteRequest( $pUrl, &$pWPRemoteArgs ) { |
| 314 | + $bt = debug_backtrace(); | |
| 315 | + | |
| 298 | 316 | $start = microtime( true ); |
| 299 | 317 | |
| 300 | - $response = wp_remote_request( $pUrl, $pWPRemoteArgs ); | |
| 318 | + $response = self::RemoteRequest( $pUrl, $pWPRemoteArgs ); | |
| 301 | 319 | |
| 302 | 320 | if ( FS_API__LOGGER_ON ) { |
| 303 | 321 | $end = microtime( true ); |
| 304 | 322 | |
| @@ -316,9 +334,9 @@ | ||
| 316 | 334 | 'result' => ! $is_http_error ? |
| 317 | 335 | $response['body'] : |
| 318 | 336 | json_encode( $response->get_error_messages() ), |
| 319 | 337 | 'code' => ! $is_http_error ? $response['response']['code'] : null, |
| 320 | - 'backtrace' => debug_backtrace(), | |
| 338 | + 'backtrace' => $bt, | |
| 321 | 339 | ); |
| 322 | 340 | } |
| 323 | 341 | |
| 324 | 342 | return $response; |
| @@ -323,8 +341,33 @@ | ||
| 323 | 341 | |
| 324 | 342 | return $response; |
| 325 | 343 | } |
| 326 | 344 | |
| 345 | + /** | |
| 346 | + * @author Leo Fajardo (@leorw) | |
| 347 | + * | |
| 348 | + * @param string $pUrl | |
| 349 | + * @param array $pWPRemoteArgs | |
| 350 | + * | |
| 351 | + * @return array|WP_Error The response array or a WP_Error on failure. | |
| 352 | + */ | |
| 353 | + static function RemoteRequest( $pUrl, $pWPRemoteArgs ) { | |
| 354 | + $response = wp_remote_request( $pUrl, $pWPRemoteArgs ); | |
| 355 | + | |
| 356 | + if ( | |
| 357 | + is_array( $response ) && | |
| 358 | + ( | |
| 359 | + empty( $response['headers'] ) || | |
| 360 | + empty( $response['headers']['x-api-server'] ) | |
| 361 | + ) | |
| 362 | + ) { | |
| 363 | + // API is considered blocked if the response doesn't include the `x-api-server` header. When there's no error but this header doesn't exist, the response is usually not in the expected form (e.g., cannot be JSON-decoded). | |
| 364 | + $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) ); | |
| 365 | + } | |
| 366 | + | |
| 367 | + return $response; | |
| 368 | + } | |
| 369 | + | |
| 327 | 370 | /** |
| 328 | 371 | * @return array |
| 329 | 372 | */ |
| 330 | 373 | static function GetLogger() { |
| @@ -364,9 +407,9 @@ | ||
| 364 | 407 | |
| 365 | 408 | $pWPRemoteArgs = array( |
| 366 | 409 | 'method' => strtoupper( $pMethod ), |
| 367 | 410 | 'connect_timeout' => 10, |
| 368 | - 'timeout' => 60, | |
| 411 | + 'timeout' => WP_FS__API_TIMEOUT, | |
| 369 | 412 | 'follow_redirects' => true, |
| 370 | 413 | 'redirection' => 5, |
| 371 | 414 | 'user-agent' => $user_agent, |
| 372 | 415 | 'blocking' => true, |
| @@ -379,12 +422,13 @@ | ||
| 379 | 422 | $pWPRemoteArgs['headers'] = array(); |
| 380 | 423 | } |
| 381 | 424 | |
| 382 | 425 | if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) { |
| 383 | - if ( is_array( $pParams ) && 0 < count( $pParams ) ) { | |
| 384 | - $pWPRemoteArgs['headers']['Content-type'] = 'application/json'; | |
| 385 | - $pWPRemoteArgs['body'] = json_encode( $pParams ); | |
| 386 | - } | |
| 426 | + $pWPRemoteArgs['headers']['Content-type'] = 'application/json'; | |
| 427 | + | |
| 428 | + if ( is_array( $pParams ) && 0 < count( $pParams ) ) { | |
| 429 | + $pWPRemoteArgs['body'] = json_encode( $pParams ); | |
| 430 | + } | |
| 387 | 431 | } |
| 388 | 432 | |
| 389 | 433 | $request_url = self::GetUrl( $pCanonizedPath, $pIsSandbox ); |
| 390 | 434 | |
| @@ -396,9 +440,9 @@ | ||
| 396 | 440 | $pWPRemoteArgs['headers']['Expect'] = ''; |
| 397 | 441 | } |
| 398 | 442 | |
| 399 | 443 | if ( 'https' === substr( strtolower( $request_url ), 0, 5 ) ) { |
| 400 | - $pWPRemoteArgs['sslverify'] = false; | |
| 444 | + $pWPRemoteArgs['sslverify'] = FS_SDK__SSLVERIFY; | |
| 401 | 445 | } |
| 402 | 446 | |
| 403 | 447 | if ( false !== $pBeforeExecutionFunction && |
| 404 | 448 | is_callable( $pBeforeExecutionFunction ) |
| @@ -428,10 +472,14 @@ | ||
| 428 | 472 | * @author Vova Feldman (@svovaf) |
| 429 | 473 | */ |
| 430 | 474 | if ( filter_var( $matches[1], FILTER_VALIDATE_IP ) ) { |
| 431 | 475 | if ( strlen( inet_pton( $matches[1] ) ) === 16 ) { |
| 432 | -// error_log('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); | |
| 433 | - // Hook to an action triggered just before cURL is executed to resolve the IP version to v4. | |
| 476 | + /** | |
| 477 | + * error_log('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); | |
| 478 | + * Hook to an action triggered just before cURL is executed to resolve the IP version to v4. | |
| 479 | + * | |
| 480 | + * @phpstan-ignore-next-line | |
| 481 | + */ | |
| 434 | 482 | add_action( 'http_api_curl', 'Freemius_Api_WordPress::CurlResolveToIPv4', 10, 1 ); |
| 435 | 483 | |
| 436 | 484 | // Re-run request. |
| 437 | 485 | $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs ); |
| @@ -532,31 +580,23 @@ | ||
| 532 | 580 | #---------------------------------------------------------------------------------- |
| 533 | 581 | #region Connectivity Test |
| 534 | 582 | #---------------------------------------------------------------------------------- |
| 535 | 583 | |
| 536 | - /** | |
| 537 | - * If successful connectivity to the API endpoint using ping.json endpoint. | |
| 538 | - * | |
| 539 | - * - OR - | |
| 540 | - * | |
| 541 | - * Validate if ping result object is valid. | |
| 542 | - * | |
| 543 | - * @param mixed $pPong | |
| 544 | - * | |
| 545 | - * @return bool | |
| 546 | - */ | |
| 547 | - public static function Test( $pPong = null ) { | |
| 548 | - $pong = is_null( $pPong ) ? | |
| 549 | - self::Ping() : | |
| 550 | - $pPong; | |
| 584 | + /** | |
| 585 | + * This method exists only for backward compatibility to prevent a fatal error from happening when called from an outdated piece of code. | |
| 586 | + * | |
| 587 | + * @param mixed $pPong | |
| 588 | + * | |
| 589 | + * @return bool | |
| 590 | + */ | |
| 591 | + public static function Test( $pPong = null ) { | |
| 592 | + return ( | |
| 593 | + is_object( $pPong ) && | |
| 594 | + isset( $pPong->api ) && | |
| 595 | + 'pong' === $pPong->api | |
| 596 | + ); | |
| 597 | + } | |
| 551 | 598 | |
| 552 | - return ( | |
| 553 | - is_object( $pong ) && | |
| 554 | - isset( $pong->api ) && | |
| 555 | - 'pong' === $pong->api | |
| 556 | - ); | |
| 557 | - } | |
| 558 | - | |
| 559 | 599 | /** |
| 560 | 600 | * Ping API to test connectivity. |
| 561 | 601 | * |
| 562 | 602 | * @return object |
| @@ -569,9 +609,9 @@ | ||
| 569 | 609 | $result = (object) $e->getResult(); |
| 570 | 610 | } catch ( Exception $e ) { |
| 571 | 611 | // Map to error object. |
| 572 | 612 | $result = (object) array( |
| 573 | - 'error' => array( | |
| 613 | + 'error' => (object) array( | |
| 574 | 614 | 'type' => 'Unknown', |
| 575 | 615 | 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', |
| 576 | 616 | 'code' => 'unknown', |
| 577 | 617 | 'http' => 402 |
| @@ -648,9 +688,9 @@ | ||
| 648 | 688 | $code = ( 0 < count( $parts ) ) ? $parts[0] : 'http_request_failed'; |
| 649 | 689 | $message = ( 1 < count( $parts ) ) ? $parts[1] : $message; |
| 650 | 690 | |
| 651 | 691 | $e = new Freemius_Exception( array( |
| 652 | - 'error' => array( | |
| 692 | + 'error' => (object) array( | |
| 653 | 693 | 'code' => $code, |
| 654 | 694 | 'message' => $message, |
| 655 | 695 | 'type' => 'CurlException', |
| 656 | 696 | ), |
| @@ -656,9 +696,9 @@ | ||
| 656 | 696 | ), |
| 657 | 697 | ) ); |
| 658 | 698 | } else { |
| 659 | 699 | $e = new Freemius_Exception( array( |
| 660 | - 'error' => array( | |
| 700 | + 'error' => (object) array( | |
| 661 | 701 | 'code' => $pError->get_error_code(), |
| 662 | 702 | 'message' => $pError->get_error_message(), |
| 663 | 703 | 'type' => 'WPRemoteException', |
| 664 | 704 | ), |
| @@ -700,5 +740,6 @@ | ||
| 700 | 740 | ) ); |
| 701 | 741 | } |
| 702 | 742 | |
| 703 | 743 | #endregion |
| 704 | - } | |
| 744 | + } | |
| 745 | + } | |