Best Mockery code snippet using Type.match
Os.php
Source:Os.php  
...37    /* Darwin */38    private function detectDarwin($ua)39    {40        /* iOS */41        if (preg_match('/\(iOS;/u', $ua)) {42            $this->data->os->name = 'iOS';43            $this->data->device->type = Constants\DeviceType::MOBILE;44        }45        if (preg_match('/(iPhone|iPad|iPod)/u', $ua) && !preg_match('/like iPhone/u', $ua)) {46            $this->data->os->name = 'iOS';47            if (preg_match('/CPU like Mac OS X/u', $ua, $match)) {48                $this->data->os->version = new Version([ 'value' => '1.0' ]);49            }50            if (preg_match('/OS (.*) like Mac OS X/u', $ua, $match)) {51                $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);52            }53            if (preg_match('/iPhone OS ([0-9._]*);/u', $ua, $match)) {54                $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);55            }56            if (preg_match('/iPhone Simulator;/u', $ua)) {57                $this->data->device->type = Constants\DeviceType::EMULATOR;58            } else {59                if (preg_match('/(iPad|iPhone( 3GS| 3G| 4S| 4| 5)?|iPod( touch)?)/u', $ua, $match)) {60                    $device = Data\DeviceModels::identify('ios', $match[0]);61                    if ($device) {62                        $this->data->device = $device;63                    }64                }65                if (preg_match('/(iPad|iPhone|iPod)1?[0-9],[0-9][0-9]?/u', $ua, $match)) {66                    $device = Data\DeviceModels::identify('ios', $match[0]);67                    if ($device) {68                        $this->data->device = $device;69                    }70                }71            }72        } /* OS X */73        elseif (preg_match('/Mac OS X/u', $ua) || preg_match('/;os=Mac/u', $ua)) {74            $this->data->os->name = 'OS X';75            if (preg_match('/Mac OS X (10[0-9\._]*)/u', $ua, $match)) {76                $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]), 'details' => 2 ]);77            }78            if (preg_match('/;os=Mac (10[0-9[\.,]*)/u', $ua, $match)) {79                $this->data->os->version = new Version([ 'value' => str_replace(',', '.', $match[1]), 'details' => 2 ]);80            }81            $this->data->device->type = Constants\DeviceType::DESKTOP;82        }83        /* Darwin */84        if (preg_match('/Darwin(?:\/([0-9]+).[0-9]+)?/u', $ua, $match)) {85            if (preg_match('/\(X11;/u', $ua)) {86                /* Darwin */87                $this->data->os->name = 'Darwin';88                $this->data->device->type = Constants\DeviceType::DESKTOP;89            } elseif (preg_match('/\((?:x86_64|i386|Power%20Macintosh)\)/u', $ua)) {90                /* OS X */91                $this->data->os->name = 'OS X';92                $this->data->device->type = Constants\DeviceType::DESKTOP;93                if (isset($match[1])) {94                    $version = Data\Darwin::getVersion('osx', $match[1]);95                    if ($version) {96                        $this->data->os->version = new Version($version);97                    }98                    if (preg_match('/CFNetwork\/([0-9\.]+)/u', $ua, $match)) {99                        $version = Data\CFNetwork::getVersion('osx', $match[1]);100                        if ($version) {101                            $this->data->os->version = new Version($version);102                        }103                    }104                }105            } else {106                /* iOS */107                $this->data->os->name = 'iOS';108                $this->data->device->type = Constants\DeviceType::MOBILE;109                if (isset($match[1])) {110                    $version = Data\Darwin::getVersion('ios', $match[1]);111                    if ($version) {112                        $this->data->os->version = new Version($version);113                    }114                    if (preg_match('/CFNetwork\/([0-9\.]+)/u', $ua, $match)) {115                        $version = Data\CFNetwork::getVersion('ios', $match[1]);116                        if ($version) {117                            $this->data->os->version = new Version($version);118                        }119                    }120                }121            }122        }123        /* Mac OS */124        if (preg_match('/(; |\()Macintosh;/u', $ua) && !preg_match('/OS X/u', $ua)) {125            $this->data->os->name = 'Mac OS';126            $this->data->device->type = Constants\DeviceType::DESKTOP;127        }128    }129    /* Android */130    private function detectAndroid($ua)131    {132        /* Android */133        if (preg_match('/Andr[0o]id/ui', $ua)) {134            $falsepositive = false;135            /* Prevent the Mobile IE 11 Franken-UA from matching Android */136            if (preg_match('/IEMobile\/1/u', $ua)) {137                $falsepositive = true;138            }139            if (preg_match('/Windows Phone 10/u', $ua)) {140                $falsepositive = true;141            }142            /* Prevent Windows 10 IoT Core from matching Android */143            if (preg_match('/Windows IoT/u', $ua)) {144                $falsepositive = true;145            }146            /* Prevent from OSes that claim to be 'like' Android from matching */147            if (preg_match('/like Android/u', $ua)) {148                $falsepositive = true;149            }150            if (preg_match('/COS like Android/u', $ua)) {151                $falsepositive = false;152            }153            if (!$falsepositive) {154                $this->data->os->name = 'Android';155                $this->data->os->version = new Version();156                if (preg_match('/Andr[0o]id(?: )?(?:AllPhone_|CyanogenMod_|OUYA )?(?:\/)?v?([0-9.]+)/ui', str_replace('-update', ',', $ua), $match)) {157                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);158                }159                if (preg_match('/Android [0-9][0-9].[0-9][0-9].[0-9][0-9]\(([^)]+)\);/u', str_replace('-update', ',', $ua), $match)) {160                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);161                }162                if (preg_match('/Android Eclair/u', $ua)) {163                    $this->data->os->version = new Version([ 'value' => '2.0', 'details' => 3 ]);164                }165                if (preg_match('/Android KeyLimePie/u', $ua)) {166                    $this->data->os->version = new Version([ 'value' => '4.4', 'details' => 3 ]);167                }168                if (preg_match('/Android (?:L|4.4.99);/u', $ua)) {169                    $this->data->os->version = new Version([ 'value' => '5', 'details' => 3, 'alias' => 'L' ]);170                }171                if (preg_match('/Android (?:M|5.[01].99);/u', $ua)) {172                    $this->data->os->version = new Version([ 'value' => '6', 'details' => 3, 'alias' => 'M' ]);173                }174                if (preg_match('/Android (?:N|6.0.99);/u', $ua)) {175                    $this->data->os->version = new Version([ 'value' => '7', 'details' => 3, 'alias' => 'N' ]);176                }177                $this->data->device->type = Constants\DeviceType::MOBILE;178                if ($this->data->os->version->toFloat() >= 3) {179                    $this->data->device->type = Constants\DeviceType::TABLET;180                }181                if ($this->data->os->version->toFloat() >= 4 && preg_match('/Mobile/u', $ua)) {182                    $this->data->device->type = Constants\DeviceType::MOBILE;183                }184                $candidates = [];185                if (preg_match('/Build/ui', $ua)) {186                    /* Normal Android useragent strings */187                    if (preg_match('/; [a-z][a-zA-Z][-_][a-zA-Z][a-zA-Z] ([^;]*[^;\s])\s+(?:BUILD|Build|build)/u', $ua, $match)) {188                        $candidates[] = $match[1];189                    }190                    if (preg_match('/Android [A-Za-z]+; (?:[a-zA-Z][a-zA-Z](?:[-_][a-zA-Z][a-zA-Z])?) Build\/([^\/]*)\//u', $ua, $match)) {191                        $candidates[] = $match[1];192                    }193                    if (preg_match('/;\+? ?(?:\*\*)?([^;]*[^;\s]);?\s+(?:BUILD|Build|build)/u', $ua, $match)) {194                        $candidates[] = $match[1];195                    }196                } elseif (preg_match('/Release\//ui', $ua)) {197                    /* WAP style useragent strings */198                    if (preg_match('/^(?U)([^\/]+)(?U)(?:(?:_CMCC_TD|_CMCC|_TD|_TDLTE|_LTE)?\/[^\/]*)? Linux\/[0-9.+]+ Android\/[0-9.]+/u', $this->removeKnownPrefixes($ua), $match)) {199                        $candidates[] = $match[1];200                    } else if (preg_match('/^(?U)([^\/]+)(?U)(?:(?:_CMCC_TD|_CMCC|_TD|_TDLTE|_LTE)?\/[^\/]*)? Android(_OS)?\/[0-9.]+/u', $this->removeKnownPrefixes($ua), $match)) {201                        $candidates[] = $match[1];202                    } else if (preg_match('/^(?U)([^\/]+)(?U)(?:(?:_CMCC_TD|_CMCC|_TD|_TDLTE|_LTE)?\/[^\/]*)? Release\/[0-9.]+/u', $this->removeKnownPrefixes($ua), $match)) {203                        $candidates[] = $match[1];204                    }205                } elseif (preg_match('/Mozilla\//ui', $ua)) {206                    /* Old Android useragent strings */207                    if (preg_match('/Linux; (?:U; )?Android [^;]+; (?:[a-zA-Z][a-zA-Z](?:[-_][a-zA-Z][a-zA-Z])?; )?(?:[^;]+; ?)?([^)\/;]+)\)/u', $ua, $match)) {208                        $candidates[] = $match[1];209                    } elseif (preg_match('/\(([^;]+);U;Android\/[^;]+;[0-9]+\*[0-9]+;CTC\/2.0\)/u', $ua, $match)) {210                        $candidates[] = $match[1];211                    }212                } else {213                    /* Other applications */214                    if (preg_match('/[34]G Explorer\/[0-9.]+ \(Linux;Android [0-9.]+,([^\)]+)\)/u', $ua, $match)) {215                        $candidates[] = $match[1];216                    }217                    if (preg_match('/GetJarSDK\/.*android\/[0-9.]+ \([^;]+; [^;]+; ([^\)]+)\)$/u', $ua, $match)) {218                        $candidates[] = $match[1];219                    }220                }221                $candidates = array_unique($candidates);222                for ($c = 0; $c < count($candidates); $c++) {223                    if (preg_match('/^[a-zA-Z][a-zA-Z](?:[-_][a-zA-Z][a-zA-Z])?$/u', $candidates[$c])) {224                        unset($candidates[$c]);225                        continue;226                    }227                    if (preg_match('/^Android [0-9\.]+$/u', $candidates[$c])) {228                        unset($candidates[$c]);229                        continue;230                    }231                    $candidates[$c] = preg_replace('/^[a-zA-Z][a-zA-Z][-_][a-zA-Z][a-zA-Z]\s+/u', '', $candidates[$c]);232                    $candidates[$c] = preg_replace('/(.*) - [0-9\.]+ - (?:with Google Apps - )?API [0-9]+ - [0-9]+x[0-9]+/', '\\1', $candidates[$c]);233                    $candidates[$c] = preg_replace('/^sprd-/u', '', $candidates[$c]);234                }235                $candidates = array_unique($candidates);236                if (count($candidates)) {237                    $this->data->device->model = $candidates[0];238                    $this->data->device->identified |= Constants\Id::PATTERN;239                    for ($c = 0; $c < count($candidates); $c++) {240                        $device = Data\DeviceModels::identify('android', $candidates[$c]);241                        if ($device->identified) {242                            $device->identified |= $this->data->device->identified;243                            $this->data->device = $device;244                            break;245                        }246                    }247                }248                if (preg_match('/HP eStation/u', $ua)) {249                    $this->data->device->manufacturer = 'HP';250                    $this->data->device->model = 'eStation';251                    $this->data->device->type = Constants\DeviceType::PRINTER;252                    $this->data->device->identified |= Constants\Id::MATCH_UA;253                    $this->data->device->generic = false;254                }255            }256        }257        if (preg_match('/\(Linux; (?:U; )?(?:([0-9.]+); )?(?:[a-zA-Z][a-zA-Z](?:[-_][a-zA-Z][a-zA-Z])?; )?([^;]+) Build/u', $ua, $match)) {258            $falsepositive = false;259            if ($match[2] == 'OpenTV') {260                $falsepositive = true;261            }262            if (!$falsepositive) {263                $this->data->device->type = Constants\DeviceType::MOBILE;264                $this->data->device->model = $match[2];265                $this->data->os->name = 'Android';266                if (!empty($match[1])) {267                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);268                }269                $device = Data\DeviceModels::identify('android', $match[2]);270                if ($device->identified) {271                    $device->identified |= Constants\Id::PATTERN;272                    $device->identified |= $this->data->device->identified;273                    $this->data->device = $device;274                }275            }276        }277        if (preg_match('/Linux x86_64; ([^;\)]+)(?:; [a-zA-Z][a-zA-Z](?:[-_][a-zA-Z][a-zA-Z])?)?\) AppleWebKit\/534.24 \(KHTML, like Gecko\) Chrome\/11.0.696.34 Safari\/534.24/u', $ua, $match)) {278            $device = Data\DeviceModels::identify('android', $match[1]);279            if ($device->identified) {280                $device->identified |= Constants\Id::PATTERN;281                $device->identified |= $this->data->device->identified;282                $this->data->os->name = 'Android';283                $this->data->device = $device;284            }285        }286        if (preg_match('/\(Linux; U; Linux Ventana; [^;]+; ([^;]+) Build/u', $ua, $match)) {287            $this->data->device->type = Constants\DeviceType::MOBILE;288            $this->data->device->model = $match[1];289            $device = Data\DeviceModels::identify('android', $match[1]);290            if ($device->identified) {291                $device->identified |= Constants\Id::PATTERN;292                $device->identified |= $this->data->device->identified;293                $this->data->os->name = 'Android';294                $this->data->device = $device;295            }296        }297        /* Aliyun OS */298        if (preg_match('/Aliyun/u', $ua) || preg_match('/YunOs/ui', $ua)) {299            $this->data->os->name = 'Aliyun OS';300            $this->data->os->family = new Family([ 'name' => 'Android' ]);301            $this->data->os->version = new Version();302            if (preg_match('/YunOs[ \/]([0-9.]+)/iu', $ua, $match)) {303                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);304            }305            if (preg_match('/AliyunOS ([0-9.]+)/u', $ua, $match)) {306                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);307            }308            $this->data->device->type = Constants\DeviceType::MOBILE;309            if (preg_match('/; ([^;]*[^;\s])\s+Build/u', $ua, $match)) {310                $this->data->device->model = $match[1];311            }312            if (isset($this->data->device->model)) {313                $this->data->device->identified |= Constants\Id::PATTERN;314                $device = Data\DeviceModels::identify('android', $this->data->device->model);315                if ($device->identified) {316                    $device->identified |= $this->data->device->identified;317                    $this->data->device = $device;318                }319            }320        }321        if (preg_match('/Android/u', $ua)) {322            if (preg_match('/Android v(1.[0-9][0-9])_[0-9][0-9].[0-9][0-9]-/u', $ua, $match)) {323                $this->data->os->name = 'Aliyun OS';324                $this->data->os->family = new Family([ 'name' => 'Android' ]);325                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);326            }327            if (preg_match('/Android[ \/](1.[0-9].[0-9].[0-9]+)-R?T/u', $ua, $match)) {328                $this->data->os->name = 'Aliyun OS';329                $this->data->os->family = new Family([ 'name' => 'Android' ]);330                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);331            }332            if (preg_match('/Android ([12].[0-9].[0-9]+)-R-20[0-9]+/u', $ua, $match)) {333                $this->data->os->name = 'Aliyun OS';334                $this->data->os->family = new Family([ 'name' => 'Android' ]);335                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 3 ]);336            }337            if (preg_match('/Android 20[0-9]+\./u', $ua, $match)) {338                $this->data->os->name = 'Aliyun OS';339                $this->data->os->family = new Family([ 'name' => 'Android' ]);340                $this->data->os->version = null;341            }342        }343        /* Baidu Yi */344        if (preg_match('/Baidu Yi/u', $ua)) {345            $this->data->os->name = 'Baidu Yi';346            $this->data->os->family = new Family([ 'name' => 'Android' ]);347            $this->data->os->version = null;348        }349        /* Google TV */350        if (preg_match('/GoogleTV/u', $ua)) {351            $this->data->os->name = 'Google TV';352            $this->data->os->family = new Family([ 'name' => 'Android' ]);353            $this->data->device->type = Constants\DeviceType::TELEVISION;354            if (preg_match('/GoogleTV [0-9\.]+; ?([^;]*[^;\s])\s+Build/u', $ua, $match)) {355                $this->data->device->model = $match[1];356            }357            if (isset($this->data->device->model) && $this->data->device->model) {358                $this->data->device->identified |= Constants\Id::PATTERN;359                $device = Data\DeviceModels::identify('android', $this->data->device->model);360                if ($device->identified) {361                    $device->identified |= $this->data->device->identified;362                    $this->data->device = $device;363                }364            }365        }366        /* LeOS */367        if (preg_match('/LeOS/u', $ua)) {368            $this->data->os->name = 'LeOS';369            $this->data->os->family = new Family([ 'name' => 'Android' ]);370            if (preg_match('/LeOS([0-9\.]*)/u', $ua, $match)) {371                $this->data->os->version = new Version([ 'value' => $match[1] ]);372            }373            $this->data->device->type = Constants\DeviceType::TABLET;374            if (preg_match('/LeOS[0-9\.]+; [^;]+; (.*) Build/u', $ua, $match)) {375                $this->data->device->model = $match[1];376            }377            if (isset($this->data->device->model) && $this->data->device->model) {378                $this->data->device->identified |= Constants\Id::PATTERN;379                $device = Data\DeviceModels::identify('android', $this->data->device->model);380                if ($device->identified) {381                    $device->identified |= $this->data->device->identified;382                    $this->data->device = $device;383                }384            }385        }386        /* WoPhone */387        if (preg_match('/WoPhone/u', $ua)) {388            $this->data->os->name = 'WoPhone';389            $this->data->os->family = new Family([ 'name' => 'Android' ]);390            if (preg_match('/WoPhone\/([0-9\.]*)/u', $ua, $match)) {391                $this->data->os->version = new Version([ 'value' => $match[1] ]);392            }393            $this->data->device->type = Constants\DeviceType::MOBILE;394        }395        /* COS */396        if (preg_match('/(COS|(China|Chinese) Operating System)/ui', $ua)) {397            if (preg_match('/COS[\/ ]?([0-9]\.[0-9.]+)/ui', $ua, $match)) {398                $this->data->os->name = 'COS';399                $this->data->os->family = new Family([ 'name' => 'Android' ]);400                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);401            } elseif (preg_match('/(?:\(|; )(?:China|Chinese) Operating System ([0-9]\.[0-9.]*);/ui', $ua, $match)) {402                $this->data->os->name = 'COS';403                $this->data->os->family = new Family([ 'name' => 'Android' ]);404                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);405            } elseif (preg_match('/COS like Android/ui', $ua, $match)) {406                $this->data->os->name = 'COS';407                $this->data->os->family = new Family([ 'name' => 'Android' ]);408                $this->data->os->version = null;409                $this->data->device->type = Constants\DeviceType::MOBILE;410            } elseif (preg_match('/(COS like Android|COSBrowser\/|\(COS;|\(COS 998;)/ui', $ua, $match)) {411                $this->data->os->name = 'COS';412                $this->data->os->family = new Family([ 'name' => 'Android' ]);413            }414        }415        /* RemixOS */416        if (preg_match('/RemixOS/u', $ua)) {417            $this->data->os->name = 'Remix OS';418            $this->data->os->version = null;419            $this->data->os->family = new Family([ 'name' => 'Android' ]);420            if (preg_match('/RemixOS ([0-9]\.[0-9])/u', $ua, $match)) {421                switch ($match[1]) {422                    case '5.1':423                        $this->data->os->version = new Version([ 'value' => '1.0' ]);424                        break;425                    case '6.0':426                        $this->data->os->version = new Version([ 'value' => '2.0' ]);427                        break;428                }429            }430            $this->data->device->type = Constants\DeviceType::DESKTOP;431        }432    }433    private function determineAndroidVersionBasedOnBuild($ua)434    {435        if ($this->data->isOs('Android')) {436            if (preg_match('/Build\/([^\);]+)/u', $ua, $match)) {437                $version = Data\BuildIds::identify($match[1]);438                if ($version) {439                    if (!isset($this->data->os->version) || $this->data->os->version == null || $this->data->os->version->value == null || $version->toFloat() < $this->data->os->version->toFloat()) {440                        $this->data->os->version = $version;441                    }442                    /* Special case for Android L */443                    if ($version->toFloat() == 5) {444                        $this->data->os->version = $version;445                    }446                }447                $this->data->os->build = $match[1];448            }449        }450    }451    /* Windows */452    private function detectWindows($ua)453    {454        if (preg_match('/(Windows|WinNT|WinCE|WinMobile|Win ?[9MX]|Win(16|32))/u', $ua)) {455            $this->data->os->name = 'Windows';456            $this->data->device->type = Constants\DeviceType::DESKTOP;457            /* Windows NT */458            if (preg_match('/Windows 2000/u', $ua)) {459                $this->data->os->version = new Version([ 'value' => '5.0', 'alias' => '2000' ]);460            }461            if (preg_match('/(Windows XP|WinXP)/u', $ua)) {462                $this->data->os->version = new Version([ 'value' => '5.1', 'alias' => 'XP' ]);463            }464            if (preg_match('/Windows Vista/u', $ua)) {465                $this->data->os->version = new Version([ 'value' => '6.0', 'alias' => 'Vista' ]);466            }467            if (preg_match('/(?:Windows NT |WinNT)([0-9][0-9]?\.[0-9])/u', $ua, $match)) {468                $this->data->os->version = new Version([ 'value' => $match[1] ]);469                switch ($match[1]) {470                    case '10.1':471                    case '10.0':472                    case '6.4':473                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '10' ]);474                        break;475                    case '6.3':476                        if (preg_match('/; ARM;/u', $ua)) {477                            $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'RT 8.1' ]);478                        } else {479                            $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '8.1' ]);480                        }481                        break;482                    case '6.2':483                        if (preg_match('/; ARM;/u', $ua)) {484                            $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'RT' ]);485                        } else {486                            $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '8' ]);487                        }488                        break;489                    case '6.1':490                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '7' ]);491                        break;492                    case '6.0':493                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'Vista' ]);494                        break;495                    case '5.2':496                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'Server 2003' ]);497                        break;498                    case '5.1':499                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'XP' ]);500                        break;501                    case '5.0':502                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '2000' ]);503                        break;504                    default:505                        $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => 'NT ' . $match[1] ]);506                        break;507                }508                $this->detectWindowsOemManufacturer($ua);509            }510            /* Windows 10 IoT Core */511            if (preg_match('/Windows IoT (1[0-9]\.[0-9]);/u', $ua, $match)) {512                $this->data->os->version = new Version([ 'value' => $match[1], 'alias' => '10 IoT Core' ]);513            }514            /* Windows */515            if (preg_match('/(Windows 95|Win95)/u', $ua)) {516                $this->data->os->version = new Version([ 'value' => '4.0', 'alias' => '95' ]);517            }518            if (preg_match('/(Windows 98|Win98)/u', $ua)) {519                $this->data->os->version = new Version([ 'value' => '4.1', 'alias' => '98' ]);520            }521            if (preg_match('/(Windows M[eE]|WinME)/u', $ua)) {522                $this->data->os->version = new Version([ 'value' => '4.9', 'alias' => 'ME' ]);523            }524            if (preg_match('/(?:Windows|Win 9x) (([1234]\.[0-9])[0-9\.]*)/u', $ua, $match)) {525                $this->data->os->version = new Version([ 'value' => $match[1] ]);526                switch ($match[2]) {527                    case '4.0':528                        $this->data->os->version = new Version([ 'value' => '4.0', 'alias' => '95' ]);529                        break;530                    case '4.1':531                        $this->data->os->version = new Version([ 'value' => '4.1', 'alias' => '98' ]);532                        break;533                    case '4.9':534                        $this->data->os->version = new Version([ 'value' => '4.9', 'alias' => 'ME' ]);535                        break;536                }537            }538            /* Windows Mobile and Windows Phone */539            if (preg_match('/WPDesktop/u', $ua)) {540                $this->data->os->name = 'Windows Phone';541                $this->data->os->version = new Version([ 'value' => '8.0', 'details' => 2 ]);542                $this->data->device->type = Constants\DeviceType::MOBILE;543                $this->data->browser->mode = 'desktop';544            }545            if (preg_match('/WP7/u', $ua)) {546                $this->data->os->name = 'Windows Phone';547                $this->data->os->version = new Version([ 'value' => '7', 'details' => 1 ]);548                $this->data->device->type = Constants\DeviceType::MOBILE;549                $this->data->browser->mode = 'desktop';550            }551            if (preg_match('/WinMobile/u', $ua)) {552                $this->data->os->name = 'Windows Mobile';553                $this->data->device->type = Constants\DeviceType::MOBILE;554                if (preg_match('/WinMobile\/([0-9.]*)/u', $ua, $match)) {555                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);556                }557            }558            if (preg_match('/(Windows CE|WindowsCE|WinCE)/u', $ua)) {559                $this->data->device->type = Constants\DeviceType::MOBILE;560                if (preg_match('/ IEMobile/u', $ua)) {561                    $this->data->os->name = 'Windows Mobile';562                    if (preg_match('/ IEMobile\/9/u', $ua)) {563                        $this->data->os->name = 'Windows Phone';564                        $this->data->os->version = new Version([ 'value' => '7.5', 'details' => 2 ]);565                    }566                    if (preg_match('/ IEMobile 8/u', $ua)) {567                        $this->data->os->version = new Version([ 'value' => '6.5', 'details' => 2 ]);568                    }569                    if (preg_match('/ IEMobile 7/u', $ua)) {570                        $this->data->os->version = new Version([ 'value' => '6.1', 'details' => 2 ]);571                    }572                    if (preg_match('/ IEMobile 6/u', $ua)) {573                        $this->data->os->version = new Version([ 'value' => '6.0', 'details' => 2 ]);574                    }575                } else {576                    $this->data->os->name = 'Windows CE';577                    if (preg_match('/WindowsCEOS\/([0-9.]*)/u', $ua, $match)) {578                        $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);579                    }580                    if (preg_match('/Windows CE ([0-9.]*)/u', $ua, $match)) {581                        $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);582                    }583                }584                $model = null;585                if (empty($model) && preg_match('/IEMobile [0-9.]+\)  ?(?:PPC; |SP; |Smartphone; )?(?:[0-9]+[Xx][0-9]+;? )?(?:VZW; )?([^;\(]+)/u', $ua, $match)) {586                    if (!preg_match('/(Profile\/MIDP|UNTRUSTED)/u', $match[1])) {587                        $model = $match[1];588                    }589                }590                if (empty($model) && preg_match('/IEMobile [0-9.]+\) (?:PPC|SP|Smartphone); (?:[0-9]+[Xx][0-9]+;? )([^;]+) Profile\/MIDP/u', $ua, $match)) {591                    $model = $match[1];592                }593                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; (?:PPC|SP|Smartphone); [0-9]+x[0-9]+; ([^;\)]+)\)$/u', $ua, $match)) {594                    $model = $match[1];595                }596                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; (?:PPC|SP|Smartphone); [0-9]+x[0-9]+; ([^;]+); (?:PPC|OpVer)/u', $ua, $match)) {597                    $model = $match[1];598                }599                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; (?:PPC|SP|Smartphone); ([^;]+) Profile\/MIDP/u', $ua, $match)) {600                    $model = $match[1];601                }602                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; (?:PPC|SP|Smartphone) ([^;\(]+)[;\/] [0-9]+x[0-9]+/u', $ua, $match)) {603                    $model = $match[1];604                }605                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; ([^;\(]+); [0-9]+x[0-9]+\)/u', $ua, $match)) {606                    if (!preg_match('/^(Smartphone|PPC$)/u', $match[1])) {607                        $model = $match[1];608                    }609                }610                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; ([^;\(]+);? ?(?:PPC|SP|Smartphone); ?[0-9]+x[0-9]+/u', $ua, $match)) {611                    if (!preg_match('/^(MIDP-2.0)/u', $match[1])) {612                        $model = $match[1];613                    }614                }615                if (empty($model) && preg_match('/MSIE [0-9.]+; Windows CE; ([^;\)]+)(?:; (?:PPC|SP|Smartphone); [0-9]+x[0-9]+)?\)( \[[a-zA-Z\-]+\])?$/u', $ua, $match)) {616                    if (!preg_match('/^(IEMobile|MIDP-2.0|Smartphone|PPC$)/u', $match[1])) {617                        $model = $match[1];618                    }619                }620                if (!empty($model)) {621                    $model = preg_replace('/(HTC\/|Toshiba\/)/', '', $model);622                    $this->data->device->model = $model;623                    $this->data->device->identified |= Constants\Id::PATTERN;624                    $this->data->os->name = 'Windows Mobile';625                    $device = Data\DeviceModels::identify('wm', $model);626                    if ($device->identified) {627                        $device->identified |= $this->data->device->identified;628                        $this->data->device = $device;629                    }630                } else {631                    if (empty($model) && preg_match('/Windows CE [^;]+; Trident\/[^;]+; IEMobile[\/ ][^;]+[\);] ([A-Z\s]+); ?([^\/\),]+)/ui', $ua, $match)) {632                        $model = $match[2];633                    }634                    if (!empty($model)) {635                        $this->data->device->model = $model;636                        $this->data->device->identified |= Constants\Id::PATTERN;637                        $this->data->os->name = 'Windows Phone';638                        $device = Data\DeviceModels::identify('wp', $model);639                        if ($device->identified) {640                            $device->identified |= $this->data->device->identified;641                            $this->data->device = $device;642                        }643                    }644                }645            }646            if (preg_match('/Microsoft Windows; (PPC|Smartphone)/u', $ua)) {647                $this->data->os->name = 'Windows Mobile';648                $this->data->device->type = Constants\DeviceType::MOBILE;649            }650            if (preg_match('/Windows CE; (PPC|Smartphone)/u', $ua)) {651                $this->data->os->name = 'Windows Mobile';652                $this->data->device->type = Constants\DeviceType::MOBILE;653            }654            /* Detect models in common places */655            if (preg_match('/Windows ?Mobile/u', $ua)) {656                $this->data->os->name = 'Windows Mobile';657                $this->data->device->type = Constants\DeviceType::MOBILE;658                if (preg_match('/Windows ?Mobile[\/ ]([0-9.]*)/u', $ua, $match)) {659                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);660                }661                if (preg_match('/Windows Mobile; (?:SHARP\/)?([^;]+); (?:PPC|Smartphone);/u', $ua, $match)) {662                    $this->data->device->model = $match[1];663                    $this->data->device->identified |= Constants\Id::PATTERN;664                    $device = Data\DeviceModels::identify('wm', $match[1]);665                    if ($device->identified) {666                        $device->identified |= $this->data->device->identified;667                        $this->data->device = $device;668                    }669                }670                if (preg_match('/\(([^;]+); U; Windows Mobile/u', $ua, $match)) {671                    $this->data->device->model = $match[1];672                    $this->data->device->identified |= Constants\Id::PATTERN;673                    $device = Data\DeviceModels::identify('wm', $match[1]);674                    if ($device->identified) {675                        $device->identified |= $this->data->device->identified;676                        $this->data->device = $device;677                    }678                }679            }680            if (preg_match('/(Windows Phone|Windows NT 1[0-9]\.[0-9]; ARM|WPDesktop|ZuneWP7)/u', $ua)) {681                $this->data->os->name = 'Windows Phone';682                $this->data->device->type = Constants\DeviceType::MOBILE;683                if (preg_match('/Windows Phone(?: OS)?[ \/]([0-9.]*)/u', $ua, $match)) {684                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);685                    if (intval($match[1]) < 7) {686                        $this->data->os->name = 'Windows Mobile';687                    }688                }689                /* Windows Mobile 6.5 */690                if (preg_match('/Windows NT 5.1; ([^;]+); Windows Phone/u', $ua, $match)) {691                    $this->data->device->model = $match[1];692                    $this->data->device->identified |= Constants\Id::PATTERN;693                    $device = Data\DeviceModels::identify('wm', $match[1]);694                    if ($device->identified) {695                        $device->identified |= $this->data->device->identified;696                        $this->data->device = $device;697                    }698                }699                /* Windows Phone 7 (buggy) */700                if (preg_match('/Windows Phone OS [^;]+; Trident\/[^;]+; IEMobile[\/ ][^;]+[\);] ([A-Z\s]+); ?([^\/\),]+)/ui', $ua, $match)) {701                    $this->data->device->manufacturer = $match[1];702                    $this->data->device->model = $match[2];703                    $this->data->device->identified |= Constants\Id::PATTERN;704                    $device = Data\DeviceModels::identify('wp', $match[2]);705                    if ($device->identified) {706                        $device->identified |= $this->data->device->identified;707                        $this->data->device = $device;708                    }709                }710                /* Windows Phone 7 and 8 */711                if (preg_match('/IEMobile\/[^;]+;(?: ARM; Touch; )?(?:rv:[0-9]+; )?(?: WpsLondonTest; )?\s*([^;\s][^;\)]*);\s*([^;\)\s][^;\)]*)[;|\)]/u', $ua, $match)) {712                    $this->data->device->manufacturer = $match[1];713                    $this->data->device->model = $match[2];714                    $this->data->device->identified |= Constants\Id::PATTERN;715                    $device = Data\DeviceModels::identify('wp', $match[2]);716                    if ($device->identified) {717                        $device->identified |= $this->data->device->identified;718                        $this->data->device = $device;719                    }720                }721                /* Windows Phone 10 */722                if (preg_match('/Windows Phone 1[0-9]\.[0-9]; Android [0-9\.]+; (?:WebView\/[0-9\.]+; )?([^;\s][^;]*);\s*([^;\)\s][^;\)]*)[;|\)]/u', $ua, $match)) {723                    $this->data->device->manufacturer = $match[1];724                    $this->data->device->model = $match[2];725                    $this->data->device->identified |= Constants\Id::PATTERN;726                    $device = Data\DeviceModels::identify('wp', $match[2]);727                    if ($device->identified) {728                        $device->identified |= $this->data->device->identified;729                        $this->data->device = $device;730                    }731                }732                /* Windows Phone 10 Continuum */733                if (preg_match('/Windows NT 1[0-9]\.[0-9]; ARM; ([^;\)\s][^;\)]*)\)/u', $ua, $match)) {734                    $this->data->device->model = $match[1];735                    $this->data->device->identified |= Constants\Id::PATTERN;736                    $device = Data\DeviceModels::identify('wp', $match[1]);737                    if ($device->identified) {738                        $device->identified |= $this->data->device->identified;739                        $this->data->device = $device;740                    }741                    $this->data->device->type = Constants\DeviceType::DESKTOP;742                }743                /* Third party browsers */744                if (preg_match('/IEMobile\/[^;]+;(?: ARM; Touch; )?\s*(?:[^\/]+\/[^\/]+);\s*([^;\s][^;]*);\s*([^;\)\s][^;\)]*)[;|\)]/u', $ua, $match)) {745                    $this->data->device->manufacturer = $match[1];746                    $this->data->device->model = $match[2];747                    $this->data->device->identified |= Constants\Id::PATTERN;748                    $device = Data\DeviceModels::identify('wp', $match[2]);749                    if ($device->identified) {750                        $device->identified |= $this->data->device->identified;751                        $this->data->device = $device;752                    }753                }754                if (preg_match('/\(Windows Phone OS\/[0-9\.]+; ([^:]+):([^;]+); [a-z]+(?:\-[a-z]+)?\)/iu', $ua, $match)) {755                    $this->data->device->manufacturer = $match[1];756                    $this->data->device->model = $match[2];757                    $this->data->device->identified |= Constants\Id::PATTERN;758                    $device = Data\DeviceModels::identify('wp', $match[2]);759                    if ($device->identified) {760                        $device->identified |= $this->data->device->identified;761                        $this->data->device = $device;762                    }763                }764                /* Desktop mode of WP 8.1 */765                if (preg_match('/WPDesktop;\s*([^;\)]*)(?:;\s*([^;\)]*))?(?:;\s*([^;\)]*))?\) like Gecko/u', $ua, $match)) {766                    if (preg_match("/^[A-Z]+$/", $match[1]) && isset($match[2])) {767                        $this->data->device->manufacturer = $match[1];768                        $this->data->device->model = $match[2];769                    } else {770                        $this->data->device->model = $match[1];771                    }772                    $this->data->device->identified |= Constants\Id::PATTERN;773                    $device = Data\DeviceModels::identify('wp', $this->data->device->model);774                    if ($device->identified) {775                        $device->identified |= $this->data->device->identified;776                        $this->data->device = $device;777                    }778                }779                /* Desktop mode of WP 7 */780                if (preg_match('/XBLWP7; ZuneWP7; ([^\)]+)\)/u', $ua, $match)) {781                    $this->data->device->model = $match[1];782                    $this->data->device->identified |= Constants\Id::PATTERN;783                    $device = Data\DeviceModels::identify('wp', $match[1]);784                    if ($device->identified) {785                        $device->identified |= $this->data->device->identified;786                        $this->data->device = $device;787                    }788                }789                /* Desktop mode of WP 8.0 and 8.1 Update (buggy version) */790                if (preg_match('/Touch; WPDesktop;\s*([^;\)]*)(?:;\s*([^;\)]*))?(?:;\s*([^;\)]*))?\)/u', $ua, $match)) {791                    if (preg_match("/^[A-Z]+$/", $match[1]) && isset($match[2])) {792                        $this->data->device->manufacturer = $match[1];793                        $this->data->device->model = $match[2];794                    } else {795                        $this->data->device->model = $match[1];796                    }797                    $this->data->device->identified |= Constants\Id::PATTERN;798                    $device = Data\DeviceModels::identify('wp', $this->data->device->model);799                    if ($device->identified) {800                        $device->identified |= $this->data->device->identified;801                        $this->data->device = $device;802                    }803                }804                if (isset($this->data->device->manufacturer) && isset($this->data->device->model)) {805                    if ($this->data->device->manufacturer == 'ARM' && $this->data->device->model == 'Touch') {806                        $this->data->device->manufacturer = null;807                        $this->data->device->model = null;808                        $this->data->device->identified = Constants\Id::NONE;809                    }810                    if ($this->data->device->model == 'XDeviceEmulator') {811                        $this->data->device->manufacturer = null;812                        $this->data->device->model = null;813                        $this->data->device->type = Constants\DeviceType::EMULATOR;814                        $this->data->device->identified |= Constants\Id::MATCH_UA;815                    }816                }817            }818        } elseif (preg_match('/WMPRO/u', $ua)) {819            $this->data->os->name = 'Windows Mobile';820            $this->data->device->type = Constants\DeviceType::MOBILE;821        }822    }823    private function detectWindowsOemManufacturer($ua)824    {825        $manufacturers = [826            'MAAR'      => 'Acer',827            'ASJB'      => 'Asus',828            'ASU2'      => 'Asus',829            'MAAU'      => 'Asus',830            'NP06'      => 'Asus',831            'NP07'      => 'Asus',832            'NP08'      => 'Asus',833            'NP09'      => 'Asus',834            'CMNTDF'    => 'Compaq',835            'CPDTDF'    => 'Compaq',836            'CPNTDF'    => 'Compaq',837            'MDDR'      => 'Dell',838            'MDDC'      => 'Dell',839            'MDDS'      => 'Dell',840            'FSJB'      => 'Fujitsu',841            'MAFS'      => 'Fujitsu',842            'MAGW'      => 'Gateway',843            'HPCMHP'    => 'HP',844            'HPDTDF'    => 'HP',845            'HPNTDF'    => 'HP',846            'MANM'      => 'Hyrican',847            'LCJB'      => 'Lenovo',848            'LEN2'      => 'Lenovo',849            'MALC'      => 'Lenovo',850            'MALE'      => 'Lenovo',851            'MALN'      => 'Lenovo',852            'MAMD'      => 'Medion',853            'MAMI'      => 'MSI',854            'MAM3'      => 'MSI',855            'MASM'      => 'Samsung',856            'SMJB'      => 'Samsung',857            'MASA'      => 'Sony',858            'MASE'      => 'Sony',859            'MASP'      => 'Sony',860            'MATB'      => 'Toshiba',861            'MATM'      => 'Toshiba',862            'MATP'      => 'Toshiba',863            'TAJB'      => 'Toshiba',864            'TNJB'      => 'Toshiba',865        ];866        $keys = array_keys($manufacturers);867        if (preg_match('/; (' . implode('|', $keys) . ')(?:JS)?[\);]/u', $ua, $match)) {868            $this->data->device->manufacturer = $manufacturers[$match[1]];869            $this->data->device->hidden = true;870            $this->data->device->identified |= Constants\Id::INFER;871        }872    }873    /* Jolla Sailfish */874    private function detectSailfish($ua)875    {876        if (preg_match('/Sailfish;/u', $ua)) {877            $this->data->os->name = 'Sailfish';878            $this->data->os->version = null;879            if (preg_match('/Jolla;/u', $ua)) {880                $this->data->device->manufacturer = 'Jolla';881            }882            if (preg_match('/Mobile/u', $ua)) {883                $this->data->device->model = 'Phone';884                $this->data->device->type = Constants\DeviceType::MOBILE;885                $this->data->device->identified = Constants\Id::PATTERN;886            }887            if (preg_match('/Tablet/u', $ua)) {888                $this->data->device->model = 'Tablet';889                $this->data->device->type = Constants\DeviceType::TABLET;890                $this->data->device->identified = Constants\Id::PATTERN;891            }892        }893    }894    /* Bada */895    private function detectBada($ua)896    {897        if (preg_match('/[b|B]ada/u', $ua)) {898            $this->data->os->name = 'Bada';899            if (preg_match('/[b|B]ada[\/ ]([0-9.]*)/u', $ua, $match)) {900                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);901            }902            $this->data->device->type = Constants\DeviceType::MOBILE;903            if (preg_match('/\(([^;]+); ([^\/]+)\//u', $ua, $match)) {904                if ($match[1] != 'Bada') {905                    $this->data->device->manufacturer = $match[1];906                    $this->data->device->model = $match[2];907                    $this->data->device->identified = Constants\Id::PATTERN;908                    $device = Data\DeviceModels::identify('bada', $match[2]);909                    if ($device->identified) {910                        $device->identified |= $this->data->device->identified;911                        $this->data->device = $device;912                    }913                }914            }915        }916    }917    /* Tizen */918    private function detectTizen($ua)919    {920        if (preg_match('/Tizen/u', $ua)) {921            $this->data->os->name = 'Tizen';922            if (preg_match('/Tizen[\/ ]?([0-9.]*[0-9])/u', $ua, $match)) {923                $this->data->os->version = new Version([ 'value' => $match[1] ]);924            }925            if (preg_match('/\(([^;]+); ([^\/]+)\//u', $ua, $match)) {926                $falsepositive = false;927                if (strtoupper($match[1]) == 'SMART-TV') {928                    $falsepositive = true;929                }930                if ($match[1] == 'TV') {931                    $falsepositive = true;932                }933                if ($match[1] == 'Linux') {934                    $falsepositive = true;935                }936                if ($match[1] == 'Tizen') {937                    $falsepositive = true;938                }939                if (!$falsepositive) {940                    $this->data->device->manufacturer = $match[1];941                    $this->data->device->model = $match[2];942                    $this->data->device->identified = Constants\Id::PATTERN;943                    $device = Data\DeviceModels::identify('tizen', $match[2]);944                    if ($device->identified) {945                        $device->identified |= $this->data->device->identified;946                        $this->data->device = $device;947                    }948                }949            }950            if (preg_match('/\s*([^;]+);\s+([^;\)]+)\)/u', $ua, $match)) {951                $falsepositive = false;952                if ($match[1] == 'U') {953                    $falsepositive = true;954                }955                if (substr($match[2], 0, 5) == 'Tizen') {956                    $falsepositive = true;957                }958                if (substr($match[2], 0, 11) == 'AppleWebKit') {959                    $falsepositive = true;960                }961                if (preg_match("/^[a-z]{2,2}(?:\-[a-z]{2,2})?$/", $match[2])) {962                    $falsepositive = true;963                }964                if (!$falsepositive) {965                    $this->data->device->model = $match[2];966                    $this->data->device->identified = Constants\Id::PATTERN;967                    $device = Data\DeviceModels::identify('tizen', $match[2]);968                    if ($device->identified) {969                        $device->identified |= $this->data->device->identified;970                        $this->data->device = $device;971                    }972                }973            }974            if (!$this->data->device->type && preg_match('/Mobile/iu', $ua, $match)) {975                $this->data->device->type = Constants\DeviceType::MOBILE;976            }977            if (preg_match('/\((SMART[ -])?TV;/iu', $ua, $match)) {978                $this->data->device->type = Constants\DeviceType::TELEVISION;979                $this->data->device->manufacturer = 'Samsung';980                $this->data->device->series = 'Smart TV';981                $this->data->device->identified = Constants\Id::PATTERN;982            }983            if (preg_match('/(?:Samsung|Tizen ?)Browser\/([0-9.]*)/u', $ua, $match)) {984                $this->data->browser->name = "Samsung Browser";985                $this->data->browser->channel = null;986                $this->data->browser->stock = true;987                $this->data->browser->version = new Version([ 'value' => $match[1] ]);988                $this->data->browser->channel = null;989            }990        }991        if (preg_match('/Linux\; U\; Android [0-9.]+\; ko\-kr\; SAMSUNG\; (NX[0-9]+[^\)]]*)/u', $ua, $match)) {992            $this->data->os->name = 'Tizen';993            $this->data->os->version = null;994            $this->data->device->type = Constants\DeviceType::CAMERA;995            $this->data->device->manufacturer = 'Samsung';996            $this->data->device->model = $match[1];997            $this->data->device->identified = Constants\Id::PATTERN;998        }999    }1000    /* Symbian */1001    private function detectSymbian($ua)1002    {1003        if (!preg_match('/(EPOC|Series|Symbian|S60|UIQ)/ui', $ua)) {1004            return;1005        }1006        /* EPOC */1007        if (preg_match('/EPOC(?:32)?[;\-\)]/u', $ua, $match)) {1008            $this->data->os->name = 'EPOC';1009            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1010            $this->data->device->type = Constants\DeviceType::PDA;1011            if (preg_match('/Crystal\/([0-9.]*)/u', $ua, $match)) {1012                $this->data->os->name = 'Series80';1013                $this->data->os->version = new Version([ 'value' => '1.0' ]);1014                $this->data->os->family->version = new Version([ 'value' => $match[1] ]);1015                $this->data->device->type = Constants\DeviceType::MOBILE;1016                $this->data->device->manufacturer = 'Nokia';1017                $this->data->device->model = '9210';1018                $this->data->device->identified |= Constants\Id::PATTERN;1019            }1020            if (preg_match('/Nokia\/Series-9200/u', $ua)) {1021                $this->data->os->name = 'Series80';1022                $this->data->os->version = new Version([ 'value' => '1.0' ]);1023                $this->data->device->type = Constants\DeviceType::MOBILE;1024                $this->data->device->manufacturer = 'Nokia';1025                $this->data->device->model = '9210i';1026                $this->data->device->identified |= Constants\Id::PATTERN;1027            }1028        }1029        /* Series 80 */1030        if (preg_match('/Series80\/([0-9.]*)/u', $ua, $match)) {1031            $this->data->os->name = 'Series80';1032            $this->data->os->version = new Version([ 'value' => $match[1] ]);1033            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1034            $this->data->device->type = Constants\DeviceType::MOBILE;1035        }1036        /* Series 60 */1037        if (preg_match('/Symbian\/3/u', $ua)) {1038            $this->data->os->name = 'Series60';1039            $this->data->os->version = new Version([ 'value' => '5.2' ]);1040            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1041            $this->data->device->type = Constants\DeviceType::MOBILE;1042        }1043        if (preg_match('/Series[ ]?60/u', $ua) || preg_match('/S60[V\/;]/u', $ua) || preg_match('/S60 Symb/u', $ua)) {1044            $this->data->os->name = 'Series60';1045            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1046            $this->data->device->type = Constants\DeviceType::MOBILE;1047            if (preg_match('/Series60\/([0-9.]*)/u', $ua, $match)) {1048                $this->data->os->version = new Version([ 'value' => $match[1] ]);1049            }1050            if (preg_match('/S60\/([0-9.]*)/u', $ua, $match)) {1051                $this->data->os->version = new Version([ 'value' => $match[1] ]);1052            }1053            if (preg_match('/S60V([0-9.]*)/u', $ua, $match)) {1054                $this->data->os->version = new Version([ 'value' => $match[1] ]);1055            }1056        }1057        /* UIQ */1058        if (preg_match('/UIQ\/([0-9.]*)/u', $ua, $match)) {1059            $this->data->os->name = 'UIQ';1060            $this->data->os->version = new Version([ 'value' => $match[1] ]);1061            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1062            $this->data->device->type = Constants\DeviceType::MOBILE;1063        }1064        /* Symbian */1065        if (preg_match('/Symbian/u', $ua)) {1066            $this->data->os->family = new Family([ 'name' => 'Symbian' ]);1067            $this->data->device->type = Constants\DeviceType::MOBILE;1068            1069            if (preg_match('/SymbianOS\/([0-9.]*)/u', $ua, $match)) {1070                $this->data->os->family->version = new Version([ 'value' => $match[1] ]);1071            }1072        }1073        if ($this->data->os->isFamily('Symbian')) {1074            if (preg_match('/Nokia-?([^\/;\)\s]+)[\s|\/|;|\)]/u', $ua, $match)) {1075                if ($match[1] != 'Browser') {1076                    $this->data->device->manufacturer = 'Nokia';1077                    $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1078                    $this->data->device->identified |= Constants\Id::PATTERN;1079                }1080            }1081            if (preg_match('/Symbian(?:\/3)?; U; (?:Nokia)?([^;]+); [a-z][a-z](?:\-[a-z][a-z])?/u', $ua, $match)) {1082                $this->data->device->manufacturer = 'Nokia';1083                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1084                $this->data->device->identified |= Constants\Id::PATTERN;1085            }1086            if (preg_match('/Vertu([^\/;]+)[\/|;]/u', $ua, $match)) {1087                $this->data->device->manufacturer = 'Vertu';1088                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1089                $this->data->device->identified |= Constants\Id::PATTERN;1090            }1091            if (preg_match('/Samsung\/([^;]*);/u', $ua, $match)) {1092                $this->data->device->manufacturer = 'Samsung';1093                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1094                $this->data->device->identified |= Constants\Id::PATTERN;1095            }1096            if (isset($this->data->device->model)) {1097                $device = Data\DeviceModels::identify('symbian', $this->data->device->model);1098                if ($device->identified) {1099                    $device->identified |= $this->data->device->identified;1100                    $this->data->device = $device;1101                }1102            }1103        }1104    }1105    private function detectNokiaOs($ua)1106    {1107        if (!preg_match('/(Series|MeeGo|Maemo|Geos)/ui', $ua)) {1108            return;1109        }1110        /* Series 40 */1111        if (preg_match('/Series40/u', $ua)) {1112            $this->data->os->name = 'Series40';1113            if (preg_match('/Nokia([^\/]+)\//u', $ua, $match)) {1114                $this->data->device->manufacturer = 'Nokia';1115                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1116                $this->data->device->identified |= Constants\Id::PATTERN;1117            }1118            if (isset($this->data->device->model)) {1119                $device = Data\DeviceModels::identify('s40', $this->data->device->model);1120                if ($device->identified) {1121                    $device->identified |= $this->data->device->identified;1122                    $this->data->device = $device;1123                }1124            }1125            if (isset($this->data->device->model)) {1126                $device = Data\DeviceModels::identify('asha', $this->data->device->model);1127                if ($device->identified) {1128                    $device->identified |= $this->data->device->identified;1129                    $this->data->os->name = 'Nokia Asha Platform';1130                    $this->data->os->version = new Version([ 'value' => '1.0' ]);1131                    $this->data->device = $device;1132                }1133                if (preg_match('/java_runtime_version=Nokia_Asha_([0-9_]+);/u', $ua, $match)) {1134                    $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1135                }1136            }1137            $this->data->device->type = Constants\DeviceType::MOBILE;1138        }1139        /* Series 30+ */1140        if (preg_match('/Series30Plus/u', $ua)) {1141            $this->data->os->name = 'Series30+';1142            if (preg_match('/Nokia([^\/]+)\//u', $ua, $match)) {1143                $this->data->device->manufacturer = 'Nokia';1144                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1145                $this->data->device->identified |= Constants\Id::PATTERN;1146            }1147            if (isset($this->data->device->model)) {1148                $device = Data\DeviceModels::identify('s30plus', $this->data->device->model);1149                if ($device->identified) {1150                    $device->identified |= $this->data->device->identified;1151                    $this->data->device = $device;1152                }1153            }1154            $this->data->device->type = Constants\DeviceType::MOBILE;1155        }1156        /* Meego */1157        if (preg_match('/MeeGo/u', $ua)) {1158            $this->data->os->name = 'MeeGo';1159            $this->data->device->type = Constants\DeviceType::MOBILE;1160            if (preg_match('/Nokia([^\);]+)\)/u', $ua, $match)) {1161                $this->data->device->manufacturer = 'Nokia';1162                $this->data->device->model = Data\DeviceModels::cleanup($match[1]);1163                $this->data->device->identified |= Constants\Id::PATTERN;1164                $this->data->device->generic = false;1165            }1166        }1167        /* Maemo */1168        if (preg_match('/Maemo/u', $ua)) {1169            $this->data->os->name = 'Maemo';1170            $this->data->device->type = Constants\DeviceType::MOBILE;1171            if (preg_match('/(N[0-9]+)/u', $ua, $match)) {1172                $this->data->device->manufacturer = 'Nokia';1173                $this->data->device->model = $match[1];1174                $this->data->device->identified |= Constants\Id::PATTERN;1175                $this->data->device->generic = false;1176            }1177        }1178        /* GEOS */1179        if (preg_match('/Geos ([0-9.]+)/u', $ua, $match)) {1180            $this->data->os->name = 'GEOS';1181            $this->data->os->version = new Version([ 'value' => $match[1] ]);1182            $this->data->device->type = Constants\DeviceType::MOBILE;1183            if (preg_match('/Nokia-([0-9]{4,4}[a-z]?)/u', $ua, $match)) {1184                $this->data->device->manufacturer = 'Nokia';1185                $this->data->device->model = $match[1];1186                $this->data->device->identified |= Constants\Id::PATTERN;1187                $this->data->device->generic = false;1188            }1189        }1190    }1191    /* WebOS */1192    private function detectWebos($ua)1193    {1194        if (preg_match('/(?:web|hpw)OS\/(?:HP webOS )?([0-9.]*)/u', $ua, $match)) {1195            $this->data->os->name = 'webOS';1196            $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1197            $this->data->device->type = preg_match('/Tablet/iu', $ua) ? Constants\DeviceType::TABLET : Constants\DeviceType::MOBILE;1198            $this->data->device->generic = false;1199        }1200        if (preg_match('/(?:Spark|elite)\/fzz/u', $ua, $match) || preg_match('/webOSBrowser/u', $ua, $match)) {1201            $this->data->os->name = 'webOS';1202            $this->data->device->type = preg_match('/Tablet/iu', $ua) ? Constants\DeviceType::TABLET : Constants\DeviceType::MOBILE;1203            $this->data->device->generic = false;1204        }1205        if (preg_match('/ (Pre|Pixi|TouchPad|P160UN?A?)\/[0-9\.]+$/u', $ua, $match)) {1206            $this->data->os->name = 'webOS';1207            $this->data->device->type = $match[1] == 'TouchPad' ? Constants\DeviceType::TABLET : Constants\DeviceType::MOBILE;1208            $this->data->device->generic = false;1209        }1210        if ($this->data->isOs('webOS')) {1211            if (preg_match('/Pre\/1.0/u', $ua)) {1212                $this->data->device->manufacturer = 'Palm';1213                $this->data->device->model = 'Pre';1214            }1215            if (preg_match('/Pre\/1.1/u', $ua)) {1216                $this->data->device->manufacturer = 'Palm';1217                $this->data->device->model = 'Pre Plus';1218            }1219            if (preg_match('/Pre\/1.2/u', $ua)) {1220                $this->data->device->manufacturer = 'Palm';1221                $this->data->device->model = 'Pre 2';1222            }1223            if (preg_match('/Pre\/3.0/u', $ua)) {1224                $this->data->device->manufacturer = 'Palm';1225                $this->data->device->model = 'Pre 3';1226            }1227            if (preg_match('/Pixi\/1.0/u', $ua)) {1228                $this->data->device->manufacturer = 'Palm';1229                $this->data->device->model = 'Pixi';1230            }1231            if (preg_match('/Pixi\/1.1/u', $ua)) {1232                $this->data->device->manufacturer = 'Palm';1233                $this->data->device->model = 'Pixi Plus';1234            }1235            if (preg_match('/P160UN?A?\/1.0/u', $ua)) {1236                $this->data->device->manufacturer = 'HP';1237                $this->data->device->model = 'Veer';1238            }1239            if (preg_match('/TouchPad\/1.0/u', $ua)) {1240                $this->data->device->manufacturer = 'HP';1241                $this->data->device->model = 'TouchPad';1242            }1243            if (preg_match('/Emulator\//u', $ua) || preg_match('/Desktop\//u', $ua)) {1244                $this->data->device->type = Constants\DeviceType::EMULATOR;1245                $this->data->device->manufacturer = null;1246                $this->data->device->model = null;1247            }1248            $this->data->device->identified |= Constants\Id::MATCH_UA;1249        }1250    }1251    /* Kai OS */1252    private function detectKaiOS($ua)1253    {1254        if (preg_match('/Kai(OS)?\/([0-9.]+)/i', $ua, $match)) {1255            $this->data->os->reset([ 'name' => 'KaiOS', 'version' => new Version([ 'value' => $match[2] ]) ]);1256            $this->data->os->family = new Family([ 'name' => 'Firefox OS' ]);1257        }1258    }1259    /* BlackBerry */1260    private function detectBlackberry($ua)1261    {1262        /* BlackBerry OS */1263        if (preg_match('/RIM([0-9]{3,3})/u', $ua, $match)) {1264            $this->data->os->name = 'BlackBerry OS';1265            $this->data->device->manufacturer = 'RIM';1266            $this->data->device->model = $match[1];1267            $this->data->device->type = Constants\DeviceType::MOBILE;1268            $this->data->device->identified = Constants\Id::INFER;1269        }1270        if (preg_match('/BlackBerry/u', $ua) && !preg_match('/BlackBerry Runtime for Android Apps/u', $ua)) {1271            $this->data->os->name = 'BlackBerry OS';1272            $this->data->device->model = 'BlackBerry';1273            $this->data->device->manufacturer = 'RIM';1274            $this->data->device->type = Constants\DeviceType::MOBILE;1275            $this->data->device->identified = Constants\Id::INFER;1276            if (!preg_match('/Opera/u', $ua)) {1277                if (preg_match('/BlackBerry([0-9]+[ei]?)\/([0-9.]*)/u', $ua, $match)) {1278                    $this->data->device->model = $match[1];1279                    $this->data->os->version = new Version([ 'value' => $match[2], 'details' => 2 ]);1280                }1281                if (preg_match('/; BlackBerry ([0-9]*);/u', $ua, $match)) {1282                    $this->data->device->model = $match[1];1283                }1284                if (preg_match('/; ([0-9]+)[^;\)]+\)/u', $ua, $match)) {1285                    $this->data->device->model = $match[1];1286                }1287                if (preg_match('/Version\/([0-9.]*)/u', $ua, $match)) {1288                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1289                }1290                if (isset($this->data->os->version) && $this->data->os->version->toFloat() >= 10) {1291                    $this->data->os->name = 'BlackBerry';1292                }1293                if ($this->data->device->model) {1294                    $device = Data\DeviceModels::identify('blackberry', $this->data->device->model);1295                    if ($device->identified) {1296                        $device->identified |= $this->data->device->identified;1297                        $this->data->device = $device;1298                    }1299                }1300            }1301        }1302        /* BlackBerry 10 */1303        if (preg_match('/\(BB(1[^;]+); ([^\)]+)\)/u', $ua, $match)) {1304            $this->data->os->name = 'BlackBerry';1305            $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1306            $this->data->device->manufacturer = 'BlackBerry';1307            $this->data->device->model = $match[2];1308            if ($this->data->device->model == 'Kbd') {1309                $this->data->device->model = 'Q series or Passport';1310            }1311            if ($this->data->device->model == 'Touch') {1312                $this->data->device->model = 'A or Z series';1313            }1314            if ($this->data->device->model == 'STL100-2') {1315                $this->data->device->model = 'Z10';1316            }1317            $this->data->device->type = preg_match('/Mobile/u', $ua) ? Constants\DeviceType::MOBILE : Constants\DeviceType::TABLET;1318            $this->data->device->identified |= Constants\Id::MATCH_UA;1319            if (preg_match('/Version\/([0-9.]+)/u', $ua, $match)) {1320                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1321            }1322        }1323        /* BlackBerry Tablet OS */1324        if (preg_match('/RIM Tablet OS ([0-9.]*)/u', $ua, $match)) {1325            $this->data->os->name = 'BlackBerry Tablet OS';1326            $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1327            $this->data->device->manufacturer = 'RIM';1328            $this->data->device->model = 'BlackBerry PlayBook';1329            $this->data->device->type = Constants\DeviceType::TABLET;1330            $this->data->device->identified |= Constants\Id::MATCH_UA;1331        } elseif (preg_match('/\(PlayBook;/u', $ua) && preg_match('/PlayBook Build\/([0-9.]*)/u', $ua, $match)) {1332            $this->data->os->name = 'BlackBerry Tablet OS';1333            $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1334            $this->data->device->manufacturer = 'RIM';1335            $this->data->device->model = 'BlackBerry PlayBook';1336            $this->data->device->type = Constants\DeviceType::TABLET;1337            $this->data->device->identified |= Constants\Id::MATCH_UA;1338        } elseif (preg_match('/PlayBook/u', $ua) && !preg_match('/Android/u', $ua)) {1339            if (preg_match('/Version\/([0-9.]*)/u', $ua, $match)) {1340                $this->data->os->name = 'BlackBerry Tablet OS';1341                $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1342                $this->data->device->manufacturer = 'RIM';1343                $this->data->device->model = 'BlackBerry PlayBook';1344                $this->data->device->type = Constants\DeviceType::TABLET;1345                $this->data->device->identified |= Constants\Id::MATCH_UA;1346            }1347        }1348        /* Internal versions of BlackBerry 10 running on the Playbook */1349        if ($this->data->isOs('BlackBerry Tablet OS', '>=', 10)) {1350            $this->data->os->name = 'BlackBerry';1351        }1352    }1353    /* Chrome OS */1354    private function detectChromeos($ua)1355    {1356        /* ChromeCast */1357        if (preg_match('/CrKey/u', $ua) && !preg_match('/Espial/u', $ua)) {1358            $this->data->device->manufacturer = 'Google';1359            $this->data->device->model = 'Chromecast';1360            $this->data->device->type = Constants\DeviceType::TELEVISION;1361            $this->data->device->identified |= Constants\Id::MATCH_UA;1362            $this->data->device->generic = false;1363        }1364        /* Chrome OS */1365        if (preg_match('/CrOS/u', $ua)) {1366            $this->data->os->name = 'Chrome OS';1367            $this->data->device->type = Constants\DeviceType::DESKTOP;1368        }1369    }1370    /* Open TV */1371    private function detectOpenTV($ua)1372    {1373        if (preg_match('/OpenTV/ui', $ua, $match)) {1374            $this->data->device->type = Constants\DeviceType::TELEVISION;1375            $this->data->os->name = 'OpenTV';1376            $this->data->os->version = null;1377            if (preg_match('/OpenTV Build\/([0-9\.]+)/u', $ua, $match)) {1378                $this->data->os->version = new Version([ 'value' => $match[1] ]);1379            }1380            if (preg_match('/OpenTV ([0-9\.]+)/u', $ua, $match)) {1381                $this->data->os->version = new Version([ 'value' => $match[1] ]);1382            }1383            if (preg_match('/Opentv([0-9]+)/u', $ua, $match)) {1384                $this->data->os->version = new Version([ 'value' => $match[1] ]);1385            }1386            if (preg_match('/OTV([0-9\.]+)/u', $ua, $match)) {1387                $this->data->os->version = new Version([ 'value' => $match[1] ]);1388            }1389        }1390    }1391    /* Qtopia */1392    private function detectQtopia($ua)1393    {1394        if (preg_match('/Qtopia/u', $ua)) {1395            $this->data->os->name = 'Qtopia';1396            if (preg_match('/Qtopia\/([0-9.]+)/u', $ua, $match)) {1397                $this->data->os->version = new Version([ 'value' => $match[1] ]);1398            }1399        }1400    }1401    /* Unix */1402    private function detectUnix($ua)1403    {1404        if (!preg_match('/(UNIX|OSF|ULTRIX|HP-UX|SunOS|Solaris|AIX|IRIX|NEWS-OS|GENIX)/ui', $ua)) {1405            return;1406        }1407        /* Unix */1408        if (preg_match('/Unix/iu', $ua)) {1409            $this->data->os->name = 'Unix';1410        }1411        /* Unix System V */1412        if (preg_match('/(?:UNIX_System_V|UNIX_SV) ([0-9.]*)/u', $ua, $match)) {1413            $this->data->os->name = 'UNIX System V';1414            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1415            $this->data->os->version = new Version([ 'value' => $match[1] ]);1416            $this->data->device->type = Constants\DeviceType::DESKTOP;1417        }1418        /* Digital Unix */1419        if (preg_match('/OSF1?[ _]/u', $ua)) {1420            $this->data->os->name = 'Digital Unix';1421            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1422            if (preg_match('/OSF1?[ _]V?([0-9.]*)/u', $ua, $match)) {1423                $this->data->os->version = new Version([ 'value' => $match[1] ]);1424            }1425            $this->data->device->type = Constants\DeviceType::DESKTOP;1426        }1427        /* Digital ULTRIX */1428        if (preg_match('/ULTRIX/u', $ua)) {1429            $this->data->os->name = 'ULTRIX';1430            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1431            if (preg_match('/ULTRIX ([0-9.]*)/u', $ua, $match)) {1432                $this->data->os->version = new Version([ 'value' => $match[1] ]);1433            }1434            $this->data->device->type = Constants\DeviceType::DESKTOP;1435        }1436        /* HP-UX */1437        if (preg_match('/HP-UX/u', $ua)) {1438            $this->data->os->name = 'HP-UX';1439            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1440            if (preg_match('/HP-UX [A-Z].0?([1-9][0-9.]*)/u', $ua, $match)) {1441                $this->data->os->version = new Version([ 'value' => $match[1] ]);1442            }1443            $this->data->device->type = Constants\DeviceType::DESKTOP;1444        }1445        /* Solaris */1446        if (preg_match('/SunOS/u', $ua)) {1447            $this->data->os->name = 'Solaris';1448            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1449            if (preg_match('/SunOS ([1234]\.[0-9\.]+)/u', $ua, $match)) {1450                $this->data->os->name = 'SunOS';1451                $this->data->os->version = new Version([ 'value' => $match[1] ]);1452                $this->data->os->family = new Family([ 'name' => 'BSD' ]);1453                if (preg_match('/SunOS 4\.1\.([1234])/u', $ua, $match)) {1454                    $this->data->os->name = 'Solaris';1455                    switch ($match[1]) {1456                        case '1':1457                            $this->data->os->version = new Version([ 'value' => '1.0' ]);1458                            break;1459                        case '2':1460                            $this->data->os->version = new Version([ 'value' => '1.0.1' ]);1461                            break;1462                        case '3':1463                            $this->data->os->version = new Version([ 'value' => '1.1' ]);1464                            break;1465                        case '4':1466                            $this->data->os->version = new Version([ 'value' => '1.1.2' ]);1467                            break;1468                    }1469                }1470            }1471            if (preg_match('/SunOS 5\.([123456](?:\.[0-9\.]*)?) /u', $ua, $match)) {1472                $this->data->os->version = new Version([ 'value' => '2.' . $match[1] ]);1473            } else if (preg_match('/SunOS 5\.([0-9\.]*)/u', $ua, $match)) {1474                $this->data->os->version = new Version([ 'value' => $match[1] ]);1475            }1476            $this->data->device->type = Constants\DeviceType::DESKTOP;1477        }1478        if (preg_match('/Solaris(?: ([0-9\.]+))?;/u', $ua, $match)) {1479            $this->data->os->name = 'Solaris';1480            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1481            if (preg_match('/Solaris ([0-9\.]+);/u', $ua, $match)) {1482                $this->data->os->version = new Version([ 'value' => $match[1] ]);1483            }1484            $this->data->device->type = Constants\DeviceType::DESKTOP;1485        }1486        /* AIX */1487        if (preg_match('/AIX/u', $ua)) {1488            $this->data->os->name = 'AIX';1489            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1490            if (preg_match('/AIX ([0-9.]*)/u', $ua, $match)) {1491                $this->data->os->version = new Version([ 'value' => $match[1] ]);1492            }1493            $this->data->device->type = Constants\DeviceType::DESKTOP;1494        }1495        /* IRIX */1496        if (preg_match('/IRIX/u', $ua)) {1497            $this->data->os->name = 'IRIX';1498            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1499            if (preg_match('/IRIX ([0-9.]*)/u', $ua, $match)) {1500                $this->data->os->version = new Version([ 'value' => $match[1] ]);1501            }1502            if (preg_match('/IRIX;?(?:64|32) ([0-9.]*)/u', $ua, $match)) {1503                $this->data->os->version = new Version([ 'value' => $match[1] ]);1504            }1505            $this->data->device->type = Constants\DeviceType::DESKTOP;1506        }1507        /* Sony NEWS OS */1508        if (preg_match('/NEWS-OS ([0-9\.]+)/u', $ua, $match)) {1509            $this->data->os->name = 'NEWS OS';1510            $this->data->os->version = new Version([ 'value' => $match[1] ]);1511            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1512            if (preg_match('/NEWS-OS [56]/u', $ua)) {1513                $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1514            }1515            $this->data->device->type = Constants\DeviceType::DESKTOP;1516        }1517        /* NEC EWS-UX */1518        if (preg_match('/EWS-UNIX rev ([0-9\.]+)/u', $ua, $match)) {1519            $this->data->os->name = 'EWS-UX';1520            $this->data->os->version = new Version([ 'value' => $match[1] ]);1521            $this->data->os->family = new Family([ 'name' => 'UNIX' ]);1522            $this->data->device->type = Constants\DeviceType::DESKTOP;1523        }1524        /* National Semiconductors GENIX */1525        if (preg_match('/GENIX ([0-9\.]+)/u', $ua, $match)) {1526            $this->data->os->name = 'GENIX';1527            $this->data->os->version = new Version([ 'value' => $match[1] ]);1528            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1529            $this->data->device->type = Constants\DeviceType::DESKTOP;1530        }1531    }1532    /* BSD */1533    private function detectBsd($ua)1534    {1535        if (!preg_match('/(BSD|DragonFly)/ui', $ua)) {1536            return;1537        }1538        if (preg_match('/X11/u', $ua)) {1539            $this->data->device->type = Constants\DeviceType::DESKTOP;1540        }1541        /* BSD/OS */1542        if (preg_match('/BSD\/386/u', $ua)) {1543            $this->data->os->name = 'BSD/OS';1544            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1545        }1546        if (preg_match('/BSD\/OS/u', $ua)) {1547            $this->data->os->name = 'BSD/OS';1548            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1549            if (preg_match('/BSD\/OS ([0-9.]*)/u', $ua, $match)) {1550                $this->data->os->version = new Version([ 'value' => $match[1] ]);1551            }1552        }1553        /* FreeBSD */1554        if (preg_match('/FreeBSD/iu', $ua)) {1555            $this->data->os->name = 'FreeBSD';1556            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1557            if (preg_match('/FreeBSD[ -\/]?([0-9.]*)/iu', $ua, $match)) {1558                $this->data->os->version = new Version([ 'value' => $match[1] ]);1559            }1560        }1561        /* OpenBSD */1562        if (preg_match('/OpenBSD/iu', $ua)) {1563            $this->data->os->name = 'OpenBSD';1564            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1565            if (preg_match('/OpenBSD ?([0-9.]*)/iu', $ua, $match)) {1566                $this->data->os->version = new Version([ 'value' => $match[1] ]);1567            }1568        }1569        /* NetBSD */1570        if (preg_match('/NetBSD/iu', $ua)) {1571            $this->data->os->name = 'NetBSD';1572            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1573            if (preg_match('/NetBSD ?([0-9.]*)/iu', $ua, $match)) {1574                $this->data->os->version = new Version([ 'value' => $match[1] ]);1575            }1576        }1577        /* DragonFly */1578        if (preg_match('/DragonFly/iu', $ua)) {1579            $this->data->os->name = 'DragonFly BSD';1580            $this->data->os->family = new Family([ 'name' => 'BSD' ]);1581        }1582    }1583    /* Linux */1584    private function detectLinux($ua)1585    {1586        if (preg_match('/Linux/u', $ua)) {1587            $this->data->os->name = 'Linux';1588            if (preg_match('/X11/u', $ua)) {1589                $this->data->device->type = Constants\DeviceType::DESKTOP;1590            }1591            if (preg_match('/Antergos Linux/u', $ua)) {1592                $this->data->os->name = 'Antergos Linux';1593                $this->data->device->type = Constants\DeviceType::DESKTOP;1594            }1595            if (preg_match('/Arch ?Linux/u', $ua)) {1596                $this->data->os->name = 'Arch Linux';1597                $this->data->device->type = Constants\DeviceType::DESKTOP;1598            }1599            if (preg_match('/Black Lab Linux/u', $ua)) {1600                $this->data->os->name = 'Black Lab Linux';1601                if (preg_match('/Black Lab Linux ([0-9\.]+)/u', $ua, $match)) {1602                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1603                }1604                $this->data->device->type = Constants\DeviceType::DESKTOP;1605            }1606            if (preg_match('/CentOS/u', $ua)) {1607                $this->data->os->name = 'CentOS';1608                if (preg_match('/CentOS\/[0-9\.\-]+el([0-9_]+)/u', $ua, $match)) {1609                    $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1610                }1611                if (preg_match('/CentOS Linux release ([0-9\.]+)/u', $ua, $match)) {1612                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1613                }1614                $this->data->device->type = Constants\DeviceType::DESKTOP;1615            }1616            if (preg_match('/Debian/u', $ua)) {1617                $this->data->os->name = 'Debian';1618                if (preg_match('/Debian\/([0-9.]*)/iu', $ua, $match)) {1619                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1620                }1621                if (preg_match('/Debian GNU\/Linux ([0-9\.]+)/u', $ua, $match)) {1622                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1623                }1624                $this->data->device->type = Constants\DeviceType::DESKTOP;1625            }1626            if (preg_match('/Fedora/u', $ua)) {1627                $this->data->os->name = 'Fedora';1628                if (preg_match('/Fedora\/[0-9\.\-]+fc([0-9]+)/u', $ua, $match)) {1629                    $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1630                }1631                if (preg_match('/Fedora release ([0-9\.]+)/u', $ua, $match)) {1632                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1633                }1634                $this->data->device->type = Constants\DeviceType::DESKTOP;1635            }1636            if (preg_match('/Gentoo/u', $ua)) {1637                $this->data->os->name = 'Gentoo';1638                if (preg_match('/Gentoo Base System release ([0-9\.]+)/u', $ua, $match)) {1639                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1640                }1641                $this->data->device->type = Constants\DeviceType::DESKTOP;1642            }1643            if (preg_match('/gNewSense/u', $ua)) {1644                $this->data->os->name = 'gNewSense';1645                if (preg_match('/gNewSense\/[^\(]+\(([0-9\.]+)/u', $ua, $match)) {1646                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1647                }1648                $this->data->device->type = Constants\DeviceType::DESKTOP;1649            }1650            if (preg_match('/Kubuntu/u', $ua)) {1651                $this->data->os->name = 'Kubuntu';1652                if (preg_match('/Kubuntu[ \/]([0-9.]*)/iu', $ua, $match)) {1653                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1654                }1655                $this->data->device->type = Constants\DeviceType::DESKTOP;1656            }1657            if (preg_match('/Linux Mint/u', $ua)) {1658                $this->data->os->name = 'Linux Mint';1659                if (preg_match('/Linux Mint ([0-9\.]+)/iu', $ua, $match)) {1660                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1661                }1662                $this->data->device->type = Constants\DeviceType::DESKTOP;1663            }1664            if (preg_match('/Mandriva Linux/u', $ua)) {1665                $this->data->os->name = 'Mandriva';1666                if (preg_match('/Mandriva Linux\/[0-9\.\-]+mdv([0-9]+)/u', $ua, $match)) {1667                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1668                }1669                $this->data->device->type = Constants\DeviceType::DESKTOP;1670            }1671            if (preg_match('/Mageia/u', $ua)) {1672                $this->data->os->name = 'Mageia';1673                if (preg_match('/Mageia\/[0-9\.\-]+mga([0-9]+)/u', $ua, $match)) {1674                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1675                }1676                if (preg_match('/Mageia ([0-9\.]+)/iu', $ua, $match)) {1677                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1678                }1679                $this->data->device->type = Constants\DeviceType::DESKTOP;1680            }1681            if (preg_match('/Mandriva/u', $ua)) {1682                $this->data->os->name = 'Mandriva';1683                if (preg_match('/Mandriva\/[0-9\.\-]+mdv([0-9]+)/u', $ua, $match)) {1684                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1685                }1686                $this->data->device->type = Constants\DeviceType::DESKTOP;1687            }1688            if (preg_match('/moonOS/u', $ua)) {1689                $this->data->os->name = 'moonOS';1690                if (preg_match('/moonOS\/([0-9.]+)/u', $ua, $match)) {1691                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1692                }1693                $this->data->device->type = Constants\DeviceType::DESKTOP;1694            }1695            if (preg_match('/Red Hat/u', $ua)) {1696                $this->data->os->name = 'Red Hat';1697                if (preg_match('/Red Hat[^\/]*\/[0-9\.\-]+el([0-9_]+)/u', $ua, $match)) {1698                    $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1699                }1700                $this->data->device->type = Constants\DeviceType::DESKTOP;1701            }1702            if (preg_match('/Slackware/u', $ua)) {1703                $this->data->os->name = 'Slackware';1704                if (preg_match('/Slackware[ \/](1[0-9.]+)/u', $ua, $match)) {1705                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1706                }1707                $this->data->device->type = Constants\DeviceType::DESKTOP;1708            }1709            if (preg_match('/SUSE/u', $ua)) {1710                $this->data->os->name = 'SUSE';1711                if (preg_match('/SUSE\/([0-9]\.[0-9]+)/u', $ua, $match)) {1712                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1713                }1714                if (preg_match('/openSUSE ([0-9\.]+)/iu', $ua, $match)) {1715                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1716                }1717                $this->data->device->type = Constants\DeviceType::DESKTOP;1718            }1719            if (preg_match('/Turbolinux/u', $ua)) {1720                $this->data->os->name = 'Turbolinux';1721                if (preg_match('/Turbolinux\/([0-9]\.[0-9]+)/u', $ua, $match)) {1722                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1723                }1724                $this->data->device->type = Constants\DeviceType::DESKTOP;1725            }1726            if (preg_match('/Ubuntu/u', $ua)) {1727                $this->data->os->name = 'Ubuntu';1728                if (preg_match('/Ubuntu\/([0-9.]*)/u', $ua, $match)) {1729                    $this->data->os->version = new Version([ 'value' => $match[1] ]);1730                }1731                if (preg_match('/Ubuntu ([0-9\.]+)/iu', $ua, $match)) {1732                    $this->data->os->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1733                }1734                $this->data->device->type = Constants\DeviceType::DESKTOP;1735            }1736            if (preg_match('/ãë¶ìë³ã\/([0-9.]*)/iu', $ua, $match)) {1737                $this->data->os->name = 'Red Star';1738                $this->data->os->version = new Version([ 'value' => $match[1] ]);1739                $this->data->device->type = Constants\DeviceType::DESKTOP;1740            }1741            if (preg_match('/Fedora\/[0-9\.\-]+rs([0-9\.]+)/u', $ua, $match)) {1742                $this->data->os->name = 'Red Star';1743                $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1744                $this->data->device->type = Constants\DeviceType::DESKTOP;1745            }1746            if (preg_match('/Linux\/X2\/R1/u', $ua)) {1747                $this->data->os->name = 'LiMo';1748                $this->data->device->type = Constants\DeviceType::MOBILE;1749            }1750            if (preg_match('/Linux\/SLP\/([0-9.]+)/u', $ua, $match)) {1751                $this->data->os->name = 'Linux SLP';1752                $this->data->os->version = new Version([ 'value' => $match[1] ]);1753                $this->data->device->type = Constants\DeviceType::MOBILE;1754            }1755            if (preg_match('/LinuxOS\//u', $ua) && preg_match('/Software\/R5/u', $ua)) {1756                $this->data->os->name = 'EZX Linux';1757                $this->data->device->type = Constants\DeviceType::MOBILE;1758            }1759        }1760        if (preg_match('/elementary OS/u', $ua)) {1761            $this->data->os->name = 'elementary OS';1762            if (preg_match('/elementary OS ([A-Za-z]+)/u', $ua, $match)) {1763                $this->data->os->version = new Version([ 'alias' => $match[1] ]);1764            }1765            $this->data->device->type = Constants\DeviceType::DESKTOP;1766        }1767        if (preg_match('/\(Ubuntu; (Mobile|Tablet)/u', $ua)) {1768            $this->data->os->name = 'Ubuntu Touch';1769            if (preg_match('/\(Ubuntu; Mobile/u', $ua)) {1770                $this->data->device->type = Constants\DeviceType::MOBILE;1771            }1772            if (preg_match('/\(Ubuntu; Tablet/u', $ua)) {1773                $this->data->device->type = Constants\DeviceType::TABLET;1774            }1775        }1776        if (preg_match('/(?:\(|; )Ubuntu ([0-9.]+) like Android/u', $ua, $match)) {1777            $this->data->os->name = 'Ubuntu Touch';1778            $this->data->os->version = new Version([ 'value' => $match[1] ]);1779            $this->data->device->type = Constants\DeviceType::MOBILE;1780        }1781        if (preg_match('/Lindows ([0-9.]+)/u', $ua, $match)) {1782            $this->data->os->name = 'Lindows';1783            $this->data->os->version = new Version([ 'value' => $match[1] ]);1784            $this->data->device->type = Constants\DeviceType::DESKTOP;1785        }1786    }1787    /* Brew */1788    private function detectBrew($ua)1789    {1790        if (preg_match('/REX; U/ui', $ua) || preg_match('/REXL4/ui', $ua)) {1791            $this->data->os->name = 'REX';1792            $this->data->device->type = Constants\DeviceType::MOBILE;1793            if (preg_match('/REX; U; [^;]+; ([^;]+); ([^;\/]+)[^;]*; NetFront/u', $ua, $match)) {1794                $this->data->device->manufacturer = Data\Manufacturers::identify(Constants\DeviceType::MOBILE, $match[1]);1795                $this->data->device->model = $match[2];1796                $this->data->device->identified = Constants\Id::PATTERN;1797                $device = Data\DeviceModels::identify('brew', $match[2]);1798                if ($device->identified) {1799                    $device->identified |= $this->data->device->identified;1800                    $this->data->device = $device;1801                }1802            }1803        }1804        if (preg_match('/[\(\s\-;]BREW[\s\/\-;]/ui', $ua) || preg_match('/BMP( [0-9.]*)?; U/u', $ua) || preg_match('/B(?:rew)?MP\/([0-9.]*)/u', $ua)) {1805            $this->data->os->name = 'Brew';1806            if (preg_match('/BREW MP/iu', $ua) || preg_match('/B(rew)?MP/iu', $ua)) {1807                $this->data->os->name = 'Brew MP';1808            }1809            if (preg_match('/; Brew ([0-9.]+);/iu', $ua, $match)) {1810                $this->data->os->version = new Version([ 'value' => $match[1] ]);1811            } elseif (preg_match('/BREW; U; ([0-9.]+)/iu', $ua, $match)) {1812                $this->data->os->version = new Version([ 'value' => $match[1] ]);1813            } elseif (preg_match('/[\(;]BREW[\/ ]([0-9.]+)/iu', $ua, $match)) {1814                $this->data->os->version = new Version([ 'value' => $match[1] ]);1815            } elseif (preg_match('/BREW MP ([0-9.]*)/iu', $ua, $match)) {1816                $this->data->os->version = new Version([ 'value' => $match[1] ]);1817            } elseif (preg_match('/BMP ([0-9.]*); U/iu', $ua, $match)) {1818                $this->data->os->version = new Version([ 'value' => $match[1] ]);1819            } elseif (preg_match('/B(?:rew)?MP\/([0-9.]*)/iu', $ua, $match)) {1820                $this->data->os->version = new Version([ 'value' => $match[1] ]);1821            }1822            $this->data->device->type = Constants\DeviceType::MOBILE;1823            if (preg_match('/(?:Brew MP|BREW|BMP) [^;]+; U; [^;]+; ([^;]+); NetFront[^\)]+\) [^\s]+ ([^\s]+)/u', $ua, $match)) {1824                $this->data->device->manufacturer = Data\Manufacturers::identify(Constants\DeviceType::MOBILE, $match[1]);1825                $this->data->device->model = $match[2];1826                $this->data->device->identified = Constants\Id::PATTERN;1827                $device = Data\DeviceModels::identify('brew', $match[2]);1828                if ($device->identified) {1829                    $device->identified |= $this->data->device->identified;1830                    $this->data->device = $device;1831                }1832            }1833            if (preg_match('/\(([^;]+);U;REX\/[^;]+;BREW\/[^;]+;(?:.*;)?[0-9]+\*[0-9]+(?:;CTC\/2.0)?\)/u', $ua, $match)) {1834                $this->data->device->model = $match[1];1835                $this->data->device->identified = Constants\Id::PATTERN;1836                $device = Data\DeviceModels::identify('brew', $match[1]);1837                if ($device->identified) {1838                    $device->identified |= $this->data->device->identified;1839                    $this->data->device = $device;1840                }1841            }1842            if (preg_match('/\(BREW [^;]+; U; [^;]+; [^;]+; ([^;]+); (Polaris|Netfront)\/[0-9\.]+\/(WAP|AMB|INT)\)/ui', $ua, $match)) {1843                $this->data->device->model = $match[1];1844                $this->data->device->identified = Constants\Id::PATTERN;1845                $device = Data\DeviceModels::identify('brew', $match[1]);1846                if ($device->identified) {1847                    $device->identified |= $this->data->device->identified;1848                    $this->data->device = $device;1849                }1850            }1851            if (preg_match('/\(BREW [^;]+; U; [^;]+; [^;]+; Opera Mobi; Presto\/[0-9\.]+\/(?:WAP|AMB|INT)\) ([^\/]+) [^\/]+\//ui', $ua, $match)) {1852                $this->data->device->model = $match[1];1853                $this->data->device->identified = Constants\Id::PATTERN;1854                $device = Data\DeviceModels::identify('brew', $match[1]);1855                if ($device->identified) {1856                    $device->identified |= $this->data->device->identified;1857                    $this->data->device = $device;1858                }1859            }1860        }1861    }1862    /* Remaining operating systems */1863    private function detectRemainingOperatingSystems($ua)1864    {1865        if (!preg_match('/(BeOS|Haiku|AmigaOS|MorphOS|AROS|VMS|RISC|Joli|OS\/2|Inferno|Syllable|Grid|MTK|MRE|MAUI|Nucleus|QNX|VRE|SpreadTrum|ThreadX)/ui', $ua)) {1866            return;1867        }1868        $patterns = [1869            [ 'name' => 'BeOS',         'regexp' => [ '/BeOS/iu' ],                                         'type' => Constants\DeviceType::DESKTOP ],1870            [ 'name' => 'Haiku',        'regexp' => [ '/Haiku/iu' ],                                        'type' => Constants\DeviceType::DESKTOP ],1871            [ 'name' => 'AmigaOS',      'regexp' => [ '/AmigaOS ?([0-9.]+)/iu', '/AmigaOS/iu' ],            'type' => Constants\DeviceType::DESKTOP ],1872            [ 'name' => 'MorphOS',      'regexp' => [ '/MorphOS(?: ([0-9.]*))?/iu' ],                       'type' => Constants\DeviceType::DESKTOP ],1873            [ 'name' => 'AROS',         'regexp' => [ '/AROS/iu' ],                                         'type' => Constants\DeviceType::DESKTOP ],1874            [ 'name' => 'OpenVMS',      'regexp' => [ '/OpenVMS V([0-9.]+)/iu', '/OpenVMS/iu' ],            'type' => Constants\DeviceType::DESKTOP ],1875            [ 'name' => 'RISC OS',      'regexp' => [ '/RISC OS(?:-NC)? ([0-9.]*)/iu', '/RISC OS/iu' ],     'type' => Constants\DeviceType::DESKTOP ],1876            [ 'name' => 'Joli OS',      'regexp' => [ '/Joli OS\/([0-9.]*)/iu' ],                           'type' => Constants\DeviceType::DESKTOP ],1877            [ 'name' => 'OS/2',         'regexp' => [ '/OS\/2;(?: (?:U; )?Warp ([0-9.]*))?/iu' ],           'type' => Constants\DeviceType::DESKTOP ],1878            [ 'name' => 'Inferno',      'regexp' => [ '/Inferno/iu' ],                                      'type' => Constants\DeviceType::DESKTOP ],1879            [ 'name' => 'Syllable',     'regexp' => [ '/Syllable/iu' ],                                     'type' => Constants\DeviceType::DESKTOP ],1880            [ 'name' => 'Grid OS',      'regexp' => [ '/Grid OS ([0-9.]*)/iu' ],                            'type' => Constants\DeviceType::TABLET ],1881            [ 'name' => 'MRE',          'regexp' => [ '/\(MTK;/iu', '/\/MTK /iu' ],                         'type' => Constants\DeviceType::MOBILE ],1882            [ 'name' => 'MRE',          'regexp' => [ '/MRE\\\\/iu' ],                                      'type' => Constants\DeviceType::MOBILE ],1883            [ 'name' => 'MRE',          'regexp' => [ '/MAUI[-_ ](?:Browser|Runtime)/iu' ],                 'type' => Constants\DeviceType::MOBILE ],1884            [ 'name' => 'MRE',          'regexp' => [ '/Browser\/MAUI/iu' ],                                'type' => Constants\DeviceType::MOBILE ],1885            [ 'name' => 'MRE',          'regexp' => [ '/Nucleus RTOS\//iu' ],                               'type' => Constants\DeviceType::MOBILE ],1886            [ 'name' => 'MRE',          'regexp' => [ '/\/Nucleus/iu' ],                                    'type' => Constants\DeviceType::MOBILE ],1887            [ 'name' => 'MRE',          'regexp' => [ '/Nucleus\//iu' ],                                    'type' => Constants\DeviceType::MOBILE ],1888            [ 'name' => 'QNX',          'regexp' => [ '/QNX/iu' ],                                          'type' => Constants\DeviceType::MOBILE ],1889            [ 'name' => 'VRE',          'regexp' => [ '/\(VRE;/iu' ],                                       'type' => Constants\DeviceType::MOBILE ],1890            [ 'name' => 'SpreadTrum',   'regexp' => [ '/\(SpreadTrum;/iu' ],                                'type' => Constants\DeviceType::MOBILE ],1891            [ 'name' => 'ThreadX',      'regexp' => [ '/ThreadX(?:_OS)?\/([0-9.]*)/iu' ] ],1892        ];1893        $count = count($patterns);1894        for ($b = 0; $b < $count; $b++) {1895            for ($r = 0; $r < count($patterns[$b]['regexp']); $r++) {1896                if (preg_match($patterns[$b]['regexp'][$r], $ua, $match)) {1897                    $this->data->os->name = $patterns[$b]['name'];1898                    if (isset($match[1]) && $match[1]) {1899                        $this->data->os->version = new Version([ 'value' => $match[1], 'details' => isset($patterns[$b]['details']) ? $patterns[$b]['details'] : null ]);1900                    } else {1901                        $this->data->os->version = null;1902                    }1903                    if (isset($patterns[$b]['type'])) {1904                        $this->data->device->type = $patterns[$b]['type'];1905                    }1906                    break;1907                }1908            }1909        }1910    }1911}...Browser.php
Source:Browser.php  
...55    }56    /* Safari */57    private function detectSafari($ua)58    {59        if (preg_match('/Safari/u', $ua)) {60            $falsepositive = false;61            if (preg_match('/Qt/u', $ua)) {62                $falsepositive = true;63            }64            if (!$falsepositive) {65                if (isset($this->data->os->name) && $this->data->os->name == 'iOS') {66                    $this->data->browser->name = 'Safari';67                    $this->data->browser->type = Constants\BrowserType::BROWSER;68                    $this->data->browser->version = null;69                    $this->data->browser->stock = true;70                    if (preg_match('/Version\/([0-9\.]+)/u', $ua, $match)) {71                        $this->data->browser->version = new Version([ 'value' => $match[1], 'hidden' => true ]);72                    }73                }74                if (isset($this->data->os->name) && ($this->data->os->name == 'OS X' || $this->data->os->name == 'Windows')) {75                    $this->data->browser->name = 'Safari';76                    $this->data->browser->type = Constants\BrowserType::BROWSER;77                    $this->data->browser->stock = $this->data->os->name == 'OS X';78                    if (preg_match('/Version\/([0-9\.]+)/u', $ua, $match)) {79                        $this->data->browser->version = new Version([ 'value' => $match[1] ]);80                    }81                    if (preg_match('/AppleWebKit\/[0-9\.]+\+/u', $ua)) {82                        $this->data->browser->name = 'WebKit Nightly Build';83                        $this->data->browser->version = null;84                    }85                }86            }87        }88        if (preg_match('/(?:Apple-PubSub|AppleSyndication)\//u', $ua)) {89            $this->data->browser->name = 'Safari RSS';90            $this->data->browser->type = Constants\BrowserType::APP_FEEDREADER;91            $this->data->browser->version = null;92            $this->data->browser->stock = true;93            $this->data->os->name = 'OS X';94            $this->data->os->version = null;95            $this->data->device->type = Constants\DeviceType::DESKTOP;96        }97    }98    /* Chrome */99    private function detectChrome($ua)100    {101        if (preg_match('/(?:Chrome|CrMo|CriOS)\/[0-9]/u', $ua) || preg_match('/Browser\/Chrome[0-9]/u', $ua)) {102            $this->data->browser->name = 'Chrome';103            $this->data->browser->type = Constants\BrowserType::BROWSER;104            $this->data->browser->stock = false;105            $version = '';106            if (preg_match('/(?:Chrome|CrMo|CriOS)\/([0-9.]*)/u', $ua, $match)) {107                $version = $match[1];108            }109            if (preg_match('/Browser\/Chrome([0-9.]*)/u', $ua, $match)) {110                $version = $match[1];111            }112            $this->data->browser->version = new Version([ 'value' => $version ]);113            if (isset($this->data->os->name) && $this->data->os->name == 'Android') {114                $channel = Data\Chrome::getChannel('mobile', $this->data->browser->version->value);115                if ($channel == 'stable') {116                    $this->data->browser->version->details = 1;117                } elseif ($channel == 'beta') {118                    $this->data->browser->channel = 'Beta';119                } else {120                    $this->data->browser->channel = 'Dev';121                }122                /* Webview for Android 4.4 and higher */123                if (implode('.', array_slice(explode('.', $version), 1, 2)) == '0.0' && (preg_match('/Version\//u', $ua) || preg_match('/Release\//u', $ua))) {124                    $this->data->browser->using = new Using([ 'name' => 'Chromium WebView', 'version' => new Version([ 'value' => explode('.', $version)[0] ]) ]);125                    $this->data->browser->type = Constants\BrowserType::UNKNOWN;126                    $this->data->browser->stock = true;127                    $this->data->browser->name = null;128                    $this->data->browser->version = null;129                    $this->data->browser->channel = null;130                }131                /* Webview for Android 5 */132                if (preg_match('/; wv\)/u', $ua)) {133                    $this->data->browser->using = new Using([ 'name' => 'Chromium WebView', 'version' => new Version([ 'value' => explode('.', $version)[0] ]) ]);134                    $this->data->browser->type = Constants\BrowserType::UNKNOWN;135                    $this->data->browser->stock = true;136                    $this->data->browser->name = null;137                    $this->data->browser->version = null;138                    $this->data->browser->channel = null;139                }140                /* LG Chromium based browsers */141                if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'LG') {142                    if (in_array($version, [ '30.0.1599.103', '34.0.1847.118', '38.0.2125.0', '38.0.2125.102' ]) && preg_match('/Version\/4/u', $ua) && !preg_match('/; wv\)/u', $ua)) {143                        $this->data->browser->name = "LG Browser";144                        $this->data->browser->channel = null;145                        $this->data->browser->stock = true;146                        $this->data->browser->version = null;147                    }148                }149                /* Samsung Chromium based browsers */150                if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Samsung') {151                    /* Version 1.0 */152                    if ($version == '18.0.1025.308' && preg_match('/Version\/1.0/u', $ua)) {153                        $this->data->browser->name = "Samsung Internet";154                        $this->data->browser->channel = null;155                        $this->data->browser->stock = true;156                        $this->data->browser->version = new Version([ 'value' => '1.0' ]);157                    }158                    /* Version 1.5 */159                    if ($version == '28.0.1500.94' && preg_match('/Version\/1.5/u', $ua)) {160                        $this->data->browser->name = "Samsung Internet";161                        $this->data->browser->channel = null;162                        $this->data->browser->stock = true;163                        $this->data->browser->version = new Version([ 'value' => '1.5' ]);164                    }165                    /* Version 1.6 */166                    if ($version == '28.0.1500.94' && preg_match('/Version\/1.6/u', $ua)) {167                        $this->data->browser->name = "Samsung Internet";168                        $this->data->browser->channel = null;169                        $this->data->browser->stock = true;170                        $this->data->browser->version = new Version([ 'value' => '1.6' ]);171                    }172                    /* Version 2.0 */173                    if ($version == '34.0.1847.76' && preg_match('/Version\/2.0/u', $ua)) {174                        $this->data->browser->name = "Samsung Internet";175                        $this->data->browser->channel = null;176                        $this->data->browser->stock = true;177                        $this->data->browser->version = new Version([ 'value' => '2.0' ]);178                    }179                    /* Version 2.1 */180                    if ($version == '34.0.1847.76' && preg_match('/Version\/2.1/u', $ua)) {181                        $this->data->browser->name = "Samsung Internet";182                        $this->data->browser->channel = null;183                        $this->data->browser->stock = true;184                        $this->data->browser->version = new Version([ 'value' => '2.1' ]);185                    }186                }187                /* Samsung Chromium based browsers */188                if (preg_match('/SamsungBrowser\/([0-9.]*)/u', $ua, $match)) {189                    $this->data->browser->name = "Samsung Internet";190                    $this->data->browser->channel = null;191                    $this->data->browser->stock = true;192                    $this->data->browser->version = new Version([ 'value' => $match[1] ]);193                    if (preg_match('/Mobile VR/', $ua)) {194                        $this->data->device->manufacturer = 'Samsung';195                        $this->data->device->model = 'Gear VR';196                        $this->data->device->type = Constants\DeviceType::HEADSET;197                    }198                }199                /* Oculus Chromium based browsers */200                if (preg_match('/OculusBrowser\/([0-9.]*)/u', $ua, $match)) {201                    $this->data->browser->name = "Oculus Browser";202                    $this->data->browser->channel = null;203                    $this->data->browser->stock = true;204                    $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);205                    if (preg_match('/Mobile VR/', $ua)) {206                        $this->data->device->manufacturer = 'Samsung';207                        $this->data->device->model = 'Gear VR';208                        $this->data->device->type = Constants\DeviceType::HEADSET;209                    }210                    if (preg_match('/Pacific/', $ua)) {211                        $this->data->device->manufacturer = 'Oculus';212                        $this->data->device->model = 'Go';213                        $this->data->device->type = Constants\DeviceType::HEADSET;214                    }215                }216            } elseif (isset($this->data->os->name) && $this->data->os->name == 'Linux' && preg_match('/SamsungBrowser\/([0-9.]*)/u', $ua, $match)) {217                $this->data->browser->name = "Samsung Internet";218                $this->data->browser->channel = null;219                $this->data->browser->stock = true;220                $this->data->browser->version = new Version([ 'value' => $match[1] ]);221                $this->data->os->name = 'Android';222                $this->data->os->version = null;223                $this->data->device->manufacturer = 'Samsung';224                $this->data->device->model = 'DeX';225                $this->data->device->identifier = '';226                $this->data->device->identified |= Constants\Id::PATTERN;227                $this->data->device->type = Constants\DeviceType::DESKTOP;228            } else {229                $channel = Data\Chrome::getChannel('desktop', $version);230                if ($channel == 'stable') {231                    if (explode('.', $version)[1] == '0') {232                        $this->data->browser->version->details = 1;233                    } else {234                        $this->data->browser->version->details = 2;235                    }236                } elseif ($channel == 'beta') {237                    $this->data->browser->channel = 'Beta';238                } else {239                    $this->data->browser->channel = 'Dev';240                }241            }242            if ($this->data->device->type == '') {243                $this->data->device->type = Constants\DeviceType::DESKTOP;244            }245        }246        /* Google Chromium */247        if (preg_match('/Chromium/u', $ua)) {248            $this->data->browser->stock = false;249            $this->data->browser->channel = '';250            $this->data->browser->name = 'Chromium';251            $this->data->browser->type = Constants\BrowserType::BROWSER;252            if (preg_match('/Chromium\/([0-9.]*)/u', $ua, $match)) {253                $this->data->browser->version = new Version([ 'value' => $match[1] ]);254            }255            if ($this->data->device->type == '') {256                $this->data->device->type = Constants\DeviceType::DESKTOP;257            }258        }259        /* Chrome Content Shell */260        if (preg_match('/Chrome\/[0-9]+\.77\.34\.5/u', $ua)) {261            $this->data->browser->using = new Using([ 'name' => 'Chrome Content Shell' ]);262            $this->data->browser->type = Constants\BrowserType::UNKNOWN;263            $this->data->browser->stock = false;264            $this->data->browser->name = null;265            $this->data->browser->version = null;266            $this->data->browser->channel = null;267        }268        /* Chromium WebView by Amazon */269        if (preg_match('/AmazonWebAppPlatform\//u', $ua)) {270            $this->data->browser->using = new Using([ 'name' => 'Amazon WebView' ]);271            $this->data->browser->type = Constants\BrowserType::UNKNOWN;272            $this->data->browser->stock = false;273            $this->data->browser->name = null;274            $this->data->browser->version = null;275            $this->data->browser->channel = null;276        }277        /* Chromium WebView by Crosswalk */278        if (preg_match('/Crosswalk\/([0-9.]*)/u', $ua, $match)) {279            $this->data->browser->using = new Using([ 'name' => 'Crosswalk WebView', 'version' => new Version([ 'value' => $match[1], 'details' => 1 ]) ]);280            $this->data->browser->type = Constants\BrowserType::UNKNOWN;281            $this->data->browser->stock = false;282            $this->data->browser->name = null;283            $this->data->browser->version = null;284            $this->data->browser->channel = null;285        }286        /* Set the browser family */287        if ($this->data->isBrowser('Chrome') || $this->data->isBrowser('Chromium')) {288            $this->data->browser->family = new Family([289                'name'      => 'Chrome',290                'version'   => !empty($this->data->browser->version) ? new Version([ 'value' => $this->data->browser->version->getMajor() ]) : null291            ]);292        }293    }294    /* Internet Explorer */295    private function detectExplorer($ua)296    {297        if (preg_match('/\(IE ([0-9.]*)/u', $ua, $match)) {298            $this->data->browser->name = 'Internet Explorer';299            $this->data->browser->version = new Version([ 'value' => $match[1] ]);300            $this->data->browser->type = Constants\BrowserType::BROWSER;301        }302        if (preg_match('/Browser\/IE([0-9.]*)/u', $ua, $match)) {303            $this->data->browser->name = 'Internet Explorer';304            $this->data->browser->version = new Version([ 'value' => $match[1] ]);305            $this->data->browser->type = Constants\BrowserType::BROWSER;306        }307        if (preg_match('/MSIE/u', $ua)) {308            $this->data->browser->name = 'Internet Explorer';309            $this->data->browser->type = Constants\BrowserType::BROWSER;310            if (preg_match('/IEMobile/u', $ua) || preg_match('/Windows CE/u', $ua) || preg_match('/Windows Phone/u', $ua) || preg_match('/WP7/u', $ua) || preg_match('/WPDesktop/u', $ua)) {311                $this->data->browser->name = 'Mobile Internet Explorer';312                if (isset($this->data->device->model) && ($this->data->device->model == 'Xbox 360' || $this->data->device->model == 'Xbox One')) {313                    $this->data->browser->name = 'Internet Explorer';314                }315            }316            if (preg_match('/MSIE ([0-9.]*)/u', $ua, $match)) {317                $this->data->browser->version = new Version([ 'value' => preg_replace("/\.([0-9])([0-9])/", '.$1.$2', $match[1]) ]);318            }319            if (preg_match('/Mac_/u', $ua)) {320                $this->data->os->name = 'Mac OS';321                $this->data->engine->name = 'Tasman';322                $this->data->device->type = Constants\DeviceType::DESKTOP;323                if (!empty($this->data->browser->version)) {324                    if ($this->data->browser->version->is('>=', '5.1.1') && $this->data->browser->version->is('<=', '5.1.3')) {325                        $this->data->os->name = 'OS X';326                    }327                    if ($this->data->browser->version->is('>=', '5.2')) {328                        $this->data->os->name = 'OS X';329                    }330                }331            }332        }333        if (preg_match('/Trident\/[789][^\)]+; rv:([0-9.]*)\)/u', $ua, $match)) {334            $this->data->browser->name = 'Internet Explorer';335            $this->data->browser->version = new Version([ 'value' => $match[1] ]);336            $this->data->browser->type = Constants\BrowserType::BROWSER;337        }338        if (preg_match('/Trident\/[789][^\)]+; Touch; rv:([0-9.]*);\s+IEMobile\//u', $ua, $match)) {339            $this->data->browser->name = 'Mobile Internet Explorer';340            $this->data->browser->version = new Version([ 'value' => $match[1] ]);341            $this->data->browser->type = Constants\BrowserType::BROWSER;342        }343        if (preg_match('/Trident\/[789][^\)]+; Touch; rv:([0-9.]*); WPDesktop/u', $ua, $match)) {344            $this->data->browser->mode = 'desktop';345            $this->data->browser->name = 'Mobile Internet Explorer';346            $this->data->browser->version = new Version([ 'value' => $match[1] ]);347            $this->data->browser->type = Constants\BrowserType::BROWSER;348        }349        /* Old versions of Pocket Internet Explorer */350        if ($this->data->isBrowser('Mobile Internet Explorer', '<', 6)) {351            $this->data->browser->name = 'Pocket Internet Explorer';352        }353        if (preg_match('/Microsoft Pocket Internet Explorer\//u', $ua)) {354            $this->data->browser->name = 'Pocket Internet Explorer';355            $this->data->browser->version = new Version([ 'value' => '1.0' ]);356            $this->data->browser->type = Constants\BrowserType::BROWSER;357            $this->data->device->type = Constants\DeviceType::MOBILE;358        }359        if (preg_match('/MSPIE ([0-9.]*)/u', $ua, $match)) {360            $this->data->browser->name = 'Pocket Internet Explorer2';361            $this->data->browser->version = new Version([ 'value' => $match[1] ]);362            $this->data->browser->type = Constants\BrowserType::BROWSER;363            $this->data->device->type = Constants\DeviceType::MOBILE;364        }365        /* Microsoft Mobile Explorer */366        if (preg_match('/MMEF([0-9])([0-9])/u', $ua, $match)) {367            $this->data->browser->name = 'Microsoft Mobile Explorer';368            $this->data->browser->version = new Version([ 'value' => $match[1] . '.' . $match[2] ]);369            $this->data->browser->type = Constants\BrowserType::BROWSER;370            $this->data->device->type = Constants\DeviceType::MOBILE;371            if (preg_match('/MMEF[0-9]+; ([^;]+); ([^\)\/]+)/u', $ua, $match)) {372                $device = Data\DeviceModels::identify('feature', $match[1] == 'CellPhone' ? $match[2] : $match[1] . ' ' . $match[2]);373                if ($device->identified) {374                    $device->identified |= $this->data->device->identified;375                    $this->data->device = $device;376                }377            }378        }379        /* Set the browser family */380        if ($this->data->isBrowser('Internet Explorer') || $this->data->isBrowser('Mobile Internet Explorer') || $this->data->isBrowser('Pocket Internet Explorer')) {381            unset($this->data->browser->family);382        }383    }384    /* Edge */385    private function detectEdge($ua)386    {387        if (preg_match('/Edge\/([0-9]+)/u', $ua, $match)) {388            $this->data->browser->name = 'Edge';389            $this->data->browser->type = Constants\BrowserType::BROWSER;390            $this->data->browser->channel = '';391            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 1 ]);392            unset($this->data->browser->family);393        }394        if (preg_match('/Edg(iOS|A)\/([0-9.]*)/u', $ua, $match)) {395            $this->data->browser->name = 'Edge';396            $this->data->browser->version = new Version([ 'value' => $match[2], 'details' => 1, 'hidden' => true ]);397            $this->data->browser->type = Constants\BrowserType::BROWSER;398        }399    }400    /* Opera */401    private function detectOpera($ua)402    {403        if (!preg_match('/(OPR|OMI|Opera|OPiOS|Coast|Oupeng)/ui', $ua)) {404            return;405        }406        if (preg_match('/OPR\/([0-9.]*)/u', $ua, $match)) {407            $this->data->browser->stock = false;408            $this->data->browser->channel = '';409            $this->data->browser->name = 'Opera';410            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);411            $this->data->browser->type = Constants\BrowserType::BROWSER;412            if (preg_match('/Edition Developer/iu', $ua)) {413                $this->data->browser->channel = 'Developer';414            }415            if (preg_match('/Edition Next/iu', $ua)) {416                $this->data->browser->channel = 'Next';417            }418            if (preg_match('/Edition Beta/iu', $ua)) {419                $this->data->browser->channel = 'Beta';420            }421            if ($this->data->device->type == Constants\DeviceType::MOBILE) {422                $this->data->browser->name = 'Opera Mobile';423            }424        }425        if (preg_match('/OMI\/([0-9]+\.[0-9]+)/u', $ua, $match)) {426            $this->data->browser->name = 'Opera Devices';427            $this->data->browser->version = new Version([ 'value' => $match[1] ]);428            $this->data->browser->type = Constants\BrowserType::BROWSER;429            $this->data->device->type = Constants\DeviceType::TELEVISION;430            if (!$this->data->isOs('Android')) {431                unset($this->data->os->name);432                unset($this->data->os->version);433            }434        }435        if ((preg_match('/Opera[\/\-\s]/iu', $ua) || preg_match('/Browser\/Opera/iu', $ua)) && !preg_match('/Opera Software/iu', $ua)) {436            $this->data->browser->stock = false;437            $this->data->browser->name = 'Opera';438            $this->data->browser->type = Constants\BrowserType::BROWSER;439            if (preg_match('/Opera[\/| ]?([0-9.]+)/u', $ua, $match)) {440                $this->data->browser->version = new Version([ 'value' => $match[1] ]);441            }442            if (preg_match('/Version\/([0-9.]+)/u', $ua, $match)) {443                if (floatval($match[1]) >= 10) {444                    $this->data->browser->version = new Version([ 'value' => $match[1] ]);445                }446            }447            if (isset($this->data->browser->version) && preg_match('/Edition Labs/u', $ua)) {448                $this->data->browser->channel = 'Labs';449            }450            if (isset($this->data->browser->version) && preg_match('/Edition Next/u', $ua)) {451                $this->data->browser->channel = 'Next';452            }453            if (preg_match('/Opera Tablet/u', $ua)) {454                $this->data->browser->name = 'Opera Mobile';455                $this->data->device->type = Constants\DeviceType::TABLET;456            }457            if (preg_match('/Opera Mobi/u', $ua)) {458                $this->data->browser->name = 'Opera Mobile';459                $this->data->device->type = Constants\DeviceType::MOBILE;460            }461            if (preg_match('/Opera Mini;/u', $ua)) {462                $this->data->browser->name = 'Opera Mini';463                $this->data->browser->version = null;464                $this->data->browser->mode = 'proxy';465                $this->data->device->type = Constants\DeviceType::MOBILE;466            }467            if (preg_match('/Opera Mini\/(?:att\/)?([0-9.]+)/u', $ua, $match)) {468                $this->data->browser->name = 'Opera Mini';469                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => (intval(substr(strrchr($match[1], '.'), 1)) > 99 ? -1 : null) ]);470                $this->data->browser->mode = 'proxy';471                $this->data->device->type = Constants\DeviceType::MOBILE;472            }473            if ($this->data->browser->name == 'Opera' && $this->data->device->type == Constants\DeviceType::MOBILE) {474                $this->data->browser->name = 'Opera Mobile';475            }476            if (preg_match('/InettvBrowser/u', $ua)) {477                $this->data->device->type = Constants\DeviceType::TELEVISION;478            }479            if (preg_match('/Opera[ -]TV/u', $ua)) {480                $this->data->browser->name = 'Opera';481                $this->data->device->type = Constants\DeviceType::TELEVISION;482            }483            if (preg_match('/Linux zbov/u', $ua)) {484                $this->data->browser->name = 'Opera Mobile';485                $this->data->browser->mode = 'desktop';486                $this->data->device->type = Constants\DeviceType::MOBILE;487                $this->data->os->name = null;488                $this->data->os->version = null;489            }490            if (preg_match('/Linux zvav/u', $ua)) {491                $this->data->browser->name = 'Opera Mini';492                $this->data->browser->version = null;493                $this->data->browser->mode = 'desktop';494                $this->data->device->type = Constants\DeviceType::MOBILE;495                $this->data->os->name = null;496                $this->data->os->version = null;497            }498            if ($this->data->device->type == '') {499                $this->data->device->type = Constants\DeviceType::DESKTOP;500            }501            if (isset($this->data->browser->family)) {502                unset($this->data->browser->family);503            }504        }505        if (preg_match('/OPiOS\/([0-9.]*)/u', $ua, $match)) {506            $this->data->browser->stock = false;507            $this->data->browser->name = 'Opera Mini';508            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);509            $this->data->browser->type = Constants\BrowserType::BROWSER;510        }511        if (preg_match('/Coast\/([0-9.]*)/u', $ua, $match)) {512            $this->data->browser->stock = false;513            $this->data->browser->name = 'Coast by Opera';514            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);515            $this->data->browser->type = Constants\BrowserType::BROWSER;516        }517        if (preg_match('/Oupeng(?:HD)?[\/-]([0-9.]*)/u', $ua, $match)) {518            $this->data->browser->stock = false;519            $this->data->browser->name = 'Opera Oupeng';520            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);521            $this->data->browser->type = Constants\BrowserType::BROWSER;522        }523    }524    /* Firefox */525    private function detectFirefox($ua)526    {527        if (!preg_match('/(Firefox|GranParadiso|Namoroka|Shiretoko|Minefield|BonEcho|Fennec|Phoenix|Firebird|Minimo|FxiOS)/ui', $ua)) {528            return;529        }530        if (preg_match('/Firefox/u', $ua)) {531            $this->data->browser->stock = false;532            $this->data->browser->name = 'Firefox';533            $this->data->browser->type = Constants\BrowserType::BROWSER;534            if (preg_match('/Firefox\/([0-9ab.]*)/u', $ua, $match)) {535                $this->data->browser->version = new Version([ 'value' => $match[1] ]);536                if (preg_match('/a/u', $match[1])) {537                    $this->data->browser->channel = 'Aurora';538                }539                if (preg_match('/b/u', $match[1])) {540                    $this->data->browser->channel = 'Beta';541                }542            }543            if (preg_match('/Aurora\/([0-9ab.]*)/u', $ua, $match)) {544                $this->data->browser->channel = 'Aurora';545                $this->data->browser->version = new Version([ 'value' => $match[1] ]);546            }547            if (preg_match('/Fennec/u', $ua)) {548                $this->data->device->type = Constants\DeviceType::MOBILE;549            }550            if (preg_match('/Mobile;(?: ([^;]+);)? rv/u', $ua, $match)) {551                $this->data->device->type = Constants\DeviceType::MOBILE;552                if (isset($match[1])) {553                    $device = Data\DeviceModels::identify('firefoxos', $match[1]);554                    if ($device->identified) {555                        $device->identified |= $this->data->device->identified;556                        $this->data->device = $device;557                        if (!$this->data->isOs('KaiOS')) {558                            $this->data->os->reset([ 'name' => 'Firefox OS' ]);559                        }560                    }561                }562            }563            if (preg_match('/Tablet;(?: ([^;]+);)? rv/u', $ua, $match)) {564                $this->data->device->type = Constants\DeviceType::TABLET;565            }566            if (preg_match('/Viera;(?: ([^;]+);)? rv/u', $ua, $match)) {567                $this->data->device->type = Constants\DeviceType::TELEVISION;568                $this->data->os->reset([ 'name' => 'Firefox OS' ]);569            }570            if ($this->data->device->type == Constants\DeviceType::MOBILE || $this->data->device->type == Constants\DeviceType::TABLET) {571                $this->data->browser->name = 'Firefox Mobile';572            }573            if ($this->data->device->type == '') {574                $this->data->device->type = Constants\DeviceType::DESKTOP;575            }576        }577        if (preg_match('/(GranParadiso|Namoroka|Shiretoko|Minefield|BonEcho)/u', $ua, $match)) {578            $this->data->browser->stock = false;579            $this->data->browser->name = 'Firefox';580            $this->data->browser->channel = str_replace('GranParadiso', 'Gran Paradiso', $match[1]);581            $this->data->browser->type = Constants\BrowserType::BROWSER;582            if (preg_match('/' . $match[1] . '\/([0-9ab.]*)/u', $ua, $match)) {583                $this->data->browser->version = new Version([ 'value' => $match[1] ]);584            }585        }586        if (preg_match('/Fennec/u', $ua)) {587            $this->data->browser->stock = false;588            $this->data->browser->name = 'Firefox Mobile';589            $this->data->browser->type = Constants\BrowserType::BROWSER;590            if (preg_match('/Fennec\/([0-9ab.]*)/u', $ua, $match)) {591                $this->data->browser->version = new Version([ 'value' => $match[1] ]);592            }593            $this->data->browser->channel = 'Fennec';594        }595        if (preg_match('/(Phoenix|Firebird|Minimo)/u', $ua, $match)) {596            $this->data->browser->stock = false;597            $this->data->browser->name = $match[1];598            $this->data->browser->type = Constants\BrowserType::BROWSER;599            if (preg_match('/' . $match[1] . '\/([0-9ab.]*)/u', $ua, $match)) {600                $this->data->browser->version = new Version([ 'value' => $match[1] ]);601            }602        }603        if (preg_match('/FxiOS\/([0-9.]*)/u', $ua, $match)) {604            $this->data->browser->name = 'Firefox';605            $this->data->browser->version = new Version([ 'value' => $match[1] ]);606            $this->data->browser->type = Constants\BrowserType::BROWSER;607        }608        if (preg_match('/Servo\/1.0 Firefox\//u', $ua)) {609            $this->data->browser->name = 'Servo Nightly Build';610            $this->data->browser->version = null;611        }612        /* Set the browser family */613        if ($this->data->isBrowser('Firefox') || $this->data->isBrowser('Firefox Mobile') || $this->data->isBrowser('Firebird')) {614            $this->data->browser->family = new Family([ 'name' => 'Firefox', 'version' => $this->data->browser->version ]);615        }616        if ($this->data->isBrowser('Minimo')) {617            $this->data->browser->family = new Family([ 'name' => 'Firefox' ]);618        }619    }620    /* Seamonkey */621    private function detectSeamonkey($ua)622    {623        if (preg_match('/SeaMonkey/u', $ua)) {624            $this->data->browser->stock = false;625            $this->data->browser->name = 'SeaMonkey';626            $this->data->browser->type = Constants\BrowserType::BROWSER;627            if (preg_match('/SeaMonkey\/([0-9ab.]*)/u', $ua, $match)) {628                $this->data->browser->version = new Version([ 'value' => $match[1] ]);629            }630        }631        if (preg_match('/PmWFx\/([0-9ab.]*)/u', $ua, $match)) {632            $this->data->browser->stock = false;633            $this->data->browser->name = 'SeaMonkey';634            $this->data->browser->version = new Version([ 'value' => $match[1] ]);635            $this->data->browser->type = Constants\BrowserType::BROWSER;636        }637    }638    /* Netscape */639    private function detectLegacyNetscape($ua)640    {641        if ($this->data->device->type == Constants\DeviceType::DESKTOP && $this->data->browser->getName() == '') {642            if (!preg_match('/compatible;/u', $ua)) {643                if (preg_match('/Mozilla\/([123].[0-9]+)/u', $ua, $match)) {644                    $this->data->browser->name = 'Netscape Navigator';645                    $this->data->browser->version = new Version([ 'value' => preg_replace("/([0-9])([0-9])/", '$1.$2', $match[1]) ]);646                    $this->data->browser->type = Constants\BrowserType::BROWSER;647                }648                if (preg_match('/Mozilla\/(4.[0-9]+)/u', $ua, $match)) {649                    $this->data->browser->name = 'Netscape Communicator';650                    $this->data->browser->version = new Version([ 'value' => preg_replace("/([0-9])([0-9])/", '$1.$2', $match[1]) ]);651                    $this->data->browser->type = Constants\BrowserType::BROWSER;652                    if (preg_match('/Nav\)/u', $ua)) {653                        $this->data->browser->name = 'Netscape Navigator';654                    }655                }656            }657        }658    }659    private function detectModernNetscape($ua)660    {661        if (preg_match('/Netscape/u', $ua)) {662            $this->data->browser->stock = false;663            $this->data->browser->name = 'Netscape';664            $this->data->browser->type = Constants\BrowserType::BROWSER;665            if (preg_match('/Netscape[0-9]?\/([0-9.]*)/u', $ua, $match)) {666                $this->data->browser->version = new Version([ 'value' => $match[1] ]);667            }668        }669        if (preg_match('/ Navigator\/(9\.[0-9.]*)/u', $ua, $match)) {670            $this->data->browser->stock = false;671            $this->data->browser->name = 'Netscape Navigator';672            $this->data->browser->type = Constants\BrowserType::BROWSER;673            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);674        }675    }676    /* Mosaic */677    private function detectMosaic($ua)678    {679        if (!preg_match('/Mosaic/ui', $ua)) {680            return;681        }682        if (preg_match('/(?:NCSA[ _])?Mosaic(?:\(tm\))?(?: for the X Window System| for Windows)?\/(?:Version )?([0-9.]*)/u', $ua, $match)) {683            $this->data->browser->name = 'NCSA Mosaic';684            $this->data->browser->version = new Version([ 'value' => $match[1] ]);685            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);686            $this->data->browser->type = Constants\BrowserType::BROWSER;687            $this->data->browser->stock = false;688        }689        if (preg_match('/AIR_Mosaic(?:\(16bit\))?\/v([0-9.]*)/u', $ua, $match)) {690            $this->data->browser->name = 'AIR Mosaic';691            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);692            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);693            $this->data->browser->type = Constants\BrowserType::BROWSER;694            $this->data->browser->stock = false;695        }696        if (preg_match('/(?:MosaicView|Spyglass[ _]Mosaic)\/([0-9.]*)/u', $ua, $match)) {697            $this->data->browser->name = 'Spyglass Mosaic';698            $this->data->browser->version = new Version([ 'value' => $match[1] ]);699            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);700            $this->data->browser->type = Constants\BrowserType::BROWSER;701            $this->data->browser->stock = false;702        }703        if (preg_match('/SPRY_Mosaic(?:\(16bit\))?\/v([0-9.]*)/u', $ua, $match)) {704            $this->data->browser->name = 'SPRY Mosaic';705            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);706            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);707            $this->data->browser->type = Constants\BrowserType::BROWSER;708            $this->data->browser->stock = false;709        }710        if (preg_match('/DCL SuperMosaic\/([0-9.]*)/u', $ua, $match)) {711            $this->data->browser->name = 'SuperMosaic';712            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);713            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);714            $this->data->browser->type = Constants\BrowserType::BROWSER;715            $this->data->browser->stock = false;716        }717        if (preg_match('/VMS_Mosaic\/([0-9.]*)/u', $ua, $match)) {718            $this->data->browser->name = 'VMS Mosaic';719            $this->data->browser->version = new Version([ 'value' => $match[1] ]);720            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);721            $this->data->browser->type = Constants\BrowserType::BROWSER;722            $this->data->browser->stock = false;723        }724        if (preg_match('/mMosaic\/([0-9.]*)/u', $ua, $match)) {725            $this->data->browser->name = 'mMosaic';726            $this->data->browser->version = new Version([ 'value' => $match[1] ]);727            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);728            $this->data->browser->type = Constants\BrowserType::BROWSER;729            $this->data->browser->stock = false;730        }731        if (preg_match('/Quarterdeck Mosaic Version ([0-9.]*)/u', $ua, $match)) {732            $this->data->browser->name = 'Quarterdeck Mosaic';733            $this->data->browser->version = new Version([ 'value' => $match[1] ]);734            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);735            $this->data->browser->type = Constants\BrowserType::BROWSER;736            $this->data->browser->stock = false;737        }738        if (preg_match('/WinMosaic\/Version ([0-9.]*)/u', $ua, $match)) {739            $this->data->browser->name = 'WinMosaic';740            $this->data->browser->version = new Version([ 'value' => $match[1] ]);741            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);742            $this->data->browser->type = Constants\BrowserType::BROWSER;743            $this->data->browser->stock = false;744        }745        if (preg_match('/Device Mosaic ([0-9.]*)/u', $ua, $match)) {746            $this->data->browser->name = 'Device Mosaic';747            $this->data->browser->version = new Version([ 'value' => $match[1] ]);748            $this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);749            $this->data->browser->type = Constants\BrowserType::BROWSER;750            $this->data->browser->stock = false;751            $this->data->device->type = Constants\DeviceType::TELEVISION;752        }753    }754    /* UC Browser */755    private function detectUC($ua)756    {757        if (!preg_match('/(UC|UBrowser)/ui', $ua)) {758            return;759        }760        if (preg_match('/UCWEB/u', $ua)) {761            $this->data->browser->stock = false;762            $this->data->browser->name = 'UC Browser';763            $this->data->browser->type = Constants\BrowserType::BROWSER;764            unset($this->data->browser->channel);765            if (preg_match('/UCWEB\/?([0-9]*[.][0-9]*)/u', $ua, $match)) {766                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);767            }768            if (!$this->data->device->type) {769                $this->data->device->type = Constants\DeviceType::MOBILE;770            }771            if (isset($this->data->os->name) && $this->data->os->name == 'Linux') {772                $this->data->os->reset();773            }774            if (preg_match('/^IUC ?\(U; ?iOS ([0-9\._]+);/u', $ua, $match)) {775                $this->data->os->name = 'iOS';776                $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);777            }778            if (preg_match('/^JUC ?\(Linux; ?U; ?(?:Android)? ?([0-9\.]+)[^;]*; ?[^;]+; ?([^;]*[^\s])\s*; ?[0-9]+\*[0-9]+;?\)/u', $ua, $match)) {779                $this->data->os->name = 'Android';780                $this->data->os->version = new Version([ 'value' => $match[1] ]);781                $this->data->device = Data\DeviceModels::identify('android', $match[2]);782            }783            if (preg_match('/\(MIDP-2.0; U; [^;]+; ([^;]*[^\s])\)/u', $ua, $match)) {784                $this->data->os->name = 'Android';785                $this->data->device->model = $match[1];786                $this->data->device->identified |= Constants\Id::PATTERN;787                $device = Data\DeviceModels::identify('android', $match[1]);788                if ($device->identified) {789                    $device->identified |= $this->data->device->identified;790                    $this->data->device = $device;791                }792            }793            if (preg_match('/\((?:Linux|MIDP-2.0); U; Adr ([0-9\.]+)(?:-update[0-9])?; [^;]+; ([^;]*[^\s])\)/u', $ua, $match)) {794                $this->data->os->name = 'Android';795                $this->data->os->version = new Version([ 'value' => $match[1] ]);796                $this->data->device->model = $match[2];797                $this->data->device->identified |= Constants\Id::PATTERN;798                $device = Data\DeviceModels::identify('android', $match[2]);799                if ($device->identified) {800                    $device->identified |= $this->data->device->identified;801                    $this->data->device = $device;802                }803            }804            if (preg_match('/\((?:iOS|iPhone);/u', $ua)) {805                $this->data->os->name = 'iOS';806                $this->data->os->version = new Version([ 'value' => '1.0' ]);807                if (preg_match('/OS[_ ]([0-9_]*);/u', $ua, $match)) {808                    $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);809                }810                if (preg_match('/; ([^;]+)\)/u', $ua, $match)) {811                    $device = Data\DeviceModels::identify('ios', $match[1]);812                    if ($device->identified) {813                        $device->identified |= $this->data->device->identified;814                        $this->data->device = $device;815                    }816                }817            }818            if (preg_match('/\(Symbian;/u', $ua)) {819                $this->data->os->name = 'Series60';820                $this->data->os->version = null;821                $this->data->os->family = new Family([ 'name' => 'Symbian' ]);822                if (preg_match('/S60 V([0-9])/u', $ua, $match)) {823                    $this->data->os->version = new Version([ 'value' => $match[1] ]);824                }825                if (preg_match('/; Nokia([^;]+)\)/iu', $ua, $match)) {826                    $this->data->device->model = $match[1];827                    $this->data->device->identified |= Constants\Id::PATTERN;828                    $device = Data\DeviceModels::identify('symbian', $match[1]);829                    if ($device->identified) {830                        $device->identified |= $this->data->device->identified;831                        $this->data->device = $device;832                    }833                }834            }835            if (preg_match('/\(Windows;/u', $ua)) {836                $this->data->os->name = 'Windows Phone';837                $this->data->os->version = null;838                if (preg_match('/wds ([0-9]+\.[0-9])/u', $ua, $match)) {839                    switch ($match[1]) {840                        case '7.1':841                            $this->data->os->version = new Version([ 'value' => '7.5' ]);842                            break;843                        case '8.0':844                            $this->data->os->version = new Version([ 'value' => '8.0' ]);845                            break;846                        case '8.1':847                            $this->data->os->version = new Version([ 'value' => '8.1' ]);848                            break;849                        case '10.0':850                            $this->data->os->version = new Version([ 'value' => '10.0' ]);851                            break;852                    }853                }854                if (preg_match('/; ([^;]+); ([^;]+)\)/u', $ua, $match)) {855                    $this->data->device->manufacturer = $match[1];856                    $this->data->device->model = $match[2];857                    $this->data->device->identified |= Constants\Id::PATTERN;858                    $device = Data\DeviceModels::identify('wp', $match[2]);859                    if ($device->identified) {860                        $device->identified |= $this->data->device->identified;861                        $this->data->device = $device;862                    }863                }864            }865        }866        if (preg_match('/Ucweb\/([0-9]*[.][0-9]*)/u', $ua, $match)) {867            $this->data->browser->stock = false;868            $this->data->browser->name = 'UC Browser';869            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);870            $this->data->browser->type = Constants\BrowserType::BROWSER;871        }872        if (preg_match('/ucweb-squid/u', $ua)) {873            $this->data->browser->stock = false;874            $this->data->browser->name = 'UC Browser';875            $this->data->browser->type = Constants\BrowserType::BROWSER;876            unset($this->data->browser->channel);877        }878        if (preg_match('/\) ?UC /u', $ua)) {879            $this->data->browser->stock = false;880            $this->data->browser->name = 'UC Browser';881            $this->data->browser->type = Constants\BrowserType::BROWSER;882            unset($this->data->browser->version);883            unset($this->data->browser->channel);884            unset($this->data->browser->mode);885            if ($this->data->device->type == Constants\DeviceType::DESKTOP) {886                $this->data->device->type = Constants\DeviceType::MOBILE;887                $this->data->browser->mode = 'desktop';888            }889        }890        if (preg_match('/UC ?Browser\/?([0-9.]*)/u', $ua, $match)) {891            $this->data->browser->stock = false;892            $this->data->browser->name = 'UC Browser';893            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);894            $this->data->browser->type = Constants\BrowserType::BROWSER;895            unset($this->data->browser->channel);896            if (!$this->data->device->type) {897                $this->data->device->type = Constants\DeviceType::MOBILE;898            }899        }900        if (preg_match('/UBrowser\/?([0-9.]*)/u', $ua, $match)) {901            $this->data->browser->stock = false;902            $this->data->browser->name = 'UC Browser';903            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);904            $this->data->browser->type = Constants\BrowserType::BROWSER;905            unset($this->data->browser->channel);906        }907        if (preg_match('/UCLite\/([0-9.]*)/u', $ua, $match)) {908            $this->data->browser->stock = false;909            $this->data->browser->name = 'UC Browser';910            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);911            $this->data->browser->type = Constants\BrowserType::BROWSER;912            unset($this->data->browser->channel);913        }914        /* U2 is the Proxy service used by UC Browser on low-end phones */915        if (preg_match('/U2\//u', $ua)) {916            $this->data->browser->stock = false;917            $this->data->browser->name = 'UC Browser';918            $this->data->browser->mode = 'proxy';919            $this->data->engine->name = 'Gecko';920            /* UC Browser running on Windows 8 is identifing itself as U2, but instead its a Trident Webview */921            if (isset($this->data->os->name) && isset($this->data->os->version)) {922                if ($this->data->os->name == 'Windows Phone' && $this->data->os->version->toFloat() >= 8) {923                    $this->data->engine->name = 'Trident';924                    $this->data->browser->mode = '';925                }926            }927            if ($this->data->device->identified < Constants\Id::MATCH_UA && preg_match('/; ([^;]*)\) U2\//u', $ua, $match)) {928                $device = Data\DeviceModels::identify('android', $match[1]);929                if ($device->identified) {930                    $device->identified |= $this->data->device->identified;931                    $this->data->device = $device;932                    if (!isset($this->data->os->name) || ($this->data->os->name != 'Android' && (!isset($this->data->os->family) || $this->data->os->family->getName() != 'Android'))) {933                        $this->data->os->name = 'Android';934                    }935                }936            }937        }938        /* U3 is the Webkit based Webview used on Android phones */939        if (preg_match('/U3\//u', $ua)) {940            $this->data->engine->name = 'Webkit';941        }942    }943    private function detectUCEngine($ua)944    {945        if (isset($this->data->browser->name)) {946            if ($this->data->browser->name == 'UC Browser') {947                if (!preg_match("/UBrowser\//", $ua) && ($this->data->device->type == 'desktop' || (isset($this->data->os->name) && ($this->data->os->name == 'Windows' || $this->data->os->name == 'OS X')))) {948                    $this->data->device->type = Constants\DeviceType::MOBILE;949                    $this->data->browser->mode = 'desktop';950                    $this->data->engine->reset();951                    $this->data->os->reset();952                } elseif (!isset($this->data->os->name) || ($this->data->os->name != 'iOS' && $this->data->os->name != 'Windows Phone' && $this->data->os->name != 'Windows' && $this->data->os->name != 'Android' && (!isset($this->data->os->family) || $this->data->os->family->getName() != 'Android'))) {953                    $this->data->engine->name = 'Gecko';954                    unset($this->data->engine->version);955                    $this->data->browser->mode = 'proxy';956                }957                if (isset($this->data->engine->name) && $this->data->engine->name == 'Presto') {958                    $this->data->engine->name = 'Webkit';959                    unset($this->data->engine->version);960                }961            }962        }963    }964    /* Netfront */965    private function detectNetfront($ua)966    {967        if (!preg_match('/(CNF|NF|NetFront|NX|Ave|COM2)/ui', $ua)) {968            return;969        }970        /* Compact NetFront */971        if (preg_match('/CNF\/([0-9.]*)/u', $ua, $match)) {972            $this->data->browser->name = 'Compact NetFront';973            $this->data->browser->version = new Version([ 'value' => $match[1] ]);974            $this->data->browser->type = Constants\BrowserType::BROWSER;975            $this->data->device->type = Constants\DeviceType::MOBILE;976        }977        /* NetFront */978        if (preg_match('/Net[fF]ront/u', $ua) && !preg_match('/NetFrontNX/u', $ua)) {979            $this->data->browser->name = 'NetFront';980            $this->data->browser->type = Constants\BrowserType::BROWSER;981            unset($this->data->browser->channel);982            if (preg_match('/NetFront[ \/]?([0-9.]*)/ui', $ua, $match)) {983                $this->data->browser->version = new Version([ 'value' => $match[1] ]);984            }985            /* Detect device type based on NetFront identifier */986            if (preg_match('/MobilePhone/u', $ua)) {987                $this->data->device->type = Constants\DeviceType::MOBILE;988            }989            if (preg_match('/DigitalMediaPlayer/u', $ua)) {990                $this->data->device->type = Constants\DeviceType::MEDIA;991            }992            if (preg_match('/PDA/u', $ua)) {993                $this->data->device->type = Constants\DeviceType::PDA;994            }995            if (preg_match('/MFP/u', $ua)) {996                $this->data->device->type = Constants\DeviceType::PRINTER;997            }998            if (preg_match('/(InettvBrowser|HbbTV|DTV|NetworkAVTV|BDPlayer)/u', $ua)) {999                $this->data->device->type = Constants\DeviceType::TELEVISION;1000            }1001            if (preg_match('/VCC/u', $ua)) {1002                $this->data->device->type = Constants\DeviceType::CAR;1003            }1004            if (preg_match('/Kindle/u', $ua)) {1005                $this->data->device->type = Constants\DeviceType::EREADER;1006            }1007            if (empty($this->data->device->type)) {1008                $this->data->device->type = Constants\DeviceType::MOBILE;1009            }1010            /* Detect OS based on NetFront identifier */1011            if (preg_match('/NF[0-9][0-9](?:WMPRO|PPC)\//ui', $ua, $match)) {1012                if (!$this->data->isOs('Windows Mobile')) {1013                    $this->data->os->reset([1014                        'name' => 'Windows Mobile'1015                    ]);1016                }1017            }1018        }1019        if (preg_match('/(?:Browser\/(?:NF|NetFr?ont-)|NF-Browser\/|ACS-NF\/|NetFront FullBrowser\/)([0-9.]*)/ui', $ua, $match)) {1020            $this->data->browser->name = 'NetFront';1021            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1022            $this->data->browser->type = Constants\BrowserType::BROWSER;1023            unset($this->data->browser->channel);1024            $this->data->device->type = Constants\DeviceType::MOBILE;1025        }1026        /* AVE-Front */1027        if (preg_match('/(?:AVE-Front|AveFront)\/([0-9.]*)/u', $ua, $match)) {1028            $this->data->browser->name = 'NetFront';1029            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1030            $this->data->browser->type = Constants\BrowserType::BROWSER;1031            if (preg_match('/Category=([^\);]+)[\);]/u', $ua, $match)) {1032                switch ($match[1]) {1033                    case 'WebPhone':1034                        $this->data->device->type = Constants\DeviceType::MOBILE;1035                        $this->data->device->subtype = Constants\DeviceSubType::DESKTOP;1036                        break;1037                    case 'WP':1038                    case 'Home Mail Tool':1039                    case 'PDA':1040                        $this->data->device->type = Constants\DeviceType::PDA;1041                        break;1042                    case 'STB':1043                        $this->data->device->type = Constants\DeviceType::TELEVISION;1044                        break;1045                    case 'GAME':1046                        $this->data->device->type = Constants\DeviceType::GAMING;1047                        $this->data->device->subtype = Constants\DeviceSubType::CONSOLE;1048                        break;1049                }1050            }1051            if (preg_match('/Product=([^\);]+)[\);]/u', $ua, $match)) {1052                if (in_array($match[1], [ 'ACCESS/NFPS', 'SUNSOFT/EnjoyMagic' ])) {1053                    $this->data->device->setIdentification([1054                        'manufacturer'  =>  'Sony',1055                        'model'         =>  'Playstation 2',1056                        'type'          =>  Constants\DeviceType::GAMING,1057                        'subtype'       =>  Constants\DeviceSubType::CONSOLE1058                    ]);1059                }1060            }1061        }1062        /* Netfront NX */1063        if (preg_match('/NX[\/ ]([0-9.]+)/u', $ua, $match)) {1064            $this->data->browser->name = 'NetFront NX';1065            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1066            $this->data->browser->type = Constants\BrowserType::BROWSER;1067            unset($this->data->browser->channel);1068            if (empty($this->data->device->type) || $this->data->isType('desktop')) {1069                if (preg_match('/(DTV|HbbTV)/iu', $ua)) {1070                    $this->data->device->type = Constants\DeviceType::TELEVISION;1071                } else {1072                    $this->data->device->type = Constants\DeviceType::DESKTOP;1073                }1074            }1075            $this->data->os->reset();1076        }1077        /* The Sony Mylo 2 identifies as Firefox 2, but is NetFront */1078        if (preg_match('/Sony\/COM2/u', $ua, $match)) {1079            $this->data->browser->reset([1080                'name' => 'NetFront',1081                'type' => Constants\BrowserType::BROWSER1082            ]);1083        }1084    }1085    /* Obigo */1086    private function detectObigo($ua)1087    {1088        $processObigoVersion = function ($version) {1089            $result = [1090                'value' => $version1091            ];1092            if (preg_match('/[0-9.]+/', $version, $match)) {1093                $result['details'] = 2;1094            }1095            if (preg_match('/([0-9])[A-Z]/', $version, $match)) {1096                $result['value'] = intval($match[1]);1097                $result['alias'] = $version;1098            }1099            return $result;1100        };1101        if (preg_match('/(?:Obigo|Teleca|AU-MIC|MIC\/)/ui', $ua)) {1102            $this->data->browser->name = 'Obigo';1103            $this->data->browser->version = null;1104            $this->data->browser->type = Constants\BrowserType::BROWSER;1105            if (preg_match('/Obigo\/0?([0-9.]+)/iu', $ua, $match)) {1106                $this->data->browser->version = new Version($processObigoVersion($match[1]));1107            } elseif (preg_match('/(?:MIC|TelecaBrowser)\/(WAP|[A-Z])?0?([0-9.]+[A-Z]?)/iu', $ua, $match)) {1108                $this->data->browser->version = new Version($processObigoVersion($match[2]));1109                if (!empty($match[1])) {1110                    $this->data->browser->name = 'Obigo ' . strtoupper($match[1]);1111                }1112            } elseif (preg_match('/(?:Obigo(?:InternetBrowser|[- ]Browser)?|Teleca)\/(WAP|[A-Z])?[0O]?([0-9.]+[A-Z]?)/ui', $ua, $match)) {1113                $this->data->browser->version = new Version($processObigoVersion($match[2]));1114                if (!empty($match[1])) {1115                    $this->data->browser->name = 'Obigo ' . strtoupper($match[1]);1116                }1117            } elseif (preg_match('/(?:Obigo|Teleca)[- ]([WAP|[A-Z])?0?([0-9.]+[A-Z]?)(?:[0-9])?(?:[\/;]|$)/ui', $ua, $match)) {1118                $this->data->browser->version = new Version($processObigoVersion($match[2]));1119                if (!empty($match[1])) {1120                    $this->data->browser->name = 'Obigo ' . strtoupper($match[1]);1121                }1122            } elseif (preg_match('/Browser\/(?:Obigo|Teleca)[_-]?(?:Browser\/)?(WAP|[A-Z])?0?([0-9.]+[A-Z]?)/ui', $ua, $match)) {1123                $this->data->browser->version = new Version($processObigoVersion($match[2]));1124                if (!empty($match[1])) {1125                    $this->data->browser->name = 'Obigo ' . strtoupper($match[1]);1126                }1127            } elseif (preg_match('/Obigo Browser (WAP|[A-Z])?0?([0-9.]+[A-Z]?)/ui', $ua, $match)) {1128                $this->data->browser->version = new Version($processObigoVersion($match[2]));1129                if (!empty($match[1])) {1130                    $this->data->browser->name = 'Obigo ' . strtoupper($match[1]);1131                }1132            }1133        }1134        if (preg_match('/(Q)0?([0-9][A-Z])/u', $ua, $match)) {1135            $this->data->browser->name = 'Obigo ' . $match[1];1136            $this->data->browser->version = new Version($processObigoVersion($match[2]));1137            $this->data->browser->type = Constants\BrowserType::BROWSER;1138        }1139    }1140    /* ANT Galio and ANT Fresco */1141    private function detectAnt($ua)1142    {1143        if (preg_match('/ANTFresco\/([0-9.]+)/iu', $ua, $match)) {1144            $this->data->browser->name = 'ANT Fresco';1145            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1146            $this->data->browser->type = Constants\BrowserType::BROWSER;1147        }1148        if (preg_match('/ANTGalio\/([0-9.]+)/iu', $ua, $match)) {1149            $this->data->browser->name = 'ANT Galio';1150            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1151            $this->data->browser->type = Constants\BrowserType::BROWSER;1152        }1153    }1154    /* Seraphic Sraf */1155    private function detectSraf($ua)1156    {1157        if (preg_match('/sraf_tv_browser/u', $ua)) {1158            $this->data->browser->name = 'Seraphic Sraf';1159            $this->data->browser->version = null;1160            $this->data->browser->type = Constants\BrowserType::BROWSER;1161            $this->data->device->type = Constants\DeviceType::TELEVISION;1162        }1163        if (preg_match('/SRAF\/([0-9.]+)/iu', $ua, $match)) {1164            $this->data->browser->name = 'Seraphic Sraf';1165            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1166            $this->data->browser->type = Constants\BrowserType::BROWSER;1167            $this->data->device->type = Constants\DeviceType::TELEVISION;1168        }1169    }1170    /* MachBlue */1171    private function detectMachBlue($ua)1172    {1173        if (preg_match('/mbxtWebKit\/([0-9.]*)/u', $ua, $match)) {1174            $this->data->os->name = '';1175            $this->data->browser->name = 'MachBlue XT';1176            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1177            $this->data->browser->type = Constants\BrowserType::BROWSER;1178            $this->data->device->type = Constants\DeviceType::TELEVISION;1179        }1180        if ($ua == 'MachBlue') {1181            $this->data->os->name = '';1182            $this->data->browser->name = 'MachBlue XT';1183            $this->data->device->type = Constants\DeviceType::TELEVISION;1184            $this->data->browser->type = Constants\BrowserType::BROWSER;1185        }1186    }1187    /* Espial */1188    private function detectEspial($ua)1189    {1190        if (preg_match('/Espial/u', $ua)) {1191            $this->data->browser->name = 'Espial';1192            $this->data->browser->channel = null;1193            $this->data->browser->type = Constants\BrowserType::BROWSER;1194            $this->data->os->name = '';1195            $this->data->os->version = null;1196            if ($this->data->device->type != Constants\DeviceType::TELEVISION) {1197                $this->data->device->type = Constants\DeviceType::TELEVISION;1198                $this->data->device->manufacturer = null;1199                $this->data->device->model = null;1200            }1201            if (preg_match('/Espial(?: Browser|TVBrowser)?\/(?:sig)?([0-9.]*)/u', $ua, $match)) {1202                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1203            }1204            if (preg_match('/;(L6200|L7200)/u', $ua, $match)) {1205                $this->data->device->manufacturer = 'Toshiba';1206                $this->data->device->model = 'Regza ' . $match[1];1207                $this->data->device->series = 'Smart TV';1208                $this->data->device->identified |= Constants\Id::MATCH_UA;1209                $this->data->device->generic = false;1210            }1211        }1212    }1213    /* Iris */1214    private function detectIris($ua)1215    {1216        if (preg_match('/Iris\//u', $ua)) {1217            $this->data->browser->name = 'Iris';1218            $this->data->browser->hidden = false;1219            $this->data->browser->stock = false;1220            $this->data->browser->type = Constants\BrowserType::BROWSER;1221            if (preg_match('/Iris\/([0-9.]*)/u', $ua, $match)) {1222                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1223            }1224            if (preg_match('/ WM([0-9]) /u', $ua, $match)) {1225                $this->data->device->reset();1226                $this->data->device->type = Constants\DeviceType::MOBILE;1227                $this->data->os->reset();1228                $this->data->os->name = 'Windows Mobile';1229                $this->data->os->version = new Version([ 'value' => $match[1] . '.0' ]);1230            }1231            if (preg_match('/Windows NT/u', $ua, $match)) {1232                $this->data->browser->mode = 'desktop';1233                $this->data->device->reset();1234                $this->data->device->type = Constants\DeviceType::MOBILE;1235                $this->data->os->reset();1236                $this->data->os->name = 'Windows Mobile';1237            }1238        }1239    }1240    /* Dolfin */1241    private function detectDolfin($ua)1242    {1243        if (preg_match('/(Dolfin|Jasmine)/u', $ua)) {1244            $this->data->browser->name = 'Dolfin';1245            $this->data->browser->type = Constants\BrowserType::BROWSER;1246            if (preg_match('/(?:Dolfin|Jasmine)\/([0-9.]*)/u', $ua, $match)) {1247                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1248            }1249            if (preg_match('/Browser\/Dolfin([0-9.]*)/u', $ua, $match)) {1250                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1251            }1252        }1253    }1254    /* WebOS */1255    private function detectWebOSBrowser($ua)1256    {1257        if (preg_match('/wOSBrowser/u', $ua)) {1258            $this->data->browser->name = 'webOS Browser';1259            $this->data->browser->type = Constants\BrowserType::BROWSER;1260            if ($this->data->os->name != 'webOS') {1261                $this->data->os->name = 'webOS';1262            }1263            if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Apple') {1264                unset($this->data->device->manufacturer);1265                unset($this->data->device->model);1266                unset($this->data->device->identifier);1267                $this->data->device->identified = Constants\Id::NONE;1268            }1269        }1270    }1271    /* Sailfish */1272    private function detectSailfishBrowser($ua)1273    {1274        if (preg_match('/Sailfish ?Browser/u', $ua)) {1275            $this->data->browser->name = 'Sailfish Browser';1276            $this->data->browser->stock = true;1277            $this->data->browser->type = Constants\BrowserType::BROWSER;1278            if (preg_match('/Sailfish ?Browser\/([0-9.]*)/u', $ua, $match)) {1279                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1280            }1281        }1282    }1283    /* Silk */1284    private function detectSilk($ua)1285    {1286        if (preg_match('/Silk/u', $ua)) {1287            if (preg_match('/Silk-Accelerated/u', $ua) || !preg_match('/PlayStation/u', $ua)) {1288                $this->data->browser->name = 'Silk';1289                $this->data->browser->channel = null;1290                $this->data->browser->type = Constants\BrowserType::BROWSER;1291                if (preg_match('/Silk\/([0-9.]*)/u', $ua, $match)) {1292                    $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1293                }1294                if (preg_match('/; ([^;]*[^;\s])\s+Build/u', $ua, $match)) {1295                    $this->data->device = Data\DeviceModels::identify('android', $match[1]);1296                }1297                if (!$this->data->device->identified) {1298                    $this->data->device->manufacturer = 'Amazon';1299                    $this->data->device->model = 'Kindle Fire';1300                    $this->data->device->type = Constants\DeviceType::TABLET;1301                    $this->data->device->identified |= Constants\Id::INFER;1302                    if (isset($this->data->os->name) && ($this->data->os->name != 'Android' || $this->data->os->name != 'FireOS')) {1303                        $this->data->os->name = 'FireOS';1304                        $this->data->os->family = new Family([ 'name' => 'Android' ]);1305                        $this->data->os->alias = null;1306                        $this->data->os->version = null;1307                    }1308                }1309            }1310        }1311    }1312    /* Nokia */1313    private function detectNokiaBrowser($ua)1314    {1315        if (!preg_match('/(BrowserNG|Nokia|OSRE|Ovi|Maemo)/ui', $ua)) {1316            return;1317        }1318        /* Nokia Browser */1319        if (preg_match('/BrowserNG/u', $ua)) {1320            $this->data->browser->name = 'Nokia Browser';1321            $this->data->browser->type = Constants\BrowserType::BROWSER;1322            if (preg_match('/BrowserNG\/([0-9.]*)/u', $ua, $match)) {1323                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3, 'builds' => false ]);1324            }1325        }1326        if (preg_match('/NokiaBrowser/u', $ua)) {1327            $this->data->browser->name = 'Nokia Browser';1328            $this->data->browser->channel = null;1329            $this->data->browser->type = Constants\BrowserType::BROWSER;1330            if (preg_match('/NokiaBrowser\/([0-9.]*)/u', $ua, $match)) {1331                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1332            }1333        }1334        if (preg_match('/Nokia-Communicator-WWW-Browser/u', $ua)) {1335            $this->data->browser->name = 'Nokia Browser';1336            $this->data->browser->channel = null;1337            $this->data->browser->type = Constants\BrowserType::BROWSER;1338            if (preg_match('/Nokia-Communicator-WWW-Browser\/([0-9.]*)/u', $ua, $match)) {1339                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1340            }1341        }1342        /* Nokia Xpress for S30+, S40 and Windows Phone */1343        if (preg_match('/OSRE/u', $ua)) {1344            $this->data->browser->name = 'Nokia Xpress';1345            $this->data->browser->mode = 'proxy';1346            $this->data->browser->type = Constants\BrowserType::BROWSER;1347            $this->data->device->type = Constants\DeviceType::MOBILE;1348            $this->data->os->name = null;1349            $this->data->os->version = null;1350        }1351        if (preg_match('/S40OviBrowser/u', $ua)) {1352            $this->data->browser->name = 'Nokia Xpress';1353            $this->data->browser->mode = 'proxy';1354            $this->data->browser->type = Constants\BrowserType::BROWSER;1355            if (preg_match('/S40OviBrowser\/([0-9.]*)/u', $ua, $match)) {1356                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1357            }1358            if (preg_match('/Nokia([^\/]+)\//u', $ua, $match)) {1359                $this->data->device->manufacturer = 'Nokia';1360                $this->data->device->model = $match[1];1361                $this->data->device->identified |= Constants\Id::PATTERN;1362                if (isset($this->data->device->model)) {1363                    $device = Data\DeviceModels::identify('s40', $this->data->device->model);1364                    if ($device->identified) {1365                        $device->identified |= $this->data->device->identified;1366                        $this->data->device = $device;1367                    }1368                }1369                if (isset($this->data->device->model)) {1370                    $device = Data\DeviceModels::identify('asha', $this->data->device->model);1371                    if ($device->identified) {1372                        $device->identified |= $this->data->device->identified;1373                        $this->data->os->name = 'Nokia Asha Platform';1374                        $this->data->os->version = new Version([ 'value' => '1.0' ]);1375                        $this->data->device = $device;1376                        if (preg_match('/java_runtime_version=Nokia_Asha_([0-9_]+);/u', $ua, $match)) {1377                            $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);1378                        }1379                    }1380                }1381            }1382            if (preg_match('/NOKIALumia([0-9]+)/u', $ua, $match)) {1383                $this->data->device->manufacturer = 'Nokia';1384                $this->data->device->model = $match[1];1385                $this->data->device->identified |= Constants\Id::PATTERN;1386                $device = Data\DeviceModels::identify('wp', $this->data->device->model);1387                if ($device->identified) {1388                    $device->identified |= $this->data->device->identified;1389                    $this->data->device = $device;1390                    $this->data->os->name = 'Windows Phone';1391                }1392            }1393        }1394        /* MicroB - the default browser for maemo */1395        if (preg_match('/Maemo[ |_]Browser/u', $ua)) {1396            $this->data->browser->name = 'MicroB';1397            $this->data->browser->type = Constants\BrowserType::BROWSER;1398            if (preg_match('/Maemo[ |_]Browser[ |_]([0-9.]*)/u', $ua, $match)) {1399                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1400            }1401        }1402    }1403    /* Konqueror */1404    private function detectKonqueror($ua)1405    {1406        if (preg_match('/[k|K]onqueror\//u', $ua)) {1407            $this->data->browser->name = 'Konqueror';1408            $this->data->browser->type = Constants\BrowserType::BROWSER;1409            if (preg_match('/[k|K]onqueror\/([0-9.]*)/u', $ua, $match)) {1410                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1411            }1412            if ($this->data->device->type == '') {1413                $this->data->device->type = Constants\DeviceType::DESKTOP;1414            }1415        }1416    }1417    /* OmniWeb */1418    private function detectOmniWeb($ua)1419    {1420        if (preg_match('/OmniWeb/u', $ua)) {1421            $this->data->browser->name = 'OmniWeb';1422            $this->data->browser->type = Constants\BrowserType::BROWSER;1423            $this->data->browser->version = null;1424            if (preg_match('/OmniWeb\/v?([0-9])[0-9][0-9]/u', $ua, $match)) {1425                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 1 ]);1426            }1427            if (preg_match('/OmniWeb\/([0-9]\.[0-9\.]+)/u', $ua, $match)) {1428                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1429            }1430            $this->data->device->reset([1431                'type' => Constants\DeviceType::DESKTOP1432            ]);1433            if (!empty($this->data->browser->version)) {1434                if ($this->data->browser->version->is('<', 3)) {1435                    $this->data->os->name = 'NextStep';1436                    $this->data->os->version = null;1437                }1438                if ($this->data->browser->version->is('>=', 4)) {1439                    if (empty($this->data->os->name) || $this->data->os->name != 'OS X') {1440                        $this->data->os->name = 'OS X';1441                        $this->data->os->version = null;1442                    }1443                }1444            }1445        }1446    }1447    /* Other browsers */1448    private function detectDesktopBrowsers($ua)1449    {1450        if (!preg_match('/(WebPositive|WebExplorer|WorldWideweb|Midori|Maxthon|Browse)/ui', $ua)) {1451            return;1452        }1453        /* WebPositive */1454        if (preg_match('/WebPositive/u', $ua, $match)) {1455            $this->data->browser->name = 'WebPositive';1456            $this->data->browser->channel = '';1457            $this->data->browser->version = null;1458            $this->data->browser->type = Constants\BrowserType::BROWSER;1459            if (preg_match('/WebPositive\/([0-9]\.[0-9.]+)/u', $ua, $match)) {1460                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1461            }1462        }1463        /* IBM WebExplorer */1464        if (preg_match('/IBM[- ]WebExplorer[ -]?(DLL ?|Window API ?)?/u', $ua)) {1465            $this->data->browser->name = 'IBM WebExplorer';1466            $this->data->browser->channel = '';1467            $this->data->browser->type = Constants\BrowserType::BROWSER;1468            if (preg_match('/IBM[- ]WebExplorer[ -]?(?:DLL ?|Window API ?)?\/v([0-9]\.[0-9\.]+)/u', $ua, $match)) {1469                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1470            }1471            $this->data->os->name = 'OS/2';1472            $this->data->device->type = 'desktop';1473        }1474        /* WorldWideweb */1475        if (preg_match('/WorldWideweb \(NEXT\)/u', $ua, $match)) {1476            $this->data->browser->name = 'WorldWideWeb';1477            $this->data->browser->channel = '';1478            $this->data->browser->version = null;1479            $this->data->browser->type = Constants\BrowserType::BROWSER;1480            $this->data->os->name = 'NextStep';1481            $this->data->device->type = 'desktop';1482        }1483        /* Midori */1484        if (preg_match('/Midori\/([0-9.]*)/u', $ua, $match)) {1485            $this->data->browser->name = 'Midori';1486            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1487            $this->data->browser->type = Constants\BrowserType::BROWSER;1488            $this->data->device->manufacturer = null;1489            $this->data->device->model = null;1490            $this->data->device->type = Constants\DeviceType::DESKTOP;1491            if (isset($this->data->os->name) && $this->data->os->name == 'OS X') {1492                $this->data->os->name = null;1493                $this->data->os->version = null;1494            }1495        }1496        if (preg_match('/midori(?:\/[0-9.]*)?$/u', $ua)) {1497            $this->data->browser->name = 'Midori';1498            $this->data->browser->type = Constants\BrowserType::BROWSER;1499            $this->data->device->type = Constants\DeviceType::DESKTOP;1500            if (preg_match('/midori\/([0-9.]*)$/u', $ua, $match)) {1501                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1502            }1503        }1504        /* Maxthon */1505        if (preg_match('/Maxthon/iu', $ua, $match)) {1506            $this->data->browser->name = 'Maxthon';1507            $this->data->browser->channel = '';1508            $this->data->browser->version = null;1509            $this->data->browser->type = Constants\BrowserType::BROWSER;1510            if (preg_match('/Maxthon[\/\' ]\(?([0-9.]*)\)?/iu', $ua, $match)) {1511                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1512            }1513            if (isset($this->data->os->name) && $this->data->browser->version && $this->data->os->name == 'Windows' && $this->data->browser->version->toFloat() < 4) {1514                $this->data->browser->version->details = 1;1515            }1516        }1517        /* Browse for Remix OS */1518        if (preg_match('/^Browse\/([0-9.]+)/u', $ua, $match)) {1519            $this->data->browser->name = 'Browse';1520            $this->data->browser->channel = '';1521            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1522            $this->data->browser->type = Constants\BrowserType::BROWSER;1523        }1524    }1525    private function detectMobileBrowsers($ua)1526    {1527        if (!preg_match('/(Ninesky|Skyfire|Dolphin|QQ|360|QHBrowser|Mercury|iBrowser|Puffin|MiniB|MxNitro|Sogou|Xiino|Palmscape|WebPro|Vision|MiuiBrowser)/ui', $ua)) {1528            return;1529        }1530        /* Xiaomi MIUI Browser */1531        if (preg_match('/MiuiBrowser\/([0-9.]*)/u', $ua, $match)) {1532            $this->data->browser->name = 'MIUI Browser';1533            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1534            $this->data->browser->type = Constants\BrowserType::BROWSER;1535            if (!$this->data->os->isFamily('Android')) {1536                $this->data->os->reset();1537                $this->data->os->name = 'Android';1538                $this->data->device->manufacturer = 'Xiaomi';1539                $this->data->device->model = null;1540                $this->data->device->type = Constants\DeviceType::MOBILE;1541            }1542        }1543        /* NineSky */1544        if (preg_match('/Ninesky(?:-android-mobile(?:-cn)?)?\/([0-9.]*)/u', $ua, $match)) {1545            $this->data->browser->reset();1546            $this->data->browser->name = 'NineSky';1547            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1548            $this->data->browser->type = Constants\BrowserType::BROWSER;1549            if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Apple') {1550                $this->data->device->reset();1551            }1552            if (!$this->data->os->isFamily('Android')) {1553                $this->data->os->reset();1554                $this->data->os->name = 'Android';1555            }1556            $this->data->device->type = Constants\DeviceType::MOBILE;1557        }1558        /* Skyfire */1559        if (preg_match('/Skyfire\/([0-9.]*)/u', $ua, $match)) {1560            $this->data->browser->name = 'Skyfire';1561            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1562            $this->data->browser->type = Constants\BrowserType::BROWSER;1563            $this->data->device->type = Constants\DeviceType::MOBILE;1564            $this->data->os->name = 'Android';1565            $this->data->os->version = null;1566        }1567        /* Dolphin HD */1568        if (preg_match('/Dolphin(?:HD|Browser)?(?:INT|CN)?\/(?:INT|CN)?-?([0-9.]*)/u', $ua, $match)) {1569            $this->data->browser->name = 'Dolphin';1570            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1571            $this->data->browser->type = Constants\BrowserType::BROWSER;1572            $this->data->device->type = Constants\DeviceType::MOBILE;1573        }1574        /* QQ Browser */1575        if (preg_match('/(M?QQBrowser)\/([0-9.]*)/u', $ua, $match)) {1576            $this->data->browser->name = 'QQ Browser';1577            $version = $match[2];1578            if (preg_match('/^[0-9][0-9]$/u', $version)) {1579                $version = $version[0] . '.' . $version[1];1580            }1581            $this->data->browser->version = new Version([ 'value' => $version, 'details' => 2 ]);1582            $this->data->browser->type = Constants\BrowserType::BROWSER;1583            $this->data->browser->channel = '';1584            if (!isset($this->data->os->name) && $match[1] == 'QQBrowser') {1585                $this->data->os->name = 'Windows';1586            }1587            if (preg_match('/MQQBrowser\/[0-9\.]+\/Adr \(Linux; U; ([0-9\.]+); [^;]+; (.+) Build/u', $ua, $match)) {1588                $this->data->os->reset([1589                    'name'      => 'Android',1590                    'version'   => new Version([ 'value' => $match[1] ])1591                ]);1592                $this->data->device->type = Constants\DeviceType::MOBILE;1593                $this->data->device->model = $match[2];1594                $this->data->device->identified |= Constants\Id::PATTERN;1595                $device = Data\DeviceModels::identify('android', $match[2]);1596                if ($device->identified) {1597                    $device->identified |= $this->data->device->identified;1598                    $this->data->device = $device;1599                }1600            }1601            if (preg_match('/MQQBrowser\/[0-9\.]+\/WP7 \([^;]+;WPOS:([0-9]\.[0-9])[0-9\.]*;([^;]+); ([^\)]+)\)/u', $ua, $match)) {1602                $this->data->os->reset([1603                    'name'      => 'Windows Phone',1604                    'version'   => new Version([ 'value' => $match[1] ])1605                ]);1606                $this->data->device->type = Constants\DeviceType::MOBILE;1607                $this->data->device->manufacturer = $match[2];1608                $this->data->device->model = $match[3];1609                $this->data->device->identified |= Constants\Id::PATTERN;1610                $device = Data\DeviceModels::identify('wp', $match[3]);1611                if ($device->identified) {1612                    $device->identified |= $this->data->device->identified;1613                    $this->data->device = $device;1614                }1615            }1616        }1617        if (preg_match('/MQQBrowser\/Mini([0-9.]*)/u', $ua, $match)) {1618            $this->data->browser->name = 'QQ Browser Mini';1619            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1620            $this->data->browser->type = Constants\BrowserType::BROWSER;1621            $this->data->browser->channel = '';1622        }1623        if (preg_match('/QQ\/([0-9.]*)/u', $ua, $match)) {1624            $this->data->browser->name = 'QQ Browser';1625            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1626            $this->data->browser->type = Constants\BrowserType::BROWSER;1627            $this->data->browser->channel = '';1628        }1629        /* 360 Phone Browser */1630        if (preg_match('/360 (?:Aphone|Android Phone) Browser/u', $ua, $match)) {1631            $this->data->browser->name = 'Qihoo 360 Browser';1632            $this->data->browser->family = null;1633            $this->data->browser->channel = '';1634            $this->data->browser->type = Constants\BrowserType::BROWSER;1635        }1636        if (preg_match('/360 (?:Aphone|Android Phone) Browser \((?:Version |V)?([0-9.]*)(?:beta)?\)/u', $ua, $match)) {1637            $this->data->browser->name = 'Qihoo 360 Browser';1638            $this->data->browser->family = null;1639            $this->data->browser->channel = '';1640            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1641            $this->data->browser->type = Constants\BrowserType::BROWSER;1642            if (!$this->data->os->isFamily('Android')) {1643                $this->data->device->type = Constants\DeviceType::MOBILE;1644                $this->data->os->reset([1645                    'name' => 'Android'1646                ]);1647            }1648        }1649        if (preg_match('/360%20(?:Browser|Lite)\/([0-9\.]+)/u', $ua, $match)) {1650            $this->data->browser->name = 'Qihoo 360 Browser';1651            $this->data->browser->family = null;1652            $this->data->browser->channel = '';1653            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1654            $this->data->browser->type = Constants\BrowserType::BROWSER;1655        }1656        if (preg_match('/QHBrowser\/([0-9\.]+)/u', $ua, $match)) {1657            $version = $match[1];1658            if (preg_match('/^[0-9][0-9][0-9]$/u', $version)) {1659                $version = $version[0] . '.' . $version[1] . '.' . $version[2];1660            }1661            $this->data->browser->name = 'Qihoo 360 Browser';1662            $this->data->browser->channel = '';1663            $this->data->browser->version = new Version([ 'value' => $version ]);1664            $this->data->browser->type = Constants\BrowserType::BROWSER;1665            if (!$this->data->isOs('iOS')) {1666                $this->data->device->type = Constants\DeviceType::MOBILE;1667                $this->data->os->reset([1668                    'name' => 'iOS'1669                ]);1670            }1671        }1672        /* Mercury */1673        if (preg_match('/(?:^| )Mercury\/([0-9\.]+)/u', $ua, $match)) {1674            $version = $match[1];1675            if (preg_match('/^[0-9][0-9][0-9]$/u', $version)) {1676                $version = $version[0] . '.' . $version[1] . '.' . $version[2];1677            }1678            $this->data->browser->name = 'Mercury Browser';1679            $this->data->browser->channel = '';1680            $this->data->browser->version = new Version([ 'value' => $version ]);1681            $this->data->browser->type = Constants\BrowserType::BROWSER;1682        }1683        /* iBrowser */1684        if (preg_match('/(?:^| )iBrowser\/([0-9.]*)/u', $ua, $match)) {1685            $this->data->browser->name = 'iBrowser';1686            $version = $match[1];1687            if (preg_match('/^[0-9][0-9]$/u', $version)) {1688                $version = $version[0] . '.' . $version[1];1689            }1690            $this->data->browser->version = new Version([ 'value' => $version, 'details' => 2 ]);1691            $this->data->browser->channel = '';1692            $this->data->browser->type = Constants\BrowserType::BROWSER;1693        }1694        if (preg_match('/iBrowser\/Mini([0-9.]*)/u', $ua, $match)) {1695            $this->data->browser->name = 'iBrowser Mini';1696            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1697            $this->data->browser->channel = '';1698            $this->data->browser->type = Constants\BrowserType::BROWSER;1699        }1700        /* Puffin */1701        if (preg_match('/Puffin\/([0-9.]+)([IA])?([PT])?/u', $ua, $match)) {1702            $this->data->browser->name = 'Puffin';1703            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => (intval(substr(strrchr($match[1], '.'), 1)) > 99 ? -1 : null) ]);1704            $this->data->browser->mode = 'proxy';1705            $this->data->browser->channel = '';1706            $this->data->browser->type = Constants\BrowserType::BROWSER;1707            if (isset($match[2])) {1708                switch ($match[2]) {1709                    case 'A':1710                        if (!$this->data->isOs('Android')) {1711                            $this->data->os->reset([ 'name' => 'Android' ]);1712                        }1713                        break;1714                    case 'I':1715                        if (!$this->data->isOs('iOS')) {1716                            $this->data->os->reset([ 'name' => 'iOS' ]);1717                        }1718                        break;1719                }1720            }1721            if (isset($match[3])) {1722                switch ($match[3]) {1723                    case 'P':1724                        $this->data->device->type = Constants\DeviceType::MOBILE;1725                        if ($this->data->os->name == 'iOS' && empty($this->data->device->model)) {1726                            $this->data->device->manufacturer = 'Apple';1727                            $this->data->device->model = 'iPhone';1728                            $this->data->device->identified = Constants\Id::MATCH_UA;1729                        }1730                        break;1731                    case 'T':1732                        $this->data->device->type = Constants\DeviceType::TABLET;1733                        if ($this->data->os->name == 'iOS' && empty($this->data->device->model)) {1734                            $this->data->device->manufacturer = 'Apple';1735                            $this->data->device->model = 'iPad';1736                            $this->data->device->identified = Constants\Id::MATCH_UA;1737                        }1738                        break;1739                }1740            }1741        }1742        /* MiniBrowser Mobile */1743        if (preg_match('/MiniBr?owserM(?:obile)?\/([0-9.]*)/u', $ua, $match)) {1744            $this->data->browser->name = 'MiniBrowser';1745            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1746            $this->data->browser->type = Constants\BrowserType::BROWSER;1747            $this->data->device->type = Constants\DeviceType::MOBILE;1748            if (!$this->data->isOs('Series60')) {1749                $this->data->os->name = 'Series60';1750                $this->data->os->version = null;1751            }1752        }1753        /* Maxthon */1754        if (preg_match('/MxNitro/iu', $ua, $match)) {1755            $this->data->browser->name = 'Maxthon Nitro';1756            $this->data->browser->channel = '';1757            $this->data->browser->version = null;1758            $this->data->browser->type = Constants\BrowserType::BROWSER;1759            if (preg_match('/MxNitro\/([0-9.]*)/iu', $ua, $match)) {1760                $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);1761            }1762        }1763        /* Sogou Mobile */1764        if (preg_match('/SogouAndroidBrowser\/([0-9.]*)/u', $ua, $match)) {1765            $this->data->browser->name = 'Sogou Mobile';1766            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1767            $this->data->browser->type = Constants\BrowserType::BROWSER;1768            if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Apple') {1769                unset($this->data->device->manufacturer);1770                unset($this->data->device->model);1771                unset($this->data->device->identifier);1772                $this->data->device->identified = Constants\Id::NONE;1773            }1774        }1775        /* Xiino */1776        if (preg_match('/Xiino\/([0-9.]+)/u', $ua, $match)) {1777            $this->data->browser->name = 'Xiino';1778            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1779            $this->data->browser->type = Constants\BrowserType::BROWSER;1780            $this->data->device->type = Constants\DeviceType::PDA;1781            $this->data->os->name = 'Palm OS';1782            if (preg_match('/\(v. ([0-9.]+)/u', $ua, $match)) {1783                $this->data->os->version = new Version([ 'value' => $match[1] ]);1784            }1785        }1786        /* Palmscape */1787        if (preg_match('/Palmscape\/(?:PR)?([0-9.]+)/u', $ua, $match)) {1788            $this->data->browser->name = 'Palmscape';1789            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1790            $this->data->browser->type = Constants\BrowserType::BROWSER;1791            $this->data->device->type = Constants\DeviceType::PDA;1792            $this->data->os->name = 'Palm OS';1793            if (preg_match('/\(v. ([0-9.]+)/u', $ua, $match)) {1794                $this->data->os->version = new Version([ 'value' => $match[1] ]);1795            }1796        }1797        /* Novarra WebPro */1798        if (preg_match('/WebPro/u', $ua) && preg_match('/PalmOS/u', $ua)) {1799            $this->data->browser->name = 'WebPro';1800            $this->data->browser->version = null;1801            $this->data->browser->type = Constants\BrowserType::BROWSER;1802            if (preg_match('/WebPro\/?([0-9.]*)/u', $ua, $match)) {1803                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1804            }1805        }1806        /* Novarra Vision */1807        if (preg_match('/(?:Vision-Browser|Novarra-Vision)\/?([0-9.]*)/u', $ua, $match)) {1808            $this->data->browser->name = 'Novarra Vision';1809            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1810            $this->data->browser->family = null;1811            $this->data->browser->mode = 'proxy';1812            $this->data->browser->type = Constants\BrowserType::BROWSER;1813            if ($this->data->device->type != Constants\DeviceType::MOBILE) {1814                $this->data->os->reset();1815                $this->data->device->type = Constants\DeviceType::MOBILE;1816            }1817        }1818    }1819    private function detectTelevisionBrowsers($ua)1820    {1821        if (!preg_match('/(Roku|LG Browser|NetCast|SonyBrowserCore|Dream|Planetweb)/ui', $ua)) {1822            return;1823        }1824        /* Web on Roku */1825        if (preg_match('/Roku/u', $ua) && preg_match('/Web\/([0-9.]+)/u', $ua, $match)) {1826            $this->data->browser->name = 'Web';1827            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1828            $this->data->browser->type = Constants\BrowserType::BROWSER;1829        }1830        /* LG Browser */1831        if (preg_match('/LG Browser\/([0-9.]*)/u', $ua, $match)) {1832            $this->data->browser->name = 'LG Browser';1833            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1834            $this->data->browser->type = Constants\BrowserType::BROWSER;1835            $this->data->device->type = Constants\DeviceType::TELEVISION;1836        }1837        if (preg_match('/NetCast/u', $ua) && preg_match('/SmartTV\//u', $ua)) {1838            unset($this->data->browser->name);1839            unset($this->data->browser->version);1840        }1841        /* Sony Browser */1842        if (preg_match('/SonyBrowserCore\/([0-9.]*)/u', $ua, $match)) {1843            unset($this->data->browser->name);1844            unset($this->data->browser->version);1845            $this->data->device->type = Constants\DeviceType::TELEVISION;1846        }1847        /* Dreamkey */1848        if (preg_match('/DreamKey\/([0-9.]*)/u', $ua, $match)) {1849            $this->data->browser->name = 'Dreamkey';1850            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1851            $this->data->browser->type = Constants\BrowserType::BROWSER;1852            $this->data->device->setIdentification([1853                'manufacturer'  =>  'Sega',1854                'model'         =>  'Dreamcast',1855                'type'          =>  Constants\DeviceType::GAMING,1856                'subtype'       =>  Constants\DeviceSubType::CONSOLE1857            ]);1858        }1859        /* Dream Passport */1860        if (preg_match('/DreamPassport\/([0-9.]*)/u', $ua, $match)) {1861            $this->data->browser->name = 'Dream Passport';1862            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1863            $this->data->browser->type = Constants\BrowserType::BROWSER;1864            $this->data->device->setIdentification([1865                'manufacturer'  =>  'Sega',1866                'model'         =>  'Dreamcast',1867                'type'          =>  Constants\DeviceType::GAMING,1868                'subtype'       =>  Constants\DeviceSubType::CONSOLE1869            ]);1870        }1871        /* Planetweb */1872        if (preg_match('/Planetweb\/v?([0-9.]*)/u', $ua, $match)) {1873            $this->data->browser->name = 'Planetweb';1874            $this->data->browser->version = new Version([ 'value' => $match[1] ]);1875            $this->data->browser->type = Constants\BrowserType::BROWSER;1876            if (preg_match('/Dreamcast/u', $ua, $match)) {1877                $this->data->device->setIdentification([1878                    'manufacturer'  =>  'Sega',1879                    'model'         =>  'Dreamcast',1880                    'type'          =>  Constants\DeviceType::GAMING,1881                    'subtype'       =>  Constants\DeviceSubType::CONSOLE1882                ]);1883            }1884            if (preg_match('/SPS/u', $ua, $match)) {1885                $this->data->device->setIdentification([1886                    'manufacturer'  =>  'Sony',1887                    'model'         =>  'Playstation 2',1888                    'type'          =>  Constants\DeviceType::GAMING,1889                    'subtype'       =>  Constants\DeviceSubType::CONSOLE1890                ]);1891            }1892        }1893    }1894    private function detectRemainingBrowsers($ua)1895    {1896        if ($data = Data\Applications::identifyBrowser($ua)) {1897            $this->data->browser->set($data['browser']);1898            if (!empty($data['device'])) {1899                $this->data->device->set($data['device']);1900            }1901        }1902    }1903    private function detectWapBrowsers($ua)1904    {1905        if (!preg_match('/(Dorado|MAUI)/ui', $ua, $match)) {1906            return;1907        }1908        if (preg_match('/Browser\/Dorado([0-9.]*)/ui', $ua, $match)) {1909            $this->data->browser->name = 'Dorado WAP';1910            $this->data->browser->type = Constants\BrowserType::BROWSER;1911            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1912        }1913        if (preg_match('/Dorado WAP-Browser\/([0-9.]*)/ui', $ua, $match)) {1914            $this->data->browser->name = 'Dorado WAP';1915            $this->data->browser->type = Constants\BrowserType::BROWSER;1916            $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);1917        }1918        if (preg_match('/MAUI[ _]WAP[ _]Browser(?:\/([0-9.]*))?/ui', $ua, $match)) {1919            $this->data->browser->name = 'MAUI WAP';1920            $this->data->browser->type = Constants\BrowserType::BROWSER;1921            if (isset($match[1])) {1922                $this->data->browser->version = new Version([ 'value' => $match[1] ]);1923            }1924        }1925        if (preg_match('/WAP Browser\/MAUI/ui', $ua, $match)) {1926            $this->data->browser->name = 'MAUI WAP';1927            $this->data->browser->type = Constants\BrowserType::BROWSER;1928        }1929    }1930}...match
Using AI Code Generation
1$pattern = new Type('string', 'integer');2$pattern = new Type('string', 'integer');3$pattern = new Type('string', 'integer');4$pattern = new Type('string', 'integer');5$pattern = new Type('string', 'integer');6$pattern = new Type('string', 'integer');7$pattern = new Type('string', 'integer');8$pattern = new Type('string', 'integer');9$pattern = new Type('string', 'integer');10$pattern = new Type('string', 'integer');match
Using AI Code Generation
1$matches = Type::match($value, $type);2if ($matches) {3    echo "Value matches the type";4} else {5    echo "Value does not match the type";6}7Example #2 Type::match() example8$matches = Type::match($value, $type);9if ($matches) {10    echo "Value matches the type";11} else {12    echo "Value does not match the type";13}14Example #3 Type::match() example15$matches = Type::match($value, $type);16if ($matches) {17    echo "Value matches the type";18} else {19    echo "Value does not match the type";20}21Example #4 Type::match() example22$matches = Type::match($value, $type);23if ($matches) {24    echo "Value matches the type";25} else {26    echo "Value does not match the type";27}28Example #5 Type::match() example29$matches = Type::match($value, $type);30if ($matches) {31    echo "Value matches the type";32} else {33    echo "Value does not match the type";34}35Example #6 Type::match() example36$matches = Type::match($value, $type);37if ($matches) {38    echo "Value matches the type";39} else {40    echo "Value does not match the type";41}42Example #7 Type::match() example43$matches = Type::match($value, $type);44if ($matches) {45    echo "Value matches the type";46} else {47    echo "Value does not match the type";48}match
Using AI Code Generation
1$Type = new Type();2$Type->match('Hello World', 'string');3$Type->match(1.234, 'float');4$Type->match(1, 'integer');5$Type->match(array(), 'array');6$Type->match(true, 'boolean');7$Type->match(null, 'null');8$Type->match(1, 'string');9$Type->match(1, 'float');10$Type->match(1, 'integer');11$Type->match(1, 'array');12$Type->match(1, 'boolean');13$Type->match(1, 'null');14$Type->match(1.234, 'string');15$Type->match(1.234, 'float');16$Type->match(1.234, 'integer');17$Type->match(1.234, 'array');18$Type->match(1.234, 'boolean');19$Type->match(1.234, 'null');20$Type->match(array(), 'string');match
Using AI Code Generation
1Type::match($type, $value);2$type->match($value);3$type->match($value, $flags);4$type->match($value, $flags, $name);5$type->match($value, $flags, $name, $message);6$type->match($value, $flags, $name, $message, $code);7Type::match($type, $value);8$type->match($value);9$type->match($value, $flags);10$type->match($value, $flags, $name);11$type->match($value, $flags, $name, $message);12$type->match($value, $flags, $name, $message, $code);13Type::match($type, $value);14$type->match($value);15$type->match($value, $flags);16$type->match($value, $flags, $name);17$type->match($value, $flags, $name, $message);18$type->match($value, $flags, $name, $message, $code);19Type::match($type, $value);20$type->match($value);21$type->match($value, $flags);22$type->match($value, $flags, $name);23$type->match($value, $flags, $name, $message);24$type->match($value, $flags, $name, $message, $code);25Type::match($type, $value);26$type->match($value);27$type->match($value, $flags);28$type->match($value, $flags, $namematch
Using AI Code Generation
1Type::match($var);2foreach(Type::match($var) as $type){3    echo $type;4}5echo Type::match($var);6echo Type::match($var, " ");7echo Type::match($var, " ", "type: ");8echo Type::match($var, " ", "type: ", " ");9echo Type::match($var, " ", "type: ", " ", ",");10echo Type::match($var, " ", "type: ", " ", ",", 2);11echo Type::match($var, " ", "type: ", " ", ",", 2, 5);12echo Type::match($var, " ", "type: ", " ", ",", 2, 5, 10);13echo Type::match($var, " ", "type: ", " ", ",", 2, 5, 10, " | ");Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Execute automation tests with match on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.
Test now for FreeGet 100 minutes of automation test minutes FREE!!
