PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta.2
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta.2
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-device-detection / src / class-device-detection.php
jetpack / jetpack_vendor / automattic / jetpack-device-detection / src Last commit date
class-device-detection.php 9 months ago class-user-agent-info.php 2 months ago functions.php 3 years ago
class-device-detection.php
251 lines
1 <?php
2 /**
3 * Device detection for Jetpack.
4 *
5 * @package automattic/jetpack-device-detection
6 */
7
8 namespace Automattic\Jetpack;
9
10 require_once __DIR__ . '/functions.php';
11 require_once __DIR__ . '/class-user-agent-info.php';
12
13 use Automattic\Jetpack\Device_Detection\User_Agent_Info;
14 use function Automattic\Jetpack\Device_Detection\wp_unslash;
15
16 /**
17 * Class Device_Detection
18 *
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.
23 */
24 class Device_Detection {
25
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 /**
41 * Returns information about the current device accessing the page.
42 *
43 * @param string $ua (Optional) User-Agent string.
44 *
45 * @return array Device information.
46 *
47 * array(
48 * 'is_phone' => (bool) Whether the current device is a mobile phone.
49 * 'is_smartphone' => (bool) Whether the current device is a smartphone.
50 * 'is_tablet' => (bool) Whether the current device is a tablet device.
51 * 'is_handheld' => (bool) Whether the current device is a handheld device.
52 * 'is_desktop' => (bool) Whether the current device is a laptop / desktop device.
53 * 'platform' => (string) Detected platform.
54 * 'is_phone_matched_ua' => (string) Matched UA.
55 * );
56 */
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
68 $ua_info = new User_Agent_Info( $ua );
69
70 $info = array(
71 'is_phone' => self::is_mobile( 'any', false, $ua_info ),
72 'is_phone_matched_ua' => self::is_mobile( 'any', true, $ua_info ),
73 'is_smartphone' => self::is_mobile( 'smart', false, $ua_info ),
74 'is_tablet' => $ua_info->is_tablet(),
75 'platform' => $ua_info->get_platform(),
76 'desktop_platform' => $ua_info->get_desktop_platform(),
77 'browser' => $ua_info->get_browser(),
78 );
79
80 $info['is_handheld'] = $info['is_phone'] || $info['is_tablet'];
81 $info['is_desktop'] = ! $info['is_handheld'];
82
83 if ( function_exists( 'apply_filters' ) ) {
84 /**
85 * Filter the value of Device_Detection::get_info.
86 *
87 * @since 1.0.0
88 *
89 * @param array $info Array of device information.
90 * @param string $ua User agent string passed to Device_Detection::get_info.
91 * @param User_Agent_Info $ua_info Instance of Automattic\Jetpack\Device_Detection\User_Agent_Info.
92 */
93 $info = apply_filters( 'jetpack_device_detection_get_info', $info, $ua, $ua_info );
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
102 return $info;
103 }
104
105 /**
106 * Detects phone devices.
107 *
108 * @param string $ua User-Agent string.
109 *
110 * @return bool
111 */
112 public static function is_phone( $ua = '' ) {
113 $device_info = self::get_info( $ua );
114 return true === $device_info['is_phone'];
115 }
116
117 /**
118 * Detects smartphone devices.
119 *
120 * @param string $ua User-Agent string.
121 *
122 * @return bool
123 */
124 public static function is_smartphone( $ua = '' ) {
125 $device_info = self::get_info( $ua );
126 return true === $device_info['is_smartphone'];
127 }
128
129 /**
130 * Detects tablet devices.
131 *
132 * @param string $ua User-Agent string.
133 *
134 * @return bool
135 */
136 public static function is_tablet( $ua = '' ) {
137 $device_info = self::get_info( $ua );
138 return true === $device_info['is_tablet'];
139 }
140
141 /**
142 * Detects desktop devices.
143 *
144 * @param string $ua User-Agent string.
145 *
146 * @return bool
147 */
148 public static function is_desktop( $ua = '' ) {
149 $device_info = self::get_info( $ua );
150 return true === $device_info['is_desktop'];
151 }
152
153 /**
154 * Detects handheld (i.e. phone + tablet) devices.
155 *
156 * @param string $ua User-Agent string.
157 *
158 * @return bool
159 */
160 public static function is_handheld( $ua = '' ) {
161 $device_info = self::get_info( $ua );
162 return true === $device_info['is_handheld'];
163 }
164
165 /**
166 * Determine if the current User Agent matches the passed $kind.
167 *
168 * @param string $kind Category of mobile device to check for. Either: any, dumb, smart.
169 * @param bool $return_matched_agent Boolean indicating if the UA should be returned.
170 * @param User_Agent_Info $ua_info Boolean indicating if the UA should be returned.
171 *
172 * @return bool|string Boolean indicating if current UA matches $kind. If `$return_matched_agent` is true, returns the UA string.
173 */
174 private static function is_mobile( $kind, $return_matched_agent, $ua_info ) {
175 $kinds = array(
176 'smart' => false,
177 'dumb' => false,
178 'any' => false,
179 );
180 $matched_agent = '';
181
182 // If an invalid kind is passed in, reset it to default.
183 if ( ! isset( $kinds[ $kind ] ) ) {
184 $kind = 'any';
185 }
186
187 if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
188 return false;
189 }
190
191 $agent = strtolower( filter_var( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) );
192 if ( strpos( $agent, 'ipad' ) ) {
193 return false;
194 }
195
196 // Remove Samsung Galaxy tablets (SCH-I800) from being mobile devices.
197 if ( strpos( $agent, 'sch-i800' ) ) {
198 return false;
199 }
200
201 if ( $ua_info->is_android_tablet() && false === $ua_info->is_kindle_touch() ) {
202 return false;
203 }
204
205 if ( $ua_info->is_blackberry_tablet() ) {
206 return false;
207 }
208
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 }
214
215 if ( ! $kinds['smart'] ) {
216 // if smart, we are not dumb so no need to check.
217 $dumb_agents = $ua_info->dumb_agents;
218
219 foreach ( $dumb_agents as $dumb_agent ) {
220 if ( false !== strpos( $agent, $dumb_agent ) ) {
221 $kinds['dumb'] = true;
222 $matched_agent = $dumb_agent;
223
224 break;
225 }
226 }
227
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';
235 }
236 }
237 }
238
239 if ( $kinds['dumb'] || $kinds['smart'] ) {
240 $kinds['any'] = true;
241 }
242
243 $value = $kinds[ $kind ];
244
245 if ( $return_matched_agent ) {
246 $value = $matched_agent;
247 }
248 return $value;
249 }
250 }
251