/** * @param string $userAgent * * @return bool */ public function canHandle($userAgent) { if (Utils::isDesktopBrowser($userAgent)) { return false; } return Utils::checkIfStartsWith($userAgent, 'UCWEB') && Utils::checkIfContains($userAgent, 'UCBrowser'); }
/** * @param string $userAgent * * @return bool */ public function canHandle($userAgent) { if (Utils::isDesktopBrowser($userAgent)) { return false; } return Utils::checkIfStartsWithAnyOf($userAgent, array('Mot-', 'MOT-', 'MOTO', 'moto')) || Utils::checkIfContains($userAgent, 'Motorola'); }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'Windows CE;')) { return 'generic_ms_mobile'; } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return bool */ public function canHandle($userAgent) { if (Utils::isMobileBrowser($userAgent)) { return false; } return Utils::checkIfContains($userAgent, 'Safari') && Utils::checkIfStartsWithAnyOf($userAgent, array('Mozilla/5.0 (Macintosh', 'Mozilla/5.0 (Windows')); }
/** * @param string $userAgent * * @return string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'Tablet')) { return 'generic_ubuntu_touch_os_tablet'; } else { return 'generic_ubuntu_touch_os'; } }
/** * @return bool */ protected function compute() { $ua = $this->request->getUserAgentNormalized(); $ua_original = $this->request->getUserAgent(); // ->contains() can take an array if (Utils::checkIfContainsAnyOf($ua, $this->thirdPartyBrowsers)) { return false; } // Lollipop implementation of webview adds a ; wv to the UA if ($this->device->device_os === 'Android' && false !== strpos($ua_original, '; wv) ')) { return true; } // Handling Chrome separately if ($this->device->device_os === 'Android' && Utils::checkIfContains($ua, 'Chrome') && !Utils::checkIfContains($ua, 'Version')) { return false; } // iOS webview logic is pretty simple if ($this->device->device_os === 'iOS' && !Utils::checkIfContains($ua, 'Safari')) { return true; } // So is Mac OS X's webview logic if ($this->device->advertised_device_os === 'Mac OS X' && !Utils::checkIfContains($ua, 'Safari')) { return true; } if ($this->device->device_os === 'Android') { if ($this->request->originalHeaderExists('HTTP_X_REQUESTED_WITH')) { $requested_with = $this->request->getOriginalHeader('HTTP_X_REQUESTED_WITH'); // The whitelist is an array with X-Requested-With header field values sent by known apps if (in_array($requested_with, $this->whitelist)) { return true; } elseif (in_array($requested_with, $this->blacklist)) { // The blacklist is an array with X-Requested-With header field values sent by known stock browsers return false; } } // Now we handle Android UAs that haven't been eliminated above (No X-Requested-With header and not a third party browser) // Make sure to use the original UA and not the normalized one if (preg_match('#Mozilla/5.0 \\(Linux;( U;)? Android.*AppleWebKit.*\\(KHTML, like Gecko\\)#', $ua_original)) { // Among those UAs in here, we are interested in UAs from apps that contain a webview style UA and add stuff to the beginning or the end of the string(FB, Flipboard etc.) // Android >= 4.4 if ((strpos($ua, 'Android 4.4') !== false || strpos($ua, 'Android 5.') !== false) && !preg_match('#^Mozilla/5.0 \\(Linux; Android [45]\\.[\\d\\.]+; .+ Build/.+\\) AppleWebKit/[\\d\\.+]+ \\(KHTML, like Gecko\\) Version/[\\d\\.]+ Chrome/([\\d]+)\\.[\\d\\.]+? (?:Mobile )?Safari/[\\d\\.+]+$#', $ua_original)) { if (preg_match('#Chrome/(\\d+)\\.#', $ua, $matches)) { if ($matches[1] < 30) { return false; } } return true; } // Android < 4.4 if (preg_match('#Android [1234]\\.[123]#', $ua) && !preg_match('#^Mozilla/5.0 \\(Linux;( U;)? Android [1234]\\.[\\d\\.]+(-update1)?; [a-zA-Z]+-[a-zA-Z]+; .+ Build/.+\\) AppleWebKit/[\\d\\.+]+ \\(KHTML, like Gecko\\) Version/[\\d\\.]+ (Mobile )?Safari/[\\d\\.+]+$#', $ua_original)) { return true; } } return false; } // Return is_app_webview = false for everything else return false; }
/** * @return bool */ protected function compute() { $ua = $this->request->getUserAgent(); // Control cap, 'controlcap_is_robot' is checked before this function is called if ($this->request->originalHeaderExists('HTTP_ACCEPT_ENCODING') && Utils::checkIfContains($ua, 'Trident/') && !Utils::checkIfContains($this->request->getOriginalHeader('HTTP_ACCEPT_ENCODING'), 'deflate')) { return true; } // Check against standard bot list return Utils::isRobot($this->request->getOriginalHeader('HTTP_USER_AGENT')); }
/** * @param string $userAgent * * @return string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'MSIE 10.0') && Utils::checkIfContains($userAgent, 'Xbox One')) { return 'microsoft_xboxone_ver1'; } if (Utils::checkIfContains($userAgent, 'MSIE 10.0')) { return 'microsoft_xbox360_ver1_subie10'; } return 'microsoft_xbox360_ver1'; }
/** * @param string $userAgent * * @return string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'Opera Mobi')) { return 'generic_opera_mobi_maemo'; } if (Utils::checkIfContains($userAgent, 'Firefox')) { return 'nokia_generic_maemo_with_firefox'; } return 'nokia_generic_maemo'; }
/** * @param string $userAgent * * @return string */ public function normalize($userAgent) { $ucbVersion = UcwebU3Handler::getUcBrowserVersion($userAgent); if ($ucbVersion === null) { return $userAgent; } //Android U2K Mobile + Tablet if (Utils::checkIfContains($userAgent, 'Adr ')) { $model = UcwebU3Handler::getUcAndroidModel($userAgent, false); $version = UcwebU3Handler::getUcAndroidVersion($userAgent, false); if ($model !== null && $version !== null) { $prefix = $version . ' U2Android ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'iPh OS')) { //iPhone U2K if (preg_match('/iPh OS (\\d)_?(\\d)?[ _\\d]?.+; iPh(\\d), ?(\\d)\\) U2/', $userAgent, $matches)) { $version = $matches[1] . '.' . $matches[2]; $model = $matches[3] . '.' . $matches[4]; $prefix = $version . ' U2iPhone ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'wds')) { //WP7&8 U2K //Add spaces and normalize $userAgent = preg_replace('|;(?! )|', '; ', $userAgent); if (preg_match('/^UCWEB.+; wds (\\d+)\\.([\\d]+);.+; ([ A-Za-z0-9_-]+); ([ A-Za-z0-9_-]+)\\) U2/', $userAgent, $matches)) { $version = $matches[1] . '.' . $matches[2]; $model = $matches[3] . '.' . $matches[4]; //Standard normalization stuff from WP matcher $model = str_replace('_blocked', '', $model); $model = preg_replace('/(NOKIA.RM-.+?)_.*/', '$1', $model, 1); $prefix = $version . ' U2WindowsPhone ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'Symbian')) { //Symbian U2K if (preg_match('/^UCWEB.+; S60 V(\\d); .+; (.+)\\) U2/', $userAgent, $matches)) { $version = 'S60 V' . $matches[1]; $model = $matches[2]; $prefix = $version . ' U2Symbian ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'Java')) { //Java U2K - check results for regex if (preg_match('/^UCWEB[^\\(]+\\(Java; .+; (.+)\\) U2/', $userAgent, $matches)) { $version = 'Java'; $model = $matches[1]; $prefix = $version . ' U2JavaApp ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } return $userAgent; }
/** * Attempt to find a conclusive match for the given $userAgent * * @param string $userAgent * * @return string Matching WURFL deviceID */ public function applyConclusiveMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'GoogleImageProxy')) { return 'google_image_proxy'; } if (Utils::checkIfStartsWith($userAgent, 'Mozilla')) { $tolerance = Utils::firstCloseParen($userAgent); } else { $tolerance = Utils::firstSlash($userAgent); } return $this->getDeviceIDFromRIS($userAgent, $tolerance); }
public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'Thunderbird')) { return 'mozilla_thunderbird'; } elseif (Utils::checkIfContains($userAgent, 'Microsoft Outlook')) { return 'ms_outlook'; } elseif (Utils::checkIfContains($userAgent, 'MSOffice')) { return 'ms_office'; } elseif (Utils::checkIfContains($userAgent, 'DesktopApp ')) { return 'generic_desktop_application'; } return WurflConstants::GENERIC_WEB_BROWSER; }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContains($userAgent, 'Series60')) { return 'nokia_generic_series60'; } if (Utils::checkIfContains($userAgent, 'Series80')) { return 'nokia_generic_series80'; } if (Utils::checkIfContains($userAgent, 'MeeGo')) { return 'nokia_generic_meego'; } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return string */ public function normalize($userAgent) { $isOperaMobile = Utils::checkIfContains($userAgent, 'Opera Mobi'); $isOperaTablet = Utils::checkIfContains($userAgent, 'Opera Tablet'); if ($isOperaMobile || $isOperaTablet) { $operaVersion = OperaMobiOrTabletOnAndroidHandler::getOperaOnAndroidVersion($userAgent, false); $androidVersion = AndroidHandler::getAndroidVersion($userAgent, false); if ($operaVersion !== null && $androidVersion !== null) { $operaModel = $isOperaTablet ? 'Opera Tablet' : 'Opera Mobi'; $prefix = $operaModel . ' ' . $operaVersion . ' Android ' . $androidVersion . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } return $userAgent; }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContainsAll($userAgent, array('Windows NT 5', 'POLARIS'))) { return 'generic_lguplus_rexos_facebook_browser'; } if (Utils::checkIfContains($userAgent, 'Windows NT 5')) { return 'generic_lguplus_rexos_webviewer_browser'; } if (Utils::checkIfContainsAll($userAgent, array('Windows CE', 'POLARIS'))) { return 'generic_lguplus_winmo_facebook_browser'; } if (Utils::checkIfContainsAll($userAgent, array('Android', 'AppleWebKit'))) { return 'generic_lguplus_android_webkit_browser'; } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { $isOperaMobi = Utils::checkIfContains($userAgent, 'Opera Mobi'); $isOperaTablet = Utils::checkIfContains($userAgent, 'Opera Tablet'); if ($isOperaMobi || $isOperaTablet) { $androidVersion = AndroidHandler::getAndroidVersion($userAgent); $androidVersionString = str_replace('.', '_', $androidVersion); $type = $isOperaTablet ? 'tablet' : 'mobi'; $deviceID = 'generic_android_ver' . $androidVersionString . '_opera_' . $type; if (in_array($deviceID, self::$constantIDs)) { return $deviceID; } else { return $isOperaTablet ? 'generic_android_ver2_1_opera_tablet' : 'generic_android_ver2_0_opera_mobi'; } } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { $isFennec = Utils::checkIfContains($userAgent, 'Fennec'); $isFirefox = Utils::checkIfContains($userAgent, 'Firefox'); if ($isFennec || $isFirefox) { if ($isFennec || Utils::checkIfContains($userAgent, 'Mobile')) { return 'generic_android_ver2_0_fennec'; } if (Utils::checkIfContains($userAgent, 'Tablet')) { return 'generic_android_ver2_0_fennec_tablet'; } if (Utils::checkIfContains($userAgent, 'Desktop')) { return 'generic_android_ver2_0_fennec_desktop'; } } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return bool */ public function canHandle($userAgent) { if (Utils::isMobileBrowser($userAgent)) { return false; } if (Utils::checkIfStartsWith($userAgent, 'Mozilla') === false) { return false; } if (Utils::checkIfContainsAnyOf($userAgent, array('Opera', 'armv', 'MOTO', 'BREW'))) { return false; } // Edge 12 signature $hasEdgeMode = Utils::checkIfContains($userAgent, ' Edge/'); // IE 11 signature $hasTridentRv = Utils::checkIfContains($userAgent, 'Trident') && Utils::checkIfContains($userAgent, 'rv:'); // IE < 11 signature $hasMsie = Utils::checkIfContains($userAgent, 'MSIE'); return $hasMsie || $hasTridentRv || $hasEdgeMode; }
/** * @param string $userAgent * * @return null|string */ public function applyConclusiveMatch($userAgent) { if (Utils::checkIfContains($userAgent, ' Build/')) { return $this->getDeviceIDFromRIS($userAgent, Utils::indexOfOrLength($userAgent, ' Build/')); } $prefixes = array('Opera/9.80 (J2ME/MIDP; Opera Mini/5' => 'uabait_opera_mini_android_v50', 'Opera/9.80 (Android; Opera Mini/5.0' => 'uabait_opera_mini_android_v50', 'Opera/9.80 (Android; Opera Mini/5.1' => 'uabait_opera_mini_android_v51'); foreach ($prefixes as $prefix => $defaultID) { if (Utils::checkIfStartsWith($userAgent, $prefix)) { // If RIS returns a non-generic match, return it, else, return the default $tolerance = strlen($prefix); $deviceID = $this->getDeviceIDFromRIS($userAgent, $tolerance); if ($deviceID === WurflConstants::NO_MATCH) { return $defaultID; } return $deviceID; } } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return string */ public function normalize($userAgent) { $ucbVersion = UcwebU3Handler::getUcBrowserVersion($userAgent); if ($ucbVersion === null) { return $userAgent; } // Windows Phone goes before Android if (Utils::checkIfContains($userAgent, 'Windows Phone')) { // Apply Version+Model--- matching normalization $model = WindowsPhoneHandler::getWindowsPhoneModel($userAgent); $version = WindowsPhoneHandler::getWindowsPhoneVersion($userAgent); if ($model !== null && $version !== null) { $prefix = $version . ' U3WP ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'Android')) { // Android U3K Mobile + Tablet // Apply Version+Model--- matching normalization $model = AndroidHandler::getAndroidModel($userAgent, false); $version = AndroidHandler::getAndroidVersion($userAgent, false); if ($model !== null && $version !== null) { $prefix = $version . ' U3Android ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'iPhone;')) { //iPhone U3K if (preg_match('/iPhone OS (\\d+)(?:_(\\d+))?(?:_\\d+)* like/', $userAgent, $matches)) { $version = $matches[1] . '.' . $matches[2]; $prefix = $version . ' U3iPhone ' . $ucbVersion . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } elseif (Utils::checkIfContains($userAgent, 'iPad')) { //iPad U3K if (preg_match('/CPU OS (\\d)_?(\\d)?.+like Mac.+; iPad([0-9,]+)\\) AppleWebKit/', $userAgent, $matches)) { $version = $matches[1] . '.' . $matches[2]; $model = $matches[3]; $prefix = $version . ' U3iPad ' . $ucbVersion . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } } return $userAgent; }
/** * @param string $userAgent * * @return string */ public function normalize($userAgent) { if (Utils::checkIfContainsAnyOf($userAgent, array('WPDesktop', 'ZuneWP7')) || Utils::checkIfContainsAll($userAgent, array('Mozilla/5.0 (Windows NT ', ' ARM;', ' Edge/'))) { $model = WindowsPhoneHandler::getWindowsPhoneDesktopModel($userAgent); $version = WindowsPhoneHandler::getWindowsPhoneDesktopVersion($userAgent); } elseif (Utils::checkIfStartsWithAnyOf($userAgent, array('Windows Phone Ad Client', 'WindowsPhoneAdClient'))) { $model = WindowsPhoneHandler::getWindowsPhoneAdClientModel($userAgent); $version = WindowsPhoneHandler::getWindowsPhoneVersion($userAgent); } elseif (Utils::checkIfContains($userAgent, 'NativeHost')) { return $userAgent; } else { $model = WindowsPhoneHandler::getWindowsPhoneModel($userAgent); $version = WindowsPhoneHandler::getWindowsPhoneVersion($userAgent); } if ($model !== null && $version !== null) { // 'WP' is for Windows Phone $prefix = 'WP' . $version . ' ' . $model . WurflConstants::RIS_DELIMITER; return $prefix . $userAgent; } return $userAgent; }
public function applyRecoveryMatch($userAgent) { // BlackBerry 10 if (Utils::checkIfContains($userAgent, 'BB10')) { if (Utils::checkIfContains($userAgent, 'Mobile')) { return 'blackberry_generic_ver10'; } else { return 'blackberry_generic_ver10_tablet'; } } elseif (Utils::checkIfContains($userAgent, 'PlayBook')) { return 'rim_playbook_ver1'; } elseif (preg_match('#Black[Bb]erry[^/\\s]+/(\\d.\\d)#', $userAgent, $matches)) { $version = $matches[1]; foreach (self::$constantIDs as $vercode => $deviceID) { if (strpos($version, $vercode) !== false) { return $deviceID; } } } return WurflConstants::NO_MATCH; }
/** * @return bool */ protected function compute() { $userAgent = $this->request->getUserAgent(); if ($this->device->getCapability('device_os') === 'iOS' && !Utils::checkIfContains($userAgent, 'Safari')) { return true; } foreach ($this->patterns as $pattern) { if ($pattern[0] === '#') { // Regex if (preg_match($pattern, $userAgent)) { return true; } continue; } // Substring matches are not abstracted for performance $patternLength = strlen($pattern); $userAgentLength = strlen($userAgent); if ($pattern[0] === '^') { // Starts with if (strpos($userAgent, substr($pattern, 1)) === 0) { return true; } } elseif ($pattern[$patternLength - 1] === '$') { // Ends with --$patternLength; $pattern = substr($pattern, 0, $patternLength); if (strpos($userAgent, $pattern) === $userAgentLength - $patternLength) { return true; } } else { // Match anywhere if (strpos($userAgent, $pattern) !== false) { return true; } } } return false; }
public function applyRecoveryMatch($userAgent) { if (preg_match('/ (\\d+)_(\\d+)[ _]/', $userAgent, $matches)) { $majorVersion = (int) $matches[1]; } else { $majorVersion = -1; } // Core-media if (Utils::checkIfContains($userAgent, 'CoreMedia')) { return 'apple_iphone_coremedia_ver1'; } // Check iPods first since they also contain 'iPhone' if (Utils::checkIfContains($userAgent, 'iPod')) { $deviceID = 'apple_ipod_touch_ver' . $majorVersion; if (in_array($deviceID, self::$constantIDs)) { return $deviceID; } else { return 'apple_ipod_touch_ver1'; } // Now check for iPad } else { if (Utils::checkIfContains($userAgent, 'iPad')) { $deviceID = 'apple_ipad_ver1_sub' . $majorVersion; if ($majorVersion === 3) { return 'apple_ipad_ver1_subua32'; } else { if ($majorVersion === 4) { return 'apple_ipad_ver1_sub42'; } } if (in_array($deviceID, self::$constantIDs)) { return $deviceID; } else { return 'apple_ipad_ver1'; } // Check iPhone last } else { if (Utils::checkIfContains($userAgent, 'iPhone')) { $deviceID = 'apple_iphone_ver' . $majorVersion; if (in_array($deviceID, self::$constantIDs)) { return $deviceID; } else { return 'apple_iphone_ver1'; } } } } return WurflConstants::NO_MATCH; }
/** * @param string $userAgent * * @return string */ public function applyRecoveryMatch($userAgent) { $map = array('Kindle/1' => 'amazon_kindle_ver1', 'Kindle/2' => 'amazon_kindle2_ver1', 'Kindle/3' => 'amazon_kindle3_ver1', 'Kindle Fire' => 'amazon_kindle_fire_ver1', 'Silk' => 'amazon_kindle_fire_ver1'); foreach ($map as $keyword => $id) { if (Utils::checkIfContains($userAgent, $keyword)) { return $id; } } return 'generic_amazon_kindle'; }
private function applyRecoveryiPad($userAgent) { if (!Utils::checkIfContains($userAgent, 'iPad')) { return null; } if (preg_match('/CPU OS (\\d+)(?:_\\d+)?.+like Mac/', $userAgent, $matches)) { $significant_version = $matches[1]; $deviceID = 'apple_ipad_ver1_sub' . $significant_version . '_subuaucweb'; if (in_array($deviceID, self::$constantIDs)) { return $deviceID; } } return 'apple_ipad_ver1_subuaucweb'; }
/** * @param string $userAgent * * @return string */ public function applyRecoveryMatch($userAgent) { return Utils::checkIfContains($userAgent, 'hpwOS/3') ? 'hp_tablet_webos_generic' : 'hp_webos_generic'; }
/** * @param string $userAgent * * @return null|string */ public function applyRecoveryMatch($userAgent) { if (Utils::checkIfContainsAnyOf($userAgent, array('WPDesktop', 'ZuneWP7')) || Utils::checkIfContainsAll($userAgent, array('Mozilla/5.0 (Windows NT ', ' ARM;', ' Edge/'))) { if (Utils::checkIfContainsAll($userAgent, array('Mozilla/5.0 (Windows NT ', ' ARM;', ' Edge/'))) { return 'generic_ms_phone_os10_desktopmode'; } if (Utils::checkIfContains($userAgent, 'WPDesktop')) { return 'generic_ms_phone_os8_desktopmode'; } if (Utils::checkIfContains($userAgent, 'Trident/5.0')) { return 'generic_ms_phone_os7_5_desktopmode'; } return 'generic_ms_phone_os7_desktopmode'; } $version = self::getWindowsPhoneVersion($userAgent); if ($version === '10.0') { return 'generic_ms_phone_os10'; } if ($version === '8.1') { return 'generic_ms_phone_os8_1'; } if ($version === '8.0') { return 'generic_ms_phone_os8'; } if ($version === '7.8') { return 'generic_ms_phone_os7_8'; } if ($version === '7.5') { return 'generic_ms_phone_os7_5'; } if ($version === '7.0') { return 'generic_ms_phone_os7'; } if ($version === '6.5') { return 'generic_ms_winmo6_5'; } //These are probably UAs of the type "Windows Phone Ad Client (Xna)/5.1.0.0 BMID/E67970D969" if (Utils::checkIfStartsWithAnyOf($userAgent, array('Windows Phone Ad Client', 'WindowsPhoneAdClient'))) { return 'generic_ms_phone_os7'; } return WurflConstants::NO_MATCH; }
public function canHandle($userAgent) { return Utils::checkIfContains($userAgent, 'Firefox/') && Utils::checkIfContainsAnyOf($userAgent, array('Mobile', 'Tablet')); }
/** * @param string $userAgent * * @return bool */ public function canHandle($userAgent) { return Utils::checkIfStartsWith($userAgent, 'Mozilla/5.0 (Macintosh') && Utils::checkIfContains($userAgent, 'HTC'); }