PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-device-detection/src/class-device-detection.php +63 -32 12.4.2 → 16.3 View file →
@@ -16,12 +16,29 @@
16 16 /**
17 17 * Class Device_Detection
18 18 *
19 19 * Determine if the current User Agent matches the passed $kind.
20 + *
21 + * Note: str_contains() and other PHP8+ functions that have a polyfill in core are not used here,
22 + * as wp-includes/compat.php may not be loaded yet.
20 23 */
21 24 class Device_Detection {
22 25
23 26 /**
27 + * Memoization cache for get_info() results.
28 + *
29 + * @var array
30 + */
31 + private static $get_info_memo = array();
32 +
33 + /**
34 + * Maximum size of the memoization cache.
35 + *
36 + * @var int
37 + */
38 + private static $max_memo_size = 100;
39 +
40 + /**
24 41 * Returns information about the current device accessing the page.
25 42 *
26 43 * @param string $ua (Optional) User-Agent string.
27 44 *
@@ -37,8 +54,18 @@
37 54 * 'is_phone_matched_ua' => (string) Matched UA.
38 55 * );
39 56 */
40 57 public static function get_info( $ua = '' ) {
58 + // Return memoized result if available.
59 + // phpcs:disable WordPress.Security.ValidatedSanitizedInput
60 + $memo_key = ! empty( $ua ) ? $ua : ( $_SERVER['HTTP_USER_AGENT'] ?? '' );
61 + // Note: UA string used raw for compatibility reasons.
62 + // No sanitization is needed as the value is never output or persisted, and is only used for memoization.
63 + // phpcs:enable WordPress.Security.ValidatedSanitizedInput
64 + if ( isset( self::$get_info_memo[ $memo_key ] ) ) {
65 + return self::$get_info_memo[ $memo_key ];
66 + }
67 +
41 68 $ua_info = new User_Agent_Info( $ua );
42 69
43 70 $info = array(
44 71 'is_phone' => self::is_mobile( 'any', false, $ua_info ),
@@ -45,8 +72,10 @@
45 72 'is_phone_matched_ua' => self::is_mobile( 'any', true, $ua_info ),
46 73 'is_smartphone' => self::is_mobile( 'smart', false, $ua_info ),
47 74 'is_tablet' => $ua_info->is_tablet(),
48 75 'platform' => $ua_info->get_platform(),
76 + 'desktop_platform' => $ua_info->get_desktop_platform(),
77 + 'browser' => $ua_info->get_browser(),
49 78 );
50 79
51 80 $info['is_handheld'] = $info['is_phone'] || $info['is_tablet'];
52 81 $info['is_desktop'] = ! $info['is_handheld'];
@@ -62,8 +91,15 @@
62 91 * @param User_Agent_Info $ua_info Instance of Automattic\Jetpack\Device_Detection\User_Agent_Info.
63 92 */
64 93 $info = apply_filters( 'jetpack_device_detection_get_info', $info, $ua, $ua_info );
65 94 }
95 +
96 + // Memoize the result.
97 + self::$get_info_memo[ $memo_key ] = $info;
98 + if ( count( self::$get_info_memo ) > self::$max_memo_size ) {
99 + array_shift( self::$get_info_memo );
100 + }
101 +
66 102 return $info;
67 103 }
68 104
69 105 /**
@@ -140,9 +176,8 @@
140 176 'smart' => false,
141 177 'dumb' => false,
142 178 'any' => false,
143 179 );
144 - $first_run = true;
145 180 $matched_agent = '';
146 181
147 182 // If an invalid kind is passed in, reset it to default.
148 183 if ( ! isset( $kinds[ $kind ] ) ) {
@@ -152,15 +187,15 @@
152 187 if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
153 188 return false;
154 189 }
155 190
156 - $agent = strtolower( filter_var( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) );
157 - if ( strpos( $agent, 'ipad' ) ) {
191 + $agent = strtolower( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
192 + if ( strpos( $agent, 'ipad' ) !== false ) {
158 193 return false;
159 194 }
160 195
161 196 // Remove Samsung Galaxy tablets (SCH-I800) from being mobile devices.
162 - if ( strpos( $agent, 'sch-i800' ) ) {
197 + if ( strpos( $agent, 'sch-i800' ) !== false ) {
163 198 return false;
164 199 }
165 200
166 201 if ( $ua_info->is_android_tablet() && false === $ua_info->is_kindle_touch() ) {
@@ -170,44 +205,40 @@
170 205 if ( $ua_info->is_blackberry_tablet() ) {
171 206 return false;
172 207 }
173 208
174 - if ( $first_run ) {
175 - $first_run = false;
209 + // checks for iPhoneTier devices & RichCSS devices.
210 + if ( $ua_info->isTierIphone() || $ua_info->isTierRichCSS() ) {
211 + $kinds['smart'] = true;
212 + $matched_agent = $ua_info->matched_agent;
213 + }
176 214
177 - // checks for iPhoneTier devices & RichCSS devices.
178 - if ( $ua_info->isTierIphone() || $ua_info->isTierRichCSS() ) {
179 - $kinds['smart'] = true;
180 - $matched_agent = $ua_info->matched_agent;
181 - }
215 + if ( ! $kinds['smart'] ) {
216 + // if smart, we are not dumb so no need to check.
217 + $dumb_agents = $ua_info->dumb_agents;
182 218
183 - if ( ! $kinds['smart'] ) {
184 - // if smart, we are not dumb so no need to check.
185 - $dumb_agents = $ua_info->dumb_agents;
219 + foreach ( $dumb_agents as $dumb_agent ) {
220 + if ( false !== strpos( $agent, $dumb_agent ) ) {
221 + $kinds['dumb'] = true;
222 + $matched_agent = $dumb_agent;
186 223
187 - foreach ( $dumb_agents as $dumb_agent ) {
188 - if ( false !== strpos( $agent, $dumb_agent ) ) {
189 - $kinds['dumb'] = true;
190 - $matched_agent = $dumb_agent;
191 -
192 - break;
193 - }
224 + break;
194 225 }
226 + }
195 227
196 - if ( ! $kinds['dumb'] ) {
197 - if ( isset( $_SERVER['HTTP_X_WAP_PROFILE'] ) ) {
198 - $kinds['dumb'] = true;
199 - $matched_agent = 'http_x_wap_profile';
200 - } elseif ( isset( $_SERVER['HTTP_ACCEPT'] ) && ( preg_match( '/wap\.|\.wap/i', $_SERVER['HTTP_ACCEPT'] ) || false !== strpos( strtolower( $_SERVER['HTTP_ACCEPT'] ), 'application/vnd.wap.xhtml+xml' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is doing the validating.
201 - $kinds['dumb'] = true;
202 - $matched_agent = 'vnd.wap.xhtml+xml';
203 - }
228 + if ( ! $kinds['dumb'] ) {
229 + if ( isset( $_SERVER['HTTP_X_WAP_PROFILE'] ) ) {
230 + $kinds['dumb'] = true;
231 + $matched_agent = 'http_x_wap_profile';
232 + } elseif ( isset( $_SERVER['HTTP_ACCEPT'] ) && ( preg_match( '/wap\.|\.wap/i', $_SERVER['HTTP_ACCEPT'] ) || false !== strpos( strtolower( $_SERVER['HTTP_ACCEPT'] ), 'application/vnd.wap.xhtml+xml' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is doing the validating.
233 + $kinds['dumb'] = true;
234 + $matched_agent = 'vnd.wap.xhtml+xml';
204 235 }
205 236 }
237 + }
206 238
207 - if ( $kinds['dumb'] || $kinds['smart'] ) {
208 - $kinds['any'] = true;
209 - }
239 + if ( $kinds['dumb'] || $kinds['smart'] ) {
240 + $kinds['any'] = true;
210 241 }
211 242
212 243 $value = $kinds[ $kind ];
213 244