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