PluginProbe ʕ •ᴥ•ʔ
Royal Addons for Elementor – Addons and Templates Kit for Elementor / 1.7.1064
Royal Addons for Elementor – Addons and Templates Kit for Elementor v1.7.1064
1.7.1064 1.7.1063 1.7.1062 1.7.1061 1.7.1060 1.7.1059 1.7.1058 trunk 1.0.0 1.1.0 1.2 1.3 1.3.1 1.3.2 1.3.21 1.3.22 1.3.23 1.3.24 1.3.25 1.3.26 1.3.27 1.3.28 1.3.29 1.3.30 1.3.31 1.3.32 1.3.33 1.3.34 1.3.35 1.3.36 1.3.37 1.3.38 1.3.39 1.3.40 1.3.41 1.3.42 1.3.43 1.3.44 1.3.45 1.3.46 1.3.47 1.3.48 1.3.49 1.3.50 1.3.51 1.3.52 1.3.53 1.3.54 1.3.55 1.3.56 1.3.57 1.3.58 1.3.59 1.3.60 1.3.61 1.3.62 1.3.63 1.3.64 1.3.65 1.3.66 1.3.67 1.3.68 1.3.69 1.3.70 1.3.71 1.3.72 1.3.73 1.3.74 1.3.75 1.3.76 1.3.77 1.3.78 1.3.79 1.3.80 1.3.81 1.3.82 1.3.83 1.3.84 1.3.85 1.3.86 1.3.87 1.3.88 1.3.89 1.3.90 1.3.91 1.3.92 1.3.93 1.3.94 1.3.95 1.3.96 1.3.97 1.3.971 1.3.972 1.3.973 1.3.974 1.3.975 1.3.976 1.3.977 1.3.978 1.3.979 1.3.980 1.3.981 1.3.982 1.3.983 1.3.984 1.3.985 1.3.986 1.3.987 1.7.1 1.7.1001 1.7.1002 1.7.1003 1.7.1004 1.7.1005 1.7.1006 1.7.1007 1.7.1008 1.7.1009 1.7.1010 1.7.1011 1.7.1012 1.7.1013 1.7.1014 1.7.1015 1.7.1016 1.7.1017 1.7.1018 1.7.1019 1.7.1020 1.7.1021 1.7.1022 1.7.1023 1.7.1024 1.7.1025 1.7.1026 1.7.1027 1.7.1028 1.7.1029 1.7.1030 1.7.1031 1.7.1032 1.7.1033 1.7.1034 1.7.1035 1.7.1036 1.7.1037 1.7.1038 1.7.1039 1.7.1040 1.7.1041 1.7.1042 1.7.1043 1.7.1044 1.7.1045 1.7.1046 1.7.1047 1.7.1048 1.7.1049 1.7.1050 1.7.1051 1.7.1052 1.7.1053 1.7.1054 1.7.1055 1.7.1056 1.7.1057
royal-elementor-addons / freemius / includes / sdk / FreemiusWordPress.php
royal-elementor-addons / freemius / includes / sdk Last commit date
Exceptions 5 days ago FreemiusBase.php 5 days ago FreemiusWordPress.php 5 days ago LICENSE.txt 5 days ago index.php 5 days ago
FreemiusWordPress.php
746 lines
1 <?php
2 /**
3 * Copyright 2016 Freemius, Inc.
4 *
5 * Licensed under the GPL v2 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://choosealicense.com/licenses/gpl-v2/
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 */
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 require_once dirname( __FILE__ ) . '/FreemiusBase.php';
22
23 if ( ! defined( 'FS_SDK__USER_AGENT' ) ) {
24 define( 'FS_SDK__USER_AGENT', 'fs-php-' . Freemius_Api_Base::VERSION );
25 }
26
27 if ( ! defined( 'FS_SDK__SIMULATE_NO_CURL' ) ) {
28 define( 'FS_SDK__SIMULATE_NO_CURL', false );
29 }
30
31 if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) {
32 define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false );
33 }
34
35 if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) {
36 define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false );
37 }
38
39 if ( ! defined( 'FS_SDK__HAS_CURL' ) ) {
40 if ( FS_SDK__SIMULATE_NO_CURL ) {
41 define( 'FS_SDK__HAS_CURL', false );
42 } else {
43 $curl_required_methods = array(
44 'curl_version',
45 'curl_exec',
46 'curl_init',
47 'curl_close',
48 'curl_setopt',
49 'curl_setopt_array',
50 'curl_error',
51 );
52
53 $has_curl = true;
54 foreach ( $curl_required_methods as $m ) {
55 if ( ! function_exists( $m ) ) {
56 $has_curl = false;
57 break;
58 }
59 }
60
61 define( 'FS_SDK__HAS_CURL', $has_curl );
62 }
63 }
64
65 if ( ! defined( 'FS_SDK__SSLVERIFY' ) ) {
66 define( 'FS_SDK__SSLVERIFY', false );
67 }
68
69 $curl_version = FS_SDK__HAS_CURL ?
70 curl_version() :
71 array( 'version' => '7.37' );
72
73 if ( ! defined( 'FS_API__PROTOCOL' ) ) {
74 define( 'FS_API__PROTOCOL', version_compare( $curl_version['version'], '7.37', '>=' ) ? 'https' : 'http' );
75 }
76
77 if ( ! defined( 'FS_API__LOGGER_ON' ) ) {
78 define( 'FS_API__LOGGER_ON', false );
79 }
80
81 if ( ! defined( 'FS_API__ADDRESS' ) ) {
82 define( 'FS_API__ADDRESS', '://api.freemius.com' );
83 }
84 if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) {
85 define( 'FS_API__SANDBOX_ADDRESS', '://sandbox-api.freemius.com' );
86 }
87
88 if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
89 class Freemius_Api_WordPress extends Freemius_Api_Base {
90 private static $_logger = array();
91
92 /**
93 * @param string $pScope 'app', 'developer', 'user' or 'install'.
94 * @param number $pID Element's id.
95 * @param string $pPublic Public key.
96 * @param string|bool $pSecret Element's secret key.
97 * @param bool $pSandbox Whether or not to run API in sandbox mode.
98 */
99 public function __construct( $pScope, $pID, $pPublic, $pSecret = false, $pSandbox = false ) {
100 // If secret key not provided, use public key encryption.
101 if ( is_bool( $pSecret ) ) {
102 $pSecret = $pPublic;
103 }
104
105 parent::Init( $pScope, $pID, $pPublic, $pSecret, $pSandbox );
106 }
107
108 public static function GetUrl( $pCanonizedPath = '', $pIsSandbox = false ) {
109 $address = ( $pIsSandbox ? FS_API__SANDBOX_ADDRESS : FS_API__ADDRESS );
110
111 if ( ':' === $address[0] ) {
112 $address = self::$_protocol . $address;
113 }
114
115 return $address . $pCanonizedPath;
116 }
117
118 #----------------------------------------------------------------------------------
119 #region Servers Clock Diff
120 #----------------------------------------------------------------------------------
121
122 /**
123 * @var int Clock diff in seconds between current server to API server.
124 */
125 private static $_clock_diff = 0;
126
127 /**
128 * Set clock diff for all API calls.
129 *
130 * @since 1.0.3
131 *
132 * @param $pSeconds
133 */
134 public static function SetClockDiff( $pSeconds ) {
135 self::$_clock_diff = $pSeconds;
136 }
137
138 /**
139 * Find clock diff between current server to API server.
140 *
141 * @since 1.0.2
142 * @return int Clock diff in seconds.
143 */
144 public static function FindClockDiff() {
145 $time = time();
146 $pong = self::Ping();
147
148 return ( $time - strtotime( $pong->timestamp ) );
149 }
150
151 #endregion
152
153 /**
154 * @var string http or https
155 */
156 private static $_protocol = FS_API__PROTOCOL;
157
158 /**
159 * Set API connection protocol.
160 *
161 * @since 1.0.4
162 */
163 public static function SetHttp() {
164 self::$_protocol = 'http';
165 }
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
176 /**
177 * @since 1.0.4
178 *
179 * @return bool
180 */
181 public static function IsHttps() {
182 return ( 'https' === self::$_protocol );
183 }
184
185 /**
186 * Sign request with the following HTTP headers:
187 * Content-MD5: MD5(HTTP Request body)
188 * Date: Current date (i.e Sat, 14 Feb 2016 20:24:46 +0000)
189 * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign,
190 * {scope_entity_secret_key}))
191 *
192 * @param string $pResourceUrl
193 * @param array $pWPRemoteArgs
194 *
195 * @return array
196 */
197 function SignRequest( $pResourceUrl, $pWPRemoteArgs ) {
198 $auth = $this->GenerateAuthorizationParams(
199 $pResourceUrl,
200 $pWPRemoteArgs['method'],
201 ! empty( $pWPRemoteArgs['body'] ) ? $pWPRemoteArgs['body'] : ''
202 );
203
204 $pWPRemoteArgs['headers']['Date'] = $auth['date'];
205 $pWPRemoteArgs['headers']['Authorization'] = $auth['authorization'];
206
207 if ( ! empty( $auth['content_md5'] ) ) {
208 $pWPRemoteArgs['headers']['Content-MD5'] = $auth['content_md5'];
209 }
210
211 return $pWPRemoteArgs;
212 }
213
214 /**
215 * Generate Authorization request headers:
216 *
217 * Content-MD5: MD5(HTTP Request body)
218 * Date: Current date (i.e Sat, 14 Feb 2016 20:24:46 +0000)
219 * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign,
220 * {scope_entity_secret_key}))
221 *
222 * @author Vova Feldman
223 *
224 * @param string $pResourceUrl
225 * @param string $pMethod
226 * @param string $pPostParams
227 *
228 * @return array
229 * @throws Freemius_Exception
230 */
231 function GenerateAuthorizationParams(
232 $pResourceUrl,
233 $pMethod = 'GET',
234 $pPostParams = ''
235 ) {
236 $pMethod = strtoupper( $pMethod );
237
238 $eol = "\n";
239 $content_md5 = '';
240 $content_type = '';
241 $now = ( time() - self::$_clock_diff );
242 $date = date( 'r', $now );
243
244 if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) {
245 $content_type = 'application/json';
246
247 if ( ! empty( $pPostParams ) ) {
248 $content_md5 = md5( $pPostParams );
249 }
250 }
251
252 $string_to_sign = implode( $eol, array(
253 $pMethod,
254 $content_md5,
255 $content_type,
256 $date,
257 $pResourceUrl
258 ) );
259
260 // If secret and public keys are identical, it means that
261 // the signature uses public key hash encoding.
262 $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP';
263
264 $auth = array(
265 'date' => $date,
266 'authorization' => $auth_type . ' ' . $this->_id . ':' .
267 $this->_public . ':' .
268 self::Base64UrlEncode( hash_hmac(
269 'sha256', $string_to_sign, $this->_secret
270 ) )
271 );
272
273 if ( ! empty( $content_md5 ) ) {
274 $auth['content_md5'] = $content_md5;
275 }
276
277 return $auth;
278 }
279
280 /**
281 * Get API request URL signed via query string.
282 *
283 * @since 1.2.3 Stopped using http_build_query(). Instead, use urlencode(). In some environments the encoding of http_build_query() can generate a URL that once used with a redirect, the `&` querystring separator is escaped to `&amp;` which breaks the URL (Added by @svovaf).
284 *
285 * @param string $pPath
286 *
287 * @throws Freemius_Exception
288 *
289 * @return string
290 */
291 function GetSignedUrl( $pPath ) {
292 $resource = explode( '?', $this->CanonizePath( $pPath ) );
293 $pResourceUrl = $resource[0];
294
295 $auth = $this->GenerateAuthorizationParams( $pResourceUrl );
296
297 return Freemius_Api_WordPress::GetUrl(
298 $pResourceUrl . '?' .
299 ( 1 < count( $resource ) && ! empty( $resource[1] ) ? $resource[1] . '&' : '' ) .
300 'authorization=' . urlencode( $auth['authorization'] ) .
301 '&auth_date=' . urlencode( $auth['date'] )
302 , $this->_isSandbox );
303 }
304
305 /**
306 * @author Vova Feldman
307 *
308 * @param string $pUrl
309 * @param array $pWPRemoteArgs
310 *
311 * @return mixed
312 */
313 private static function ExecuteRequest( $pUrl, &$pWPRemoteArgs ) {
314 $bt = debug_backtrace();
315
316 $start = microtime( true );
317
318 $response = self::RemoteRequest( $pUrl, $pWPRemoteArgs );
319
320 if ( FS_API__LOGGER_ON ) {
321 $end = microtime( true );
322
323 $has_body = ( isset( $pWPRemoteArgs['body'] ) && ! empty( $pWPRemoteArgs['body'] ) );
324 $is_http_error = is_wp_error( $response );
325
326 self::$_logger[] = array(
327 'id' => count( self::$_logger ),
328 'start' => $start,
329 'end' => $end,
330 'total' => ( $end - $start ),
331 'method' => $pWPRemoteArgs['method'],
332 'path' => $pUrl,
333 'body' => $has_body ? $pWPRemoteArgs['body'] : null,
334 'result' => ! $is_http_error ?
335 $response['body'] :
336 json_encode( $response->get_error_messages() ),
337 'code' => ! $is_http_error ? $response['response']['code'] : null,
338 'backtrace' => $bt,
339 );
340 }
341
342 return $response;
343 }
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
370 /**
371 * @return array
372 */
373 static function GetLogger() {
374 return self::$_logger;
375 }
376
377 /**
378 * @param string $pCanonizedPath
379 * @param string $pMethod
380 * @param array $pParams
381 * @param null|array $pWPRemoteArgs
382 * @param bool $pIsSandbox
383 * @param null|callable $pBeforeExecutionFunction
384 *
385 * @return object[]|object|null
386 *
387 * @throws \Freemius_Exception
388 */
389 private static function MakeStaticRequest(
390 $pCanonizedPath,
391 $pMethod = 'GET',
392 $pParams = array(),
393 $pWPRemoteArgs = null,
394 $pIsSandbox = false,
395 $pBeforeExecutionFunction = null
396 ) {
397 // Connectivity errors simulation.
398 if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) {
399 self::ThrowCloudFlareDDoSException();
400 } else if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) {
401 self::ThrowSquidAclException();
402 }
403
404 if ( empty( $pWPRemoteArgs ) ) {
405 $user_agent = 'Freemius/WordPress-SDK/' . Freemius_Api_Base::VERSION . '; ' .
406 home_url();
407
408 $pWPRemoteArgs = array(
409 'method' => strtoupper( $pMethod ),
410 'connect_timeout' => 10,
411 'timeout' => 60,
412 'follow_redirects' => true,
413 'redirection' => 5,
414 'user-agent' => $user_agent,
415 'blocking' => true,
416 );
417 }
418
419 if ( ! isset( $pWPRemoteArgs['headers'] ) ||
420 ! is_array( $pWPRemoteArgs['headers'] )
421 ) {
422 $pWPRemoteArgs['headers'] = array();
423 }
424
425 if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) {
426 $pWPRemoteArgs['headers']['Content-type'] = 'application/json';
427
428 if ( is_array( $pParams ) && 0 < count( $pParams ) ) {
429 $pWPRemoteArgs['body'] = json_encode( $pParams );
430 }
431 }
432
433 $request_url = self::GetUrl( $pCanonizedPath, $pIsSandbox );
434
435 $resource = explode( '?', $pCanonizedPath );
436
437 if ( FS_SDK__HAS_CURL ) {
438 // Disable the 'Expect: 100-continue' behaviour. This causes cURL to wait
439 // for 2 seconds if the server does not support this header.
440 $pWPRemoteArgs['headers']['Expect'] = '';
441 }
442
443 if ( 'https' === substr( strtolower( $request_url ), 0, 5 ) ) {
444 $pWPRemoteArgs['sslverify'] = FS_SDK__SSLVERIFY;
445 }
446
447 if ( false !== $pBeforeExecutionFunction &&
448 is_callable( $pBeforeExecutionFunction )
449 ) {
450 $pWPRemoteArgs = call_user_func( $pBeforeExecutionFunction, $resource[0], $pWPRemoteArgs );
451 }
452
453 $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs );
454
455 if ( is_wp_error( $result ) ) {
456 /**
457 * @var WP_Error $result
458 */
459 if ( self::IsCurlError( $result ) ) {
460 /**
461 * With dual stacked DNS responses, it's possible for a server to
462 * have IPv6 enabled but not have IPv6 connectivity. If this is
463 * the case, cURL will try IPv4 first and if that fails, then it will
464 * fall back to IPv6 and the error EHOSTUNREACH is returned by the
465 * operating system.
466 */
467 $matches = array();
468 $regex = '/Failed to connect to ([^:].*): Network is unreachable/';
469 if ( preg_match( $regex, $result->get_error_message( 'http_request_failed' ), $matches ) ) {
470 /**
471 * Validate IP before calling `inet_pton()` to avoid PHP un-catchable warning.
472 * @author Vova Feldman (@svovaf)
473 */
474 if ( filter_var( $matches[1], FILTER_VALIDATE_IP ) ) {
475 if ( strlen( inet_pton( $matches[1] ) ) === 16 ) {
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 */
482 add_action( 'http_api_curl', 'Freemius_Api_WordPress::CurlResolveToIPv4', 10, 1 );
483
484 // Re-run request.
485 $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs );
486 }
487 }
488 }
489 }
490
491 if ( is_wp_error( $result ) ) {
492 self::ThrowWPRemoteException( $result );
493 }
494 }
495
496 $response_body = $result['body'];
497
498 if ( empty( $response_body ) ) {
499 return null;
500 }
501
502 $decoded = json_decode( $response_body );
503
504 if ( is_null( $decoded ) ) {
505 if ( preg_match( '/Please turn JavaScript on/i', $response_body ) &&
506 preg_match( '/text\/javascript/', $response_body )
507 ) {
508 self::ThrowCloudFlareDDoSException( $response_body );
509 } else if ( preg_match( '/Access control configuration prevents your request from being allowed at this time. Please contact your service provider if you feel this is incorrect./', $response_body ) &&
510 preg_match( '/squid/', $response_body )
511 ) {
512 self::ThrowSquidAclException( $response_body );
513 } else {
514 $decoded = (object) array(
515 'error' => (object) array(
516 'type' => 'Unknown',
517 'message' => $response_body,
518 'code' => 'unknown',
519 'http' => 402
520 )
521 );
522 }
523 }
524
525 return $decoded;
526 }
527
528
529 /**
530 * Makes an HTTP request. This method can be overridden by subclasses if
531 * developers want to do fancier things or use something other than wp_remote_request()
532 * to make the request.
533 *
534 * @param string $pCanonizedPath The URL to make the request to
535 * @param string $pMethod HTTP method
536 * @param array $pParams The parameters to use for the POST body
537 * @param null|array $pWPRemoteArgs wp_remote_request options.
538 *
539 * @return object[]|object|null
540 *
541 * @throws Freemius_Exception
542 */
543 public function MakeRequest(
544 $pCanonizedPath,
545 $pMethod = 'GET',
546 $pParams = array(),
547 $pWPRemoteArgs = null
548 ) {
549 $resource = explode( '?', $pCanonizedPath );
550
551 // Only sign request if not ping.json connectivity test.
552 $sign_request = ( '/v1/ping.json' !== strtolower( substr( $resource[0], - strlen( '/v1/ping.json' ) ) ) );
553
554 return self::MakeStaticRequest(
555 $pCanonizedPath,
556 $pMethod,
557 $pParams,
558 $pWPRemoteArgs,
559 $this->_isSandbox,
560 $sign_request ? array( &$this, 'SignRequest' ) : null
561 );
562 }
563
564 /**
565 * Sets CURLOPT_IPRESOLVE to CURL_IPRESOLVE_V4 for cURL-Handle provided as parameter
566 *
567 * @param resource $handle A cURL handle returned by curl_init()
568 *
569 * @return resource $handle A cURL handle returned by curl_init() with CURLOPT_IPRESOLVE set to
570 * CURL_IPRESOLVE_V4
571 *
572 * @link https://gist.github.com/golderweb/3a2aaec2d56125cc004e
573 */
574 static function CurlResolveToIPv4( $handle ) {
575 curl_setopt( $handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
576
577 return $handle;
578 }
579
580 #----------------------------------------------------------------------------------
581 #region Connectivity Test
582 #----------------------------------------------------------------------------------
583
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 }
598
599 /**
600 * Ping API to test connectivity.
601 *
602 * @return object
603 */
604 public static function Ping() {
605 try {
606 $result = self::MakeStaticRequest( '/v' . FS_API__VERSION . '/ping.json' );
607 } catch ( Freemius_Exception $e ) {
608 // Map to error object.
609 $result = (object) $e->getResult();
610 } catch ( Exception $e ) {
611 // Map to error object.
612 $result = (object) array(
613 'error' => (object) array(
614 'type' => 'Unknown',
615 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')',
616 'code' => 'unknown',
617 'http' => 402
618 )
619 );
620 }
621
622 return $result;
623 }
624
625 #endregion
626
627 #----------------------------------------------------------------------------------
628 #region Connectivity Exceptions
629 #----------------------------------------------------------------------------------
630
631 /**
632 * @param \WP_Error $pError
633 *
634 * @return bool
635 */
636 private static function IsCurlError( WP_Error $pError ) {
637 $message = $pError->get_error_message( 'http_request_failed' );
638
639 return ( 0 === strpos( $message, 'cURL' ) );
640 }
641
642 /**
643 * @param WP_Error $pError
644 *
645 * @throws Freemius_Exception
646 */
647 private static function ThrowWPRemoteException( WP_Error $pError ) {
648 if ( self::IsCurlError( $pError ) ) {
649 $message = $pError->get_error_message( 'http_request_failed' );
650
651 #region Check if there are any missing cURL methods.
652
653 $curl_required_methods = array(
654 'curl_version',
655 'curl_exec',
656 'curl_init',
657 'curl_close',
658 'curl_setopt',
659 'curl_setopt_array',
660 'curl_error',
661 );
662
663 // Find all missing methods.
664 $missing_methods = array();
665 foreach ( $curl_required_methods as $m ) {
666 if ( ! function_exists( $m ) ) {
667 $missing_methods[] = $m;
668 }
669 }
670
671 if ( ! empty( $missing_methods ) ) {
672 throw new Freemius_Exception( array(
673 'error' => (object) array(
674 'type' => 'cUrlMissing',
675 'message' => $message,
676 'code' => 'curl_missing',
677 'http' => 402
678 ),
679 'missing_methods' => $missing_methods,
680 ) );
681 }
682
683 #endregion
684
685 // cURL error - "cURL error {{errno}}: {{error}}".
686 $parts = explode( ':', substr( $message, strlen( 'cURL error ' ) ), 2 );
687
688 $code = ( 0 < count( $parts ) ) ? $parts[0] : 'http_request_failed';
689 $message = ( 1 < count( $parts ) ) ? $parts[1] : $message;
690
691 $e = new Freemius_Exception( array(
692 'error' => (object) array(
693 'code' => $code,
694 'message' => $message,
695 'type' => 'CurlException',
696 ),
697 ) );
698 } else {
699 $e = new Freemius_Exception( array(
700 'error' => (object) array(
701 'code' => $pError->get_error_code(),
702 'message' => $pError->get_error_message(),
703 'type' => 'WPRemoteException',
704 ),
705 ) );
706 }
707
708 throw $e;
709 }
710
711 /**
712 * @param string $pResult
713 *
714 * @throws Freemius_Exception
715 */
716 private static function ThrowCloudFlareDDoSException( $pResult = '' ) {
717 throw new Freemius_Exception( array(
718 'error' => (object) array(
719 'type' => 'CloudFlareDDoSProtection',
720 'message' => $pResult,
721 'code' => 'cloudflare_ddos_protection',
722 'http' => 402
723 )
724 ) );
725 }
726
727 /**
728 * @param string $pResult
729 *
730 * @throws Freemius_Exception
731 */
732 private static function ThrowSquidAclException( $pResult = '' ) {
733 throw new Freemius_Exception( array(
734 'error' => (object) array(
735 'type' => 'SquidCacheBlock',
736 'message' => $pResult,
737 'code' => 'squid_cache_block',
738 'http' => 402
739 )
740 ) );
741 }
742
743 #endregion
744 }
745 }
746