PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 4.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v4.1
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-connect.php

class-mainwp-connect.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 4.1, at class/class-mainwp-connect.php

1,874 lines 57.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Connect
4 *
5 * MainWP Connect functions.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 /**
13 * Class MainWP_Connect
14 *
15 * @package MainWP\Dashboard
16 */
17 class MainWP_Connect {
18
19 // phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.WP.AlternativeFunctions, WordPress.PHP.NoSilencedErrors -- Using cURL functions.
20
21 /**
22 * Method get_class_name()
23 *
24 * Get Class Name.
25 *
26 * @return object Class name.
27 */
28 public static function get_class_name() {
29 return __CLASS__;
30 }
31
32 /**
33 * Method try visit.
34 *
35 * Try connecting to Child Site via cURL.
36 *
37 * @param string $url Child Site URL.
38 * @param bool $verifyCertificate Option to check SSL Certificate. Default = null.
39 * @param string $http_user HTTPAuth Username. Default = null.
40 * @param string $http_pass HTTPAuth Password. Default = null.
41 * @param int $sslVersion Child Site SSL Version.
42 * @param bool $forceUseIPv4 Option to fource IP4. Default = null.
43 * @param bool $no_body Option to set CURLOPT_NOBODY option. Default = false.
44 *
45 * @return array $out. 'host IP, Returned HTTP Code, Error Message, http Status error message.
46 */
47 public static function try_visit( $url, $verifyCertificate = null, $http_user = null, $http_pass = null, $sslVersion = 0, $forceUseIPv4 = null, $no_body = false ) { // phpcs:ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
48
49 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
50 $postdata = array( 'test' => 'yes' );
51
52 $ch = curl_init();
53
54 $proxy = new \WP_HTTP_Proxy();
55 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
56 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
57 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
58 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
59
60 if ( $proxy->use_authentication() ) {
61 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
62 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
63 }
64 }
65
66 curl_setopt( $ch, CURLOPT_URL, $url );
67 if ( $no_body ) {
68 curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'HEAD' ); // HTTP request is 'HEAD', but sometime return 4xx - error code.
69 }
70 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
71 curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
72 curl_setopt( $ch, CURLOPT_POST, true );
73 curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
74 curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
75 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
76 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
77
78 if ( ! empty( $http_user ) && ! empty( $http_pass ) ) {
79 $http_pass = stripslashes( $http_pass );
80 curl_setopt( $ch, CURLOPT_USERPWD, "$http_user:$http_pass" );
81 }
82
83 $ssl_verifyhost = false;
84 if ( null !== $verifyCertificate ) {
85 if ( 1 == $verifyCertificate ) {
86 $ssl_verifyhost = true;
87 } elseif ( 2 == $verifyCertificate ) {
88 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
89 $ssl_verifyhost = true;
90 }
91 }
92 } else {
93 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
94 $ssl_verifyhost = true;
95 }
96 }
97
98 if ( $ssl_verifyhost ) {
99 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
100 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, true );
101 } else {
102 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
103 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
104 }
105
106 curl_setopt( $ch, CURLOPT_SSLVERSION, $sslVersion );
107 curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'X-Requested-With: XMLHttpRequest' ) );
108 curl_setopt( $ch, CURLOPT_REFERER, get_option( 'siteurl' ) );
109
110 $force_use_ipv4 = false;
111 if ( null !== $forceUseIPv4 ) {
112 if ( 1 == $forceUseIPv4 ) {
113 $force_use_ipv4 = true;
114 } elseif ( 2 == $forceUseIPv4 ) {
115 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
116 $force_use_ipv4 = true;
117 }
118 }
119 } else {
120 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
121 $force_use_ipv4 = true;
122 }
123 }
124
125 if ( $force_use_ipv4 ) {
126 if ( defined( 'CURLOPT_IPRESOLVE' ) && defined( 'CURL_IPRESOLVE_V4' ) ) {
127 curl_setopt( $ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
128 }
129 }
130
131 $disabled_functions = ini_get( 'disable_functions' );
132 if ( empty( $disabled_functions ) || ( stristr( $disabled_functions, 'curl_multi_exec' ) === false ) ) {
133 $mh = curl_multi_init();
134 @curl_multi_add_handle( $mh, $ch );
135
136 do {
137 curl_multi_exec( $mh, $running );
138 while ( $info = curl_multi_info_read( $mh ) ) {
139 $data = curl_multi_getcontent( $info['handle'] );
140 $err = curl_error( $info['handle'] );
141 $http_status = curl_getinfo( $info['handle'], CURLINFO_HTTP_CODE );
142 $errno = curl_errno( $info['handle'] );
143 $realurl = curl_getinfo( $info['handle'], CURLINFO_EFFECTIVE_URL );
144
145 curl_multi_remove_handle( $mh, $info['handle'] );
146 }
147 usleep( 10000 );
148 } while ( $running > 0 );
149
150 curl_multi_close( $mh );
151 } else {
152 $data = curl_exec( $ch );
153 $err = curl_error( $ch );
154 $http_status = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
155 $errno = curl_errno( $ch );
156 $realurl = curl_getinfo( $ch, CURLINFO_EFFECTIVE_URL );
157 curl_close( $ch );
158 }
159
160 MainWP_Logger::instance()->debug( ' :: tryVisit :: [url=' . $url . '] [http_status=' . $http_status . '] [error=' . $err . '] [data=' . $data . ']' );
161
162 $host = wp_parse_url( ( empty( $realurl ) ? $url : $realurl ), PHP_URL_HOST );
163 $ip = false;
164 $target = false;
165
166 $found = false;
167 $dnsRecord = @dns_get_record( $host );
168 MainWP_Logger::instance()->debug( ' :: tryVisit :: [dnsRecord=' . MainWP_Utility::value_to_string( $dnsRecord, 1 ) . ']' );
169
170 if ( false !== $dnsRecord && is_array( $dnsRecord ) ) {
171 if ( ! isset( $dnsRecord['ip'] ) ) {
172 foreach ( $dnsRecord as $dnsRec ) {
173 if ( isset( $dnsRec['ip'] ) ) {
174 $ip = $dnsRec['ip'];
175 break;
176 }
177 }
178 } else {
179 $ip = $dnsRecord['ip'];
180 }
181
182 if ( ! isset( $dnsRecord['host'] ) ) {
183 foreach ( $dnsRecord as $dnsRec ) {
184 if ( $dnsRec['host'] == $host ) {
185 if ( 'CNAME' == $dnsRec['type'] ) {
186 $target = $dnsRec['target'];
187 }
188 $found = true;
189 break;
190 }
191 }
192 } else {
193 $found = ( $dnsRecord['host'] == $host );
194 if ( 'CNAME' == $dnsRecord['type'] ) {
195 $target = $dnsRecord['target'];
196 }
197 }
198 }
199
200 if ( false === $ip ) {
201 $ip = gethostbynamel( $host );
202 }
203 if ( ( false !== $target ) && ( $target != $host ) ) {
204 $host .= ' (CNAME: ' . $target . ')';
205 }
206
207 $out = array(
208 'host' => $host,
209 'httpCode' => $http_status,
210 'error' => ( '' == $err && false === $found ? 'Invalid host.' : $err ),
211 'httpCodeString' => MainWP_Utility::get_http_codes( $http_status ),
212 );
213 if ( false !== $ip ) {
214 $out['ip'] = $ip;
215 }
216
217 return $out;
218 }
219
220 /**
221 * Method check_ignored_http_code()
222 *
223 * Check if http error code is being ignored.
224 *
225 * @param mixed $value http error code.
226 *
227 * @return bolean True|False.
228 */
229 public static function check_ignored_http_code( $value ) {
230 if ( 200 == $value ) {
231 return true;
232 }
233 $ignored_code = get_option( 'mainwp_ignore_HTTP_response_status', '' );
234 $ignored_code = trim( $ignored_code );
235 if ( ! empty( $ignored_code ) ) {
236 $ignored_code = explode( ',', $ignored_code );
237 foreach ( $ignored_code as $code ) {
238 $code = trim( $code );
239 if ( $value == $code ) {
240 return true;
241 }
242 }
243 }
244 return false;
245 }
246
247 /**
248 * Method check_website_status()
249 *
250 * Check if the Website returns and http errors.
251 *
252 * @param array $website Child Site information.
253 *
254 * @return mixed False|try visit result.
255 */
256 public static function check_website_status( $website ) {
257 $http_user = null;
258 $http_pass = null;
259 $sslVersion = null;
260 $verifyCertificate = null;
261 $forceUseIPv4 = null;
262 if ( is_object( $website ) && isset( $website->url ) ) {
263 $url = $website->url;
264 $verifyCertificate = isset( $website->verify_certificate ) ? $website->verify_certificate : null;
265 $forceUseIPv4 = $website->force_use_ipv4;
266 $http_user = $website->http_user;
267 $http_pass = $website->http_pass;
268 $sslVersion = $website->ssl_version;
269 } else {
270 $url = $website;
271 }
272
273 if ( ! MainWP_Utility::is_domain_valid( $url ) ) {
274 return false;
275 }
276
277 $noBody = false;
278 return self::try_visit( $url, $verifyCertificate, $http_user, $http_pass, $sslVersion, $forceUseIPv4, $noBody );
279 }
280
281 /**
282 * Method get_post_data_authed()
283 *
284 * Get authorized $_POST data & build query.
285 *
286 * @param mixed $website Array of Child Site Info.
287 * @param mixed $what What we are posting.
288 * @param null $params Post parameters.
289 *
290 * @return mixed null|http_build_query()
291 */
292 public static function get_post_data_authed( &$website, $what, $params = null ) {
293 if ( $website && '' != $what ) {
294 $data = array();
295 $data['user'] = $website->adminname;
296 $data['function'] = $what;
297 $data['nonce'] = wp_rand( 0, 9999 );
298
299 $params_filter = apply_filters( 'mainwp_pre_fetch_authed_data', false, $params, $what, $website );
300 if ( is_array( $params_filter ) && ! empty( $params_filter ) ) {
301 $data = array_merge( $data, $params_filter );
302 }
303
304 if ( null != $params ) {
305 $data = array_merge( $data, $params );
306 }
307
308 if ( ( 0 == $website->nossl ) && function_exists( 'openssl_verify' ) ) {
309 $data['nossl'] = 0;
310 openssl_sign( $what . $data['nonce'], $signature, base64_decode( $website->privkey ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
311 } else {
312 $data['nossl'] = 1;
313 $signature = md5( $what . $data['nonce'] . $website->nosslkey );
314 }
315 $data['mainwpsignature'] = base64_encode( $signature ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
316
317 /** This filter is documented in ../widgets/widget-mainwp-recent-posts.php */
318 $recent_number = apply_filters( 'mainwp_recent_posts_pages_number', 5 );
319 if ( 5 !== $recent_number ) {
320 $data['recent_number'] = $recent_number;
321 }
322
323 /**
324 * Current user global.
325 *
326 * @global string
327 */
328 global $current_user;
329
330 if ( ( ! defined( 'DOING_CRON' ) || false === DOING_CRON ) && ( ! defined( 'WP_CLI' ) || false === WP_CLI ) ) {
331 if ( is_object( $current_user ) && property_exists( $current_user, 'ID' ) && $current_user->ID ) {
332
333 /**
334 * Filter: mainwp_alter_login_user
335 *
336 * Filtes users accounts so it allows you user to jump to child site under alternative administartor account.
337 *
338 * @param int $website->id Child site ID.
339 * @param int $current_user->ID User ID.
340 *
341 * @since Unknown
342 */
343 $alter_user = apply_filters( 'mainwp_alter_login_user', false, $website->id, $current_user->ID );
344 if ( ! empty( $alter_user ) ) {
345 $data['alt_user'] = rawurlencode( $alter_user );
346 }
347 }
348 }
349
350 return http_build_query( $data, '', '&' );
351 }
352
353 return null;
354 }
355
356 /**
357 * Method get_get_data_authed()
358 *
359 * Get authorized $_GET data & build query.
360 *
361 * @param mixed $website Child Site data.
362 * @param mixed $paramValue OpenSSL parameter.
363 * @param string $paramName Parameter name.
364 * @param bool $asArray true|false Default is false.
365 *
366 * @return string $url
367 */
368 public static function get_get_data_authed( $website, $paramValue, $paramName = 'where', $asArray = false ) {
369 $params = array();
370 if ( $website && '' != $paramValue ) {
371 $nonce = wp_rand( 0, 9999 );
372 if ( ( 0 == $website->nossl ) && function_exists( 'openssl_verify' ) ) {
373 $nossl = 0;
374 openssl_sign( $paramValue . $nonce, $signature, base64_decode( $website->privkey ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
375 } else {
376 $nossl = 1;
377 $signature = md5( $paramValue . $nonce . $website->nosslkey );
378 }
379 $signature = base64_encode( $signature ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
380
381 $params = array(
382 'login_required' => 1,
383 'user' => rawurlencode( $website->adminname ),
384 'mainwpsignature' => rawurlencode( $signature ),
385 'nonce' => $nonce,
386 'nossl' => $nossl,
387 $paramName => rawurlencode( $paramValue ),
388 );
389
390 /**
391 * Current user global.
392 *
393 * @global string
394 */
395 global $current_user;
396
397 if ( ( ! defined( 'DOING_CRON' ) || false === DOING_CRON ) && ( ! defined( 'WP_CLI' ) || false === WP_CLI ) ) {
398 if ( $current_user && $current_user->ID ) {
399 /** This filter is documented in ../class/class-mainwp-connect.php */
400 $alter_user = apply_filters( 'mainwp_alter_login_user', false, $website->id, $current_user->ID );
401 if ( ! empty( $alter_user ) ) {
402 $params['alt_user'] = rawurlencode( $alter_user );
403 }
404 }
405 }
406 }
407
408 if ( $asArray ) {
409 return $params;
410 }
411
412 $url = ( isset( $website->url ) && '' != $website->url ? $website->url : $website->siteurl );
413 $url .= ( substr( $url, - 1 ) != '/' ? '/' : '' );
414 $url .= '?';
415
416 foreach ( $params as $key => $value ) {
417 $url .= $key . '=' . $value . '&';
418 }
419
420 return rtrim( $url, '&' );
421 }
422
423 /**
424 * Method get_post_data_not_authed()
425 *
426 * Get not authorized $_POST data.
427 *
428 * @param mixed $url Child site URL.
429 * @param mixed $admin Admin Username.
430 * @param mixed $what What function to perform.
431 * @param null $params Function parameters.
432 *
433 * @return mixed null|http_build_query()
434 */
435 public static function get_post_data_not_authed( $url, $admin, $what, $params = null ) {
436 if ( '' != $url && '' != $admin && '' != $what ) {
437 $data = array();
438 $data['user'] = $admin;
439 $data['function'] = $what;
440 if ( null != $params ) {
441 $data = array_merge( $data, $params );
442 }
443
444 return http_build_query( $data, '', '&' );
445 }
446
447 return null;
448 }
449
450 /**
451 * Method fetch_urls_authed()
452 *
453 * Fethech authorized URLs.
454 *
455 * @param object $websites Websites information.
456 * @param string $what Action to perorm.
457 * @param array $params Request parameters.
458 * @param mixed $handler Request handler.
459 * @param mixed $output Request output.
460 * @param mixed $whatPage Request URL. Default /admin-ajax.php.
461 * @param array $others Request additional information.
462 * @param bool $is_external_hook Check if external hook is used.
463 *
464 * @return bool true|false
465 */
466 public static function fetch_urls_authed( &$websites, $what, $params = null, $handler, &$output, $whatPage = null, $others = array(), $is_external_hook = false ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity -- complex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
467
468 if ( ! is_array( $websites ) || empty( $websites ) ) {
469 return false;
470 }
471
472 if ( ! is_array( $params ) ) {
473 $params = array();
474 }
475
476 $chunkSize = 10;
477 if ( count( $websites ) > $chunkSize ) {
478 $total = count( $websites );
479 $loops = ceil( $total / $chunkSize );
480 for ( $i = 0; $i < $loops; $i ++ ) {
481 $newSites = array_slice( $websites, $i * $chunkSize, $chunkSize, true );
482 self::fetch_urls_authed( $newSites, $what, $params, $handler, $output, $whatPage, $others, $is_external_hook );
483 sleep( 5 );
484 }
485
486 return false;
487 }
488
489 if ( $is_external_hook ) {
490 /**
491 * Filter: mainwp_response_json_format
492 *
493 * Filters whether response should be in the JSON format.
494 *
495 * @since Unknown
496 */
497 $json_format = apply_filters( 'mainwp_response_json_format', false );
498 } else {
499 $json_format = true;
500 }
501
502 $debug = false;
503 if ( $debug ) {
504 self::debug_fetch_urls_authed( $websites, $what, $params, $handler, $output, $whatPage, $json_format, $others );
505 return;
506 }
507
508 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
509 $mh = curl_multi_init();
510
511 $timeout = 20 * 60 * 60;
512
513 $disabled_functions = ini_get( 'disable_functions' );
514 $handleToWebsite = array();
515 $requestUrls = array();
516 $requestHandles = array();
517
518 $dirs = MainWP_System_Utility::get_mainwp_dir();
519 $cookieDir = $dirs[0] . 'cookies';
520
521 self::init_cookiesdir( $cookieDir );
522
523 foreach ( $websites as $website ) {
524 $url = $website->url;
525 if ( '/' != substr( $url, - 1 ) ) {
526 $url .= '/';
527 }
528
529 if ( false === strpos( $url, 'wp-admin' ) ) {
530 $url .= 'wp-admin/';
531 }
532
533 if ( null != $whatPage ) {
534 $url .= $whatPage;
535 } else {
536 $url .= 'admin-ajax.php';
537 }
538
539 if ( property_exists( $website, 'http_user' ) ) {
540 $http_user = $website->http_user;
541 }
542 if ( property_exists( $website, 'http_pass' ) ) {
543 $http_pass = $website->http_pass;
544 }
545
546 $_new_post = null;
547 if ( isset( $params ) && isset( $params['new_post'] ) ) {
548 $_new_post = $params['new_post'];
549
550 /**
551 * Filter is being replaced with mainwp_pre_posting_posts.
552 *
553 * @deprecated
554 */
555 $params = apply_filters_deprecated(
556 'mainwp-pre-posting-posts',
557 array(
558 ( is_array( $params ) ? $params : array() ),
559 (object) array(
560 'id' => $website->id,
561 'url' => $website->url,
562 'name' => $website->name,
563 ),
564 ),
565 '4.0.7.2',
566 'mainwp_pre_posting_posts'
567 );
568
569 /**
570 * Filter: mainwp_pre_posting_posts
571 *
572 * Prepares parameters for the authenticated cURL post.
573 *
574 * @since 4.1
575 */
576 $params = apply_filters(
577 'mainwp_pre_posting_posts',
578 ( is_array( $params ) ? $params : array() ),
579 (object) array(
580 'id' => $website->id,
581 'url' => $website->url,
582 'name' => $website->name,
583 )
584 );
585 }
586
587 $ch = curl_init();
588
589 $proxy = new \WP_HTTP_Proxy();
590 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
591 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
592 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
593 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
594
595 if ( $proxy->use_authentication() ) {
596 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
597 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
598 }
599 }
600
601 if ( ( null != $website ) && ( ( property_exists( $website, 'wpe' ) && 1 != $website->wpe ) || ( isset( $others['upgrade'] ) && ( true == $others['upgrade'] ) ) ) ) {
602 $cookieFile = $cookieDir . '/' . sha1( sha1( 'mainwp' . LOGGED_IN_SALT . $website->id ) . NONCE_SALT . 'WP_Cookie' );
603 if ( ! file_exists( $cookieFile ) ) {
604 @file_put_contents( $cookieFile, '' );
605 }
606
607 if ( file_exists( $cookieFile ) ) {
608 @chmod( $cookieFile, 0644 );
609 curl_setopt( $ch, CURLOPT_COOKIEJAR, $cookieFile );
610 curl_setopt( $ch, CURLOPT_COOKIEFILE, $cookieFile );
611 }
612 }
613
614 curl_setopt( $ch, CURLOPT_URL, $url );
615 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
616 curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
617 curl_setopt( $ch, CURLOPT_POST, true );
618
619 if ( is_array( $params ) ) {
620 $params['json_result'] = $json_format;
621 }
622
623 $postdata = self::get_post_data_authed( $website, $what, $params );
624 curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
625 curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
626 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
627 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
628 if ( ! empty( $http_user ) && ! empty( $http_pass ) ) {
629 $http_pass = stripslashes( $http_pass );
630 curl_setopt( $ch, CURLOPT_USERPWD, "$http_user:$http_pass" );
631 }
632
633 $ssl_verifyhost = false;
634 $verifyCertificate = isset( $website->verify_certificate ) ? $website->verify_certificate : null;
635 if ( null !== $verifyCertificate ) {
636 if ( 1 == $verifyCertificate ) {
637 $ssl_verifyhost = true;
638 } elseif ( 2 == $verifyCertificate ) {
639 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
640 $ssl_verifyhost = true;
641 }
642 }
643 } else {
644 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
645 $ssl_verifyhost = true;
646 }
647 }
648
649 if ( $ssl_verifyhost ) {
650 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
651 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, true );
652 } else {
653 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
654 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
655 }
656
657 curl_setopt( $ch, CURLOPT_SSLVERSION, $website->ssl_version );
658
659 curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
660 set_time_limit( $timeout );
661
662 if ( empty( $disabled_functions ) || ( false === stristr( $disabled_functions, 'curl_multi_exec' ) ) ) {
663 @curl_multi_add_handle( $mh, $ch );
664 }
665
666 $handleToWebsite[ self::get_resource_id( $ch ) ] = $website;
667 $requestUrls[ self::get_resource_id( $ch ) ] = $website->url;
668 $requestHandles[ self::get_resource_id( $ch ) ] = $ch;
669
670 if ( null != $_new_post ) {
671 $params['new_post'] = $_new_post;
672 }
673 }
674
675 if ( empty( $disabled_functions ) || ( false === stristr( $disabled_functions, 'curl_multi_exec' ) ) ) {
676 $lastRun = 0;
677 do {
678 if ( 20 < time() - $lastRun ) {
679 @set_time_limit( $timeout );
680 $lastRun = time();
681 }
682
683 curl_multi_exec( $mh, $running );
684 while ( $info = curl_multi_info_read( $mh ) ) {
685 $data = curl_multi_getcontent( $info['handle'] );
686 $contains = ( 0 < preg_match( '/<mainwp>(.*)<\/mainwp>/', $data, $results ) );
687 curl_multi_remove_handle( $mh, $info['handle'] );
688
689 if ( ! $contains && isset( $requestUrls[ self::get_resource_id( $info['handle'] ) ] ) ) {
690 curl_setopt( $info['handle'], CURLOPT_URL, $requestUrls[ self::get_resource_id( $info['handle'] ) ] );
691 curl_multi_add_handle( $mh, $info['handle'] );
692 unset( $requestUrls[ self::get_resource_id( $info['handle'] ) ] );
693 $running ++;
694 continue;
695 }
696
697 if ( null != $handler ) {
698 $site = &$handleToWebsite[ self::get_resource_id( $info['handle'] ) ];
699 call_user_func_array( $handler, array( $data, $site, &$output ) );
700 }
701
702 unset( $handleToWebsite[ self::get_resource_id( $info['handle'] ) ] );
703 if ( 'resource' === gettype( $info['handle'] ) ) {
704 curl_close( $info['handle'] );
705 }
706 unset( $info['handle'] );
707 }
708 usleep( 10000 );
709 } while ( $running > 0 );
710
711 curl_multi_close( $mh );
712 } else {
713 foreach ( $requestHandles as $id => $ch ) {
714 $data = curl_exec( $ch );
715
716 if ( null != $handler ) {
717 $site = &$handleToWebsite[ self::get_resource_id( $ch ) ];
718 call_user_func_array( $handler, array( $data, $site, &$output ) );
719 }
720 }
721 }
722
723 return true;
724 }
725
726 /**
727 * Method debug_fetch_urls_authed()
728 *
729 * To debug fetch authorized URLs.
730 *
731 * @param object $websites Websites information.
732 * @param string $what Action to perorm.
733 * @param array $params Request parameters.
734 * @param mixed $handler Request handler.
735 * @param mixed $output Request output.
736 * @param mixed $whatPage Request URL. Default /admin-ajax.php.
737 * @param bool $json_format Use JSON format.
738 * @param array $others Request additional information.
739 */
740 private static function debug_fetch_urls_authed( $websites, $what, $params, $handler, $output, $whatPage, $json_format, $others ) { // phpcs:ignore -- complex method. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
741 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
742
743 $timeout = 20 * 60 * 60;
744
745 $handleToWebsite = array();
746 $requestUrls = array();
747 $requestHandles = array();
748
749 $dirs = MainWP_System_Utility::get_mainwp_dir();
750 $cookieDir = $dirs[0] . 'cookies';
751
752 self::init_cookiesdir( $cookieDir );
753
754 foreach ( $websites as $website ) {
755 $url = $website->url;
756 if ( '/' != substr( $url, - 1 ) ) {
757 $url .= '/';
758 }
759
760 if ( false === strpos( $url, 'wp-admin' ) ) {
761 $url .= 'wp-admin/';
762 }
763
764 if ( null != $whatPage ) {
765 $url .= $whatPage;
766 } else {
767 $url .= 'admin-ajax.php';
768 }
769
770 if ( property_exists( $website, 'http_user' ) ) {
771 $http_user = $website->http_user;
772 }
773 if ( property_exists( $website, 'http_pass' ) ) {
774 $http_pass = $website->http_pass;
775 }
776
777 $_new_post = null;
778 if ( isset( $params ) && isset( $params['new_post'] ) ) {
779 $_new_post = $params['new_post'];
780
781 /**
782 * Filter is being replaced with mainwp_pre_posting_posts.
783 *
784 * @deprecated
785 */
786 $params = apply_filters_deprecated(
787 'mainwp-pre-posting-posts',
788 array(
789 ( is_array( $params ) ? $params : array() ),
790 (object) array(
791 'id' => $website->id,
792 'url' => $website->url,
793 'name' => $website->name,
794 ),
795 ),
796 '4.0.7.2',
797 'mainwp_pre_posting_posts'
798 );
799
800 /** This filter is documented in ../class/class-mainwp-connect.php */
801 $params = apply_filters(
802 'mainwp_pre_posting_posts',
803 ( is_array( $params ) ? $params : array() ),
804 (object) array(
805 'id' => $website->id,
806 'url' => $website->url,
807 'name' => $website->name,
808 )
809 );
810 }
811
812 $ch = curl_init();
813
814 $proxy = new \WP_HTTP_Proxy();
815 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
816 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
817 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
818 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
819
820 if ( $proxy->use_authentication() ) {
821 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
822 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
823 }
824 }
825
826 if ( ( null != $website ) && ( ( property_exists( $website, 'wpe' ) && 1 != $website->wpe ) || ( isset( $others['upgrade'] ) && ( true == $others['upgrade'] ) ) ) ) {
827 $cookieFile = $cookieDir . '/' . sha1( sha1( 'mainwp' . LOGGED_IN_SALT . $website->id ) . NONCE_SALT . 'WP_Cookie' );
828 if ( ! file_exists( $cookieFile ) ) {
829 @file_put_contents( $cookieFile, '' );
830 }
831
832 if ( file_exists( $cookieFile ) ) {
833 @chmod( $cookieFile, 0644 );
834 curl_setopt( $ch, CURLOPT_COOKIEJAR, $cookieFile );
835 curl_setopt( $ch, CURLOPT_COOKIEFILE, $cookieFile );
836 }
837 }
838
839 curl_setopt( $ch, CURLOPT_URL, $url );
840 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
841 curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
842 curl_setopt( $ch, CURLOPT_POST, true );
843
844 $params['json_result'] = $json_format;
845
846 $postdata = self::get_post_data_authed( $website, $what, $params );
847 curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
848 curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
849 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
850 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
851 if ( ! empty( $http_user ) && ! empty( $http_pass ) ) {
852 $http_pass = stripslashes( $http_pass );
853 curl_setopt( $ch, CURLOPT_USERPWD, "$http_user:$http_pass" );
854 }
855
856 $ssl_verifyhost = false;
857 $verifyCertificate = isset( $website->verify_certificate ) ? $website->verify_certificate : null;
858 if ( null !== $verifyCertificate ) {
859 if ( 1 == $verifyCertificate ) {
860 $ssl_verifyhost = true;
861 } elseif ( 2 == $verifyCertificate ) {
862 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
863 $ssl_verifyhost = true;
864 }
865 }
866 } else {
867 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
868 $ssl_verifyhost = true;
869 }
870 }
871
872 if ( $ssl_verifyhost ) {
873 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
874 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, true );
875 } else {
876 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
877 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
878 }
879
880 curl_setopt( $ch, CURLOPT_SSLVERSION, $website->ssl_version );
881 curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'X-Requested-With: XMLHttpRequest' ) );
882 curl_setopt( $ch, CURLOPT_REFERER, get_option( 'siteurl' ) );
883
884 $force_use_ipv4 = false;
885 $forceUseIPv4 = isset( $website->force_use_ipv4 ) ? $website->force_use_ipv4 : null;
886 if ( null !== $forceUseIPv4 ) {
887 if ( 1 == $forceUseIPv4 ) {
888 $force_use_ipv4 = true;
889 } elseif ( 2 == $forceUseIPv4 ) {
890 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
891 $force_use_ipv4 = true;
892 }
893 }
894 } else {
895 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
896 $force_use_ipv4 = true;
897 }
898 }
899
900 if ( $force_use_ipv4 ) {
901 if ( defined( 'CURLOPT_IPRESOLVE' ) && defined( 'CURL_IPRESOLVE_V4' ) ) {
902 curl_setopt( $ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
903 }
904 }
905
906 curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
907 set_time_limit( $timeout );
908
909 $handleToWebsite[ self::get_resource_id( $ch ) ] = $website;
910 $requestUrls[ self::get_resource_id( $ch ) ] = $website->url;
911 $requestHandles[ self::get_resource_id( $ch ) ] = $ch;
912
913 if ( null != $_new_post ) {
914 $params['new_post'] = $_new_post;
915 }
916 }
917
918 foreach ( $requestHandles as $id => $ch ) {
919 $website = &$handleToWebsite[ self::get_resource_id( $ch ) ];
920
921 $identifier = null;
922 $semLock = '103218';
923 $identifier = self::get_lock_identifier( $semLock );
924 $minimumDelay = ( ( false === get_option( 'mainwp_minimumDelay' ) ) ? 200 : get_option( 'mainwp_minimumDelay' ) );
925 if ( 0 < $minimumDelay ) {
926 $minimumDelay = $minimumDelay / 1000;
927 }
928 $minimumIPDelay = ( ( false === get_option( 'mainwp_minimumIPDelay' ) ) ? 400 : get_option( 'mainwp_minimumIPDelay' ) );
929 if ( 0 < $minimumIPDelay ) {
930 $minimumIPDelay = $minimumIPDelay / 1000;
931 }
932
933 MainWP_Utility::end_session();
934 $delay = true;
935 while ( $delay ) {
936 self::lock( $identifier );
937
938 if ( 0 < $minimumDelay ) {
939 $lastRequest = MainWP_DB_Common::instance()->get_last_request_timestamp();
940 if ( $lastRequest > ( ( microtime( true ) ) - $minimumDelay ) ) {
941 self::release( $identifier );
942 usleep( ( $minimumDelay - ( ( microtime( true ) ) - $lastRequest ) ) * 1000 * 1000 );
943 continue;
944 }
945 }
946
947 if ( 0 < $minimumIPDelay && null != $website ) {
948 $ip = MainWP_DB::instance()->get_wp_ip( $website->id );
949
950 if ( null != $ip && '' != $ip ) {
951 $lastRequest = MainWP_DB_Common::instance()->get_last_request_timestamp( $ip );
952
953 if ( $lastRequest > ( ( microtime( true ) ) - $minimumIPDelay ) ) {
954 self::release( $identifier );
955 usleep( ( $minimumIPDelay - ( ( microtime( true ) ) - $lastRequest ) ) * 1000 * 1000 );
956 continue;
957 }
958 }
959 }
960
961 $delay = false;
962 }
963
964 $maximumRequests = ( ( false === get_option( 'mainwp_maximumRequests' ) ) ? 4 : get_option( 'mainwp_maximumRequests' ) );
965 $maximumIPRequests = ( ( false === get_option( 'mainwp_maximumIPRequests' ) ) ? 1 : get_option( 'mainwp_maximumIPRequests' ) );
966
967 $first = true;
968 $delay = true;
969 while ( $delay ) {
970 if ( ! $first ) {
971 self::lock( $identifier );
972 } else {
973 $first = false;
974 }
975
976 MainWP_DB_Common::instance()->close_open_requests();
977
978 if ( 0 < $maximumRequests ) {
979 $nrOfOpenRequests = MainWP_DB_Common::instance()->get_nrof_open_requests();
980 if ( $nrOfOpenRequests >= $maximumRequests ) {
981 self::release( $identifier );
982 usleep( 200000 );
983 continue;
984 }
985 }
986
987 if ( 0 < $maximumIPRequests && null != $website ) {
988 $ip = MainWP_DB::instance()->get_wp_ip( $website->id );
989
990 if ( null != $ip && '' != $ip ) {
991 $nrOfOpenRequests = MainWP_DB_Common::instance()->get_nrof_open_requests( $ip );
992 if ( $nrOfOpenRequests >= $maximumIPRequests ) {
993 self::release( $identifier );
994 usleep( 200000 );
995 continue;
996 }
997 }
998 }
999
1000 $delay = false;
1001 }
1002
1003 if ( null != $website ) {
1004 MainWP_DB_Common::instance()->insert_or_update_request_log( $website->id, null, microtime( true ), null );
1005 }
1006
1007 if ( null != $identifier ) {
1008 self::release( $identifier );
1009 }
1010
1011 $data = curl_exec( $ch );
1012
1013 if ( null != $website ) {
1014 MainWP_DB_Common::instance()->insert_or_update_request_log( $website->id, $ip, null, microtime( true ) );
1015 }
1016
1017 if ( null != $handler ) {
1018 call_user_func_array( $handler, array( $data, $website, &$output ) );
1019 }
1020 }
1021 }
1022
1023 /**
1024 * Method get_resource_id()
1025 *
1026 * Get resource id.
1027 *
1028 * @param mixed $resource The given resource.
1029 *
1030 * @return $result Resource ID only.
1031 */
1032 public static function get_resource_id( $resource ) {
1033 if ( ! is_resource( $resource ) ) {
1034 return false;
1035 }
1036
1037 $resourceString = (string) $resource;
1038 $exploded = explode( '#', $resourceString );
1039 $result = array_pop( $exploded );
1040
1041 return $result;
1042 }
1043
1044 /**
1045 * Method get_lock_identifier(
1046 *
1047 * Get lock identifier.
1048 *
1049 * @param mixed $pLockName Provided Lock Name.
1050 *
1051 * @return mixed false|sem_get()|@fopen
1052 */
1053 public static function get_lock_identifier( $pLockName ) {
1054 if ( ( null == $pLockName ) || ( false == $pLockName ) ) {
1055 return false;
1056 }
1057
1058 if ( function_exists( 'sem_get' ) ) {
1059 return sem_get( $pLockName );
1060 } else {
1061 $fh = @fopen( sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'lock' . $pLockName . '.txt', 'w+' );
1062 if ( ! $fh ) {
1063 return false;
1064 }
1065
1066 return $fh;
1067 }
1068
1069 return false;
1070 }
1071
1072 /**
1073 * Method lock()
1074 *
1075 * Use sem_acquire or @flock to lock the $identifier.
1076 *
1077 * @param mixed $identifier Identifier.
1078 *
1079 * @return mixed false|sem_acquire()|@flock
1080 */
1081 public static function lock( $identifier ) {
1082 if ( ( null == $identifier ) || ( false == $identifier ) ) {
1083 return false;
1084 }
1085
1086 if ( function_exists( 'sem_acquire' ) ) {
1087 return sem_acquire( $identifier );
1088 } else {
1089 for ( $i = 0; $i < 3; $i ++ ) {
1090 if ( @flock( $identifier, LOCK_EX ) ) {
1091 return $identifier;
1092 } else {
1093 sleep( 1 );
1094 }
1095 }
1096
1097 return false;
1098 }
1099
1100 return false;
1101 }
1102
1103 /**
1104 * Method release()
1105 *
1106 * Use sem_release or @flock, @fclose to unlock $identifier.
1107 *
1108 * @param mixed $identifier Identifier.
1109 *
1110 * @return mixed false|sem_release()|@flock
1111 */
1112 public static function release( $identifier ) {
1113 if ( ( null == $identifier ) || ( false == $identifier ) ) {
1114 return false;
1115 }
1116
1117 if ( function_exists( 'sem_release' ) ) {
1118 return sem_release( $identifier );
1119 } else {
1120 @flock( $identifier, LOCK_UN );
1121 @fclose( $identifier );
1122 }
1123
1124 return false;
1125 }
1126
1127 /**
1128 * Method fetch_url_authed()
1129 *
1130 * Updates the child site via authenticated request.
1131 *
1132 * @param object $website Website information.
1133 * @param string $what Function to perform.
1134 * @param null $params Function paramerters.
1135 * @param bool $checkConstraints Whether or not to check contraints.
1136 * @param bool $pForceFetch Whether or not to force the fetch.
1137 * @param bool $pRetryFailed Whether or not to retry the fetch process.
1138 * @param null $rawResponse Raw response.
1139 *
1140 * @return mixed $information
1141 */
1142 public static function fetch_url_authed(
1143 &$website,
1144 $what,
1145 $params = null,
1146 $checkConstraints = false,
1147 $pForceFetch = false,
1148 $pRetryFailed = true,
1149 $rawResponse = null ) {
1150
1151 if ( ! is_array( $params ) ) {
1152 $params = array();
1153 }
1154
1155 $others = array(
1156 'force_use_ipv4' => $website->force_use_ipv4,
1157 'upgrade' => ( 'upgradeplugintheme' === $what || 'upgrade' === $what || 'upgradetranslation' === $what ),
1158 );
1159
1160 $request_update = MainWP_Premium_Update::maybe_request_premium_updates( $website, $what, $params );
1161
1162 if ( isset( $rawResponse ) && $rawResponse ) {
1163 $others['raw_response'] = 'yes';
1164 }
1165
1166 $params['optimize'] = ( ( 1 == get_option( 'mainwp_optimize' ) ) ? 1 : 0 );
1167
1168 $updating_website = false;
1169 $type = '';
1170 $list = '';
1171 if ( 'upgradeplugintheme' === $what || 'upgrade' === $what || 'upgradetranslation' === $what ) {
1172 $updating_website = true;
1173 if ( 'upgradeplugintheme' === $what || 'upgradetranslation' === $what ) {
1174 $type = $params['type'];
1175 $list = $params['list'];
1176 } else {
1177 $type = 'wp';
1178 $list = '';
1179 }
1180 }
1181
1182 if ( $updating_website ) {
1183 /**
1184 * Action: mainwp_website_before_updated
1185 *
1186 * Fires before the child site update process.
1187 *
1188 * @param object $website Object conaining child site info.
1189 * @param string $type Type parameter.
1190 * @param string $list List parameter.
1191 *
1192 * @since Unknown
1193 */
1194 do_action( 'mainwp_website_before_updated', $website, $type, $list );
1195 }
1196
1197 $params['json_result'] = true;
1198 $postdata = self::get_post_data_authed( $website, $what, $params );
1199 $others['function'] = $what;
1200
1201 $information = array();
1202
1203 if ( ! $request_update ) {
1204 $information = self::fetch_url( $website, $website->url, $postdata, $checkConstraints, $website->verify_certificate, $pRetryFailed, $website->http_user, $website->http_pass, $website->ssl_version, $others );
1205 } else {
1206 $slug = $params['list'];
1207 $information['upgrades'] = array( $slug => 1 );
1208 }
1209
1210 if ( is_array( $information ) && isset( $information['sync'] ) && ! empty( $information['sync'] ) ) {
1211 MainWP_Sync::sync_information_array( $website, $information['sync'] );
1212 unset( $information['sync'] );
1213 }
1214
1215 if ( $updating_website ) {
1216 /**
1217 * Action: mainwp_website_updated
1218 *
1219 * Fires after the child site update process.
1220 *
1221 * @param object $website Object conaining child site info.
1222 * @param string $type Type parameter.
1223 * @param string $list List parameter.
1224 * @param array $information Array containng the information fetched from the child site.
1225 *
1226 * @since Unknown
1227 */
1228 do_action( 'mainwp_website_updated', $website, $type, $list, $information );
1229 if ( 1 == get_option( 'mainwp_check_http_response', 0 ) ) {
1230 MainWP_Monitoring_Handler::handle_check_website( $website );
1231 }
1232 }
1233
1234 return $information;
1235 }
1236
1237 /**
1238 * Method fetch_url_not_authed()
1239 *
1240 * Fetch not authorized URL.
1241 *
1242 * @param string $url URL to fetch from.
1243 * @param string $admin Admin name.
1244 * @param string $what Function to perform.
1245 * @param null $params Function paramerters.
1246 * @param bool $pForceFetch true|false Whether or not to force the fetch.
1247 * @param null $verifyCertificate Verify the SSL Certificate.
1248 * @param null $http_user htaccess username.
1249 * @param null $http_pass htaccess password.
1250 * @param integer $sslVersion SSL version to check for.
1251 * @param array $others Other functions to perform.
1252 *
1253 * @return mixed self::fetch_url() Fetch URL.
1254 */
1255 public static function fetch_url_not_authed(
1256 $url,
1257 $admin,
1258 $what,
1259 $params = null,
1260 $pForceFetch = false,
1261 $verifyCertificate = null,
1262 $http_user = null,
1263 $http_pass = null,
1264 $sslVersion = 0,
1265 $others = array() ) {
1266
1267 if ( empty( $params ) ) {
1268 $params = array();
1269 }
1270
1271 if ( is_array( $params ) ) {
1272 $params['json_result'] = true;
1273 }
1274
1275 $postdata = self::get_post_data_not_authed( $url, $admin, $what, $params );
1276 $website = null;
1277
1278 $others['function'] = $what;
1279 return self::fetch_url( $website, $url, $postdata, false, $verifyCertificate, true, $http_user, $http_pass, $sslVersion, $others );
1280 }
1281
1282 /**
1283 * Method fetch_url()
1284 *
1285 * Fetch URL.
1286 *
1287 * @param object $website Child Site info.
1288 * @param string $url URL to fetch from.
1289 * @param mixed $postdata Post data to fetch.
1290 * @param bool $checkConstraints true|false Whether or not to check contraints.
1291 * @param null $verifyCertificate Verify SSL Certificate.
1292 * @param bool $pRetryFailed ture|false Whether or not the Retry has failed.
1293 * @param null $http_user htaccess username.
1294 * @param null $http_pass htaccess password.
1295 * @param integer $sslVersion SSL version.
1296 * @param array $others Other functions to perform.
1297 *
1298 * @throws \Exception Excetpion message.
1299 *
1300 * @return mixed self::m_fetch_url()
1301 */
1302 public static function fetch_url(
1303 &$website,
1304 $url,
1305 $postdata,
1306 $checkConstraints = false,
1307 $verifyCertificate = null,
1308 $pRetryFailed = true,
1309 $http_user = null,
1310 $http_pass = null,
1311 $sslVersion = 0,
1312 $others = array() ) {
1313
1314 $start = time();
1315
1316 try {
1317 $tmpUrl = $url;
1318 if ( '/' != substr( $tmpUrl, - 1 ) ) {
1319 $tmpUrl .= '/';
1320 }
1321
1322 if ( false === strpos( $url, 'wp-admin' ) ) {
1323 $tmpUrl .= 'wp-admin/admin-ajax.php';
1324 }
1325
1326 return self::m_fetch_url( $website, $tmpUrl, $postdata, $checkConstraints, $verifyCertificate, $http_user, $http_pass, $sslVersion, $others );
1327 } catch ( \Exception $e ) {
1328 if ( ! $pRetryFailed || ( 30 < ( time() - $start ) ) ) {
1329 throw $e;
1330 }
1331
1332 try {
1333 return self::m_fetch_url( $website, $url, $postdata, $checkConstraints, $verifyCertificate, $http_user, $http_pass, $sslVersion, $others );
1334 } catch ( \Exception $ex ) {
1335 throw $e;
1336 }
1337 }
1338 }
1339
1340 /**
1341 * Method m_fetch_url()
1342 *
1343 * M Fetch URL.
1344 *
1345 * @param object $website Child Site info.
1346 * @param string $url URL to fetch from.
1347 * @param mixed $postdata Post data to fetch.
1348 * @param bool $checkConstraints true|false Whether or not to check contraints.
1349 * @param null $verifyCertificate Verify SSL Certificate.
1350 * @param null $http_user htaccess username.
1351 * @param null $http_pass htaccess password.
1352 * @param integer $sslVersion SSL version.
1353 * @param array $others Other functions to perform.
1354 *
1355 * @throws MainWP_Exception Exception message.
1356 *
1357 * @return mixed $data, $information.
1358 */
1359 public static function m_fetch_url( // phpcs:ignore -- complex method. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
1360 &$website,
1361 $url,
1362 $postdata,
1363 $checkConstraints = false,
1364 $verifyCertificate = null,
1365 $http_user = null,
1366 $http_pass = null,
1367 $sslVersion = 0,
1368 $others = array() ) {
1369
1370 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
1371
1372 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'Request to [' . $url . '] [' . MainWP_Utility::value_to_string( $postdata, 1 ) . ']' );
1373
1374 $identifier = null;
1375 if ( $checkConstraints ) {
1376 self::check_constraints( $identifier, $website );
1377 }
1378
1379 if ( null != $website ) {
1380 MainWP_DB_Common::instance()->insert_or_update_request_log( $website->id, null, microtime( true ), null );
1381 }
1382
1383 if ( null != $identifier ) {
1384 self::release( $identifier );
1385 }
1386
1387 $dirs = MainWP_System_Utility::get_mainwp_dir();
1388 $cookieDir = $dirs[0] . 'cookies';
1389
1390 self::init_cookiesdir( $cookieDir );
1391
1392 $ch = curl_init();
1393
1394 $proxy = new \WP_HTTP_Proxy();
1395 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
1396 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
1397 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
1398 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
1399
1400 if ( $proxy->use_authentication() ) {
1401 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
1402 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
1403 }
1404 }
1405
1406 if ( ( null != $website ) && ( ( property_exists( $website, 'wpe' ) && 1 != $website->wpe ) || ( isset( $others['upgrade'] ) && ( true == $others['upgrade'] ) ) ) ) {
1407 $cookieFile = $cookieDir . '/' . sha1( sha1( 'mainwp' . LOGGED_IN_SALT . $website->id ) . NONCE_SALT . 'WP_Cookie' );
1408 if ( ! file_exists( $cookieFile ) ) {
1409 @file_put_contents( $cookieFile, '' );
1410 }
1411
1412 if ( file_exists( $cookieFile ) ) {
1413 @chmod( $cookieFile, 0644 );
1414 curl_setopt( $ch, CURLOPT_COOKIEJAR, $cookieFile );
1415 curl_setopt( $ch, CURLOPT_COOKIEFILE, $cookieFile );
1416 }
1417 }
1418
1419 curl_setopt( $ch, CURLOPT_URL, $url );
1420 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
1421 curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
1422 curl_setopt( $ch, CURLOPT_POST, true );
1423 curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
1424 curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
1425 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
1426 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
1427
1428 if ( ! empty( $http_user ) && ! empty( $http_pass ) ) {
1429 $http_pass = stripslashes( $http_pass );
1430 curl_setopt( $ch, CURLOPT_USERPWD, "$http_user:$http_pass" );
1431 }
1432
1433 $ssl_verifyhost = false;
1434 if ( null !== $verifyCertificate ) {
1435 if ( 1 == $verifyCertificate ) {
1436 $ssl_verifyhost = true;
1437 } elseif ( 2 == $verifyCertificate ) {
1438 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
1439 $ssl_verifyhost = true;
1440 }
1441 }
1442 } else {
1443 if ( ( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 == get_option( 'mainwp_sslVerifyCertificate' ) ) ) ) {
1444 $ssl_verifyhost = true;
1445 }
1446 }
1447
1448 if ( $ssl_verifyhost ) {
1449 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
1450 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, true );
1451 } else {
1452 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
1453 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
1454 }
1455
1456 curl_setopt( $ch, CURLOPT_SSLVERSION, $sslVersion );
1457 curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'X-Requested-With: XMLHttpRequest' ) );
1458 curl_setopt( $ch, CURLOPT_REFERER, get_option( 'siteurl' ) );
1459
1460 $force_use_ipv4 = false;
1461 $forceUseIPv4 = isset( $others['force_use_ipv4'] ) ? $others['force_use_ipv4'] : null;
1462 if ( null !== $forceUseIPv4 ) {
1463 if ( 1 == $forceUseIPv4 ) {
1464 $force_use_ipv4 = true;
1465 } elseif ( 2 == $forceUseIPv4 ) {
1466 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
1467 $force_use_ipv4 = true;
1468 }
1469 }
1470 } else {
1471 if ( 1 == get_option( 'mainwp_forceUseIPv4' ) ) {
1472 $force_use_ipv4 = true;
1473 }
1474 }
1475
1476 if ( $force_use_ipv4 ) {
1477 if ( defined( 'CURLOPT_IPRESOLVE' ) && defined( 'CURL_IPRESOLVE_V4' ) ) {
1478 curl_setopt( $ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
1479 }
1480 }
1481
1482 $timeout = 20 * 60 * 60;
1483 curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
1484 set_time_limit( $timeout );
1485
1486 MainWP_Utility::end_session();
1487
1488 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'Executing handlers' );
1489
1490 $disabled_functions = ini_get( 'disable_functions' );
1491 if ( empty( $disabled_functions ) || ( false === stristr( $disabled_functions, 'curl_multi_exec' ) ) ) {
1492 $mh = @curl_multi_init();
1493 @curl_multi_add_handle( $mh, $ch );
1494
1495 $lastRun = 0;
1496 do {
1497 if ( 20 < time() - $lastRun ) {
1498 @set_time_limit( $timeout );
1499 $lastRun = time();
1500 }
1501 @curl_multi_exec( $mh, $running );
1502 while ( $info = @curl_multi_info_read( $mh ) ) {
1503 $data = @curl_multi_getcontent( $info['handle'] );
1504
1505 $http_status = @curl_getinfo( $info['handle'], CURLINFO_HTTP_CODE );
1506 $err = @curl_error( $info['handle'] );
1507 $real_url = @curl_getinfo( $info['handle'], CURLINFO_EFFECTIVE_URL );
1508
1509 @curl_multi_remove_handle( $mh, $info['handle'] );
1510 }
1511 usleep( 10000 );
1512 } while ( $running > 0 );
1513
1514 @curl_multi_close( $mh );
1515 } else {
1516 $data = @curl_exec( $ch );
1517 $http_status = @curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1518 $err = @curl_error( $ch );
1519 $real_url = @curl_getinfo( $ch, CURLINFO_EFFECTIVE_URL );
1520 }
1521
1522 $host = wp_parse_url( $real_url, PHP_URL_HOST );
1523 $ip = gethostbyname( $host );
1524
1525 if ( null != $website ) {
1526 MainWP_DB_Common::instance()->insert_or_update_request_log( $website->id, $ip, null, microtime( true ) );
1527 }
1528
1529 $raw_response = isset( $others['raw_response'] ) && 'yes' == $others['raw_response'] ? true : false;
1530
1531 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'http status: [' . $http_status . '] err: [' . $err . '] data: [' . $data . ']' );
1532 if ( '400' == $http_status ) {
1533 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'post data: [' . MainWP_Utility::value_to_string( $postdata, 1 ) . ']' );
1534 }
1535
1536 if ( ( false === $data ) && ( 0 == $http_status ) ) {
1537 MainWP_Logger::instance()->debug_for_website( $website, 'fetch_url', '[' . $url . '] HTTP Error: [status=0][' . $err . ']' );
1538 throw new MainWP_Exception( 'HTTPERROR', $err );
1539 } elseif ( empty( $data ) && ! empty( $err ) ) {
1540 MainWP_Logger::instance()->debug_for_website( $website, 'fetch_url', '[' . $url . '] HTTP Error: [status=' . $http_status . '][' . $err . ']' );
1541 throw new MainWP_Exception( 'HTTPERROR', $err );
1542 } elseif ( 0 < preg_match( '/<mainwp>(.*)<\/mainwp>/', $data, $results ) ) {
1543 $result = $results[1];
1544 $information = MainWP_System_Utility::get_child_response( base64_decode( $result ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1545
1546 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'information: [OK]' );
1547 return $information;
1548 } elseif ( 200 == $http_status && ! empty( $err ) ) {
1549 throw new MainWP_Exception( 'HTTPERROR', $err );
1550 } elseif ( $raw_response ) {
1551 MainWP_Logger::instance()->debug_for_website( $website, 'm_fetch_url', 'Response: [RAW]' );
1552 return $data;
1553 } else {
1554 MainWP_Logger::instance()->debug_for_website( $website, 'fetch_url', '[' . $url . '] Result was: [' . $data . ']' );
1555 throw new MainWP_Exception( 'NOMAINWP', $url );
1556 }
1557 }
1558
1559 /**
1560 * Method check_constraints()
1561 *
1562 * Check connection delay constraints.
1563 *
1564 * @param mixed $identifier Lock identifier.
1565 * @param mixed $website Object child site.
1566 */
1567 private static function check_constraints( &$identifier, $website ) {
1568 $semLock = '103218';
1569 $identifier = self::get_lock_identifier( $semLock );
1570 $minimumDelay = ( ( false === get_option( 'mainwp_minimumDelay' ) ) ? 200 : get_option( 'mainwp_minimumDelay' ) );
1571 if ( 0 < $minimumDelay ) {
1572 $minimumDelay = $minimumDelay / 1000;
1573 }
1574 $minimumIPDelay = ( ( false === get_option( 'mainwp_minimumIPDelay' ) ) ? 1000 : get_option( 'mainwp_minimumIPDelay' ) );
1575 if ( 0 < $minimumIPDelay ) {
1576 $minimumIPDelay = $minimumIPDelay / 1000;
1577 }
1578
1579 MainWP_Utility::end_session();
1580 $delay = true;
1581 while ( $delay ) {
1582 self::lock( $identifier );
1583 if ( 0 < $minimumDelay && self::check_constraints_last_request( $identifier, $minimumDelay ) ) {
1584 continue;
1585 }
1586
1587 if ( 0 < $minimumIPDelay && null != $website ) {
1588 $ip = MainWP_DB::instance()->get_wp_ip( $website->id );
1589 if ( null != $ip && '' !== $ip ) {
1590 if ( self::check_constraints_last_request( $identifier, $minimumIPDelay, $ip ) ) {
1591 continue;
1592 }
1593 }
1594 }
1595 $delay = false;
1596 }
1597
1598 $maximumRequests = ( ( false === get_option( 'mainwp_maximumRequests' ) ) ? 4 : get_option( 'mainwp_maximumRequests' ) );
1599 $maximumIPRequests = ( ( false === get_option( 'mainwp_maximumIPRequests' ) ) ? 1 : get_option( 'mainwp_maximumIPRequests' ) );
1600
1601 $first = true;
1602 $delay = true;
1603 while ( $delay ) {
1604 if ( ! $first ) {
1605 self::lock( $identifier );
1606 } else {
1607 $first = false;
1608 }
1609
1610 MainWP_DB_Common::instance()->close_open_requests();
1611
1612 if ( 0 < $maximumRequests && self::check_constraints_open_requests( $identifier, $maximumRequests ) ) {
1613 continue;
1614 }
1615
1616 if ( 0 < $maximumIPRequests && null != $website ) {
1617 $ip = MainWP_DB::instance()->get_wp_ip( $website->id );
1618 if ( null != $ip && '' != $ip ) {
1619 if ( self::check_constraints_open_requests( $identifier, $maximumIPRequests, $ip ) ) {
1620 continue;
1621 }
1622 }
1623 }
1624 $delay = false;
1625 }
1626 }
1627
1628 /**
1629 * Method check_constraints_last_request().
1630 *
1631 * Check constraints for last requests.
1632 *
1633 * @param mixed $identifier connect identifier.
1634 * @param int $minimumDelay minimum delay.
1635 * @param string|null $ip ip address.
1636 */
1637 private static function check_constraints_last_request( $identifier, $minimumDelay, $ip = null ) {
1638 $lastRequest = MainWP_DB_Common::instance()->get_last_request_timestamp( $ip );
1639 if ( $lastRequest > ( ( microtime( true ) ) - $minimumDelay ) ) {
1640 self::release( $identifier );
1641 usleep( ( $minimumDelay - ( ( microtime( true ) ) - $lastRequest ) ) * 1000 * 1000 );
1642 return true;
1643 }
1644 return false;
1645 }
1646
1647 /**
1648 * Method check_constraints_open_requests().
1649 *
1650 * Check constraints for open requests.
1651 *
1652 * @param mixed $identifier connect identifier.
1653 * @param int $maximumRequests maximum requests.
1654 * @param string|null $ip ip address.
1655 */
1656 private static function check_constraints_open_requests( $identifier, $maximumRequests, $ip = null ) {
1657 $nrOfOpenRequests = MainWP_DB_Common::instance()->get_nrof_open_requests( $ip );
1658 if ( $nrOfOpenRequests >= $maximumRequests ) {
1659 self::release( $identifier );
1660 usleep( 200000 );
1661 return true;
1662 }
1663 return false;
1664 }
1665
1666 /**
1667 * Method download_to_file()
1668 *
1669 * Download to file.
1670 *
1671 * @param mixed $url Download URL.
1672 * @param mixed $file File to download to.
1673 * @param bool $size Size of file.
1674 * @param null $http_user htaccess username.
1675 * @param null $http_pass htaccess password.
1676 *
1677 * @throws MainWP_Exception Exception message.
1678 */
1679 public static function download_to_file( $url, $file, $size = false, $http_user = null, $http_pass = null ) {
1680
1681 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
1682
1683 /**
1684 * WordPress files system object.
1685 *
1686 * @global object
1687 */
1688 global $wp_filesystem;
1689
1690 if ( $wp_filesystem->exists( $file ) && ( ( false == $size ) || ( $wp_filesystem->size( $file ) > $size ) ) ) {
1691 $wp_filesystem->delete( $file );
1692 }
1693
1694 if ( ! $wp_filesystem->exists( dirname( $file ) ) ) {
1695 $wp_filesystem->mkdir( dirname( $file ), 0777, true );
1696 }
1697
1698 if ( ! $wp_filesystem->exists( dirname( $file ) ) ) {
1699 throw new MainWP_Exception( __( 'MainWP plugin could not create directory in order to download the file.', 'mainwp' ) );
1700 }
1701
1702 if ( ! is_writable( @dirname( $file ) ) ) {
1703 throw new MainWP_Exception( __( 'MainWP upload directory is not writable.', 'mainwp' ) );
1704 }
1705
1706 $fp = fopen( $file, 'a' );
1707 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
1708 if ( false !== $size ) {
1709 if ( $wp_filesystem->exists( $file ) ) {
1710 $size = $wp_filesystem->size( $file );
1711 $url .= '&foffset=' . $size;
1712 }
1713 }
1714 $ch = curl_init( str_replace( ' ', '%20', $url ) );
1715
1716 $proxy = new \WP_HTTP_Proxy();
1717 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
1718 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
1719 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
1720 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
1721
1722 if ( $proxy->use_authentication() ) {
1723 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
1724 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
1725 }
1726 }
1727
1728 curl_setopt( $ch, CURLOPT_FILE, $fp );
1729 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
1730 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
1731 curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
1732 if ( ! empty( $http_user ) && ! empty( $http_pass ) ) {
1733 $http_pass = stripslashes( $http_pass );
1734 curl_setopt( $ch, CURLOPT_USERPWD, "$http_user:$http_pass" );
1735 }
1736 curl_exec( $ch );
1737 curl_close( $ch );
1738 fclose( $fp );
1739 }
1740
1741 /**
1742 * Method init_coockiesdir()
1743 *
1744 * Check for cookies directory and crate it if it doesn't already exist,
1745 * set the file permissions and update htaccess.
1746 *
1747 * @param mixed $cookieDir Cookies directory.
1748 *
1749 * @return void
1750 */
1751 public static function init_cookiesdir( $cookieDir ) {
1752
1753 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
1754
1755 /**
1756 * WordPress files system object.
1757 *
1758 * @global object
1759 */
1760 global $wp_filesystem;
1761
1762 if ( $hasWPFileSystem && ! empty( $wp_filesystem ) ) {
1763
1764 if ( ! $wp_filesystem->is_dir( $cookieDir ) ) {
1765 $wp_filesystem->mkdir( $cookieDir, 0777, true );
1766 }
1767
1768 if ( ! file_exists( $cookieDir . '/.htaccess' ) ) {
1769 $file_htaccess = $cookieDir . '/.htaccess';
1770 $wp_filesystem->put_contents( $file_htaccess, 'deny from all' );
1771 }
1772
1773 if ( ! file_exists( $cookieDir . '/index.php' ) ) {
1774 $file_index = $cookieDir . '/index.php';
1775 $wp_filesystem->touch( $file_index );
1776 }
1777 } else {
1778
1779 if ( ! file_exists( $cookieDir ) ) {
1780 @mkdir( $cookieDir, 0777, true );
1781 }
1782
1783 if ( ! file_exists( $cookieDir . '/.htaccess' ) ) {
1784 $file_htaccess = @fopen( $cookieDir . '/.htaccess', 'w+' );
1785 @fwrite( $file_htaccess, 'deny from all' );
1786 @fclose( $file_htaccess );
1787 }
1788
1789 if ( ! file_exists( $cookieDir . '/index.php' ) ) {
1790 $file_index = @fopen( $cookieDir . '/index.php', 'w+' );
1791 @fclose( $file_index );
1792 }
1793 }
1794 }
1795
1796 /**
1797 * Method get_file_content()
1798 *
1799 * Get contents of file.
1800 *
1801 * @param mixed $url File Location.
1802 *
1803 * @return mixed false|$data
1804 */
1805 public static function get_file_content( $url ) {
1806 $agent = 'Mozilla/5.0 (compatible; MainWP/' . MainWP_System::$version . '; +http://mainwp.com)';
1807 $ch = curl_init();
1808
1809 $proxy = new \WP_HTTP_Proxy();
1810 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
1811 curl_setopt( $ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );
1812 curl_setopt( $ch, CURLOPT_PROXY, $proxy->host() );
1813 curl_setopt( $ch, CURLOPT_PROXYPORT, $proxy->port() );
1814
1815 if ( $proxy->use_authentication() ) {
1816 curl_setopt( $ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
1817 curl_setopt( $ch, CURLOPT_PROXYUSERPWD, $proxy->authentication() );
1818 }
1819 }
1820
1821 curl_setopt( $ch, CURLOPT_HEADER, 0 );
1822 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
1823 curl_setopt( $ch, CURLOPT_URL, $url );
1824 curl_setopt( $ch, CURLOPT_USERAGENT, $agent );
1825 curl_setopt( $ch, CURLOPT_ENCODING, 'none' );
1826
1827 $data = @curl_exec( $ch );
1828 $httpCode = @curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1829
1830 curl_close( $ch );
1831
1832 if ( 200 == $httpCode ) {
1833 return $data;
1834 } else {
1835 return false;
1836 }
1837 }
1838
1839 /**
1840 * Method get_favico_url()
1841 *
1842 * Get Child Site favicon URL.
1843 *
1844 * @param mixed $website Child Site info.
1845 *
1846 * @return mixed $faviurl Favicon URL.
1847 */
1848 public static function get_favico_url( $website ) {
1849 $favi = MainWP_DB::instance()->get_website_option( $website, 'favi_icon', '' );
1850 $faviurl = '';
1851
1852 if ( ! empty( $favi ) ) {
1853 if ( false !== strpos( $favi, 'favi-' . intval( $website->id ) . '-' ) ) {
1854 $dirs = MainWP_System_Utility::get_icons_dir();
1855 if ( file_exists( $dirs[0] . $favi ) ) {
1856 $faviurl = $dirs[1] . $favi;
1857 } else {
1858 $faviurl = '';
1859 }
1860 } elseif ( ( 0 === strpos( $favi, '//' ) ) || ( 0 === strpos( $favi, 'http' ) ) ) {
1861 $faviurl = $favi;
1862 } else {
1863 $faviurl = $website->url . $favi;
1864 $faviurl = MainWP_Utility::remove_http_prefix( $faviurl );
1865 }
1866 }
1867 if ( empty( $faviurl ) ) {
1868 $faviurl = MAINWP_PLUGIN_URL . 'assets/images/sitefavi.png';
1869 }
1870
1871 return $faviurl;
1872 }
1873 }
1874