PluginProbe
Passster – Password Protect Pages and Content / 4.3.16
Passster – Password Protect Pages and Content v4.3.16
4.3.16 4.3.15 4.3.14 4.3.12 4.3.13 4.3.11 4.3.10 4.3.9 4.3.8 4.3.7 4.3.6 4.3.5 trunk 3.5.4 3.5.5.2 3.5.5.8 3.5.5.9 4.0 4.1.4 4.2.10 4.2.11 4.2.12 4.2.13 4.2.14 4.2.15 All 48 releases
← All changes | inc/freemius/includes/class-fs-api.php +158 -122 4.04.3.16 View file →
@@ -188,15 +188,17 @@
188 188 *
189 189 * @param string $path
190 190 * @param string $method
191 191 * @param array $params
192 - * @param bool $retry Is in retry or first call attempt.
192 + * @param bool $in_retry Is in retry or first call attempt.
193 193 *
194 194 * @return array|mixed|string|void
195 195 */
196 - private function _call( $path, $method = 'GET', $params = array(), $retry = false ) {
196 + private function _call( $path, $method = 'GET', $params = array(), $in_retry = false ) {
197 197 $this->_logger->entrance( $method . ':' . $path );
198 198
199 + $force_http = ( ! $in_retry && self::$_options->get_option( 'api_force_http', false ) );
200 +
199 201 if ( self::is_temporary_down() ) {
200 202 $result = $this->get_temporary_unavailable_error();
201 203 } else {
202 204 /**
@@ -223,14 +225,17 @@
223 225 }
224 226
225 227 $result = $this->_api->Api( $path, $method, $params );
226 228
227 - if ( null !== $result &&
228 - isset( $result->error ) &&
229 - isset( $result->error->code ) &&
230 - 'request_expired' === $result->error->code
229 + if (
230 + ! $in_retry &&
231 + null !== $result &&
232 + isset( $result->error ) &&
233 + isset( $result->error->code )
231 234 ) {
232 - if ( ! $retry ) {
235 + $retry = false;
236 +
237 + if ( 'request_expired' === $result->error->code ) {
233 238 $diff = isset( $result->error->timestamp ) ?
234 239 ( time() - strtotime( $result->error->timestamp ) ) :
235 240 false;
236 241
@@ -236,17 +241,37 @@
236 241
237 242 // Try to sync clock diff.
238 243 if ( false !== $this->_sync_clock_diff( $diff ) ) {
239 244 // Retry call with new synced clock.
240 - return $this->_call( $path, $method, $params, true );
245 + $retry = true;
241 246 }
247 + } else if (
248 + Freemius_Api_WordPress::IsHttps() &&
249 + FS_Api::is_ssl_error_response( $result )
250 + ) {
251 + $force_http = true;
252 + $retry = true;
242 253 }
254 +
255 + if ( $retry ) {
256 + if ( $force_http ) {
257 + $this->toggle_force_http( true );
258 + }
259 +
260 + $result = $this->_call( $path, $method, $params, true );
261 + }
243 262 }
244 263 }
245 264
246 - if ( $this->_logger->is_on() && self::is_api_error( $result ) ) {
247 - // Log API errors.
248 - $this->_logger->api_error( $result );
265 + if ( self::is_api_error( $result ) ) {
266 + if ( $this->_logger->is_on() ) {
267 + // Log API errors.
268 + $this->_logger->api_error( $result );
269 + }
270 +
271 + if ( $force_http ) {
272 + $this->toggle_force_http( false );
273 + }
249 274 }
250 275
251 276 return $result;
252 277 }
@@ -292,11 +317,14 @@
292 317 if ( WP_FS__DEV_MODE || $this->_api->IsSandbox() ) {
293 318 $flush = true;
294 319 }
295 320
296 - $cached_result = self::$_cache->get( $cache_key );
321 + $has_valid_cache = self::$_cache->has_valid( $cache_key, $expiration );
322 + $cached_result = $has_valid_cache ?
323 + self::$_cache->get( $cache_key ) :
324 + null;
297 325
298 - if ( $flush || ! self::$_cache->has_valid( $cache_key, $expiration ) ) {
326 + if ( $flush || is_null( $cached_result ) ) {
299 327 $result = $this->call( $path );
300 328
301 329 if ( ! is_object( $result ) || isset( $result->error ) ) {
302 330 // Api returned an error.
@@ -326,9 +354,11 @@
326 354 }
327 355 }
328 356 }
329 357
330 - self::$_cache->set( $cache_key, $result, $expiration );
358 + if ( is_numeric( $expiration ) ) {
359 + self::$_cache->set( $cache_key, $result, $expiration );
360 + }
331 361
332 362 $cached_result = $result;
333 363 } else {
334 364 $this->_logger->log( 'Using cached API result.' );
@@ -336,8 +366,45 @@
336 366
337 367 return $cached_result;
338 368 }
339 369
370 + /**
371 + * @todo Remove this method after migrating Freemius::safe_remote_post() to FS_Api::call().
372 + *
373 + * @author Leo Fajardo (@leorw)
374 + * @since 2.5.4
375 + *
376 + * @param string $url
377 + * @param array $remote_args
378 + *
379 + * @return array|WP_Error The response array or a WP_Error on failure.
380 + */
381 + static function remote_request( $url, $remote_args ) {
382 + if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
383 + require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php';
384 + }
385 +
386 + if ( method_exists( 'Freemius_Api_WordPress', 'RemoteRequest' ) ) {
387 + return Freemius_Api_WordPress::RemoteRequest( $url, $remote_args );
388 + }
389 +
390 + // The following is for backward compatibility when a modified PHP SDK version is in use and the `Freemius_Api_WordPress:RemoteRequest()` method doesn't exist.
391 + $response = wp_remote_request( $url, $remote_args );
392 +
393 + if (
394 + is_array( $response ) &&
395 + (
396 + empty( $response['headers'] ) ||
397 + empty( $response['headers']['x-api-server'] )
398 + )
399 + ) {
400 + // 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).
401 + $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) );
402 + }
403 +
404 + return $response;
405 + }
406 +
340 407 /**
341 408 * Check if there's a cached version of the API request.
342 409 *
343 410 * @author Vova Feldman (@svovaf)
@@ -406,53 +473,40 @@
406 473 // return $method . '_' . array_pop($exploded) . '_' . md5($canonized . json_encode($params));
407 474 return strtolower( $method . ':' . $canonized ) . ( ! empty( $params ) ? '#' . md5( json_encode( $params ) ) : '' );
408 475 }
409 476
410 - /**
411 - * Test API connectivity.
412 - *
413 - * @author Vova Feldman (@svovaf)
414 - * @since 1.0.9 If fails, try to fallback to HTTP.
415 - * @since 1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if
416 - * temporary down.
417 - *
418 - * @return bool True if successful connectivity to the API.
419 - */
420 - static function test() {
421 - self::_init();
477 + /**
478 + * @author Leo Fajardo (@leorw)
479 + * @since 2.5.4
480 + *
481 + * @param bool $is_http
482 + */
483 + private function toggle_force_http( $is_http ) {
484 + self::$_options->set_option( 'api_force_http', $is_http, true );
422 485
423 - $cache_key = 'ping_test';
486 + if ( $is_http ) {
487 + Freemius_Api_WordPress::SetHttp();
488 + } else if ( method_exists( 'Freemius_Api_WordPress', 'SetHttps' ) ) {
489 + Freemius_Api_WordPress::SetHttps();
490 + }
491 + }
424 492
425 - $test = self::$_cache->get_valid( $cache_key, null );
493 + /**
494 + * @author Leo Fajardo (@leorw)
495 + * @since 2.5.4
496 + *
497 + * @param mixed $response
498 + *
499 + * @return bool
500 + */
501 + static function is_blocked( $response ) {
502 + return (
503 + self::is_api_error_object( $response, true ) &&
504 + isset( $response->error->code ) &&
505 + 'api_blocked' === $response->error->code
506 + );
507 + }
426 508
427 - if ( is_null( $test ) ) {
428 - $test = Freemius_Api_WordPress::Test();
429 -
430 - if ( false === $test && Freemius_Api_WordPress::IsHttps() ) {
431 - // Fallback to HTTP, since HTTPS fails.
432 - Freemius_Api_WordPress::SetHttp();
433 -
434 - self::$_options->set_option( 'api_force_http', true, true );
435 -
436 - $test = Freemius_Api_WordPress::Test();
437 -
438 - if ( false === $test ) {
439 - /**
440 - * API connectivity test fail also in HTTP request, therefore,
441 - * fallback to HTTPS to keep connection secure.
442 - *
443 - * @since 1.1.6
444 - */
445 - self::$_options->set_option( 'api_force_http', false, true );
446 - }
447 - }
448 -
449 - self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC );
450 - }
451 -
452 - return $test;
453 - }
454 -
455 509 /**
456 510 * Check if API is temporary down.
457 511 *
458 512 * @author Vova Feldman (@svovaf)
@@ -485,58 +539,8 @@
485 539 );
486 540 }
487 541
488 542 /**
489 - * Ping API for connectivity test, and return result object.
490 - *
491 - * @author Vova Feldman (@svovaf)
492 - * @since 1.0.9
493 - *
494 - * @param null|string $unique_anonymous_id
495 - * @param array $params
496 - *
497 - * @return object
498 - */
499 - function ping( $unique_anonymous_id = null, $params = array() ) {
500 - $this->_logger->entrance();
501 -
502 - if ( self::is_temporary_down() ) {
503 - return $this->get_temporary_unavailable_error();
504 - }
505 -
506 - $pong = is_null( $unique_anonymous_id ) ?
507 - Freemius_Api_WordPress::Ping() :
508 - $this->_call( 'ping.json?' . http_build_query( array_merge(
509 - array( 'uid' => $unique_anonymous_id ),
510 - $params
511 - ) ) );
512 -
513 - if ( $this->is_valid_ping( $pong ) ) {
514 - return $pong;
515 - }
516 -
517 - if ( self::should_try_with_http( $pong ) ) {
518 - // Fallback to HTTP, since HTTPS fails.
519 - Freemius_Api_WordPress::SetHttp();
520 -
521 - self::$_options->set_option( 'api_force_http', true, true );
522 -
523 - $pong = is_null( $unique_anonymous_id ) ?
524 - Freemius_Api_WordPress::Ping() :
525 - $this->_call( 'ping.json?' . http_build_query( array_merge(
526 - array( 'uid' => $unique_anonymous_id ),
527 - $params
528 - ) ) );
529 -
530 - if ( ! $this->is_valid_ping( $pong ) ) {
531 - self::$_options->set_option( 'api_force_http', false, true );
532 - }
533 - }
534 -
535 - return $pong;
536 - }
537 -
538 - /**
539 543 * Check if based on the API result we should try
540 544 * to re-run the same request with HTTP instead of HTTPS.
541 545 *
542 546 * @author Vova Feldman (@svovaf)
@@ -563,22 +567,8 @@
563 567 ) ) );
564 568
565 569 }
566 570
567 - /**
568 - * Check if valid ping request result.
569 - *
570 - * @author Vova Feldman (@svovaf)
571 - * @since 1.1.1
572 - *
573 - * @param mixed $pong
574 - *
575 - * @return bool
576 - */
577 - function is_valid_ping( $pong ) {
578 - return Freemius_Api_WordPress::Test( $pong );
579 - }
580 -
581 571 function get_url( $path = '' ) {
582 572 return Freemius_Api_WordPress::GetUrl( $path, $this->_api->IsSandbox() );
583 573 }
584 574
@@ -594,8 +584,16 @@
594 584 self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME );
595 585 self::$_cache->clear();
596 586 }
597 587
588 + /**
589 + * @author Leo Fajardo (@leorw)
590 + * @since 2.5.4
591 + */
592 + static function clear_force_http_flag() {
593 + self::$_options->unset_option( 'api_force_http' );
594 + }
595 +
598 596 #----------------------------------------------------------------------------------
599 597 #region Error Handling
600 598 #----------------------------------------------------------------------------------
601 599
@@ -616,16 +614,54 @@
616 614 * @author Vova Feldman (@svovaf)
617 615 * @since 2.0.0
618 616 *
619 617 * @param mixed $result
618 + * @param bool $ignore_message
620 619 *
621 620 * @return bool Is API result contains an error.
622 621 */
623 - static function is_api_error_object( $result ) {
622 + static function is_api_error_object( $result, $ignore_message = false ) {
624 623 return (
625 624 is_object( $result ) &&
626 625 isset( $result->error ) &&
627 - isset( $result->error->message )
626 + ( $ignore_message || isset( $result->error->message ) )
627 + );
628 + }
629 +
630 + /**
631 + * @author Leo Fajardo (@leorw)
632 + * @since 2.5.4
633 + *
634 + * @param WP_Error|object|string $response
635 + *
636 + * @return bool
637 + */
638 + static function is_ssl_error_response( $response ) {
639 + $http_error = null;
640 +
641 + if ( $response instanceof WP_Error ) {
642 + if (
643 + isset( $response->errors ) &&
644 + isset( $response->errors['http_request_failed'] )
645 + ) {
646 + $http_error = strtolower( $response->errors['http_request_failed'][0] );
647 + }
648 + } else if (
649 + self::is_api_error_object( $response ) &&
650 + ! empty( $response->error->message )
651 + ) {
652 + $http_error = $response->error->message;
653 + }
654 +
655 + return (
656 + ! empty( $http_error ) &&
657 + (
658 + false !== strpos( $http_error, 'curl error 35' ) ||
659 + (
660 + false === strpos( $http_error, '</html>' ) &&
661 + false !== strpos( $http_error, 'ssl' )
662 + )
663 + )
628 664 );
629 665 }
630 666
631 667 /**