This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * General helpers. |
||
4 | */ |
||
5 | |||
6 | if ( ! defined( 'ABSPATH' ) ) { |
||
7 | exit; |
||
8 | } |
||
9 | |||
10 | class autoptimizeUtils |
||
11 | { |
||
12 | /** |
||
13 | * Returns true when mbstring is available. |
||
14 | * |
||
15 | * @param bool|null $override Allows overriding the decision. |
||
16 | * |
||
17 | * @return bool |
||
18 | */ |
||
19 | public static function mbstring_available( $override = null ) |
||
20 | { |
||
21 | static $available = null; |
||
22 | |||
23 | if ( null === $available ) { |
||
24 | $available = \extension_loaded( 'mbstring' ); |
||
25 | } |
||
26 | |||
27 | if ( null !== $override ) { |
||
28 | $available = $override; |
||
29 | } |
||
30 | |||
31 | return $available; |
||
32 | } |
||
33 | |||
34 | /** |
||
35 | * Multibyte-capable strpos() if support is available on the server. |
||
36 | * If not, it falls back to using \strpos(). |
||
37 | * |
||
38 | * @param string $haystack Haystack. |
||
39 | * @param string $needle Needle. |
||
40 | * @param int $offset Offset. |
||
41 | * @param string|null $encoding Encoding. Default null. |
||
42 | * |
||
43 | * @return int|false |
||
44 | */ |
||
45 | public static function strpos( $haystack, $needle, $offset = 0, $encoding = null ) |
||
46 | { |
||
47 | if ( self::mbstring_available() ) { |
||
48 | return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strpos( $haystack, $needle, $offset, $encoding ); |
||
49 | } else { |
||
50 | return \strpos( $haystack, $needle, $offset ); |
||
51 | } |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * Attempts to return the number of characters in the given $string if |
||
56 | * mbstring is available. Returns the number of bytes |
||
57 | * (instead of characters) as fallback. |
||
58 | * |
||
59 | * @param string $string String. |
||
60 | * @param string|null $encoding Encoding. |
||
61 | * |
||
62 | * @return int Number of characters or bytes in given $string |
||
63 | * (characters if/when supported, bytes otherwise). |
||
64 | */ |
||
65 | public static function strlen( $string, $encoding = null ) |
||
66 | { |
||
67 | if ( self::mbstring_available() ) { |
||
68 | return ( null === $encoding ) ? \mb_strlen( $string ) : \mb_strlen( $string, $encoding ); |
||
69 | } else { |
||
70 | return \strlen( $string ); |
||
71 | } |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Our wrapper around implementations of \substr_replace() |
||
76 | * that attempts to not break things horribly if at all possible. |
||
77 | * Uses mbstring if available, before falling back to regular |
||
78 | * substr_replace() (which works just fine in the majority of cases). |
||
79 | * |
||
80 | * @param string $string String. |
||
81 | * @param string $replacement Replacement. |
||
82 | * @param int $start Start offset. |
||
83 | * @param int|null $length Length. |
||
84 | * @param string|null $encoding Encoding. |
||
85 | * |
||
86 | * @return string |
||
87 | */ |
||
88 | public static function substr_replace( $string, $replacement, $start, $length = null, $encoding = null ) |
||
89 | { |
||
90 | if ( self::mbstring_available() ) { |
||
91 | $strlen = self::strlen( $string, $encoding ); |
||
92 | |||
93 | if ( $start < 0 ) { |
||
94 | if ( -$start < $strlen ) { |
||
95 | $start = $strlen + $start; |
||
96 | } else { |
||
97 | $start = 0; |
||
98 | } |
||
99 | } elseif ( $start > $strlen ) { |
||
100 | $start = $strlen; |
||
101 | } |
||
102 | |||
103 | if ( null === $length || '' === $length ) { |
||
0 ignored issues
–
show
Unused Code
Bug
introduced
by
![]() |
|||
104 | $start2 = $strlen; |
||
105 | } elseif ( $length < 0 ) { |
||
106 | $start2 = $strlen + $length; |
||
107 | if ( $start2 < $start ) { |
||
108 | $start2 = $start; |
||
109 | } |
||
110 | } else { |
||
111 | $start2 = $start + $length; |
||
112 | } |
||
113 | |||
114 | if ( null === $encoding ) { |
||
115 | $leader = $start ? \mb_substr( $string, 0, $start ) : ''; |
||
116 | $trailer = ( $start2 < $strlen ) ? \mb_substr( $string, $start2, null ) : ''; |
||
117 | } else { |
||
118 | $leader = $start ? \mb_substr( $string, 0, $start, $encoding ) : ''; |
||
119 | $trailer = ( $start2 < $strlen ) ? \mb_substr( $string, $start2, null, $encoding ) : ''; |
||
120 | } |
||
121 | |||
122 | return "{$leader}{$replacement}{$trailer}"; |
||
123 | } |
||
124 | |||
125 | return ( null === $length ) ? \substr_replace( $string, $replacement, $start ) : \substr_replace( $string, $replacement, $start, $length ); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Decides whether this is a "subdirectory site" or not. |
||
130 | * |
||
131 | * @param bool $override Allows overriding the decision when needed. |
||
132 | * |
||
133 | * @return bool |
||
134 | */ |
||
135 | public static function siteurl_not_root( $override = null ) |
||
136 | { |
||
137 | static $subdir = null; |
||
138 | |||
139 | if ( null === $subdir ) { |
||
140 | $parts = self::get_ao_wp_site_url_parts(); |
||
141 | $subdir = ( isset( $parts['path'] ) && ( '/' !== $parts['path'] ) ); |
||
142 | } |
||
143 | |||
144 | if ( null !== $override ) { |
||
145 | $subdir = $override; |
||
146 | } |
||
147 | |||
148 | return $subdir; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Parse AUTOPTIMIZE_WP_SITE_URL into components using \parse_url(), but do |
||
153 | * so only once per request/lifecycle. |
||
154 | * |
||
155 | * @return array |
||
156 | */ |
||
157 | public static function get_ao_wp_site_url_parts() |
||
158 | { |
||
159 | static $parts = array(); |
||
160 | |||
161 | if ( empty( $parts ) ) { |
||
162 | $parts = \parse_url( AUTOPTIMIZE_WP_SITE_URL ); |
||
163 | } |
||
164 | |||
165 | return $parts; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Modify given $cdn_url to include the site path when needed. |
||
170 | * |
||
171 | * @param string $cdn_url CDN URL to tweak. |
||
172 | * @param bool $force_cache_miss Force a cache miss in order to be able |
||
173 | * to re-run the filter. |
||
174 | * |
||
175 | * @return string |
||
176 | */ |
||
177 | public static function tweak_cdn_url_if_needed( $cdn_url, $force_cache_miss = false ) |
||
178 | { |
||
179 | static $results = array(); |
||
180 | |||
181 | if ( ! isset( $results[ $cdn_url ] ) || $force_cache_miss ) { |
||
182 | |||
183 | // In order to return unmodified input when there's no need to tweak. |
||
184 | $results[ $cdn_url ] = $cdn_url; |
||
185 | |||
186 | // Behind a default true filter for backcompat, and only for sites |
||
187 | // in a subfolder/subdirectory, but still easily turned off if |
||
188 | // not wanted/needed... |
||
189 | if ( autoptimizeUtils::siteurl_not_root() ) { |
||
190 | $check = apply_filters( 'autoptimize_filter_cdn_magic_path_check', true, $cdn_url ); |
||
191 | if ( $check ) { |
||
192 | $site_url_parts = autoptimizeUtils::get_ao_wp_site_url_parts(); |
||
193 | $cdn_url_parts = \parse_url( $cdn_url ); |
||
194 | $schemeless = self::is_protocol_relative( $cdn_url ); |
||
195 | $cdn_url_parts = self::maybe_replace_cdn_path( $site_url_parts, $cdn_url_parts ); |
||
0 ignored issues
–
show
It seems like
$site_url_parts defined by \autoptimizeUtils::get_ao_wp_site_url_parts() on line 192 can also be of type false ; however, autoptimizeUtils::maybe_replace_cdn_path() does only seem to accept array , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() It seems like
$cdn_url_parts defined by self::maybe_replace_cdn_..._parts, $cdn_url_parts) on line 195 can also be of type false ; however, autoptimizeUtils::maybe_replace_cdn_path() does only seem to accept array , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
196 | if ( false !== $cdn_url_parts ) { |
||
197 | $results[ $cdn_url ] = self::assemble_parsed_url( $cdn_url_parts, $schemeless ); |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | |||
203 | return $results[ $cdn_url ]; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * When siteurl contains a path other than '/' and the CDN URL does not have |
||
208 | * a path or it's path is '/', this will modify the CDN URL's path component |
||
209 | * to match that of the siteurl. |
||
210 | * This is to support "magic" CDN urls that worked that way before v2.4... |
||
211 | * |
||
212 | * @param array $site_url_parts Site URL components array. |
||
213 | * @param array $cdn_url_parts CDN URL components array. |
||
214 | * |
||
215 | * @return array|false |
||
216 | */ |
||
217 | public static function maybe_replace_cdn_path( array $site_url_parts, array $cdn_url_parts ) |
||
218 | { |
||
219 | if ( isset( $site_url_parts['path'] ) && '/' !== $site_url_parts['path'] ) { |
||
220 | if ( ! isset( $cdn_url_parts['path'] ) || '/' === $cdn_url_parts['path'] ) { |
||
221 | $cdn_url_parts['path'] = $site_url_parts['path']; |
||
222 | return $cdn_url_parts; |
||
223 | } |
||
224 | } |
||
225 | |||
226 | return false; |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Given an array or components returned from \parse_url(), assembles back |
||
231 | * the complete URL. |
||
232 | * If optional |
||
233 | * |
||
234 | * @param array $parsed_url URL components array. |
||
235 | * @param bool $schemeless Whether the assembled URL should be |
||
236 | * protocol-relative (schemeless) or not. |
||
237 | * |
||
238 | * @return string |
||
239 | */ |
||
240 | public static function assemble_parsed_url( array $parsed_url, $schemeless = false ) |
||
241 | { |
||
242 | $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] . '://' : ''; |
||
243 | if ( $schemeless ) { |
||
244 | $scheme = '//'; |
||
245 | } |
||
246 | $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : ''; |
||
247 | $port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : ''; |
||
248 | $user = isset( $parsed_url['user'] ) ? $parsed_url['user'] : ''; |
||
249 | $pass = isset( $parsed_url['pass'] ) ? ':' . $parsed_url['pass'] : ''; |
||
250 | $pass = ( $user || $pass ) ? "$pass@" : ''; |
||
251 | $path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : ''; |
||
252 | $query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : ''; |
||
253 | $fragment = isset( $parsed_url['fragment'] ) ? '#' . $parsed_url['fragment'] : ''; |
||
254 | |||
255 | return "$scheme$user$pass$host$port$path$query$fragment"; |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Returns true if given $url is protocol-relative. |
||
260 | * |
||
261 | * @param string $url URL to check. |
||
262 | * |
||
263 | * @return bool |
||
264 | */ |
||
265 | public static function is_protocol_relative( $url ) |
||
266 | { |
||
267 | $result = false; |
||
268 | |||
269 | if ( ! empty( $url ) ) { |
||
270 | $result = ( 0 === strpos( $url, '//' ) ); |
||
271 | } |
||
272 | |||
273 | return $result; |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Canonicalizes the given path regardless of it existing or not. |
||
278 | * |
||
279 | * @param string $path Path to normalize. |
||
280 | * |
||
281 | * @return string |
||
282 | */ |
||
283 | public static function path_canonicalize( $path ) |
||
284 | { |
||
285 | $patterns = array( |
||
286 | '~/{2,}~', |
||
287 | '~/(\./)+~', |
||
288 | '~([^/\.]+/(?R)*\.{2,}/)~', |
||
289 | '~\.\./~', |
||
290 | ); |
||
291 | $replacements = array( |
||
292 | '/', |
||
293 | '/', |
||
294 | '', |
||
295 | '', |
||
296 | ); |
||
297 | |||
298 | return preg_replace( $patterns, $replacements, $path ); |
||
299 | } |
||
300 | |||
301 | /** |
||
302 | * Checks to see if 3rd party services are available and stores result in option |
||
303 | * |
||
304 | * TODO This should be two separate methods. |
||
305 | * |
||
306 | * @param string $return_result should we return resulting service status array (default no). |
||
307 | * |
||
308 | * @return null|array Service status or null. |
||
309 | */ |
||
310 | public static function check_service_availability( $return_result = false ) |
||
311 | { |
||
312 | $service_availability_resp = wp_remote_get( 'https://misc.optimizingmatters.com/api/autoptimize_service_availablity.json?from=aomain&ver=' . AUTOPTIMIZE_PLUGIN_VERSION ); |
||
313 | View Code Duplication | if ( ! is_wp_error( $service_availability_resp ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
314 | if ( '200' == wp_remote_retrieve_response_code( $service_availability_resp ) ) { |
||
315 | $availabilities = json_decode( wp_remote_retrieve_body( $service_availability_resp ), true ); |
||
316 | if ( is_array( $availabilities ) ) { |
||
317 | autoptimizeOptionWrapper::update_option( 'autoptimize_service_availablity', $availabilities ); |
||
318 | if ( $return_result ) { |
||
0 ignored issues
–
show
The expression
$return_result of type false|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
319 | return $availabilities; |
||
320 | } |
||
321 | } |
||
322 | } |
||
323 | } |
||
324 | return null; |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * Returns true if the string is a valid regex. |
||
329 | * |
||
330 | * @param string $string String, duh. |
||
331 | * |
||
332 | * @return bool |
||
333 | */ |
||
334 | public static function str_is_valid_regex( $string ) |
||
335 | { |
||
336 | set_error_handler( function() {}, E_WARNING ); |
||
337 | $is_regex = ( false !== preg_match( $string, '' ) ); |
||
338 | restore_error_handler(); |
||
339 | |||
340 | return $is_regex; |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Returns true if a certain WP plugin is active/loaded. |
||
345 | * |
||
346 | * @param string $plugin_file Main plugin file. |
||
347 | * |
||
348 | * @return bool |
||
349 | */ |
||
350 | public static function is_plugin_active( $plugin_file ) |
||
351 | { |
||
352 | static $ipa_exists = null; |
||
353 | if ( null === $ipa_exists ) { |
||
354 | if ( ! function_exists( '\is_plugin_active' ) ) { |
||
355 | require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
||
356 | } |
||
357 | $ipa_exists = function_exists( '\is_plugin_active' ); |
||
358 | } |
||
359 | |||
360 | return $ipa_exists && \is_plugin_active( $plugin_file ); |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Returns a node without ID attrib for use in noscript tags |
||
365 | * |
||
366 | * @param string $node an html tag. |
||
367 | * |
||
368 | * @return string |
||
369 | */ |
||
370 | public static function remove_id_from_node( $node ) { |
||
371 | if ( strpos( $node, 'id=' ) === false || apply_filters( 'autoptimize_filter_utils_keep_ids', false ) ) { |
||
372 | return $node; |
||
373 | } else { |
||
374 | return preg_replace( '#(.*) id=[\'|"].*[\'|"] (.*)#Um', '$1 $2', $node ); |
||
375 | } |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * Returns true if given $str ends with given $test. |
||
380 | * |
||
381 | * @param string $str String to check. |
||
382 | * @param string $test Ending to match. |
||
383 | * |
||
384 | * @return bool |
||
385 | */ |
||
386 | public static function str_ends_in( $str, $test ) |
||
387 | { |
||
388 | // @codingStandardsIgnoreStart |
||
389 | // substr_compare() is bugged on 5.5.11: https://3v4l.org/qGYBH |
||
390 | // return ( 0 === substr_compare( $str, $test, -strlen( $test ) ) ); |
||
391 | // @codingStandardsIgnoreEnd |
||
392 | |||
393 | $length = strlen( $test ); |
||
394 | |||
395 | return ( substr( $str, -$length, $length ) === $test ); |
||
396 | } |
||
397 | } |
||
398 |