zoukankan      html  css  js  c++  java
  • PHP判断是手机端访问还是PC端访问网站

    Mobile_Detect 是一个轻量级的开源移动设备(手机)检测的 PHP Class,

    它使用 User-Agent 中的字符串,并结合 HTTP Header,来检测移动设备环境。

    这个设备检测的 PHP 类库最强大的地方是,它有一个非常完整的库,

    可以检测出所用的设备类型(包括操作类型,以及手机品牌等都能检测)和浏览器的详细信息。

    完整的Mobile_Detect代码如下:

    1. <?php  
    2. /** 
    3.  * MIT License 
    4.  * =========== 
    5.  * 
    6.  * Permission is hereby granted, free of charge, to any person obtaining 
    7.  * a copy of this software and associated documentation files (the 
    8.  * "Software"), to deal in the Software without restriction, including 
    9.  * without limitation the rights to use, copy, modify, merge, publish, 
    10.  * distribute, sublicense, and/or sell copies of the Software, and to 
    11.  * permit persons to whom the Software is furnished to do so, subject to 
    12.  * the following conditions: 
    13.  * 
    14.  * The above copyright notice and this permission notice shall be included 
    15.  * in all copies or substantial portions of the Software. 
    16.  * 
    17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
    18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
    20.  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
    21.  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
    22.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
    23.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
    24.  * 
    25.  * 
    26.  * @author      Serban Ghita <serbanghita@gmail.com> 
    27.  *              Victor Stanciu <vic.stanciu@gmail.com> (until v. 1.0) 
    28.  * @license     MIT License https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt 
    29.  * @link        Official page: http://mobiledetect.net 
    30.  *              GitHub Repository: https://github.com/serbanghita/Mobile-Detect 
    31.  *              Google Code Old Page: http://code.google.com/p/php-mobile-detect/ 
    32.  * @version     2.6.6 
    33.  */  
    34.   
    35. class Mobile_Detect  
    36. {  
    37.     /** 
    38.      * Mobile detection type. 
    39.      */  
    40.     const DETECTION_TYPE_MOBILE     = 'mobile';  
    41.   
    42.     /** 
    43.      * Extended detection type. 
    44.      */  
    45.     const DETECTION_TYPE_EXTENDED   = 'extended';  
    46.   
    47.     /** 
    48.      * A frequently used regular expression to extract version #s. 
    49.      */  
    50.     const VER                       = '([w._+]+)';  
    51.   
    52.     /** 
    53.      * Top-level device. 
    54.      */  
    55.     const MOBILE_GRADE_A            = 'A';  
    56.   
    57.     /** 
    58.      * Mid-level device. 
    59.      */  
    60.     const MOBILE_GRADE_B            = 'B';  
    61.   
    62.     /** 
    63.      * Low-level device. 
    64.      */  
    65.     const MOBILE_GRADE_C            = 'C';  
    66.   
    67.     /** 
    68.      * Stores the version number of the current release. 
    69.      * @var array 
    70.      */  
    71.     protected $scriptVersion = '2.6.6';  
    72.   
    73.     /** 
    74.      * The User-Agent HTTP header is stored in here. 
    75.      * @var string 
    76.      */  
    77.     protected $userAgent = null;  
    78.   
    79.     /** 
    80.      * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE. 
    81.      * @var array 
    82.      */  
    83.     protected $httpHeaders = array();  
    84.   
    85.     /** 
    86.      * All the rules combined. 
    87.      * @var array 
    88.      */  
    89.     protected $mobileDetectionRules = null;  
    90.   
    91.     /** 
    92.      * The rules, but extended. 
    93.      * @var array 
    94.      */  
    95.     protected $mobileDetectionRulesExtended = null;  
    96.   
    97.     /** 
    98.      * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED. 
    99.      * 
    100.      * @var string 
    101.      */  
    102.     protected $detectionType = self::DETECTION_TYPE_MOBILE;  
    103.   
    104.     /** 
    105.      * List of mobile devices (phones). 
    106.      * 
    107.      * @var array 
    108.      */  
    109.     protected $phoneDevices = array(  
    110.         'iPhone'        => 'iPhone.*Mobile|iPod', // |iTunes  
    111.         'BlackBerry'    => 'BlackBerry|BB10|rim[0-9]+',  
    112.         'HTC'           => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*EVO',  
    113.         'Nexus'         => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile',  
    114.         // @todo: Is 'Dell Streak' a tablet or a phone? ;)  
    115.         'Dell'          => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|001DL|101DL|GS01',  
    116.         'Motorola'      => 'Motorola|Droid.*Build|DROIDX|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT909|XT910|XT912|XT928',  
    117.         'Samsung'       => 'Samsung|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535',  
    118.         'LG'            => 'LG;|(LG|LG-)?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999)',  
    119.         'Sony'          => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h',  
    120.         'Asus'          => 'Asus.*Galaxy|PadFone.*Mobile',  
    121.         // @ref: http://www.micromaxinfo.com/mobiles/smartphones  
    122.         // Added because the codes might conflict with Acer Tablets.  
    123.         'Micromax'      => 'Micromax.*(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)',  
    124.         'Palm'          => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.  
    125.         'Vertu'         => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)  
    126.         // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)  
    127.         // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.  
    128.         'Pantech'       => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',  
    129.         // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.  
    130.         'Fly'           => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',  
    131.         // Added simvalley mobile just for fun. They have some interesting devices.  
    132.         // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html  
    133.         'SimValley'     => '(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)',  
    134.         // @Tapatalk is a mobile app; @ref: http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039  
    135.         'GenericPhone'  => 'Tapatalk|PDA;|SAGEM|mmp|pocket|psp|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|wap|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser|LG-P500'  
    136.     );  
    137.   
    138.     /** 
    139.      * List of tablet devices. 
    140.      * 
    141.      * @var array 
    142.      */  
    143.     protected $tabletDevices = array(  
    144.         'iPad'              => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.  
    145.         'NexusTablet'       => '^.*Android.*Nexus(((?:(?!Mobile))|(?:(s(7|10).+))).)*$',  
    146.         'SamsungTablet'     => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-I9205|GT-P5200|GT-P5210|SM-T311|SM-T310|SM-T210|SM-T211|SM-P900',  
    147.         // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/  
    148.         'Kindle'            => 'Kindle|Silk.*Accelerated|Android.*(KFTT|KFOTE)',  
    149.         // Only the Surface tablets with Windows RT are considered mobile.  
    150.         // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx  
    151.         'SurfaceTablet'     => 'Windows NT [0-9.]+; ARM;',  
    152.         // @note: watch out for PadFone, see #132  
    153.         'AsusTablet'        => 'Transformer|TF101|^.*PadFone((?!Mobile).)*$|ME301T|ME371MG',  
    154.         'BlackBerryTablet'  => 'PlayBook|RIM Tablet',  
    155.         'HTCtablet'         => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',  
    156.         'MotorolaTablet'    => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',  
    157.         'NookTablet'        => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|LogicPD Zoom2',  
    158.         // @ref: http://www.acer.ro/ac/ro/RO/content/drivers  
    159.         // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)  
    160.         // @note: Can conflict with Micromax phones codes.  
    161.         'AcerTablet'        => 'Android.*; (A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71)',  
    162.         // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/  
    163.         // @ref: http://us.toshiba.com/tablets/tablet-finder  
    164.         // @ref: http://www.toshiba.co.jp/regza/tablet/  
    165.         'ToshibaTablet'     => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',  
    166.         // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html  
    167.         'LGTablet'          => 'L-06C|LG-V900|LG-V909',  
    168.         'FujitsuTablet'     => 'Android.*(F-01D|F-05E|F-10D|M532|Q572)',  
    169.         // Prestigio Tablets http://www.prestigio.com/support  
    170.         'PrestigioTablet'   => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D',  
    171.         // @ref: http://support.lenovo.com/en_GB/downloads/default.page?#  
    172.         'LenovoTablet'      => 'IdeaTab|S2110|S6000|K3011|A3000|A1000|A2107|A2109|A1107',  
    173.         'YarvikTablet'      => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',  
    174.         'MedionTablet'      => 'Android.*OYO|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',  
    175.         'ArnovaTablet'      => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',  
    176.         // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/  
    177.         'IRUTablet'         => 'M702pro',  
    178.         'MegafonTablet'     => 'MegaFon V9|ZTE V9',  
    179.         // @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/  
    180.         'AllViewTablet'           => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',  
    181.         // @reference: http://wiki.archosfans.com/index.php?title=Main_Page  
    182.         'ArchosTablet'      => 'Android.*ARCHOS|101G9|80G9',  
    183.         // @reference: http://en.wikipedia.org/wiki/NOVO7  
    184.         'AinolTablet'       => 'NOVO7|Novo7Aurora|Novo7Basic|NOVO7PALADIN',  
    185.         // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER  
    186.         // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser  
    187.         // @ref: http://www.sony.jp/support/tablet/  
    188.         'SonyTablet'        => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT211|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201',  
    189.         // @ref: db + http://www.cube-tablet.com/buy-products.html  
    190.         'CubeTablet'        => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',  
    191.         // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001  
    192.         'CobyTablet'        => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',  
    193.         // @ref: http://www.match.net.cn/products.asp  
    194.         'MIDTablet'         => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733',  
    195.         // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)  
    196.         // @ref: http://www.imp3.net/14/show.php?itemid=20454  
    197.         'SMiTTablet'        => 'Android.*(MID|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',  
    198.         // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2  
    199.         'RockChipTablet'    => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',  
    200.         // @ref: http://www.telstra.com.au/home-phone/thub-2/  
    201.         'TelstraTablet'     => 'T-Hub2',  
    202.         // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/  
    203.         'FlyTablet'         => 'IQ310|Fly Vision',  
    204.         // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html  
    205.         'bqTablet'          => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)',  
    206.         // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290  
    207.         // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)  
    208.         'HuaweiTablet'      => 'MediaPad|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',  
    209.         // Nec or Medias Tab  
    210.         'NecTablet'         => 'N-06D|N-08D',  
    211.         // Pantech Tablets: http://www.pantechusa.com/phones/  
    212.         'PantechTablet'     => 'Pantech.*P4100',  
    213.         // Broncho Tablets: http://www.broncho.cn/ (hard to find)  
    214.         'BronchoTablet'     => 'Broncho.*(N701|N708|N802|a710)',  
    215.         // @ref: http://versusuk.com/support.html  
    216.         'VersusTablet'      => 'TOUCHPAD.*[78910]|TOUCHTAB',  
    217.         // @ref: http://www.zync.in/index.php/our-products/tablet-phablets  
    218.         'ZyncTablet'        => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',  
    219.         // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/  
    220.         'PositivoTablet'    => 'TB07STA|TB10STA|TB07FTA|TB10FTA',  
    221.         // @ref: https://www.nabitablet.com/  
    222.         'NabiTablet'        => 'Android.*Nabi',  
    223.         'KoboTablet'        => 'Kobo Touch|K080|Vox Build|Arc Build',  
    224.         // French Danew Tablets http://www.danew.com/produits-tablette.php  
    225.         'DanewTablet'       => 'DSlide.*(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)',  
    226.         // Texet Tablets and Readers http://www.texet.ru/tablet/  
    227.         'TexetTablet'       => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',  
    228.         // @note: Avoid detecting 'PLAYSTATION 3' as mobile.  
    229.         'PlaystationTablet' => 'Playstation.*(Portable|Vita)',  
    230.         // @ref: http://www.galapad.net/product.html  
    231.         'GalapadTablet'     => 'Android.*G1',  
    232.         // @ref: http://www.micromaxinfo.com/tablet/funbook  
    233.         'MicromaxTablet'    => 'Funbook|Micromax.*(P250|P560|P360|P362|P600|P300|P350|P500|P275)',  
    234.         // http://www.karbonnmobiles.com/products_tablet.php  
    235.         'KarbonnTablet'     => 'Android.*(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)',  
    236.         // @ref: http://www.gloryunion.cn/products.asp  
    237.         // @ref: http://www.allwinnertech.com/en/apply/mobile.html  
    238.         // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.  
    239.         'GUTablet'          => 'TX-A1301|TX-M9002|Q702', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G  
    240.         'GenericTablet'     => 'Android.*97D|Tablet(?!.*PC)|ViewPad7|BNTV250A|MID-WCDMA|LogicPD Zoom2|A7EB|CatNova8|A1_07|CT704|CT1002|M721|hp-tablet|rk30sdk',  
    241.     );  
    242.   
    243.     /** 
    244.      * List of mobile Operating Systems. 
    245.      * 
    246.      * @var array 
    247.      */  
    248.     protected $operatingSystems = array(  
    249.         'AndroidOS'         => 'Android',  
    250.         'BlackBerryOS'      => 'blackberry|BB10|rim tablet os',  
    251.         'PalmOS'            => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',  
    252.         'SymbianOS'         => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|S60',  
    253.         // @reference: http://en.wikipedia.org/wiki/Windows_Mobile  
    254.         'WindowsMobileOS'   => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',  
    255.         // @reference: http://en.wikipedia.org/wiki/Windows_Phone  
    256.         // http://wifeng.cn/?r=blog&a=view&id=106  
    257.         // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx  
    258.         'WindowsPhoneOS'   => 'Windows Phone OS|XBLWP7|ZuneWP7',  
    259.         'iOS'               => 'iPhone.*Mobile|iPod|iPad',  
    260.         // http://en.wikipedia.org/wiki/MeeGo  
    261.         // @todo: research MeeGo in UAs  
    262.         'MeeGoOS'           => 'MeeGo',  
    263.         // http://en.wikipedia.org/wiki/Maemo  
    264.         // @todo: research Maemo in UAs  
    265.         'MaemoOS'           => 'Maemo',  
    266.         'JavaOS'            => 'J2ME/|MIDP|CLDC', // '|Java/' produces bug #135  
    267.         'webOS'             => 'webOS|hpwOS',  
    268.         'badaOS'            => 'Bada',  
    269.         'BREWOS'            => 'BREW',  
    270.     );  
    271.   
    272.     /** 
    273.      * List of mobile User Agents. 
    274.      * 
    275.      * @var array 
    276.      */  
    277.     protected $userAgents = array(  
    278.         // @reference: https://developers.google.com/chrome/mobile/docs/user-agent  
    279.         'Chrome'          => 'CrMo|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',  
    280.         'Dolfin'          => 'Dolfin',  
    281.         'Opera'           => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+',  
    282.         'Skyfire'         => 'Skyfire',  
    283.         'IE'              => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+  
    284.         'Firefox'         => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',  
    285.         'Bolt'            => 'bolt',  
    286.         'TeaShark'        => 'teashark',  
    287.         'Blazer'          => 'Blazer',  
    288.         // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3  
    289.         'Safari'          => 'Version.*Mobile.*Safari|Safari.*Mobile',  
    290.         // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser)  
    291.         //'Midori'          => 'midori',  
    292.         'Tizen'           => 'Tizen',  
    293.         'UCBrowser'       => 'UC.*Browser|UCWEB',  
    294.         // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7  
    295.         'DiigoBrowser'    => 'DiigoBrowser',  
    296.         // http://www.puffinbrowser.com/index.php  
    297.         'Puffin'            => 'Puffin',  
    298.         // @ref: http://mercury-browser.com/index.html  
    299.         'Mercury'          => 'Mercury',  
    300.         // @reference: http://en.wikipedia.org/wiki/Minimo  
    301.         // http://en.wikipedia.org/wiki/Vision_Mobile_Browser  
    302.         'GenericBrowser'  => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision'  
    303.     );  
    304.   
    305.     /** 
    306.      * Utilities. 
    307.      * 
    308.      * @var array 
    309.      */  
    310.     protected $utilities = array(  
    311.         // Experimental. When a mobile device wants to switch to 'Desktop Mode'.  
    312.         // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/  
    313.         // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011  
    314.         'DesktopMode' => 'WPDesktop',  
    315.         'TV'          => 'SonyDTV|HbbTV', // experimental  
    316.         'WebKit'      => '(webkit)[ /]([w.]+)',  
    317.         'Bot'         => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',  
    318.         'MobileBot'   => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2',  
    319.         'Watch'       => 'SM-V700',  
    320.     );  
    321.   
    322.     /** 
    323.      * The individual segments that could exist in a User-Agent string. VER refers to the regular 
    324.      * expression defined in the constant self::VER. 
    325.      * 
    326.      * @var array 
    327.      */  
    328.     protected $properties = array(  
    329.   
    330.         // Build  
    331.         'Mobile'        => 'Mobile/[VER]',  
    332.         'Build'         => 'Build/[VER]',  
    333.         'Version'       => 'Version/[VER]',  
    334.         'VendorID'      => 'VendorID/[VER]',  
    335.   
    336.         // Devices  
    337.         'iPad'          => 'iPad.*CPU[a-z ]+[VER]',  
    338.         'iPhone'        => 'iPhone.*CPU[a-z ]+[VER]',  
    339.         'iPod'          => 'iPod.*CPU[a-z ]+[VER]',  
    340.         //'BlackBerry'    => array('BlackBerry[VER]', 'BlackBerry [VER];'),  
    341.         'Kindle'        => 'Kindle/[VER]',  
    342.   
    343.         // Browser  
    344.         'Chrome'        => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),  
    345.         'Dolfin'        => 'Dolfin/[VER]',  
    346.         // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference  
    347.         'Firefox'       => 'Firefox/[VER]',  
    348.         'Fennec'        => 'Fennec/[VER]',  
    349.         // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx  
    350.         'IE'      => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),  
    351.         // http://en.wikipedia.org/wiki/NetFront  
    352.         'NetFront'      => 'NetFront/[VER]',  
    353.         'NokiaBrowser'  => 'NokiaBrowser/[VER]',  
    354.         'Opera'         => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),  
    355.         'Opera Mini'    => 'Opera Mini/[VER]',  
    356.         'Opera Mobi'    => 'Version/[VER]',  
    357.         'UC Browser'    => 'UC Browser[VER]',  
    358.         // @note: Safari 7534.48.3 is actually Version 5.1.  
    359.         // @note: On BlackBerry the Version is overwriten by the OS.  
    360.         'Safari'        => array( 'Version/[VER]', 'Safari/[VER]' ),  
    361.         'Skyfire'       => 'Skyfire/[VER]',  
    362.         'Tizen'         => 'Tizen/[VER]',  
    363.         'Webkit'        => 'webkit[ /][VER]',  
    364.   
    365.         // Engine  
    366.         'Gecko'         => 'Gecko/[VER]',  
    367.         'Trident'       => 'Trident/[VER]',  
    368.         'Presto'        => 'Presto/[VER]',  
    369.   
    370.         // OS  
    371.         'iOS'              => ' OS [VER] ',  
    372.         'Android'          => 'Android [VER]',  
    373.         'BlackBerry'       => array('BlackBerry[w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),  
    374.         'BREW'             => 'BREW [VER]',  
    375.         'Java'             => 'Java/[VER]',  
    376.         // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx  
    377.         // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases  
    378.         'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),  
    379.         'Windows Phone'    => 'Windows Phone [VER]',  
    380.         'Windows CE'       => 'Windows CE/[VER]',  
    381.         // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd  
    382.         'Windows NT'       => 'Windows NT [VER]',  
    383.         'Symbian'          => array('SymbianOS/[VER]', 'Symbian/[VER]'),  
    384.         'webOS'            => array('webOS/[VER]', 'hpwOS/[VER];'),  
    385.     );  
    386.   
    387.     /** 
    388.      * Construct an instance of this class. 
    389.      * 
    390.      * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored. 
    391.      *                       If left empty, will use the global _SERVER['HTTP_*'] vars instead. 
    392.      * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT 
    393.      *                          from the $headers array instead. 
    394.      */  
    395.     public function __construct(  
    396.         array $headers = null,  
    397.         $userAgent = null  
    398.     ){  
    399.         $this->setHttpHeaders($headers);  
    400.         $this->setUserAgent($userAgent);  
    401.   
    402.         $this->setMobileDetectionRules();  
    403.         $this->setMobileDetectionRulesExtended();  
    404.     }  
    405.   
    406.     /** 
    407.     * Get the current script version. 
    408.     * This is useful for the demo.php file, 
    409.     * so people can check on what version they are testing 
    410.     * for mobile devices. 
    411.     * 
    412.     * @return string The version number in "X.Y.Z" format. 
    413.     */  
    414.     public function getScriptVersion()  
    415.     {  
    416.         return $this->scriptVersion;  
    417.     }  
    418.   
    419.     /** 
    420.      * Set the HTTP Headers. Must be PHP-flavored. 
    421.      * 
    422.      * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract 
    423.      *                           the headers. The default null is left for backwards compatibilty. 
    424.      */  
    425.     public function setHttpHeaders($httpHeaders = null)  
    426.     {  
    427.         //use global _SERVER if $httpHeaders aren't defined  
    428.         if (!is_array($httpHeaders) || !count($httpHeaders)) {  
    429.             $httpHeaders = $_SERVER;  
    430.         }  
    431.   
    432.         //Only save HTTP headers. In PHP land, that means only _SERVER vars that  
    433.         //start with HTTP_.  
    434.         foreach ($httpHeaders as $key => $value) {  
    435.             if (substr($key,0,5) == 'HTTP_') {  
    436.                 $this->httpHeaders[$key] = $value;  
    437.             }  
    438.         }  
    439.     }  
    440.   
    441.     /** 
    442.      * Retrieves the HTTP headers. 
    443.      * 
    444.      * @return array 
    445.      */  
    446.     public function getHttpHeaders()  
    447.     {  
    448.         return $this->httpHeaders;  
    449.     }  
    450.   
    451.     /** 
    452.      * Retrieves a particular header. If it doesn't exist, no exception/error is caused. 
    453.      * Simply null is returned. 
    454.      * 
    455.      * @param string $header The name of the header to retrieve. Can be HTTP compliant such as 
    456.      *                       "User-Agent" or "X-Device-User-Agent" or can be php-esque with the 
    457.      *                       all-caps, HTTP_ prefixed, underscore seperated awesomeness. 
    458.      * 
    459.      * @return string|null The value of the header. 
    460.      */  
    461.     public function getHttpHeader($header)  
    462.     {  
    463.         //are we using PHP-flavored headers?  
    464.         if (strpos($header, '_') === false) {  
    465.             $header = str_replace('-', '_', $header);  
    466.             $header = strtoupper($header);  
    467.         }  
    468.   
    469.         //test the alternate, too  
    470.         $altHeader = 'HTTP_' . $header;  
    471.   
    472.         //Test both the regular and the HTTP_ prefix  
    473.         if (isset($this->httpHeaders[$header])) {  
    474.             return $this->httpHeaders[$header];  
    475.         } elseif (isset($this->httpHeaders[$altHeader])) {  
    476.             return $this->httpHeaders[$altHeader];  
    477.         }  
    478.     }  
    479.   
    480.     /** 
    481.      * Set the User-Agent to be used. 
    482.      * 
    483.      * @param string $userAgent The user agent string to set. 
    484.      */  
    485.     public function setUserAgent($userAgent = null)  
    486.     {  
    487.         if (!empty($userAgent)) {  
    488.             $this->userAgent = $userAgent;  
    489.         } else {  
    490.             $this->userAgent = $this->getHttpHeader('User-Agent');  
    491.   
    492.             if (empty($this->userAgent)) {  
    493.                 $this->userAgent = $this->getHttpHeader('X-Device-User-Agent');  
    494.             }  
    495.   
    496.             //Header can occur on devices using Opera Mini (can expose the real device type).  
    497.             //Let's concatenate it (we need this extra info in the regexes).  
    498.             if ($operaMiniUa = $this->getHttpHeader('X-OperaMini-Phone-UA')) {  
    499.                 $this->userAgent .= ' ' . $operaMiniUa;  
    500.             }  
    501.         }  
    502.     }  
    503.   
    504.     /** 
    505.      * Retrieve the User-Agent. 
    506.      * 
    507.      * @return string|null The user agent if it's set. 
    508.      */  
    509.     public function getUserAgent()  
    510.     {  
    511.         return $this->userAgent;  
    512.     }  
    513.   
    514.     /** 
    515.      * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or 
    516.      * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set. 
    517.      * 
    518.      * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default 
    519.      *                     parameter is null which will default to self::DETECTION_TYPE_MOBILE. 
    520.      */  
    521.     public function setDetectionType($type = null)  
    522.     {  
    523.         if ($type === null) {  
    524.             $type = self::DETECTION_TYPE_MOBILE;  
    525.         }  
    526.   
    527.         if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {  
    528.             return;  
    529.         }  
    530.   
    531.         $this->detectionType = $type;  
    532.     }  
    533.   
    534.     /** 
    535.      * Retrieve the list of known phone devices. 
    536.      * 
    537.      * @return array List of phone devices. 
    538.      */  
    539.     public function getPhoneDevices()  
    540.     {  
    541.         return $this->phoneDevices;  
    542.     }  
    543.   
    544.     /** 
    545.      * Retrieve the list of known tablet devices. 
    546.      * 
    547.      * @return array List of tablet devices. 
    548.      */  
    549.     public function getTabletDevices()  
    550.     {  
    551.         return $this->tabletDevices;  
    552.     }  
    553.   
    554.     /** 
    555.      * Method sets the mobile detection rules. This method is used for the magic methods $detect->is*(). 
    556.      */  
    557.     public function setMobileDetectionRules()  
    558.     {  
    559.         // Merge all rules together.  
    560.         $this->mobileDetectionRules = array_merge(  
    561.             $this->phoneDevices,  
    562.             $this->tabletDevices,  
    563.             $this->operatingSystems,  
    564.             $this->userAgents  
    565.         );  
    566.   
    567.     }  
    568.   
    569.     /** 
    570.      * Method sets the mobile detection rules + utilities. 
    571.      * The reason this is separate is because utilities rules 
    572.      * don't necessary imply mobile. This method is used inside 
    573.      * the new $detect->is('stuff') method. 
    574.      */  
    575.     public function setMobileDetectionRulesExtended()  
    576.     {  
    577.         // Merge all rules together.  
    578.         $this->mobileDetectionRulesExtended = array_merge(  
    579.             $this->phoneDevices,  
    580.             $this->tabletDevices,  
    581.             $this->operatingSystems,  
    582.             $this->userAgents,  
    583.             $this->utilities  
    584.         );  
    585.   
    586.     }  
    587.   
    588.     /** 
    589.      * Retrieve the current set of rules. 
    590.      * 
    591.      * @return array 
    592.      */  
    593.     public function getRules()  
    594.     {  
    595.         if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {  
    596.             return $this->mobileDetectionRulesExtended;  
    597.         } else {  
    598.             return $this->mobileDetectionRules;  
    599.         }  
    600.     }  
    601.   
    602.     /** 
    603.     * Check the HTTP headers for signs of mobile. 
    604.     * This is the fastest mobile check possible; it's used 
    605.     * inside isMobile() method. 
    606.     * 
    607.     * @return bool 
    608.     */  
    609.     public function checkHttpHeadersForMobile()  
    610.     {  
    611.         return(  
    612.             isset($this->httpHeaders['HTTP_ACCEPT']) &&  
    613.                 (strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/x-obml2d') !== false || // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/  
    614.                  strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.rim.html') !== false || // BlackBerry devices.  
    615.                  strpos($this->httpHeaders['HTTP_ACCEPT'], 'text/vnd.wap.wml') !== false ||  
    616.                  strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.wap.xhtml+xml') !== false) ||  
    617.             isset($this->httpHeaders['HTTP_X_WAP_PROFILE'])             || // @todo: validate  
    618.             isset($this->httpHeaders['HTTP_X_WAP_CLIENTID'])            ||  
    619.             isset($this->httpHeaders['HTTP_WAP_CONNECTION'])            ||  
    620.             isset($this->httpHeaders['HTTP_PROFILE'])                   ||  
    621.             isset($this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA'])      || // Reported by Nokia devices (eg. C3)  
    622.             isset($this->httpHeaders['HTTP_X_NOKIA_IPADDRESS'])         ||  
    623.             isset($this->httpHeaders['HTTP_X_NOKIA_GATEWAY_ID'])        ||  
    624.             isset($this->httpHeaders['HTTP_X_ORANGE_ID'])               ||  
    625.             isset($this->httpHeaders['HTTP_X_VODAFONE_3GPDPCONTEXT'])   ||  
    626.             isset($this->httpHeaders['HTTP_X_HUAWEI_USERID'])           ||  
    627.             isset($this->httpHeaders['HTTP_UA_OS'])                     || // Reported by Windows Smartphones.  
    628.             isset($this->httpHeaders['HTTP_X_MOBILE_GATEWAY'])          || // Reported by Verizon, Vodafone proxy system.  
    629.             isset($this->httpHeaders['HTTP_X_ATT_DEVICEID'])            || // Seen this on HTC Sensation. @ref: SensationXE_Beats_Z715e  
    630.             //HTTP_X_NETWORK_TYPE = WIFI  
    631.             ( isset($this->httpHeaders['HTTP_UA_CPU']) &&  
    632.                     $this->httpHeaders['HTTP_UA_CPU'] == 'ARM'          // Seen this on a HTC.  
    633.             )  
    634.         );  
    635.     }  
    636.   
    637.     /** 
    638.      * Magic overloading method. 
    639.      * 
    640.      * @method boolean is[...]() 
    641.      * @param  string                 $name 
    642.      * @param  array                  $arguments 
    643.      * @return mixed 
    644.      * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is' 
    645.      */  
    646.     public function __call($name, $arguments)  
    647.     {  
    648.         //make sure the name starts with 'is', otherwise  
    649.         if (substr($name, 0, 2) != 'is') {  
    650.             throw new BadMethodCallException("No such method exists: $name");  
    651.         }  
    652.   
    653.         $this->setDetectionType(self::DETECTION_TYPE_MOBILE);  
    654.   
    655.         $key = substr($name, 2);  
    656.   
    657.         return $this->matchUAAgainstKey($key);  
    658.     }  
    659.   
    660.     /** 
    661.     * Find a detection rule that matches the current User-agent. 
    662.     * 
    663.     * @param null $userAgent deprecated 
    664.     * @return boolean 
    665.     */  
    666.     private function matchDetectionRulesAgainstUA($userAgent = null)  
    667.     {  
    668.         // Begin general search.  
    669.         foreach ($this->getRules() as $_regex) {  
    670.             if (empty($_regex)) {  
    671.                 continue;  
    672.             }  
    673.             if ($this->match($_regex, $userAgent)) {  
    674.                 return true;  
    675.             }  
    676.         }  
    677.   
    678.         return false;  
    679.     }  
    680.   
    681.     /** 
    682.     * Search for a certain key in the rules array. 
    683.     * If the key is found the try to match the corresponding 
    684.     * regex agains the User-Agent. 
    685.     * 
    686.     * @param string $key 
    687.     * @param null $userAgent deprecated 
    688.     * @return mixed 
    689.     */  
    690.     private function matchUAAgainstKey($key, $userAgent = null)  
    691.     {  
    692.         // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.  
    693.         $key = strtolower($key);  
    694.   
    695.         //change the keys to lower case  
    696.         $_rules = array_change_key_case($this->getRules());  
    697.   
    698.         if (array_key_exists($key, $_rules)) {  
    699.             if (empty($_rules[$key])) {  
    700.                 return null;  
    701.             }  
    702.   
    703.             return $this->match($_rules[$key], $userAgent);  
    704.         }  
    705.   
    706.         return false;  
    707.     }  
    708.   
    709.     /** 
    710.     * Check if the device is mobile. 
    711.     * Returns true if any type of mobile device detected, including special ones 
    712.     * @param null $userAgent deprecated 
    713.     * @param null $httpHeaders deprecated 
    714.     * @return bool 
    715.     */  
    716.     public function isMobile($userAgent = null, $httpHeaders = null)  
    717.     {  
    718.   
    719.         if ($httpHeaders) {  
    720.             $this->setHttpHeaders($httpHeaders);  
    721.         }  
    722.   
    723.         if ($userAgent) {  
    724.             $this->setUserAgent($userAgent);  
    725.         }  
    726.   
    727.         $this->setDetectionType(self::DETECTION_TYPE_MOBILE);  
    728.   
    729.         if ($this->checkHttpHeadersForMobile()) {  
    730.             return true;  
    731.         } else {  
    732.             return $this->matchDetectionRulesAgainstUA();  
    733.         }  
    734.   
    735.     }  
    736.   
    737.     /** 
    738.      * Check if the device is a tablet. 
    739.      * Return true if any type of tablet device is detected. 
    740.      * 
    741.      * @param  string $userAgent   deprecated 
    742.      * @param  array  $httpHeaders deprecated 
    743.      * @return bool 
    744.      */  
    745.     public function isTablet($userAgent = null, $httpHeaders = null)  
    746.     {  
    747.         $this->setDetectionType(self::DETECTION_TYPE_MOBILE);  
    748.   
    749.         foreach ($this->tabletDevices as $_regex) {  
    750.             if ($this->match($_regex, $userAgent)) {  
    751.                 return true;  
    752.             }  
    753.         }  
    754.   
    755.         return false;  
    756.     }  
    757.   
    758.     /** 
    759.      * This method checks for a certain property in the 
    760.      * userAgent. 
    761.      * @todo: The httpHeaders part is not yet used. 
    762.      * 
    763.      * @param $key 
    764.      * @param  string        $userAgent   deprecated 
    765.      * @param  string        $httpHeaders deprecated 
    766.      * @return bool|int|null 
    767.      */  
    768.     public function is($key, $userAgent = null, $httpHeaders = null)  
    769.     {  
    770.         // Set the UA and HTTP headers only if needed (eg. batch mode).  
    771.         if ($httpHeaders) {  
    772.             $this->setHttpHeaders($httpHeaders);  
    773.         }  
    774.   
    775.         if ($userAgent) {  
    776.             $this->setUserAgent($userAgent);  
    777.         }  
    778.   
    779.         $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);  
    780.   
    781.         return $this->matchUAAgainstKey($key);  
    782.     }  
    783.   
    784.     /** 
    785.      * Retrieve the list of mobile operating systems. 
    786.      * 
    787.      * @return array The list of mobile operating systems. 
    788.      */  
    789.     public function getOperatingSystems()  
    790.     {  
    791.         return $this->operatingSystems;  
    792.     }  
    793.   
    794.     /** 
    795.      * Some detection rules are relative (not standard), 
    796.      * because of the diversity of devices, vendors and 
    797.      * their conventions in representing the User-Agent or 
    798.      * the HTTP headers. 
    799.      * 
    800.      * This method will be used to check custom regexes against 
    801.      * the User-Agent string. 
    802.      * 
    803.      * @param $regex 
    804.      * @param  string $userAgent 
    805.      * @return bool 
    806.      * 
    807.      * @todo: search in the HTTP headers too. 
    808.      */  
    809.     public function match($regex, $userAgent = null)  
    810.     {  
    811.         // Escape the special character which is the delimiter.  
    812.         $regex = str_replace('/', '/', $regex);  
    813.   
    814.         return (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));  
    815.     }  
    816.   
    817.     /** 
    818.      * Get the properties array. 
    819.      * 
    820.      * @return array 
    821.      */  
    822.     public function getProperties()  
    823.     {  
    824.         return $this->properties;  
    825.     }  
    826.   
    827.     /** 
    828.      * Prepare the version number. 
    829.      * 
    830.      * @todo Remove the error supression from str_replace() call. 
    831.      * 
    832.      * @param string $ver The string version, like "2.6.21.2152"; 
    833.      * 
    834.      * @return float 
    835.      */  
    836.     public function prepareVersionNo($ver)  
    837.     {  
    838.         $ver = str_replace(array('_', ' ', '/'), array('.', '.', '.'), $ver);  
    839.         $arrVer = explode('.', $ver, 2);  
    840.   
    841.         if (isset($arrVer[1])) {  
    842.             $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.  
    843.         }  
    844.   
    845.         return (float) implode('.', $arrVer);  
    846.     }  
    847.   
    848.     /** 
    849.      * Check the version of the given property in the User-Agent. 
    850.      * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) 
    851.      * 
    852.      * @param  string $propertyName 
    853.      * @param  string $type 
    854.      * @return mixed  $version 
    855.      */  
    856.     public function version($propertyName, $type = 'text')  
    857.     {  
    858.         if (empty($propertyName)) {  
    859.             return false;  
    860.         }  
    861.   
    862.         if (!in_array($type, array('text', 'float'))) {  
    863.             $type = 'text';  
    864.         }  
    865.   
    866.         $properties = $this->getProperties();  
    867.   
    868.         // Check if the property exists in the properties array.  
    869.         if (array_key_exists($propertyName, $properties)) {  
    870.   
    871.             // Prepare the pattern to be matched.  
    872.             // Make sure we always deal with an array (string is converted).  
    873.             $properties[$propertyName] = (array) $properties[$propertyName];  
    874.   
    875.             foreach ($properties[$propertyName] as $propertyMatchString) {  
    876.   
    877.                 $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);  
    878.   
    879.                 // Escape the special character which is the delimiter.  
    880.                 $propertyPattern = str_replace('/', '/', $propertyPattern);  
    881.   
    882.                 // Identify and extract the version.  
    883.                 preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);  
    884.   
    885.                 if (!empty($match[1])) {  
    886.                     $version = ( $type == 'float' ? $this->prepareVersionNo($match[1]) : $match[1] );  
    887.   
    888.                     return $version;  
    889.                 }  
    890.   
    891.             }  
    892.   
    893.         }  
    894.   
    895.         return false;  
    896.     }  
    897.   
    898.     /** 
    899.      * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants. 
    900.      * 
    901.      * @return string One of the self::MOBILE_GRADE_* constants. 
    902.      */  
    903.     public function mobileGrade()  
    904.     {  
    905.         $isMobile = $this->isMobile();  
    906.   
    907.         if (  
    908.             // Apple iOS 3.2-5.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3), iPad 3 (5.1), original iPhone (3.1), iPhone 3 (3.2), 3GS (4.3), 4 (4.3 / 5.0), and 4S (5.1)  
    909.             $this->version('iPad', 'float')>=4.3 ||  
    910.             $this->version('iPhone', 'float')>=3.1 ||  
    911.             $this->version('iPod', 'float')>=3.1 ||  
    912.   
    913.             // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)  
    914.             // Android 3.1 (Honeycomb)  - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM  
    915.             // Android 4.0 (ICS)  - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices  
    916.             // Android 4.1 (Jelly Bean)  - Tested on a Galaxy Nexus and Galaxy 7  
    917.             ( $this->version('Android', 'float')>2.1 && $this->is('Webkit') ) ||  
    918.   
    919.             // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800  
    920.             $this->version('Windows Phone OS', 'float')>=7.0 ||  
    921.   
    922.             // Blackberry 7 - Tested on BlackBerry® Torch 9810  
    923.             // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670  
    924.             $this->is('BlackBerry') && $this->version('BlackBerry', 'float')>=6.0 ||  
    925.             // Blackberry Playbook (1.0-2.0) - Tested on PlayBook  
    926.             $this->match('Playbook.*Tablet') ||  
    927.   
    928.             // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0)  
    929.             ( $this->version('webOS', 'float')>=1.4 && $this->match('Palm|Pre|Pixi') ) ||  
    930.             // Palm WebOS 3.0  - Tested on HP TouchPad  
    931.             $this->match('hp.*TouchPad') ||  
    932.   
    933.             // Firefox Mobile (12 Beta) - Tested on Android 2.3 device  
    934.             ( $this->is('Firefox') && $this->version('Firefox', 'float')>=12 ) ||  
    935.   
    936.             // Chrome for Android - Tested on Android 4.0, 4.1 device  
    937.             ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', 'float')>=4.0 ) ||  
    938.   
    939.             // Skyfire 4.1 - Tested on Android 2.3 device  
    940.             ( $this->is('Skyfire') && $this->version('Skyfire', 'float')>=4.1 && $this->is('AndroidOS') && $this->version('Android', 'float')>=2.3 ) ||  
    941.   
    942.             // Opera Mobile 11.5-12: Tested on Android 2.3  
    943.             ( $this->is('Opera') && $this->version('Opera Mobi', 'float')>11 && $this->is('AndroidOS') ) ||  
    944.   
    945.             // Meego 1.2 - Tested on Nokia 950 and N9  
    946.             $this->is('MeeGoOS') ||  
    947.   
    948.             // Tizen (pre-release) - Tested on early hardware  
    949.             $this->is('Tizen') ||  
    950.   
    951.             // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser  
    952.             // @todo: more tests here!  
    953.             $this->is('Dolfin') && $this->version('Bada', 'float')>=2.0 ||  
    954.   
    955.             // UC Browser - Tested on Android 2.3 device  
    956.             ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', 'float')>=2.3 ) ||  
    957.   
    958.             // Kindle 3 and Fire  - Tested on the built-in WebKit browser for each  
    959.             ( $this->match('Kindle Fire') ||  
    960.             $this->is('Kindle') && $this->version('Kindle', 'float')>=3.0 ) ||  
    961.   
    962.             // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet  
    963.             $this->is('AndroidOS') && $this->is('NookTablet') ||  
    964.   
    965.             // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7  
    966.             $this->version('Chrome', 'float')>=11 && !$isMobile ||  
    967.   
    968.             // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7  
    969.             $this->version('Safari', 'float')>=5.0 && !$isMobile ||  
    970.   
    971.             // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7  
    972.             $this->version('Firefox', 'float')>=4.0 && !$isMobile ||  
    973.   
    974.             // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7  
    975.             $this->version('MSIE', 'float')>=7.0 && !$isMobile ||  
    976.   
    977.             // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7  
    978.             // @reference: http://my.opera.com/community/openweb/idopera/  
    979.             $this->version('Opera', 'float')>=10 && !$isMobile  
    980.   
    981.   
    982.         ){  
    983.             return self::MOBILE_GRADE_A;  
    984.         }  
    985.   
    986.         if (  
    987.             $this->version('iPad', 'float')<4.3 ||  
    988.             $this->version('iPhone', 'float')<3.1 ||  
    989.             $this->version('iPod', 'float')<3.1 ||  
    990.   
    991.             // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770  
    992.             $this->is('Blackberry') && $this->version('BlackBerry', 'float')>=5 && $this->version('BlackBerry', 'float')<6 ||  
    993.   
    994.             //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3  
    995.             ( $this->version('Opera Mini', 'float')>=5.0 && $this->version('Opera Mini', 'float')<=6.5 &&  
    996.             ($this->version('Android', 'float')>=2.3 || $this->is('iOS')) ) ||  
    997.   
    998.             // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)  
    999.             $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||  
    1000.   
    1001.             // @todo: report this (tested on Nokia N71)  
    1002.             $this->version('Opera Mobi', 'float')>=11 && $this->is('SymbianOS')  
    1003.         ){  
    1004.             return self::MOBILE_GRADE_B;  
    1005.         }  
    1006.   
    1007.         if (  
    1008.             // Blackberry 4.x - Tested on the Curve 8330  
    1009.             $this->version('BlackBerry', 'float')<5.0 ||  
    1010.             // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)  
    1011.             $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', 'float')<=5.2  
    1012.   
    1013.   
    1014.         ){  
    1015.             return self::MOBILE_GRADE_C;  
    1016.         }  
    1017.   
    1018.         //All older smartphone platforms and featurephones - Any device that doesn't support media queries  
    1019.         //will receive the basic, C grade experience.  
    1020.         return self::MOBILE_GRADE_C;  
    1021.     }  
    1022. }  


    简单的使用方法如下:

      1. //使用实例  
      2.    
      3. include 'Mobile_Detect.php';  
      4. $detect = new Mobile_Detect();  
      5.    
      6. // Check for any mobile device.  
      7. if ($detect->isMobile())  
      8.    
      9. // Check for any tablet.  
      10. if($detect->isTablet())  
      11.    
      12. // Check for any mobile device, excluding tablets.  
      13. if ($detect->isMobile() && !$detect->isTablet())  
      14.    
      15. if ($detect->isMobile() && !$detect->isTablet())  
      16.    
      17. // Alternative to $detect->isAndroidOS()  
      18. $detect->is('AndroidOS');  
      19.    
      20. // Batch usage  
      21. foreach($userAgents as $userAgent){  
      22.   $detect->setUserAgent($userAgent);  
      23.   $isMobile = $detect->isMobile();  
      24. }  
      25.    
      26. // Version check.  
      27. $detect->version('iPad'); // 4.3 (float) 
  • 相关阅读:
    P1144 最短路计数 题解 最短路应用题
    C++高精度加减乘除模板
    HDU3746 Teacher YYF 题解 KMP算法
    POJ3080 Blue Jeans 题解 KMP算法
    POJ2185 Milking Grid 题解 KMP算法
    POJ2752 Seek the Name, Seek the Fame 题解 KMP算法
    POJ2406 Power Strings 题解 KMP算法
    HDU2087 剪花布条 题解 KMP算法
    eclipse创建maven项目(详细)
    maven的作用及优势
  • 原文地址:https://www.cnblogs.com/sweet521/p/5684351.html
Copyright © 2011-2022 走看看