PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 3.1.2
Adminify – White Label, Admin Menu Editor, Login Customizer v3.1.2
4.3.2 4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 All 165 releases
adminify / lib / freemius / includes / sdk / FreemiusWordPress.php

FreemiusWordPress.php in Adminify – White Label, Admin Menu Editor, Login Customizer 3.1.2, at lib/freemius/includes/sdk/FreemiusWordPress.php

739 lines 21.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 mixed
352 */
353 static function RemoteRequest( $pUrl, $pWPRemoteArgs ) {
354 $response = wp_remote_request( $pUrl, $pWPRemoteArgs );
355
356 if (
357 empty( $response['headers'] ) ||
358 empty( $response['headers']['x-api-server'] )
359 ) {
360 // 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).
361 $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) );
362 }
363
364 return $response;
365 }
366
367 /**
368 * @return array
369 */
370 static function GetLogger() {
371 return self::$_logger;
372 }
373
374 /**
375 * @param string $pCanonizedPath
376 * @param string $pMethod
377 * @param array $pParams
378 * @param null|array $pWPRemoteArgs
379 * @param bool $pIsSandbox
380 * @param null|callable $pBeforeExecutionFunction
381 *
382 * @return object[]|object|null
383 *
384 * @throws \Freemius_Exception
385 */
386 private static function MakeStaticRequest(
387 $pCanonizedPath,
388 $pMethod = 'GET',
389 $pParams = array(),
390 $pWPRemoteArgs = null,
391 $pIsSandbox = false,
392 $pBeforeExecutionFunction = null
393 ) {
394 // Connectivity errors simulation.
395 if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) {
396 self::ThrowCloudFlareDDoSException();
397 } else if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) {
398 self::ThrowSquidAclException();
399 }
400
401 if ( empty( $pWPRemoteArgs ) ) {
402 $user_agent = 'Freemius/WordPress-SDK/' . Freemius_Api_Base::VERSION . '; ' .
403 home_url();
404
405 $pWPRemoteArgs = array(
406 'method' => strtoupper( $pMethod ),
407 'connect_timeout' => 10,
408 'timeout' => 60,
409 'follow_redirects' => true,
410 'redirection' => 5,
411 'user-agent' => $user_agent,
412 'blocking' => true,
413 );
414 }
415
416 if ( ! isset( $pWPRemoteArgs['headers'] ) ||
417 ! is_array( $pWPRemoteArgs['headers'] )
418 ) {
419 $pWPRemoteArgs['headers'] = array();
420 }
421
422 if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) {
423 $pWPRemoteArgs['headers']['Content-type'] = 'application/json';
424
425 if ( is_array( $pParams ) && 0 < count( $pParams ) ) {
426 $pWPRemoteArgs['body'] = json_encode( $pParams );
427 }
428 }
429
430 $request_url = self::GetUrl( $pCanonizedPath, $pIsSandbox );
431
432 $resource = explode( '?', $pCanonizedPath );
433
434 if ( FS_SDK__HAS_CURL ) {
435 // Disable the 'Expect: 100-continue' behaviour. This causes cURL to wait
436 // for 2 seconds if the server does not support this header.
437 $pWPRemoteArgs['headers']['Expect'] = '';
438 }
439
440 if ( 'https' === substr( strtolower( $request_url ), 0, 5 ) ) {
441 $pWPRemoteArgs['sslverify'] = FS_SDK__SSLVERIFY;
442 }
443
444 if ( false !== $pBeforeExecutionFunction &&
445 is_callable( $pBeforeExecutionFunction )
446 ) {
447 $pWPRemoteArgs = call_user_func( $pBeforeExecutionFunction, $resource[0], $pWPRemoteArgs );
448 }
449
450 $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs );
451
452 if ( is_wp_error( $result ) ) {
453 /**
454 * @var WP_Error $result
455 */
456 if ( self::IsCurlError( $result ) ) {
457 /**
458 * With dual stacked DNS responses, it's possible for a server to
459 * have IPv6 enabled but not have IPv6 connectivity. If this is
460 * the case, cURL will try IPv4 first and if that fails, then it will
461 * fall back to IPv6 and the error EHOSTUNREACH is returned by the
462 * operating system.
463 */
464 $matches = array();
465 $regex = '/Failed to connect to ([^:].*): Network is unreachable/';
466 if ( preg_match( $regex, $result->get_error_message( 'http_request_failed' ), $matches ) ) {
467 /**
468 * Validate IP before calling `inet_pton()` to avoid PHP un-catchable warning.
469 * @author Vova Feldman (@svovaf)
470 */
471 if ( filter_var( $matches[1], FILTER_VALIDATE_IP ) ) {
472 if ( strlen( inet_pton( $matches[1] ) ) === 16 ) {
473 // error_log('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.');
474 // Hook to an action triggered just before cURL is executed to resolve the IP version to v4.
475 add_action( 'http_api_curl', 'Freemius_Api_WordPress::CurlResolveToIPv4', 10, 1 );
476
477 // Re-run request.
478 $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs );
479 }
480 }
481 }
482 }
483
484 if ( is_wp_error( $result ) ) {
485 self::ThrowWPRemoteException( $result );
486 }
487 }
488
489 $response_body = $result['body'];
490
491 if ( empty( $response_body ) ) {
492 return null;
493 }
494
495 $decoded = json_decode( $response_body );
496
497 if ( is_null( $decoded ) ) {
498 if ( preg_match( '/Please turn JavaScript on/i', $response_body ) &&
499 preg_match( '/text\/javascript/', $response_body )
500 ) {
501 self::ThrowCloudFlareDDoSException( $response_body );
502 } 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 ) &&
503 preg_match( '/squid/', $response_body )
504 ) {
505 self::ThrowSquidAclException( $response_body );
506 } else {
507 $decoded = (object) array(
508 'error' => (object) array(
509 'type' => 'Unknown',
510 'message' => $response_body,
511 'code' => 'unknown',
512 'http' => 402
513 )
514 );
515 }
516 }
517
518 return $decoded;
519 }
520
521
522 /**
523 * Makes an HTTP request. This method can be overridden by subclasses if
524 * developers want to do fancier things or use something other than wp_remote_request()
525 * to make the request.
526 *
527 * @param string $pCanonizedPath The URL to make the request to
528 * @param string $pMethod HTTP method
529 * @param array $pParams The parameters to use for the POST body
530 * @param null|array $pWPRemoteArgs wp_remote_request options.
531 *
532 * @return object[]|object|null
533 *
534 * @throws Freemius_Exception
535 */
536 public function MakeRequest(
537 $pCanonizedPath,
538 $pMethod = 'GET',
539 $pParams = array(),
540 $pWPRemoteArgs = null
541 ) {
542 $resource = explode( '?', $pCanonizedPath );
543
544 // Only sign request if not ping.json connectivity test.
545 $sign_request = ( '/v1/ping.json' !== strtolower( substr( $resource[0], - strlen( '/v1/ping.json' ) ) ) );
546
547 return self::MakeStaticRequest(
548 $pCanonizedPath,
549 $pMethod,
550 $pParams,
551 $pWPRemoteArgs,
552 $this->_isSandbox,
553 $sign_request ? array( &$this, 'SignRequest' ) : null
554 );
555 }
556
557 /**
558 * Sets CURLOPT_IPRESOLVE to CURL_IPRESOLVE_V4 for cURL-Handle provided as parameter
559 *
560 * @param resource $handle A cURL handle returned by curl_init()
561 *
562 * @return resource $handle A cURL handle returned by curl_init() with CURLOPT_IPRESOLVE set to
563 * CURL_IPRESOLVE_V4
564 *
565 * @link https://gist.github.com/golderweb/3a2aaec2d56125cc004e
566 */
567 static function CurlResolveToIPv4( $handle ) {
568 curl_setopt( $handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
569
570 return $handle;
571 }
572
573 #----------------------------------------------------------------------------------
574 #region Connectivity Test
575 #----------------------------------------------------------------------------------
576
577 /**
578 * This method exists only for backward compatibility to prevent a fatal error from happening when called from an outdated piece of code.
579 *
580 * @param mixed $pPong
581 *
582 * @return bool
583 */
584 public static function Test( $pPong = null ) {
585 return (
586 is_object( $pPong ) &&
587 isset( $pPong->api ) &&
588 'pong' === $pPong->api
589 );
590 }
591
592 /**
593 * Ping API to test connectivity.
594 *
595 * @return object
596 */
597 public static function Ping() {
598 try {
599 $result = self::MakeStaticRequest( '/v' . FS_API__VERSION . '/ping.json' );
600 } catch ( Freemius_Exception $e ) {
601 // Map to error object.
602 $result = (object) $e->getResult();
603 } catch ( Exception $e ) {
604 // Map to error object.
605 $result = (object) array(
606 'error' => (object) array(
607 'type' => 'Unknown',
608 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')',
609 'code' => 'unknown',
610 'http' => 402
611 )
612 );
613 }
614
615 return $result;
616 }
617
618 #endregion
619
620 #----------------------------------------------------------------------------------
621 #region Connectivity Exceptions
622 #----------------------------------------------------------------------------------
623
624 /**
625 * @param \WP_Error $pError
626 *
627 * @return bool
628 */
629 private static function IsCurlError( WP_Error $pError ) {
630 $message = $pError->get_error_message( 'http_request_failed' );
631
632 return ( 0 === strpos( $message, 'cURL' ) );
633 }
634
635 /**
636 * @param WP_Error $pError
637 *
638 * @throws Freemius_Exception
639 */
640 private static function ThrowWPRemoteException( WP_Error $pError ) {
641 if ( self::IsCurlError( $pError ) ) {
642 $message = $pError->get_error_message( 'http_request_failed' );
643
644 #region Check if there are any missing cURL methods.
645
646 $curl_required_methods = array(
647 'curl_version',
648 'curl_exec',
649 'curl_init',
650 'curl_close',
651 'curl_setopt',
652 'curl_setopt_array',
653 'curl_error',
654 );
655
656 // Find all missing methods.
657 $missing_methods = array();
658 foreach ( $curl_required_methods as $m ) {
659 if ( ! function_exists( $m ) ) {
660 $missing_methods[] = $m;
661 }
662 }
663
664 if ( ! empty( $missing_methods ) ) {
665 throw new Freemius_Exception( array(
666 'error' => (object) array(
667 'type' => 'cUrlMissing',
668 'message' => $message,
669 'code' => 'curl_missing',
670 'http' => 402
671 ),
672 'missing_methods' => $missing_methods,
673 ) );
674 }
675
676 #endregion
677
678 // cURL error - "cURL error {{errno}}: {{error}}".
679 $parts = explode( ':', substr( $message, strlen( 'cURL error ' ) ), 2 );
680
681 $code = ( 0 < count( $parts ) ) ? $parts[0] : 'http_request_failed';
682 $message = ( 1 < count( $parts ) ) ? $parts[1] : $message;
683
684 $e = new Freemius_Exception( array(
685 'error' => (object) array(
686 'code' => $code,
687 'message' => $message,
688 'type' => 'CurlException',
689 ),
690 ) );
691 } else {
692 $e = new Freemius_Exception( array(
693 'error' => (object) array(
694 'code' => $pError->get_error_code(),
695 'message' => $pError->get_error_message(),
696 'type' => 'WPRemoteException',
697 ),
698 ) );
699 }
700
701 throw $e;
702 }
703
704 /**
705 * @param string $pResult
706 *
707 * @throws Freemius_Exception
708 */
709 private static function ThrowCloudFlareDDoSException( $pResult = '' ) {
710 throw new Freemius_Exception( array(
711 'error' => (object) array(
712 'type' => 'CloudFlareDDoSProtection',
713 'message' => $pResult,
714 'code' => 'cloudflare_ddos_protection',
715 'http' => 402
716 )
717 ) );
718 }
719
720 /**
721 * @param string $pResult
722 *
723 * @throws Freemius_Exception
724 */
725 private static function ThrowSquidAclException( $pResult = '' ) {
726 throw new Freemius_Exception( array(
727 'error' => (object) array(
728 'type' => 'SquidCacheBlock',
729 'message' => $pResult,
730 'code' => 'squid_cache_block',
731 'http' => 402
732 )
733 ) );
734 }
735
736 #endregion
737 }
738 }
739