Completed
Push — add/jetpack-mobile-package ( 96545e...4a9724 )
by
unknown
08:23
created

Device_Detection::get_info()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 1
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Device detection for Jetpack.
4
 *
5
 * @package automattic/jetpack-device-detection
6
 */
7
8
namespace Automattic\Jetpack;
9
10
/**
11
 * Class Device_Detection
12
 *
13
 * Determine if the current User Agent matches the passed $kind.
14
 */
15
class Device_Detection {
16
17
	/**
18
	 * Returns information about the current device accessing the page.
19
	 *
20
	 * @param string $ua (Optional) User-Agent string.
21
	 *
22
	 * @return array Device information.
23
	 *
24
	 * array(
25
	 *  'is_mobile'            => (bool) Whether the current device is a mobile phone.
26
	 *  'is_smartphone'        => (bool) Whether the current device is a smartphone.
27
	 *  'is_tablet'            => (bool) Whether the current device is a tablet device.
28
	 *  'is_handheld'          => (bool) Whether the current device is a handheld device.
29
	 *  'is_desktop'           => (bool) Whether the current device is a laptop / desktop device.
30
	 *  'platform'             => (string) Detected platform.
31
	 *  'is_mobile_matched_ua' => (string) Matched UA.
32
	 * );
33
	 */
34
	public static function get_info( $ua = '' ) {
35
		$ua_info = new Jetpack_User_Agent_Info( $ua );
36
37
		$info = array(
38
			'is_mobile'            => self::is_mobile( 'any', false, $ua_info ),
39
			'is_mobile_matched_ua' => self::is_mobile( 'any', true, $ua_info ),
40
			'is_smartphone'        => self::is_mobile( 'smart', false, $ua_info ),
41
			'is_tablet'            => $ua_info->is_tablet(),
42
			'platform'             => $ua_info->get_platform(),
43
		);
44
45
		$info['is_handheld'] = $info['is_mobile'] || $info['is_tablet'];
46
		$info['is_desktop']  = ! $info['is_handheld'];
47
48
		if ( function_exists( 'apply_filters' ) ) {
49
			$info = apply_filters( 'jetpack_device_detection_get_info', $info, $ua, $ua_info );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $ua.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
50
		}
51
		return $info;
52
	}
53
54
	/**
55
	 * Determine if the current User Agent matches the passed $kind.
56
	 *
57
	 * @param string                  $kind                 Category of mobile device to check for. Either: any, dumb, smart.
58
	 * @param bool                    $return_matched_agent Boolean indicating if the UA should be returned.
59
	 * @param Jetpack_User_Agent_Info $ua_info              Boolean indicating if the UA should be returned.
60
	 *
61
	 * @return bool|string Boolean indicating if current UA matches $kind. If `$return_matched_agent` is true, returns the UA string.
62
	 */
63
	private static function is_mobile( $kind = 'any', $return_matched_agent = false, $ua_info ) {
64
		$kinds         = array(
65
			'smart' => false,
66
			'dumb'  => false,
67
			'any'   => false,
68
		);
69
		$first_run     = true;
70
		$matched_agent = '';
71
72
		// If an invalid kind is passed in, reset it to default.
73
		if ( ! isset( $kinds[ $kind ] ) ) {
74
				$kind = 'any';
75
		}
76
77
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) || strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'ipad' ) ) {
78
			return false;
79
		}
80
81
		// Remove Samsung Galaxy tablets (SCH-I800) from being mobile devices
82
		if ( strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'sch-i800' ) ) {
83
			return false;
84
		}
85
86
		if ( $ua_info->is_android_tablet() && false === $ua_info->is_kindle_touch() ) {
87
			return false;
88
		}
89
90
		if ( $ua_info->is_blackberry_tablet() ) {
91
			return false;
92
		}
93
94
		if ( $first_run ) {
95
			$first_run = false;
0 ignored issues
show
Unused Code introduced by
$first_run is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
96
97
			// checks for iPhoneTier devices & RichCSS devices
98
			if ( $ua_info->isTierIphone() || $ua_info->isTierRichCSS() ) {
99
				$kinds['smart'] = true;
100
				$matched_agent  = $ua_info->matched_agent;
101
			}
102
103
			if ( ! $kinds['smart'] ) {
104
				// if smart, we are not dumb so no need to check
105
				$dumb_agents = $ua_info->dumb_agents;
106
				$agent       = strtolower( $_SERVER['HTTP_USER_AGENT'] );
107
108
				foreach ( $dumb_agents as $dumb_agent ) {
109
					if ( false !== strpos( $agent, $dumb_agent ) ) {
110
						$kinds['dumb'] = true;
111
						$matched_agent = $dumb_agent;
112
113
						break;
114
					}
115
				}
116
117
				if ( ! $kinds['dumb'] ) {
118
					if ( isset( $_SERVER['HTTP_X_WAP_PROFILE'] ) ) {
119
						$kinds['dumb'] = true;
120
						$matched_agent = 'http_x_wap_profile';
121
					} elseif ( isset( $_SERVER['HTTP_ACCEPT'] ) && ( preg_match( '/wap\.|\.wap/i', $_SERVER['HTTP_ACCEPT'] ) || false !== strpos( strtolower( $_SERVER['HTTP_ACCEPT'] ), 'application/vnd.wap.xhtml+xml' ) ) ) {
122
						$kinds['dumb'] = true;
123
						$matched_agent = 'vnd.wap.xhtml+xml';
124
					}
125
				}
126
			}
127
128
			if ( $kinds['dumb'] || $kinds['smart'] ) {
129
				$kinds['any'] = true;
130
			}
131
		}
132
133
		$value = $kinds[ $kind ];
134
135
		if ( $return_matched_agent ) {
136
			$value = $matched_agent;
137
		}
138
		return $value;
139
	}
140
}
141
142
143
class Jetpack_User_Agent_Info {
144
145
	public $useragent;
146
	public $matched_agent;
147
	public $isTierIphone; // Stores whether is the iPhone tier of devices.
148
	public $isTierRichCss; // Stores whether the device can probably support Rich CSS, but JavaScript (jQuery) support is not assumed.
149
	public $isTierGenericMobile; // Stores whether it is another mobile device, which cannot be assumed to support CSS or JS (eg, older BlackBerry, RAZR)
150
151
	private $_platform            = null; // Stores the device platform name
152
	const PLATFORM_WINDOWS        = 'windows';
153
	const PLATFORM_IPHONE         = 'iphone';
154
	const PLATFORM_IPOD           = 'ipod';
155
	const PLATFORM_IPAD           = 'ipad';
156
	const PLATFORM_BLACKBERRY     = 'blackberry';
157
	const PLATFORM_BLACKBERRY_10  = 'blackberry_10';
158
	const PLATFORM_SYMBIAN        = 'symbian_series60';
159
	const PLATFORM_SYMBIAN_S40    = 'symbian_series40';
160
	const PLATFORM_J2ME_MIDP      = 'j2me_midp';
161
	const PLATFORM_ANDROID        = 'android';
162
	const PLATFORM_ANDROID_TABLET = 'android_tablet';
163
	const PLATFORM_FIREFOX_OS     = 'firefoxOS';
164
165
	public $dumb_agents = array(
166
		'nokia',
167
		'blackberry',
168
		'philips',
169
		'samsung',
170
		'sanyo',
171
		'sony',
172
		'panasonic',
173
		'webos',
174
		'ericsson',
175
		'alcatel',
176
		'palm',
177
		'windows ce',
178
		'opera mini',
179
		'series60',
180
		'series40',
181
		'au-mic,',
182
		'audiovox',
183
		'avantgo',
184
		'blazer',
185
		'danger',
186
		'docomo',
187
		'epoc',
188
		'ericy',
189
		'i-mode',
190
		'ipaq',
191
		'midp-',
192
		'mot-',
193
		'netfront',
194
		'nitro',
195
		'palmsource',
196
		'pocketpc',
197
		'portalmmm',
198
		'rover',
199
		'sie-',
200
		'symbian',
201
		'cldc-',
202
		'j2me',
203
		'smartphone',
204
		'up.browser',
205
		'up.link',
206
		'up.link',
207
		'vodafone/',
208
		'wap1.',
209
		'wap2.',
210
		'mobile',
211
		'googlebot-mobile',
212
	);
213
214
215
	/**
216
	 * The constructor.
217
	 *
218
	 * @param string $ua (Optional) User agent.
219
	 */
220
	function __construct( $ua = '' ) {
221
		if ( $ua ) {
222
			$this->useragent = $ua;
223
		} else {
224
			if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
225
				$this->useragent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
226
			}
227
		}
228
	}
229
230
	/**
231
	 * This method detects the mobile User Agent name.
232
	 *
233
	 * @return string The matched User Agent name, false otherwise.
234
	 */
235
	function get_mobile_user_agent_name() {
236
		if ( $this->is_chrome_for_iOS() ) { // keep this check before the safari rule
237
			return 'chrome-for-ios';
238
		} elseif ( $this->is_iphone_or_ipod( 'iphone-safari' ) ) {
239
			return 'iphone';
240
		} elseif ( $this->is_ipad( 'ipad-safari' ) ) {
241
			return 'ipad';
242
		} elseif ( $this->is_android_tablet() ) { // keep this check before the android rule
243
			return 'android_tablet';
244
		} elseif ( $this->is_android() ) {
245
			return 'android';
246
		} elseif ( $this->is_blackberry_10() ) {
247
			return 'blackberry_10';
248
		} elseif ( $this->is_blackbeberry() ) {
249
			return 'blackberry';
250
		} elseif ( $this->is_WindowsPhone7() ) {
251
			return 'win7';
252
		} elseif ( $this->is_windows_phone_8() ) {
253
			return 'winphone8';
254
		} elseif ( $this->is_opera_mini() ) {
255
			return 'opera-mini';
256
		} elseif ( $this->is_opera_mini_dumb() ) {
257
			return 'opera-mini-dumb';
258
		} elseif ( $this->is_opera_mobile() ) {
259
			return 'opera-mobi';
260
		} elseif ( $this->is_blackberry_tablet() ) {
261
			return 'blackberry_tablet';
262
		} elseif ( $this->is_kindle_fire() ) {
263
			return 'kindle-fire';
264
		} elseif ( $this->is_PalmWebOS() ) {
265
			return 'webos';
266
		} elseif ( $this->is_S60_OSSBrowser() ) {
267
			return 'series60';
268
		} elseif ( $this->is_firefox_os() ) {
269
			return 'firefoxOS';
270
		} elseif ( $this->is_firefox_mobile() ) {
271
			return 'firefox_mobile';
272
		} elseif ( $this->is_MaemoTablet() ) {
273
			return 'maemo';
274
		} elseif ( $this->is_MeeGo() ) {
275
			return 'meego';
276
		} elseif ( $this->is_TouchPad() ) {
277
			return 'hp_tablet';
278
		} elseif ( $this->is_facebook_for_iphone() ) {
279
			return 'facebook-for-iphone';
280
		} elseif ( $this->is_facebook_for_ipad() ) {
281
			return 'facebook-for-ipad';
282
		} elseif ( $this->is_twitter_for_iphone() ) {
283
			return 'twitter-for-iphone';
284
		} elseif ( $this->is_twitter_for_ipad() ) {
285
			return 'twitter-for-ipad';
286
		} elseif ( $this->is_wordpress_for_ios() ) {
287
			return 'ios-app';
288
		} elseif ( $this->is_iphone_or_ipod( 'iphone-not-safari' ) ) {
289
			return 'iphone-unknown';
290
		} elseif ( $this->is_ipad( 'ipad-not-safari' ) ) {
291
			return 'ipad-unknown';
292
		} elseif ( $this->is_Nintendo_3DS() ) {
293
			return 'nintendo-3ds';
294
		} else {
295
			$agent       = strtolower( $_SERVER['HTTP_USER_AGENT'] );
296
			$dumb_agents = $this->dumb_agents;
297
			foreach ( $dumb_agents as $dumb_agent ) {
298
				if ( false !== strpos( $agent, $dumb_agent ) ) {
299
					return $dumb_agent;
300
				}
301
			}
302
		}
303
304
		return false;
305
	}
306
307
	/**
308
	 * This method detects the mobile device's platform. All return strings are from the class constants.
309
	 * Note that this function returns the platform name, not the UA name/type. You should use a different function
310
	 * if you need to test the UA capabilites.
311
	 *
312
	 * @return string Name of the platform, false otherwise.
313
	 */
314
	public function get_platform() {
315
		if ( isset( $this->_platform ) ) {
316
			  return $this->_platform;
317
		}
318
319
		if ( strpos( $this->useragent, 'windows phone' ) !== false ) {
320
			 $this->_platform = self::PLATFORM_WINDOWS;
321
		} elseif ( strpos( $this->useragent, 'windows ce' ) !== false ) {
322
			$this->_platform = self::PLATFORM_WINDOWS;
323
		} elseif ( strpos( $this->useragent, 'ipad' ) !== false ) {
324
			$this->_platform = self::PLATFORM_IPAD;
325
		} elseif ( strpos( $this->useragent, 'ipod' ) !== false ) {
326
			$this->_platform = self::PLATFORM_IPOD;
327
		} elseif ( strpos( $this->useragent, 'iphone' ) !== false ) {
328
			$this->_platform = self::PLATFORM_IPHONE;
329
		} elseif ( strpos( $this->useragent, 'android' ) !== false ) {
330
			if ( $this->is_android_tablet() ) {
331
				$this->_platform = self::PLATFORM_ANDROID_TABLET;
332
			} else {
333
				$this->_platform = self::PLATFORM_ANDROID;
334
			}
335
		} elseif ( $this->is_kindle_fire() ) {
336
			$this->_platform = self::PLATFORM_ANDROID_TABLET;
337
		} elseif ( $this->is_blackberry_10() ) {
338
			$this->_platform = self::PLATFORM_BLACKBERRY_10;
339
		} elseif ( strpos( $this->useragent, 'blackberry' ) !== false ) {
340
			$this->_platform = self::PLATFORM_BLACKBERRY;
341
		} elseif ( $this->is_blackberry_tablet() ) {
342
			$this->_platform = self::PLATFORM_BLACKBERRY;
343
		} elseif ( $this->is_symbian_platform() ) {
344
			$this->_platform = self::PLATFORM_SYMBIAN;
345
		} elseif ( $this->is_symbian_s40_platform() ) {
346
			$this->_platform = self::PLATFORM_SYMBIAN_S40;
347
		} elseif ( $this->is_J2ME_platform() ) {
348
			$this->_platform = self::PLATFORM_J2ME_MIDP;
349
		} elseif ( $this->is_firefox_os() ) {
350
			$this->_platform = self::PLATFORM_FIREFOX_OS;
351
		} else {
352
			$this->_platform = false;
353
		}
354
355
		return $this->_platform;
356
	}
357
358
	/*
359
	 * This method detects for UA which can display iPhone-optimized web content.
360
	 * Includes iPhone, iPod Touch, Android, WebOS, Fennec (Firefox mobile), etc.
361
	 *
362
	 */
363
	function isTierIphone() {
364
		if ( isset( $this->isTierIphone ) ) {
365
			return $this->isTierIphone;
366
		}
367
		if ( $this->is_iphoneOrIpod() ) {
368
			$this->matched_agent       = 'iphone';
369
			$this->isTierIphone        = true;
370
			$this->isTierRichCss       = false;
371
			$this->isTierGenericMobile = false;
372 View Code Duplication
		} elseif ( $this->is_android() ) {
373
			$this->matched_agent       = 'android';
374
			$this->isTierIphone        = true;
375
			$this->isTierRichCss       = false;
376
			$this->isTierGenericMobile = false;
377
		} elseif ( $this->is_windows_phone_8() ) {
378
			$this->matched_agent       = 'winphone8';
379
			$this->isTierIphone        = true;
380
			$this->isTierRichCss       = false;
381
			$this->isTierGenericMobile = false;
382 View Code Duplication
		} elseif ( $this->is_WindowsPhone7() ) {
383
			$this->matched_agent       = 'win7';
384
			$this->isTierIphone        = true;
385
			$this->isTierRichCss       = false;
386
			$this->isTierGenericMobile = false;
387
		} elseif ( $this->is_blackberry_10() ) {
388
			$this->matched_agent       = 'blackberry-10';
389
			$this->isTierIphone        = true;
390
			$this->isTierRichCss       = false;
391
			$this->isTierGenericMobile = false;
392 View Code Duplication
		} elseif ( $this->is_blackbeberry() && $this->detect_blackberry_browser_version() == 'blackberry-webkit' ) {
393
			$this->matched_agent       = 'blackberry-webkit';
394
			$this->isTierIphone        = true;
395
			$this->isTierRichCss       = false;
396
			$this->isTierGenericMobile = false;
397
		} elseif ( $this->is_blackberry_tablet() ) {
398
			$this->matched_agent       = 'blackberry_tablet';
399
			$this->isTierIphone        = true;
400
			$this->isTierRichCss       = false;
401
			$this->isTierGenericMobile = false;
402 View Code Duplication
		} elseif ( $this->is_PalmWebOS() ) {
403
			$this->matched_agent       = 'webos';
404
			$this->isTierIphone        = true;
405
			$this->isTierRichCss       = false;
406
			$this->isTierGenericMobile = false;
407
		} elseif ( $this->is_TouchPad() ) {
408
			$this->matched_agent       = 'hp_tablet';
409
			$this->isTierIphone        = true;
410
			$this->isTierRichCss       = false;
411
			$this->isTierGenericMobile = false;
412 View Code Duplication
		} elseif ( $this->is_firefox_os() ) {
413
			$this->matched_agent       = 'firefoxOS';
414
			$this->isTierIphone        = true;
415
			$this->isTierRichCss       = false;
416
			$this->isTierGenericMobile = false;
417
		} elseif ( $this->is_firefox_mobile() ) {
418
			$this->matched_agent       = 'fennec';
419
			$this->isTierIphone        = true;
420
			$this->isTierRichCss       = false;
421
			$this->isTierGenericMobile = false;
422 View Code Duplication
		} elseif ( $this->is_opera_mobile() ) {
423
			$this->matched_agent       = 'opera-mobi';
424
			$this->isTierIphone        = true;
425
			$this->isTierRichCss       = false;
426
			$this->isTierGenericMobile = false;
427
		} elseif ( $this->is_MaemoTablet() ) {
428
			$this->matched_agent       = 'maemo';
429
			$this->isTierIphone        = true;
430
			$this->isTierRichCss       = false;
431
			$this->isTierGenericMobile = false;
432 View Code Duplication
		} elseif ( $this->is_MeeGo() ) {
433
			$this->matched_agent       = 'meego';
434
			$this->isTierIphone        = true;
435
			$this->isTierRichCss       = false;
436
			$this->isTierGenericMobile = false;
437
		} elseif ( $this->is_kindle_touch() ) {
438
			$this->matched_agent       = 'kindle-touch';
439
			$this->isTierIphone        = true;
440
			$this->isTierRichCss       = false;
441
			$this->isTierGenericMobile = false;
442 View Code Duplication
		} elseif ( $this->is_Nintendo_3DS() ) {
443
			$this->matched_agent       = 'nintendo-3ds';
444
			$this->isTierIphone        = true;
445
			$this->isTierRichCss       = false;
446
			$this->isTierGenericMobile = false;
447
		} else {
448
			$this->isTierIphone = false;
449
		}
450
		return $this->isTierIphone;
451
	}
452
453
	/*
454
	 * This method detects for UA which are likely to be capable
455
	 * but may not necessarily support JavaScript.
456
	 * Excludes all iPhone Tier UA.
457
	 *
458
	 */
459
	function isTierRichCss() {
460
		if ( isset( $this->isTierRichCss ) ) {
461
			return $this->isTierRichCss;
462
		}
463
		if ( $this->isTierIphone() ) {
464
			return false;
465
		}
466
467
		// The following devices are explicitly ok.
468
		if ( $this->is_S60_OSSBrowser() ) {
469
			$this->matched_agent       = 'series60';
470
			$this->isTierIphone        = false;
471
			$this->isTierRichCss       = true;
472
			$this->isTierGenericMobile = false;
473 View Code Duplication
		} elseif ( $this->is_opera_mini() ) {
474
			$this->matched_agent       = 'opera-mini';
475
			$this->isTierIphone        = false;
476
			$this->isTierRichCss       = true;
477
			$this->isTierGenericMobile = false;
478
		} elseif ( $this->is_blackbeberry() ) {
479
			$detectedDevice = $this->detect_blackberry_browser_version();
480
			if ( $detectedDevice === 'blackberry-5' || $detectedDevice == 'blackberry-4.7' || $detectedDevice === 'blackberry-4.6' ) {
481
				$this->matched_agent       = $detectedDevice;
482
				$this->isTierIphone        = false;
483
				$this->isTierRichCss       = true;
484
				$this->isTierGenericMobile = false;
485
			}
486
		} else {
487
			$this->isTierRichCss = false;
488
		}
489
490
		return $this->isTierRichCss;
491
	}
492
493
	// Detects if the user is using a tablet.
494
	// props Corey Gilmore, BGR.com
495
	function is_tablet() {
496
		return ( 0 // never true, but makes it easier to manage our list of tablet conditions
497
				|| self::is_ipad()
498
				|| self::is_android_tablet()
499
				|| self::is_blackberry_tablet()
500
				|| self::is_kindle_fire()
501
				|| self::is_MaemoTablet()
502
				|| self::is_TouchPad()
503
		);
504
	}
505
506
	/*
507
	 *  Detects if the current UA is the default iPhone or iPod Touch Browser.
508
	 *
509
	 *  DEPRECATED: use is_iphone_or_ipod
510
	 *
511
	 */
512
	function is_iphoneOrIpod() {
513
514
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
515
			return false;
516
		}
517
518
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
519 View Code Duplication
		if ( ( strpos( $ua, 'iphone' ) !== false ) || ( strpos( $ua, 'ipod' ) !== false ) ) {
520
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
521
				return false;
522
			} else {
523
				return true;
524
			}
525
		} else {
526
			return false;
527
		}
528
	}
529
530
531
	/*
532
	 *  Detects if the current UA is iPhone Mobile Safari or another iPhone or iPod Touch Browser.
533
	 *
534
	 *  They type can check for any iPhone, an iPhone using Safari, or an iPhone using something other than Safari.
535
	 *
536
	 *  Note: If you want to check for Opera mini, Opera mobile or Firefox mobile (or any 3rd party iPhone browser),
537
	 *  you should put the check condition before the check for 'iphone-any' or 'iphone-not-safari'.
538
	 *  Otherwise those browsers will be 'catched' by the iphone string.
539
	 *
540
	 */
541
	static function is_iphone_or_ipod( $type = 'iphone-any' ) {
542
543
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
544
			return false;
545
		}
546
547
		$ua        = strtolower( $_SERVER['HTTP_USER_AGENT'] );
548
		$is_iphone = ( strpos( $ua, 'iphone' ) !== false ) || ( strpos( $ua, 'ipod' ) !== false );
549
		$is_safari = ( false !== strpos( $ua, 'safari' ) );
550
551
		if ( 'iphone-safari' == $type ) {
552
			return $is_iphone && $is_safari;
553
		} elseif ( 'iphone-not-safari' == $type ) {
554
			return $is_iphone && ! $is_safari;
555
		} else {
556
			return $is_iphone;
557
		}
558
	}
559
560
561
	/*
562
	*  Detects if the current UA is Chrome for iOS
563
	*
564
	*  The User-Agent string in Chrome for iOS is the same as the Mobile Safari User-Agent, with CriOS/<ChromeRevision> instead of Version/<VersionNum>.
565
	*  - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3
566
	*/
567
	static function is_chrome_for_iOS() {
568
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
569
			return false;
570
		}
571
572
		if ( self::is_iphone_or_ipod( 'iphone-safari' ) === false ) {
573
			return false;
574
		}
575
576
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
577
578
		if ( strpos( $ua, 'crios/' ) !== false ) {
579
			return true;
580
		} else {
581
			return false;
582
		}
583
	}
584
585
586
	/*
587
	 *  Detects if the current UA is Twitter for iPhone
588
	 *
589
	 * Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; nb-no) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPhone
590
	 * Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
591
	 *
592
	 */
593
	static function is_twitter_for_iphone() {
594
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
595
			return false;
596
		}
597
598
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
599
600
		if ( strpos( $ua, 'ipad' ) !== false ) {
601
			return false;
602
		}
603
604
		if ( strpos( $ua, 'twitter for iphone' ) !== false ) {
605
			return true;
606
		} else {
607
			return false;
608
		}
609
	}
610
611
	/*
612
	 * Detects if the current UA is Twitter for iPad
613
	 *
614
	 * Old version 4.X - Mozilla/5.0 (iPad; U; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPad
615
	 * Ver 5.0 or Higher - Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
616
	 *
617
	 */
618
	static function is_twitter_for_ipad() {
619
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
620
			return false;
621
		}
622
623
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
624
625
		if ( strpos( $ua, 'twitter for ipad' ) !== false ) {
626
			return true;
627 View Code Duplication
		} elseif ( strpos( $ua, 'ipad' ) !== false && strpos( $ua, 'twitter for iphone' ) !== false ) {
628
			return true;
629
		} else {
630
			return false;
631
		}
632
	}
633
634
635
	/*
636
	 * Detects if the current UA is Facebook for iPhone
637
	 * - Facebook 4020.0 (iPhone; iPhone OS 5.0.1; fr_FR)
638
	 * - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/2.0]
639
	 * - Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.1.1;FBSS/2; FBCR/3ITA;FBID/phone;FBLC/en_US]
640
	 */
641
	static function is_facebook_for_iphone() {
642
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
643
			return false;
644
		}
645
646
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
647
648
		if ( false === strpos( $ua, 'iphone' ) ) {
649
			return false;
650
		}
651
652
		if ( false !== strpos( $ua, 'facebook' ) && false === strpos( $ua, 'ipad' ) ) {
653
			return true;
654
		} elseif ( false !== strpos( $ua, 'fbforiphone' ) && false === strpos( $ua, 'tablet' ) ) {
655
			return true;
656
		} elseif ( false !== strpos( $ua, 'fban/fbios;' ) && false === strpos( $ua, 'tablet' ) ) { // FB app v5.0 or higher
657
			return true;
658
		} else {
659
			return false;
660
		}
661
	}
662
663
	/*
664
	 * Detects if the current UA is Facebook for iPad
665
	 * - Facebook 4020.0 (iPad; iPhone OS 5.0.1; en_US)
666
	 * - Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]
667
	 * - Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10A403 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/6.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US]
668
	 */
669 View Code Duplication
	static function is_facebook_for_ipad() {
670
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
671
			return false;
672
		}
673
674
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
675
676
		if ( false === strpos( $ua, 'ipad' ) ) {
677
			return false;
678
		}
679
680
		if ( false !== strpos( $ua, 'facebook' ) || false !== strpos( $ua, 'fbforiphone' ) || false !== strpos( $ua, 'fban/fbios;' ) ) {
681
			return true;
682
		} else {
683
			return false;
684
		}
685
	}
686
687
	/*
688
	 *  Detects if the current UA is WordPress for iOS
689
	 */
690
	static function is_wordpress_for_ios() {
691
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
692
			return false;
693
		}
694
695
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
696
		if ( false !== strpos( $ua, 'wp-iphone' ) ) {
697
			return true;
698
		} else {
699
			return false;
700
		}
701
	}
702
703
	/*
704
	 * Detects if the current device is an iPad.
705
	 * They type can check for any iPad, an iPad using Safari, or an iPad using something other than Safari.
706
	 *
707
	 * Note: If you want to check for Opera mini, Opera mobile or Firefox mobile (or any 3rd party iPad browser),
708
	 * you should put the check condition before the check for 'iphone-any' or 'iphone-not-safari'.
709
	 * Otherwise those browsers will be 'catched' by the ipad string.
710
	 *
711
	*/
712
	static function is_ipad( $type = 'ipad-any' ) {
713
714
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
715
			return false;
716
		}
717
718
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
719
720
		$is_ipad   = ( false !== strpos( $ua, 'ipad' ) );
721
		$is_safari = ( false !== strpos( $ua, 'safari' ) );
722
723
		if ( 'ipad-safari' == $type ) {
724
			return $is_ipad && $is_safari;
725
		} elseif ( 'ipad-not-safari' == $type ) {
726
			return $is_ipad && ! $is_safari;
727
		} else {
728
			return $is_ipad;
729
		}
730
	}
731
732
	/*
733
	 * Detects if the current browser is Firefox Mobile (Fennec)
734
	 *
735
	 * http://www.useragentstring.com/pages/Fennec/
736
	 * Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.1.1) Gecko/20110415 Firefox/4.0.2pre Fennec/4.0.1
737
	 * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1
738
	 */
739
	static function is_firefox_mobile() {
740
741
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
742
			return false;
743
		}
744
745
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
746
747
		if ( strpos( $ua, 'fennec' ) !== false ) {
748
			return true;
749
		} else {
750
			return false;
751
		}
752
	}
753
754
	/*
755
	 * Detects if the current browser is Firefox for desktop
756
	 *
757
	 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
758
	 * Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion
759
	 * The platform section will include 'Mobile' for phones and 'Tablet' for tablets.
760
	 *
761
	 */
762 View Code Duplication
	static function is_firefox_desktop() {
763
764
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
765
			return false;
766
		}
767
768
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
769
770
		if ( false !== strpos( $ua, 'firefox' ) && false === strpos( $ua, 'mobile' ) && false === strpos( $ua, 'tablet' ) ) {
771
			return true;
772
		} else {
773
			return false;
774
		}
775
	}
776
777
	/*
778
	 * Detects if the current browser is FirefoxOS Native browser
779
	*
780
	* Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
781
	*
782
	*/
783 View Code Duplication
	static function is_firefox_os() {
784
785
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
786
			return false;
787
		}
788
789
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
790
791
		if ( strpos( $ua, 'mozilla' ) !== false && strpos( $ua, 'mobile' ) !== false && strpos( $ua, 'gecko' ) !== false && strpos( $ua, 'firefox' ) !== false ) {
792
			return true;
793
		} else {
794
			return false;
795
		}
796
	}
797
798
799
	/*
800
	 * Detects if the current browser is Opera Mobile
801
	 *
802
	 * What is the difference between Opera Mobile and Opera Mini?
803
	 * - Opera Mobile is a full Internet browser for mobile devices.
804
	 * - Opera Mini always uses a transcoder to convert the page for a small display.
805
	 * (it uses Opera advanced server compression technology to compress web content before it gets to a device.
806
	 *  The rendering engine is on Opera's server.)
807
	 *
808
	 * Opera/9.80 (Windows NT 6.1; Opera Mobi/14316; U; en) Presto/2.7.81 Version/11.00"
809
	 * Opera/9.50 (Nintendo DSi; Opera/507; U; en-US)
810
	 */
811 View Code Duplication
	static function is_opera_mobile() {
812
813
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
814
			return false;
815
		}
816
817
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
818
819
		if ( strpos( $ua, 'opera' ) !== false && strpos( $ua, 'mobi' ) !== false ) {
820
			return true;
821
		} elseif ( strpos( $ua, 'opera' ) !== false && strpos( $ua, 'nintendo dsi' ) !== false ) {
822
			return true;
823
		} else {
824
			return false;
825
		}
826
	}
827
828
829
	/*
830
	 * Detects if the current browser is Opera Mini
831
	 *
832
	 * Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
833
	 * Opera/9.80 (Android;Opera Mini/6.0.24212/24.746 U;en) Presto/2.5.25 Version/10.5454
834
	 * Opera/9.80 (iPhone; Opera Mini/5.0.019802/18.738; U; en) Presto/2.4.15
835
	 * Opera/9.80 (J2ME/iPhone;Opera Mini/5.0.019802/886; U; ja) Presto/2.4.15
836
	 * Opera/9.80 (J2ME/iPhone;Opera Mini/5.0.019802/886; U; ja) Presto/2.4.15
837
	 * Opera/9.80 (Series 60; Opera Mini/5.1.22783/23.334; U; en) Presto/2.5.25 Version/10.54
838
	 * Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/22.387; U; en) Presto/2.5.25 Version/10.54
839
	 *
840
	 */
841
	static function is_opera_mini() {
842
843
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
844
			return false;
845
		}
846
847
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
848
849 View Code Duplication
		if ( strpos( $ua, 'opera' ) !== false && strpos( $ua, 'mini' ) !== false ) {
850
			return true;
851
		} else {
852
			return false;
853
		}
854
	}
855
856
	/*
857
	 * Detects if the current browser is Opera Mini, but not on a smart device OS(Android, iOS, etc)
858
	 * Used to send users on dumb devices to m.wor
859
	 */
860
	static function is_opera_mini_dumb() {
861
862
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
863
			return false;
864
		}
865
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
866
867
		if ( self::is_opera_mini() ) {
868
			if ( strpos( $ua, 'android' ) !== false || strpos( $ua, 'iphone' ) !== false || strpos( $ua, 'ipod' ) !== false
869
			|| strpos( $ua, 'ipad' ) !== false || strpos( $ua, 'blackberry' ) !== false ) {
870
				return false;
871
			} else {
872
				return true;
873
			}
874
		} else {
875
			return false;
876
		}
877
	}
878
879
	/*
880
	 * Detects if the current browser is Opera Mobile or Mini.
881
	 * DEPRECATED: use is_opera_mobile or is_opera_mini
882
	 *
883
	 * Opera Mini 5 Beta: Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.15650/756; U; en) Presto/2.2.0
884
	 * Opera Mini 8: Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
885
	 */
886
	static function is_OperaMobile() {
887
		_deprecated_function( __FUNCTION__, 'always', 'is_opera_mini() or is_opera_mobile()' );
888
889
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
890
			return false;
891
		}
892
893
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
894
895
		if ( strpos( $ua, 'opera' ) !== false ) {
896 View Code Duplication
			if ( ( strpos( $ua, 'mini' ) !== false ) || ( strpos( $ua, 'mobi' ) !== false ) ) {
897
				return true;
898
			} else {
899
				return false;
900
			}
901
		} else {
902
			return false;
903
		}
904
	}
905
906
	/*
907
	 * Detects if the current browser is a Windows Phone 7 device.
908
	 * ex: Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; LG; GW910)
909
	 */
910 View Code Duplication
	static function is_WindowsPhone7() {
911
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
912
			return false;
913
		}
914
915
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
916
917
		if ( false === strpos( $ua, 'windows phone os 7' ) ) {
918
			return false;
919
		} else {
920
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
921
				return false;
922
			} else {
923
				return true;
924
			}
925
		}
926
	}
927
928
	/*
929
	 * Detects if the current browser is a Windows Phone 8 device.
930
	 * ex: Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ARM; Touch; IEMobile/10.0; <Manufacturer>; <Device> [;<Operator>])
931
	 */
932
	static function is_windows_phone_8() {
933
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
934
			return false;
935
		}
936
937
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
938
		if ( strpos( $ua, 'windows phone 8' ) === false ) {
939
			return false;
940
		} else {
941
			return true;
942
		}
943
	}
944
945
946
	/*
947
	 * Detects if the current browser is on a Palm device running the new WebOS. This EXCLUDES TouchPad.
948
	 *
949
	 * ex1: Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.1
950
	 * ex2: Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pixi/1.1
951
	 *
952
	 */
953 View Code Duplication
	static function is_PalmWebOS() {
954
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
955
			return false;
956
		}
957
958
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
959
960
		if ( false === strpos( $ua, 'webos' ) ) {
961
			return false;
962
		} else {
963
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
964
				return false;
965
			} else {
966
				return true;
967
			}
968
		}
969
	}
970
971
	/*
972
	 * Detects if the current browser is the HP TouchPad default browser. This excludes phones wt WebOS.
973
	 *
974
	 * TouchPad Emulator: Mozilla/5.0 (hp-desktop; Linux; hpwOS/2.0; U; it-IT) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 Desktop/1.0
975
	 * TouchPad: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0
976
	 *
977
	 */
978
	static function is_TouchPad() {
979
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
980
			return false;
981
		}
982
983
		$http_user_agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
984
		if ( false !== strpos( $http_user_agent, 'hp-tablet' ) || false !== strpos( $http_user_agent, 'hpwos' ) || false !== strpos( $http_user_agent, 'touchpad' ) ) {
985
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
986
				return false;
987
			} else {
988
				return true;
989
			}
990
		} else {
991
			return false;
992
		}
993
	}
994
995
996
	/*
997
	 * Detects if the current browser is the Series 60 Open Source Browser.
998
	 *
999
	 * OSS Browser 3.2 on E75: Mozilla/5.0 (SymbianOS/9.3; U; Series60/3.2 NokiaE75-1/110.48.125 Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413
1000
	 *
1001
	 * 7.0 Browser (Nokia 5800 XpressMusic (v21.0.025)) : Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Nokia5800d-1/21.0.025; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413
1002
	 *
1003
	 * Browser 7.1 (Nokia N97 (v12.0.024)) : Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/12.0.024; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.12344
1004
	 *
1005
	 */
1006
	static function is_S60_OSSBrowser() {
1007
1008
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1009
			return false;
1010
		}
1011
1012
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1013
		if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1014
			return false;
1015
		}
1016
1017
		$pos_webkit = strpos( $agent, 'webkit' );
1018
		if ( $pos_webkit !== false ) {
1019
			// First, test for WebKit, then make sure it's either Symbian or S60.
1020
			if ( strpos( $agent, 'symbian' ) !== false || strpos( $agent, 'series60' ) !== false ) {
1021
					return true;
1022
			} else {
1023
				return false;
1024
			}
1025 View Code Duplication
		} elseif ( strpos( $agent, 'symbianos' ) !== false && strpos( $agent, 'series60' ) !== false ) {
1026
			return true;
1027
		} elseif ( strpos( $agent, 'nokia' ) !== false && strpos( $agent, 'series60' ) !== false ) {
1028
			return true;
1029
		}
1030
1031
		return false;
1032
	}
1033
1034
	/*
1035
	 *
1036
	 * Detects if the device platform is the Symbian Series 60.
1037
	 *
1038
	 */
1039
	static function is_symbian_platform() {
1040
1041
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1042
			return false;
1043
		}
1044
1045
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1046
1047
		$pos_webkit = strpos( $agent, 'webkit' );
1048
		if ( $pos_webkit !== false ) {
1049
			// First, test for WebKit, then make sure it's either Symbian or S60.
1050
			if ( strpos( $agent, 'symbian' ) !== false || strpos( $agent, 'series60' ) !== false ) {
1051
					return true;
1052
			} else {
1053
				return false;
1054
			}
1055 View Code Duplication
		} elseif ( strpos( $agent, 'symbianos' ) !== false && strpos( $agent, 'series60' ) !== false ) {
1056
			return true;
1057
		} elseif ( strpos( $agent, 'nokia' ) !== false && strpos( $agent, 'series60' ) !== false ) {
1058
			return true;
1059
		} elseif ( strpos( $agent, 'opera mini' ) !== false ) {
1060
			if ( strpos( $agent, 'symbianos' ) !== false || strpos( $agent, 'symbos' ) !== false || strpos( $agent, 'series 60' ) !== false ) {
1061
				return true;
1062
			}
1063
		}
1064
1065
		return false;
1066
	}
1067
1068
	/*
1069
	 *
1070
	 * Detects if the device platform is the Symbian Series 40.
1071
	 * Nokia Browser for Series 40 is a proxy based browser, previously known as Ovi Browser.
1072
	 * This browser will report 'NokiaBrowser' in the header, however some older version will also report 'OviBrowser'.
1073
	 *
1074
	 */
1075 View Code Duplication
	static function is_symbian_s40_platform() {
1076
1077
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1078
			return false;
1079
		}
1080
1081
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1082
1083
		if ( strpos( $agent, 'series40' ) !== false ) {
1084
			if ( strpos( $agent, 'nokia' ) !== false || strpos( $agent, 'ovibrowser' ) !== false || strpos( $agent, 'nokiabrowser' ) !== false ) {
1085
				return true;
1086
			}
1087
		}
1088
1089
		return false;
1090
	}
1091
1092 View Code Duplication
	static function is_J2ME_platform() {
1093
1094
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1095
			return false;
1096
		}
1097
1098
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1099
1100
		if ( strpos( $agent, 'j2me/midp' ) !== false ) {
1101
			return true;
1102
		} elseif ( strpos( $agent, 'midp' ) !== false && strpos( $agent, 'cldc' ) ) {
1103
			return true;
1104
		}
1105
1106
		return false;
1107
	}
1108
1109
1110
	/*
1111
	 * Detects if the current UA is on one of the Maemo-based Nokia Internet Tablets.
1112
	 */
1113
	static function is_MaemoTablet() {
1114
1115
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1116
			return false;
1117
		}
1118
1119
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1120
1121
		$pos_maemo = strpos( $agent, 'maemo' );
1122
		if ( $pos_maemo === false ) {
1123
			return false;
1124
		}
1125
1126
		// Must be Linux + Tablet, or else it could be something else.
1127 View Code Duplication
		if ( strpos( $agent, 'tablet' ) !== false && strpos( $agent, 'linux' ) !== false ) {
1128
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1129
				return false;
1130
			} else {
1131
				return true;
1132
			}
1133
		} else {
1134
			return false;
1135
		}
1136
	}
1137
1138
	/*
1139
	 * Detects if the current UA is a MeeGo device (Nokia Smartphone).
1140
	 */
1141 View Code Duplication
	static function is_MeeGo() {
1142
1143
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1144
			return false;
1145
		}
1146
1147
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1148
1149
		if ( false === strpos( $ua, 'meego' ) ) {
1150
			return false;
1151
		} else {
1152
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1153
				return false;
1154
			} else {
1155
				return true;
1156
			}
1157
		}
1158
	}
1159
1160
1161
	/*
1162
	 is_webkit() can be used to check the User Agent for an webkit generic browser
1163
	 */
1164 View Code Duplication
	static function is_webkit() {
1165
1166
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1167
			return false;
1168
		}
1169
1170
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1171
1172
		$pos_webkit = strpos( $agent, 'webkit' );
1173
1174
		if ( $pos_webkit !== false ) {
1175
			return true;
1176
		} else {
1177
			return false;
1178
		}
1179
	}
1180
1181
	/**
1182
	 * Detects if the current browser is the Native Android browser.
1183
	 *
1184
	 * @return boolean true if the browser is Android otherwise false
1185
	 */
1186 View Code Duplication
	static function is_android() {
1187
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1188
			return false;
1189
		}
1190
1191
		$agent       = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1192
		$pos_android = strpos( $agent, 'android' );
1193
		if ( $pos_android !== false ) {
1194
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1195
				return false;
1196
			} else {
1197
				return true;
1198
			}
1199
		} else {
1200
			return false;
1201
		}
1202
	}
1203
1204
1205
	/**
1206
	 * Detects if the current browser is the Native Android Tablet browser.
1207
	 *  Assumes 'Android' should be in the user agent, but not 'mobile'
1208
	 *
1209
	 * @return boolean true if the browser is Android and not 'mobile' otherwise false
1210
	 */
1211
	static function is_android_tablet() {
1212
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1213
			return false;
1214
		}
1215
1216
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1217
1218
		$pos_android      = strpos( $agent, 'android' );
1219
		$pos_mobile       = strpos( $agent, 'mobile' );
1220
		$post_android_app = strpos( $agent, 'wp-android' );
1221
1222
		if ( false !== $pos_android && false === $pos_mobile && false === $post_android_app ) {
1223
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1224
				return false;
1225
			} else {
1226
				return true;
1227
			}
1228
		} else {
1229
			return false;
1230
		}
1231
	}
1232
1233
	/**
1234
	 * Detects if the current browser is the Kindle Fire Native browser.
1235
	 *
1236
	 * Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true
1237
	 * Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=false
1238
	 *
1239
	 * @return boolean true if the browser is Kindle Fire Native browser otherwise false
1240
	 */
1241
	static function is_kindle_fire() {
1242
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1243
			return false;
1244
		}
1245
1246
		$agent        = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1247
		$pos_silk     = strpos( $agent, 'silk/' );
1248
		$pos_silk_acc = strpos( $agent, 'silk-accelerated=' );
1249
		if ( $pos_silk !== false && $pos_silk_acc !== false ) {
1250
			return true;
1251
		} else {
1252
			return false;
1253
		}
1254
	}
1255
1256
1257
	/**
1258
	 * Detects if the current browser is the Kindle Touch Native browser
1259
	 *
1260
	 * Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+
1261
	 *
1262
	 * @return boolean true if the browser is Kindle monochrome Native browser otherwise false
1263
	 */
1264 View Code Duplication
	static function is_kindle_touch() {
1265
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1266
			return false;
1267
		}
1268
		$agent            = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1269
		$pos_kindle_touch = strpos( $agent, 'kindle/3.0+' );
1270
		if ( false !== $pos_kindle_touch && false === self::is_kindle_fire() ) {
1271
			return true;
1272
		} else {
1273
			return false;
1274
		}
1275
	}
1276
1277
1278
	// Detect if user agent is the WordPress.com Windows 8 app (used ONLY on the custom oauth stylesheet)
1279 View Code Duplication
	static function is_windows8_auth() {
1280
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1281
			return false;
1282
		}
1283
1284
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1285
		$pos   = strpos( $agent, 'msauthhost' );
1286
		if ( false !== $pos ) {
1287
			return true;
1288
		} else {
1289
			return false;
1290
		}
1291
	}
1292
1293
	// Detect if user agent is the WordPress.com Windows 8 app.
1294 View Code Duplication
	static function is_wordpress_for_win8() {
1295
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1296
			return false;
1297
		}
1298
1299
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1300
		$pos   = strpos( $agent, 'wp-windows8' );
1301
		if ( false !== $pos ) {
1302
			return true;
1303
		} else {
1304
			return false;
1305
		}
1306
	}
1307
1308
1309
	// Detect if user agent is the WordPress.com Desktop app.
1310
	static function is_wordpress_desktop_app() {
1311
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1312
			return false;
1313
		}
1314
1315
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1316
		$pos   = strpos( $agent, 'WordPressDesktop' );
1317
		if ( false !== $pos ) {
1318
			return true;
1319
		} else {
1320
			return false;
1321
		}
1322
	}
1323
1324
1325
	/*
1326
	 * is_blackberry_tablet() can be used to check the User Agent for a RIM blackberry tablet
1327
	 * The user agent of the BlackBerry® Tablet OS follows a format similar to the following:
1328
	 * Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+
1329
	 *
1330
	 */
1331
	static function is_blackberry_tablet() {
1332
1333
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1334
			return false;
1335
		}
1336
1337
		$agent          = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1338
		$pos_playbook   = stripos( $agent, 'PlayBook' );
1339
		$pos_rim_tablet = stripos( $agent, 'RIM Tablet' );
1340
1341
		if ( ( false === $pos_playbook ) || ( false === $pos_rim_tablet ) ) {
1342
			return false;
1343
		} else {
1344
			return true;
1345
		}
1346
	}
1347
1348
	/*
1349
	 is_blackbeberry() can be used to check the User Agent for a blackberry device
1350
	 Note that opera mini on BB matches this rule.
1351
	 */
1352 View Code Duplication
	static function is_blackbeberry() {
1353
1354
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1355
			return false;
1356
		}
1357
1358
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1359
1360
		$pos_blackberry = strpos( $agent, 'blackberry' );
1361
		if ( $pos_blackberry !== false ) {
1362
			if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() ) {
1363
				return false;
1364
			} else {
1365
				return true;
1366
			}
1367
		} else {
1368
			return false;
1369
		}
1370
	}
1371
1372
	/*
1373
	 is_blackberry_10() can be used to check the User Agent for a BlackBerry 10 device.
1374
	*/
1375
	static function is_blackberry_10() {
1376
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1377
		return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
1378
	}
1379
1380
	/**
1381
	 * Retrieve the blackberry OS version.
1382
	 *
1383
	 * Return strings are from the following list:
1384
	 * - blackberry-10
1385
	 * - blackberry-7
1386
	 * - blackberry-6
1387
	 * - blackberry-torch //only the first edition. The 2nd edition has the OS7 onboard and doesn't need any special rule.
1388
	 * - blackberry-5
1389
	 * - blackberry-4.7
1390
	 * - blackberry-4.6
1391
	 * - blackberry-4.5
1392
	 *
1393
	 * @return string Version of the BB OS.
1394
	 * If version is not found, get_blackbeberry_OS_version will return boolean false.
1395
	 */
1396
	static function get_blackbeberry_OS_version() {
1397
1398
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1399
			return false;
1400
		}
1401
1402
		if ( self::is_blackberry_10() ) {
1403
			return 'blackberry-10';
1404
		}
1405
1406
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1407
1408
		$pos_blackberry = stripos( $agent, 'blackberry' );
1409
		if ( false === $pos_blackberry ) {
1410
			// not a blackberry device
1411
			return false;
1412
		}
1413
1414
		// blackberry devices OS 6.0 or higher
1415
		// Mozilla/5.0 (BlackBerry; U; BlackBerry 9670; en) AppleWebKit/534.3+ (KHTML, like Gecko) Version/6.0.0.286 Mobile Safari/534.3+
1416
		// Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+
1417
		// Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0 Mobile Safari/534.11+
1418
		$pos_webkit = stripos( $agent, 'webkit' );
1419
		if ( false !== $pos_webkit ) {
1420
			// detected blackberry webkit browser
1421
			$pos_torch = stripos( $agent, 'BlackBerry 9800' );
1422
			if ( false !== $pos_torch ) {
1423
				return 'blackberry-torch'; // match the torch first edition. the 2nd edition should use the OS7 and doesn't need any special rule
1424
			} else {
1425
				// detecting the BB OS version for devices running OS 6.0 or higher
1426
				if ( preg_match( '#Version\/([\d\.]+)#i', $agent, $matches ) ) {
1427
					$version     = $matches[1];
1428
					$version_num = explode( '.', $version );
1429
					if ( false === is_array( $version_num ) || count( $version_num ) <= 1 ) {
1430
						return 'blackberry-6'; // not a BB device that match our rule.
1431
					} else {
1432
						return 'blackberry-' . $version_num[0];
1433
					}
1434
				} else {
1435
					// if doesn't match returns the minimun version with a webkit browser. we should never fall here.
1436
					return 'blackberry-6'; // not a BB device that match our rule.
1437
				}
1438
			}
1439
		}
1440
1441
		// blackberry devices <= 5.XX
1442
		// BlackBerry9000/5.0.0.93 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/179
1443
		if ( preg_match( '#BlackBerry\w+\/([\d\.]+)#i', $agent, $matches ) ) {
1444
			$version = $matches[1];
1445
		} else {
1446
			return false; // not a BB device that match our rule.
1447
		}
1448
1449
		$version_num = explode( '.', $version );
1450
1451 View Code Duplication
		if ( is_array( $version_num ) === false || count( $version_num ) <= 1 ) {
1452
			return false;
1453
		}
1454
		if ( $version_num[0] == 5 ) {
1455
			return 'blackberry-5';
1456
		} elseif ( $version_num[0] == 4 && $version_num[1] == 7 ) {
1457
			return 'blackberry-4.7';
1458
		} elseif ( $version_num[0] == 4 && $version_num[1] == 6 ) {
1459
			return 'blackberry-4.6';
1460
		} elseif ( $version_num[0] == 4 && $version_num[1] == 5 ) {
1461
			return 'blackberry-4.5';
1462
		} else {
1463
			return false;
1464
		}
1465
1466
	}
1467
1468
	/**
1469
	 * Retrieve the blackberry browser version.
1470
	 *
1471
	 * Return string are from the following list:
1472
	 * - blackberry-10
1473
	 * - blackberry-webkit
1474
	 * - blackberry-5
1475
	 * - blackberry-4.7
1476
	 * - blackberry-4.6
1477
	 *
1478
	 * @return string Type of the BB browser.
1479
	 * If browser's version is not found, detect_blackbeberry_browser_version will return boolean false.
1480
	 */
1481
	static function detect_blackberry_browser_version() {
1482
1483
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1484
			return false;
1485
		}
1486
1487
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1488
1489
		if ( self::is_blackberry_10() ) {
1490
			return 'blackberry-10';
1491
		}
1492
1493
		$pos_blackberry = strpos( $agent, 'blackberry' );
1494
		if ( false === $pos_blackberry ) {
1495
			// not a blackberry device
1496
			return false;
1497
		}
1498
1499
		$pos_webkit = strpos( $agent, 'webkit' );
1500
1501
		if ( ! ( false === $pos_webkit ) ) {
1502
			return 'blackberry-webkit';
1503
		} else {
1504
			if ( preg_match( '#BlackBerry\w+\/([\d\.]+)#i', $agent, $matches ) ) {
1505
				$version = $matches[1];
1506
			} else {
1507
				return false; // not a BB device that match our rule.
1508
			}
1509
1510
			$version_num = explode( '.', $version );
1511
1512 View Code Duplication
			if ( false === is_array( $version_num ) || count( $version_num ) <= 1 ) {
1513
				return false;
1514
			}
1515
1516
			if ( $version_num[0] == 5 ) {
1517
				return 'blackberry-5';
1518
			} elseif ( $version_num[0] == 4 && $version_num[1] == 7 ) {
1519
				return 'blackberry-4.7';
1520
			} elseif ( $version_num[0] == 4 && $version_num[1] == 6 ) {
1521
				return 'blackberry-4.6';
1522
			} else {
1523
				// A very old BB device is found or this is a BB device that doesn't match our rules.
1524
				return false;
1525
			}
1526
		}
1527
1528
	}
1529
1530
	// Checks if a visitor is coming from one of the WordPress mobile apps
1531
	static function is_mobile_app() {
1532
1533
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1534
			return false;
1535
		}
1536
1537
		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1538
1539
		if ( isset( $_SERVER['X_USER_AGENT'] ) && preg_match( '|wp-webos|', $_SERVER['X_USER_AGENT'] ) ) {
1540
			return true; // wp4webos 1.1 or higher
1541
		}
1542
1543
		$app_agents = array( 'wp-android', 'wp-blackberry', 'wp-iphone', 'wp-nokia', 'wp-webos', 'wp-windowsphone' );
1544
		// the mobile reader on iOS has an incorrect UA when loading the reader
1545
		// currently it is the default one provided by the iOS framework which
1546
		// causes problems with 2-step-auth
1547
		// User-Agent	WordPress/3.1.4 CFNetwork/609 Darwin/13.0.0
1548
		$app_agents[] = 'wordpress/3.1';
1549
1550
		foreach ( $app_agents as $app_agent ) {
1551
			if ( false !== strpos( $agent, $app_agent ) ) {
1552
				return true;
1553
			}
1554
		}
1555
		return false;
1556
	}
1557
1558
	/*
1559
	 * Detects if the current browser is Nintendo 3DS handheld.
1560
	 *
1561
	 * example: Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7498.US
1562
	 * can differ in language, version and region
1563
	 */
1564
	static function is_Nintendo_3DS() {
1565
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1566
			return false;
1567
		}
1568
1569
		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1570
		if ( strpos( $ua, 'nintendo 3ds' ) !== false ) {
1571
			return true;
1572
		}
1573
		return false;
1574
	}
1575
1576
	/**
1577
	 * Was the current request made by a known bot?
1578
	 *
1579
	 * @return boolean
1580
	 */
1581
	static function is_bot() {
1582
		static $is_bot = null;
1583
1584
		if ( is_null( $is_bot ) ) {
1585
			$is_bot = self::is_bot_user_agent( $_SERVER['HTTP_USER_AGENT'] );
1586
		}
1587
1588
		return $is_bot;
1589
	}
1590
1591
	/**
1592
	 * Is the given user-agent a known bot?
1593
	 * If you want an is_bot check for the current request's UA, use is_bot() instead of passing a user-agent to this method.
1594
	 *
1595
	 * @param $ua (string) A user-agent string
1596
	 * @return boolean
1597
	 */
1598
	static function is_bot_user_agent( $ua = null ) {
1599
1600
		if ( empty( $ua ) ) {
1601
			return false;
1602
		}
1603
1604
		$bot_agents = array(
1605
			'alexa',
1606
			'altavista',
1607
			'ask jeeves',
1608
			'attentio',
1609
			'baiduspider',
1610
			'bingbot',
1611
			'chtml generic',
1612
			'crawler',
1613
			'fastmobilecrawl',
1614
			'feedfetcher-google',
1615
			'firefly',
1616
			'froogle',
1617
			'gigabot',
1618
			'googlebot',
1619
			'googlebot-mobile',
1620
			'heritrix',
1621
			'httrack',
1622
			'ia_archiver',
1623
			'irlbot',
1624
			'iescholar',
1625
			'infoseek',
1626
			'jumpbot',
1627
			'linkcheck',
1628
			'lycos',
1629
			'mediapartners',
1630
			'mediobot',
1631
			'motionbot',
1632
			'msnbot',
1633
			'mshots',
1634
			'openbot',
1635
			'pss-webkit-request',
1636
			'pythumbnail',
1637
			'scooter',
1638
			'slurp',
1639
			'snapbot',
1640
			'spider',
1641
			'taptubot',
1642
			'technoratisnoop',
1643
			'teoma',
1644
			'twiceler',
1645
			'yahooseeker',
1646
			'yahooysmcm',
1647
			'yammybot',
1648
			'ahrefsbot',
1649
			'pingdom.com_bot',
1650
			'kraken',
1651
			'yandexbot',
1652
			'twitterbot',
1653
			'tweetmemebot',
1654
			'openhosebot',
1655
			'queryseekerspider',
1656
			'linkdexbot',
1657
			'grokkit-crawler',
1658
			'livelapbot',
1659
			'germcrawler',
1660
			'domaintunocrawler',
1661
			'grapeshotcrawler',
1662
			'cloudflare-alwaysonline',
1663
		);
1664
1665
		foreach ( $bot_agents as $bot_agent ) {
1666
			if ( false !== stripos( $ua, $bot_agent ) ) {
1667
				return true;
1668
			}
1669
		}
1670
1671
		return false;
1672
	}
1673
}
1674