Optimiseweb_MobileDetect - Version 0.1.6

Version Notes

Updated to Mobile Detect 2.7.1

Download this release

Release Info

Developer Kathir Vel
Extension Optimiseweb_MobileDetect
Version 0.1.6
Comparing to
See all releases


Code changes from version 0.1.4 to 0.1.6

app/code/community/Optimiseweb/MobileDetect/Library/Mobile_Detect.php CHANGED
@@ -1,803 +1,1111 @@
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 v1.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.0
33
- */
34
-
35
- class Mobile_Detect {
36
-
37
- protected $scriptVersion = '2.6.0';
38
-
39
- // External info.
40
- protected $userAgent = null;
41
- protected $httpHeaders;
42
-
43
- // Arrays holding all detection rules.
44
- protected $mobileDetectionRules = null;
45
- protected $mobileDetectionRulesExtended = null;
46
- // Type of detection to use.
47
- protected $detectionType = 'mobile'; // mobile, extended @todo: refactor this.
48
-
49
- // List of mobile devices (phones)
50
- protected $phoneDevices = array(
51
- 'iPhone' => '\biPhone.*Mobile|\biPod|\biTunes',
52
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
53
- '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|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b',
54
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile',
55
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
56
- 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
57
- 'Motorola' => 'Motorola|\bDroid\b.*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',
58
- 'Samsung' => 'Samsung|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-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-I9300 |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',
59
- 'LG' => '\bLG\b;|(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)',
60
- 'Sony' => 'sony|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i',
61
- 'Asus' => 'Asus.*Galaxy',
62
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.
63
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
64
- // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
65
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
66
- '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',
67
- // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
68
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
69
- // Added simvalley mobile just for fun. They have some interesting devices.
70
- // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
71
- 'SimValley' => '\b(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)\b',
72
- // @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
73
- 'GenericPhone' => 'Tapatalk|PDA;|PPC;|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'
74
- );
75
- // List of tablet devices.
76
- protected $tabletDevices = array(
77
- 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
78
- 'NexusTablet' => '^.*Android.*Nexus(((?:(?!Mobile))|(?:(\s(7|10).+))).)*$',
79
- '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',
80
- // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/
81
- 'Kindle' => 'Kindle|Silk.*Accelerated',
82
- // Only the Surface tablets with Windows RT are considered mobile.
83
- // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
84
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;',
85
- 'AsusTablet' => 'Transformer|TF101',
86
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
87
- 'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
88
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
89
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNTV250A|LogicPD Zoom2',
90
- // @ref: http://www.acer.ro/ac/ro/RO/content/drivers
91
- // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
92
- 'AcerTablet' => 'Android.*\b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71)\b',
93
- // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
94
- // @ref: http://us.toshiba.com/tablets/tablet-finder
95
- // @ref: http://www.toshiba.co.jp/regza/tablet/
96
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)',
97
- // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
98
- 'LGTablet' => '\bL-06C|LG-V900|LG-V909\b',
99
- 'YarvikTablet' => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',
100
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
101
- 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',
102
- // @reference: http://wiki.archosfans.com/index.php?title=Main_Page
103
- 'ArchosTablet' => 'Android.*ARCHOS|101G9|80G9',
104
- // @reference: http://en.wikipedia.org/wiki/NOVO7
105
- 'AinolTablet' => 'NOVO7|Novo7Aurora|Novo7Basic|NOVO7PALADIN',
106
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
107
- // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
108
- // @ref: http://www.sony.jp/support/tablet/
109
- 'SonyTablet' => 'Sony Tablet|Sony Tablet S|SGPT12|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT211|SGPT213|EBRD1101|EBRD1102|EBRD1201',
110
- // @ref: db + http://www.cube-tablet.com/buy-products.html
111
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
112
- // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001
113
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
114
- // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
115
- // @ref: http://www.imp3.net/14/show.php?itemid=20454
116
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
117
- // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2
118
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
119
- // @ref: http://www.telstra.com.au/home-phone/thub-2/
120
- 'TelstraTablet' => 'T-Hub2',
121
- // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
122
- 'FlyTablet' => 'IQ310|Fly Vision',
123
- // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html
124
- 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)',
125
- // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
126
- // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
127
- 'HuaweiTablet' => 'MediaPad|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
128
- // Nec or Medias Tab
129
- 'NecTablet' => '\bN-06D|\bN-08D',
130
- // Pantech Tablets: http://www.pantechusa.com/phones/
131
- 'PantechTablet' => 'Pantech.*P4100',
132
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
133
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
134
- // @ref: http://versusuk.com/support.html
135
- 'VersusTablet' => 'TOUCHPAD.*[78910]',
136
- // @ref: http://www.zync.in/index.php/our-products/tablet-phablets
137
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
138
- // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
139
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
140
- // @ref: https://www.nabitablet.com/
141
- 'NabiTablet' => 'Android.*\bNabi',
142
- // @note: Avoid detecting 'PLAYSTATION 3' as mobile.
143
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
144
- 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|ViewPad7|MID7015|BNTV250A|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|hp-tablet',
145
- );
146
- // List of mobile Operating Systems.
147
- protected $operatingSystems = array(
148
- 'AndroidOS' => 'Android',
149
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
150
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
151
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
152
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
153
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
154
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
155
- // http://wifeng.cn/?r=blog&a=view&id=106
156
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
157
- 'WindowsPhoneOS' => 'Windows Phone OS|XBLWP7|ZuneWP7',
158
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
159
- // http://en.wikipedia.org/wiki/MeeGo
160
- // @todo: research MeeGo in UAs
161
- 'MeeGoOS' => 'MeeGo',
162
- // http://en.wikipedia.org/wiki/Maemo
163
- // @todo: research Maemo in UAs
164
- 'MaemoOS' => 'Maemo',
165
- 'JavaOS' => 'J2ME/|Java/|\bMIDP\b|\bCLDC\b',
166
- 'webOS' => 'webOS|hpwOS',
167
- 'badaOS' => '\bBada\b',
168
- 'BREWOS' => 'BREW',
169
- );
170
- // List of mobile User Agents.
171
- protected $userAgents = array(
172
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
173
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
174
- 'Dolfin' => '\bDolfin\b',
175
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|OPR/[0-9.]+',
176
- 'Skyfire' => 'Skyfire',
177
- 'IE' => 'IEMobile|MSIEMobile',
178
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
179
- 'Bolt' => 'bolt',
180
- 'TeaShark' => 'teashark',
181
- 'Blazer' => 'Blazer',
182
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
183
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile',
184
- // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser)
185
- //'Midori' => 'midori',
186
- 'Tizen' => 'Tizen',
187
- 'UCBrowser' => 'UC.*Browser|UCWEB',
188
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7
189
- 'DiigoBrowser' => 'DiigoBrowser',
190
- // http://www.puffinbrowser.com/index.php
191
- 'Puffin' => 'Puffin',
192
- // @ref: http://mercury-browser.com/index.html
193
- 'Mercury' => '\bMercury\b',
194
- // @reference: http://en.wikipedia.org/wiki/Minimo
195
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
196
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision'
197
- );
198
- // Utilities.
199
- protected $utilities = array(
200
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
201
- // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
202
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
203
- 'DesktopMode' => 'WPDesktop',
204
- 'TV' => 'SonyDTV115', // experimental
205
- 'WebKit' => '(webkit)[ /]([\w.]+)',
206
- 'Bot' => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
207
- 'MobileBot' => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2',
208
- );
209
- // Properties list.
210
- // @reference: http://user-agent-string.info/list-of-ua#Mobile Browser
211
- const VER = '([\w._]+)';
212
- protected $properties = array(
213
-
214
- // Build
215
- 'Mobile' => 'Mobile/[VER]',
216
- 'Build' => 'Build/[VER]',
217
- 'Version' => 'Version/[VER]',
218
- 'VendorID' => 'VendorID/[VER]',
219
-
220
- // Devices
221
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
222
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
223
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
224
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
225
- 'Kindle' => 'Kindle/[VER]',
226
-
227
- // Browser
228
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
229
- 'Dolfin' => 'Dolfin/[VER]',
230
- // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
231
- 'Firefox' => 'Firefox/[VER]',
232
- 'Fennec' => 'Fennec/[VER]',
233
- // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
234
- 'IEMobile' => array('IEMobile/[VER];', 'IEMobile [VER]'),
235
- 'MSIE' => 'MSIE [VER];',
236
- // http://en.wikipedia.org/wiki/NetFront
237
- 'NetFront' => 'NetFront/[VER]',
238
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
239
- 'Opera' => 'Version/[VER]',
240
- 'Opera Mini' => 'Opera Mini/[VER]',
241
- 'Opera Mobi' => 'Version/[VER]',
242
- 'UC Browser' => 'UC Browser[VER]',
243
- 'Safari' => 'Version/[VER]',
244
- 'Skyfire' => 'Skyfire/[VER]',
245
- 'Tizen' => 'Tizen/[VER]',
246
- 'Webkit' => 'webkit[ /][VER]',
247
-
248
- // Engine
249
- 'Gecko' => 'Gecko/[VER]',
250
- 'Trident' => 'Trident/[VER]',
251
- 'Presto' => 'Presto/[VER]',
252
-
253
- // OS
254
- 'Android' => 'Android [VER]',
255
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]'),
256
- 'BREW' => 'BREW [VER]',
257
- 'Java' => 'Java/[VER]',
258
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
259
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
260
- 'Windows Phone OS' => 'Windows Phone OS [VER]',
261
- 'Windows Phone' => 'Windows Phone [VER]',
262
- 'Windows CE' => 'Windows CE/[VER]',
263
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
264
- 'Windows NT' => 'Windows NT [VER]',
265
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
266
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
267
-
268
-
269
- );
270
-
271
- function __construct(){
272
-
273
- $this->setHttpHeaders();
274
- $this->setUserAgent();
275
-
276
- $this->setMobileDetectionRules();
277
- $this->setMobileDetectionRulesExtended();
278
-
279
- }
280
-
281
-
282
- /**
283
- * Get the current script version.
284
- * This is useful for the demo.php file,
285
- * so people can check on what version they are testing
286
- * for mobile devices.
287
- */
288
- public function getScriptVersion(){
289
-
290
- return $this->scriptVersion;
291
-
292
- }
293
-
294
- public function setHttpHeaders($httpHeaders = null){
295
-
296
- if(!empty($httpHeaders)){
297
- $this->httpHeaders = $httpHeaders;
298
- } else {
299
- foreach($_SERVER as $key => $value){
300
- if(substr($key,0,5)=='HTTP_'){
301
- $this->httpHeaders[$key] = $value;
302
- }
303
- }
304
- }
305
-
306
- }
307
-
308
- public function getHttpHeaders(){
309
-
310
- return $this->httpHeaders;
311
-
312
- }
313
-
314
- public function setUserAgent($userAgent = null){
315
-
316
- if(!empty($userAgent)){
317
- $this->userAgent = $userAgent;
318
- } else {
319
- $this->userAgent = isset($this->httpHeaders['HTTP_USER_AGENT']) ? $this->httpHeaders['HTTP_USER_AGENT'] : null;
320
-
321
- if(empty($this->userAgent)){
322
- $this->userAgent = isset($this->httpHeaders['HTTP_X_DEVICE_USER_AGENT']) ? $this->httpHeaders['HTTP_X_DEVICE_USER_AGENT'] : null;
323
- }
324
- // Header can occur on devices using Opera Mini (can expose the real device type). Let's concatenate it (we need this extra info in the regexes).
325
- if(!empty($this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA'])){
326
- $this->userAgent .= ' '.$this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA'];
327
- }
328
- }
329
-
330
- }
331
-
332
- public function getUserAgent(){
333
-
334
- return $this->userAgent;
335
-
336
- }
337
-
338
- function setDetectionType($type = null){
339
-
340
- $this->detectionType = (!empty($type) ? $type : 'mobile');
341
-
342
- }
343
-
344
- public function getPhoneDevices(){
345
-
346
- return $this->phoneDevices;
347
-
348
- }
349
-
350
- public function getTabletDevices(){
351
-
352
- return $this->tabletDevices;
353
-
354
- }
355
-
356
- /**
357
- * Method sets the mobile detection rules.
358
- *
359
- * This method is used for the magic methods $detect->is*()
360
- */
361
- public function setMobileDetectionRules(){
362
- // Merge all rules together.
363
- $this->mobileDetectionRules = array_merge(
364
- $this->phoneDevices,
365
- $this->tabletDevices,
366
- $this->operatingSystems,
367
- $this->userAgents
368
- );
369
-
370
- }
371
-
372
- /**
373
- * Method sets the mobile detection rules + utilities.
374
- * The reason this is separate is because utilities rules
375
- * don't necessary imply mobile.
376
- *
377
- * This method is used inside the new $detect->is('stuff') method.
378
- *
379
- * @return bool
380
- */
381
- public function setMobileDetectionRulesExtended(){
382
-
383
- // Merge all rules together.
384
- $this->mobileDetectionRulesExtended = array_merge(
385
- $this->phoneDevices,
386
- $this->tabletDevices,
387
- $this->operatingSystems,
388
- $this->userAgents,
389
- $this->utilities
390
- );
391
-
392
- }
393
-
394
- /**
395
- * @return array
396
- */
397
- public function getRules()
398
- {
399
-
400
- if($this->detectionType=='extended'){
401
- return $this->mobileDetectionRulesExtended;
402
- } else {
403
- return $this->mobileDetectionRules;
404
- }
405
-
406
- }
407
-
408
- /**
409
- * Check the HTTP headers for signs of mobile.
410
- * This is the fastest mobile check possible; it's used
411
- * inside isMobile() method.
412
- * @return boolean
413
- */
414
- public function checkHttpHeadersForMobile(){
415
-
416
- if(
417
- isset($this->httpHeaders['HTTP_ACCEPT']) &&
418
- (strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/x-obml2d') !== false || // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
419
- strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.rim.html') !== false || // BlackBerry devices.
420
- strpos($this->httpHeaders['HTTP_ACCEPT'], 'text/vnd.wap.wml') !== false ||
421
- strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.wap.xhtml+xml') !== false) ||
422
- isset($this->httpHeaders['HTTP_X_WAP_PROFILE']) || // @todo: validate
423
- isset($this->httpHeaders['HTTP_X_WAP_CLIENTID']) ||
424
- isset($this->httpHeaders['HTTP_WAP_CONNECTION']) ||
425
- isset($this->httpHeaders['HTTP_PROFILE']) ||
426
- isset($this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA']) || // Reported by Nokia devices (eg. C3)
427
- isset($this->httpHeaders['HTTP_X_NOKIA_IPADDRESS']) ||
428
- isset($this->httpHeaders['HTTP_X_NOKIA_GATEWAY_ID']) ||
429
- isset($this->httpHeaders['HTTP_X_ORANGE_ID']) ||
430
- isset($this->httpHeaders['HTTP_X_VODAFONE_3GPDPCONTEXT']) ||
431
- isset($this->httpHeaders['HTTP_X_HUAWEI_USERID']) ||
432
- isset($this->httpHeaders['HTTP_UA_OS']) || // Reported by Windows Smartphones.
433
- isset($this->httpHeaders['HTTP_X_MOBILE_GATEWAY']) || // Reported by Verizon, Vodafone proxy system.
434
- isset($this->httpHeaders['HTTP_X_ATT_DEVICEID']) || // Seend this on HTC Sensation. @ref: SensationXE_Beats_Z715e
435
- //HTTP_X_NETWORK_TYPE = WIFI
436
- ( isset($this->httpHeaders['HTTP_UA_CPU']) &&
437
- $this->httpHeaders['HTTP_UA_CPU'] == 'ARM' // Seen this on a HTC.
438
- )
439
- ){
440
-
441
- return true;
442
-
443
- }
444
-
445
- return false;
446
-
447
- }
448
-
449
- /**
450
- * Magic overloading method.
451
- *
452
- * @method boolean is[...]()
453
- * @param string $name
454
- * @param array $arguments
455
- * @return mixed
456
- */
457
- public function __call($name, $arguments)
458
- {
459
-
460
- $this->setDetectionType('mobile');
461
-
462
- $key = substr($name, 2);
463
- return $this->matchUAAgainstKey($key);
464
-
465
- }
466
-
467
- /**
468
- * Find a detection rule that matches the current User-agent.
469
- *
470
- * @param null $userAgent deprecated
471
- * @return boolean
472
- */
473
- private function matchDetectionRulesAgainstUA($userAgent = null){
474
-
475
- // Begin general search.
476
- foreach($this->getRules() as $_regex){
477
- if(empty($_regex)){ continue; }
478
- if( $this->match($_regex, $userAgent) ){
479
- //var_dump( $_regex );
480
- return true;
481
- }
482
- }
483
-
484
- return false;
485
-
486
- }
487
-
488
- /**
489
- * Search for a certain key in the rules array.
490
- * If the key is found the try to match the corresponding
491
- * regex agains the User-agent.
492
- *
493
- * @param string $key
494
- * @param null $userAgent deprecated
495
- * @return mixed
496
- */
497
- private function matchUAAgainstKey($key, $userAgent = null){
498
-
499
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
500
- $key = strtolower($key);
501
- $_rules = array_change_key_case($this->getRules());
502
-
503
- if(array_key_exists($key, $_rules)){
504
- if(empty($_rules[$key])){ return null; }
505
- return $this->match($_rules[$key], $userAgent);
506
- }
507
-
508
- return false;
509
-
510
- }
511
-
512
- /**
513
- * Check if the device is mobile.
514
- * Returns true if any type of mobile device detected, including special ones
515
- * @param null $userAgent deprecated
516
- * @param null $httpHeaders deprecated
517
- * @return bool
518
- */
519
- public function isMobile($userAgent = null, $httpHeaders = null) {
520
-
521
- if($httpHeaders){ $this->setHttpHeaders($httpHeaders); }
522
- if($userAgent){ $this->setUserAgent($userAgent); }
523
-
524
- $this->setDetectionType('mobile');
525
-
526
- if ($this->checkHttpHeadersForMobile()) {
527
- return true;
528
- } else {
529
- return $this->matchDetectionRulesAgainstUA();
530
- }
531
-
532
- }
533
-
534
- /**
535
- * Check if the device is a tablet.
536
- * Return true if any type of tablet device is detected.
537
- *
538
- * @param null $userAgent deprecated
539
- * @param null $httpHeaders deprecated
540
- * @return bool
541
- */
542
- public function isTablet($userAgent = null, $httpHeaders = null) {
543
-
544
- $this->setDetectionType('mobile');
545
-
546
- foreach($this->tabletDevices as $_regex){
547
- if($this->match($_regex, $userAgent)){
548
- return true;
549
- }
550
- }
551
-
552
- return false;
553
-
554
- }
555
-
556
- /**
557
- * This method checks for a certain property in the
558
- * userAgent.
559
- * @todo: The httpHeaders part is not yet used.
560
- *
561
- * @param $key
562
- * @param string $userAgent deprecated
563
- * @param string $httpHeaders deprecated
564
- * @return bool|int|null
565
- */
566
- public function is($key, $userAgent = null, $httpHeaders = null){
567
-
568
-
569
- // Set the UA and HTTP headers only if needed (eg. batch mode).
570
- if($httpHeaders) $this->setHttpHeaders($httpHeaders);
571
- if($userAgent) $this->setUserAgent($userAgent);
572
-
573
- $this->setDetectionType('extended');
574
-
575
- return $this->matchUAAgainstKey($key);
576
-
577
- }
578
-
579
- public function getOperatingSystems(){
580
-
581
- return $this->operatingSystems;
582
-
583
- }
584
-
585
- /**
586
- * Some detection rules are relative (not standard),
587
- * because of the diversity of devices, vendors and
588
- * their conventions in representing the User-Agent or
589
- * the HTTP headers.
590
- *
591
- * This method will be used to check custom regexes against
592
- * the User-Agent string.
593
- *
594
- * @param $regex
595
- * @param string $userAgent
596
- * @return bool
597
- *
598
- * @todo: search in the HTTP headers too.
599
- */
600
- function match($regex, $userAgent=null){
601
-
602
- // Escape the special character which is the delimiter.
603
- $regex = str_replace('/', '\/', $regex);
604
-
605
- return (bool)preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));
606
-
607
- }
608
-
609
- /**
610
- * Get the properties array.
611
- * @return array
612
- */
613
- function getProperties(){
614
-
615
- return $this->properties;
616
-
617
- }
618
-
619
- /**
620
- * Prepare the version number.
621
- *
622
- * @param $ver
623
- * @return int
624
- */
625
- function prepareVersionNo($ver){
626
-
627
- $ver = str_replace(array('_', ' ', '/'), array('.', '.', '.'), $ver);
628
- $arrVer = explode('.', $ver, 2);
629
- if(isset($arrVer[1])){
630
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
631
- }
632
- $ver = (float)implode('.', $arrVer);
633
-
634
- return $ver;
635
-
636
- }
637
-
638
- /**
639
- * Check the version of the given property in the User-Agent.
640
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
641
- *
642
- * @param string $propertyName
643
- * @return mixed $version
644
- */
645
- function version($propertyName, $type = 'text'){
646
-
647
- if(empty($propertyName)){ return false; }
648
- if( !in_array($type, array('text', 'float')) ){ $type = 'text'; }
649
-
650
- $properties = $this->getProperties();
651
-
652
- // Check if the property exists in the properties array.
653
- if( array_key_exists($propertyName, $properties) ){
654
-
655
- // Prepare the pattern to be matched.
656
- // Make sure we always deal with an array (string is converted).
657
- $properties[$propertyName] = (array)$properties[$propertyName];
658
-
659
- foreach($properties[$propertyName] as $propertyMatchString){
660
-
661
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
662
-
663
- // Escape the special character which is the delimiter.
664
- $propertyPattern = str_replace('/', '\/', $propertyPattern);
665
-
666
- // Identify and extract the version.
667
- preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
668
-
669
- if(!empty($match[1])){
670
- $version = ( $type == 'float' ? $this->prepareVersionNo($match[1]) : $match[1] );
671
- return $version;
672
- }
673
-
674
- }
675
-
676
- }
677
-
678
- return false;
679
-
680
- }
681
-
682
- function mobileGrade(){
683
-
684
- $isMobile = $this->isMobile();
685
-
686
- if(
687
- // 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)
688
- $this->version('iPad')>=4.3 ||
689
- $this->version('iPhone')>=3.1 ||
690
- $this->version('iPod')>=3.1 ||
691
-
692
- // 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)
693
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
694
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
695
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
696
- ( $this->version('Android')>2.1 && $this->is('Webkit') ) ||
697
-
698
- // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800
699
- $this->version('Windows Phone OS')>=7.0 ||
700
-
701
- // Blackberry 7 - Tested on BlackBerry® Torch 9810
702
- // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670
703
- $this->version('BlackBerry')>=6.0 ||
704
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
705
- $this->match('Playbook.*Tablet') ||
706
-
707
- // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0)
708
- ( $this->version('webOS')>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
709
- // Palm WebOS 3.0 - Tested on HP TouchPad
710
- $this->match('hp.*TouchPad') ||
711
-
712
- // Firefox Mobile (12 Beta) - Tested on Android 2.3 device
713
- ( $this->is('Firefox') && $this->version('Firefox')>=12 ) ||
714
-
715
- // Chrome for Android - Tested on Android 4.0, 4.1 device
716
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android')>=4.0 ) ||
717
-
718
- // Skyfire 4.1 - Tested on Android 2.3 device
719
- ( $this->is('Skyfire') && $this->version('Skyfire')>=4.1 && $this->is('AndroidOS') && $this->version('Android')>=2.3 ) ||
720
-
721
- // Opera Mobile 11.5-12: Tested on Android 2.3
722
- ( $this->is('Opera') && $this->version('Opera Mobi')>11 && $this->is('AndroidOS') ) ||
723
-
724
- // Meego 1.2 - Tested on Nokia 950 and N9
725
- $this->is('MeeGoOS') ||
726
-
727
- // Tizen (pre-release) - Tested on early hardware
728
- $this->is('Tizen') ||
729
-
730
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
731
- // @todo: more tests here!
732
- $this->is('Dolfin') && $this->version('Bada')>=2.0 ||
733
-
734
- // UC Browser - Tested on Android 2.3 device
735
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android')>=2.3 ) ||
736
-
737
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
738
- ( $this->match('Kindle Fire') ||
739
- $this->is('Kindle') && $this->version('Kindle')>=3.0 ) ||
740
-
741
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
742
- $this->is('AndroidOS') && $this->is('NookTablet') ||
743
-
744
- // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7
745
- $this->version('Chrome')>=11 && !$isMobile ||
746
-
747
- // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7
748
- $this->version('Safari')>=5.0 && !$isMobile ||
749
-
750
- // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7
751
- $this->version('Firefox')>=4.0 && !$isMobile ||
752
-
753
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
754
- $this->version('MSIE')>=7.0 && !$isMobile ||
755
-
756
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
757
- // @reference: http://my.opera.com/community/openweb/idopera/
758
- $this->version('Opera')>=10 && !$isMobile
759
-
760
-
761
- ){
762
- return 'A';
763
- }
764
-
765
- if(
766
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
767
- $this->version('BlackBerry')>=5 && $this->version('BlackBerry')<6 ||
768
-
769
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
770
- ( $this->version('Opera Mini')>=5.0 && $this->version('Opera Mini')<=6.5 &&
771
- ($this->version('Android')>=2.3 || $this->is('iOS')) ) ||
772
-
773
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
774
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
775
-
776
- // @todo: report this (tested on Nokia N71)
777
- $this->version('Opera Mobi')>=11 && $this->is('SymbianOS')
778
-
779
- ){
780
- return 'B';
781
- }
782
-
783
- if(
784
- // Blackberry 4.x - Tested on the Curve 8330
785
- $this->version('BlackBerry')<5.0 ||
786
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
787
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile')<=5.2
788
-
789
-
790
- ){
791
-
792
- return 'C';
793
-
794
- }
795
-
796
- // All older smartphone platforms and featurephones - Any device that doesn't support media queries will receive the basic, C grade experience
797
- return 'C';
798
-
799
-
800
- }
801
-
802
-
803
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.7.1
33
+ */
34
+
35
+ class Mobile_Detect
36
+ {
37
+ /**
38
+ * Mobile detection type.
39
+ *
40
+ * @deprecated since version 2.6.9
41
+ */
42
+ const DETECTION_TYPE_MOBILE = 'mobile';
43
+
44
+ /**
45
+ * Extended detection type.
46
+ *
47
+ * @deprecated since version 2.6.9
48
+ */
49
+ const DETECTION_TYPE_EXTENDED = 'extended';
50
+
51
+ /**
52
+ * A frequently used regular expression to extract version #s.
53
+ *
54
+ * @deprecated since version 2.6.9
55
+ */
56
+ const VER = '([\w._\+]+)';
57
+
58
+ /**
59
+ * Top-level device.
60
+ */
61
+ const MOBILE_GRADE_A = 'A';
62
+
63
+ /**
64
+ * Mid-level device.
65
+ */
66
+ const MOBILE_GRADE_B = 'B';
67
+
68
+ /**
69
+ * Low-level device.
70
+ */
71
+ const MOBILE_GRADE_C = 'C';
72
+
73
+ /**
74
+ * Stores the version number of the current release.
75
+ */
76
+ const VERSION = '2.7.1';
77
+
78
+ /**
79
+ * A type for the version() method indicating a string return value.
80
+ */
81
+ const VERSION_TYPE_STRING = 'text';
82
+
83
+ /**
84
+ * A type for the version() method indicating a float return value.
85
+ */
86
+ const VERSION_TYPE_FLOAT = 'float';
87
+
88
+ /**
89
+ * The User-Agent HTTP header is stored in here.
90
+ * @var string
91
+ */
92
+ protected $userAgent = null;
93
+
94
+ /**
95
+ * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
96
+ * @var array
97
+ */
98
+ protected $httpHeaders = array();
99
+
100
+ /**
101
+ * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
102
+ *
103
+ * @deprecated since version 2.6.9
104
+ *
105
+ * @var string
106
+ */
107
+ protected $detectionType = self::DETECTION_TYPE_MOBILE;
108
+
109
+ /**
110
+ * List of mobile devices (phones).
111
+ *
112
+ * @var array
113
+ */
114
+ protected static $phoneDevices = array(
115
+ 'iPhone' => '\biPhone.*Mobile|\biPod', // |\biTunes
116
+ 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
117
+ '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.*\bEVO\b|T-Mobile G1',
118
+ 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile',
119
+ // @todo: Is 'Dell Streak' a tablet or a phone? ;)
120
+ 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
121
+ 'Motorola' => 'Motorola|\bDroid\b.*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|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925',
122
+ '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-I9082|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-S7710|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-I959|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',
123
+ 'LG' => '\bLG\b;|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|P500|P509|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)',
124
+ 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i',
125
+ 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
126
+ // @ref: http://www.micromaxinfo.com/mobiles/smartphones
127
+ // Added because the codes might conflict with Acer Tablets.
128
+ 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
129
+ 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.
130
+ 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
131
+ // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
132
+ // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
133
+ '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',
134
+ // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
135
+ 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
136
+ // Added simvalley mobile just for fun. They have some interesting devices.
137
+ // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
138
+ 'SimValley' => '\b(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)\b',
139
+ // @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
140
+ 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser'
141
+ );
142
+
143
+ /**
144
+ * List of tablet devices.
145
+ *
146
+ * @var array
147
+ */
148
+ protected static $tabletDevices = array(
149
+ 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
150
+ 'NexusTablet' => '^.*Android.*Nexus(((?:(?!Mobile))|(?:(\s(7|10).+))).)*$',
151
+ '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',
152
+ // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/
153
+ 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFTT|KFOTE|WFJWAE)\b',
154
+ // Only the Surface tablets with Windows RT are considered mobile.
155
+ // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
156
+ 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;',
157
+ // @ref: http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
158
+ 'HPTablet' => 'HP Slate 7|HP ElitePad 900|hp-tablet|EliteBook.*Touch',
159
+ // @note: watch out for PadFone, see #132
160
+ 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101',
161
+ 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
162
+ 'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
163
+ 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
164
+ 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
165
+ // @ref: http://www.acer.ro/ac/ro/RO/content/drivers
166
+ // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
167
+ // @ref: http://us.acer.com/ac/en/US/content/group/tablets
168
+ // @note: Can conflict with Micromax and Motorola phones codes.
169
+ 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810)\b|W3-810',
170
+ // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
171
+ // @ref: http://us.toshiba.com/tablets/tablet-finder
172
+ // @ref: http://www.toshiba.co.jp/regza/tablet/
173
+ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
174
+ // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
175
+ 'LGTablet' => '\bL-06C|LG-V900|LG-V909\b',
176
+ 'FujitsuTablet' => 'Android.*\b(F-01D|F-05E|F-10D|M532|Q572)\b',
177
+ // Prestigio Tablets http://www.prestigio.com/support
178
+ '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',
179
+ // @ref: http://support.lenovo.com/en_GB/downloads/default.page?#
180
+ 'LenovoTablet' => 'IdeaTab|S2110|S6000|K3011|A3000|A1000|A2107|A2109|A1107',
181
+ 'YarvikTablet' => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',
182
+ 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
183
+ 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',
184
+ // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
185
+ 'IRUTablet' => 'M702pro',
186
+ 'MegafonTablet' => 'MegaFon V9|ZTE V9',
187
+ // @ref: http://www.e-boda.ro/tablete-pc.html
188
+ 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
189
+ // @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/
190
+ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
191
+ // @reference: http://wiki.archosfans.com/index.php?title=Main_Page
192
+ 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b',
193
+ // @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product
194
+ 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
195
+ // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
196
+ // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
197
+ // @ref: http://www.sony.jp/support/tablet/
198
+ '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',
199
+ // @ref: db + http://www.cube-tablet.com/buy-products.html
200
+ 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
201
+ // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001
202
+ 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
203
+ // @ref: http://www.match.net.cn/products.asp
204
+ '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',
205
+ // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
206
+ // @ref: http://www.imp3.net/14/show.php?itemid=20454
207
+ 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
208
+ // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2
209
+ 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
210
+ // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
211
+ 'FlyTablet' => 'IQ310|Fly Vision',
212
+ // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html
213
+ 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus',
214
+ // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
215
+ // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
216
+ 'HuaweiTablet' => 'MediaPad|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
217
+ // Nec or Medias Tab
218
+ 'NecTablet' => '\bN-06D|\bN-08D',
219
+ // Pantech Tablets: http://www.pantechusa.com/phones/
220
+ 'PantechTablet' => 'Pantech.*P4100',
221
+ // Broncho Tablets: http://www.broncho.cn/ (hard to find)
222
+ 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
223
+ // @ref: http://versusuk.com/support.html
224
+ 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
225
+ // @ref: http://www.zync.in/index.php/our-products/tablet-phablets
226
+ 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
227
+ // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
228
+ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
229
+ // @ref: https://www.nabitablet.com/
230
+ 'NabiTablet' => 'Android.*\bNabi',
231
+ 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
232
+ // French Danew Tablets http://www.danew.com/produits-tablette.php
233
+ 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
234
+ // Texet Tablets and Readers http://www.texet.ru/tablet/
235
+ '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',
236
+ // @note: Avoid detecting 'PLAYSTATION 3' as mobile.
237
+ 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
238
+ // @ref: http://www.galapad.net/product.html
239
+ 'GalapadTablet' => 'Android.*\bG1\b',
240
+ // @ref: http://www.micromaxinfo.com/tablet/funbook
241
+ 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
242
+ // http://www.karbonnmobiles.com/products_tablet.php
243
+ 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
244
+ // @ref: http://www.myallfine.com/Products.asp
245
+ 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
246
+ // @ref: http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
247
+ 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
248
+ // @ref: http://www.yonesnav.com/products/products.php
249
+ 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
250
+ // @ref: http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
251
+ // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
252
+ 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
253
+ // @ref: http://www.gloryunion.cn/products.asp
254
+ // @ref: http://www.allwinnertech.com/en/apply/mobile.html
255
+ // @ref: http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
256
+ // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
257
+ '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
258
+ // @ref: http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
259
+ 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
260
+ // @ref: http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
261
+ // @todo: add more tests.
262
+ 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
263
+ // @ref: http://hclmetablet.com/India/index.php
264
+ 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
265
+ // @ref: http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
266
+ 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
267
+ // @ref: http://www.telstra.com.au/home-phone/thub-2/
268
+ 'TelstraTablet' => 'T-Hub2',
269
+ 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|ViewPad7|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|SmartTabII10',
270
+ );
271
+
272
+ /**
273
+ * List of mobile Operating Systems.
274
+ *
275
+ * @var array
276
+ */
277
+ protected static $operatingSystems = array(
278
+ 'AndroidOS' => 'Android',
279
+ 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
280
+ 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
281
+ 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
282
+ // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
283
+ 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
284
+ // @reference: http://en.wikipedia.org/wiki/Windows_Phone
285
+ // http://wifeng.cn/?r=blog&a=view&id=106
286
+ // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
287
+ 'WindowsPhoneOS' => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7',
288
+ 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
289
+ // http://en.wikipedia.org/wiki/MeeGo
290
+ // @todo: research MeeGo in UAs
291
+ 'MeeGoOS' => 'MeeGo',
292
+ // http://en.wikipedia.org/wiki/Maemo
293
+ // @todo: research Maemo in UAs
294
+ 'MaemoOS' => 'Maemo',
295
+ 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
296
+ 'webOS' => 'webOS|hpwOS',
297
+ 'badaOS' => '\bBada\b',
298
+ 'BREWOS' => 'BREW',
299
+ );
300
+
301
+ /**
302
+ * List of mobile User Agents.
303
+ *
304
+ * @var array
305
+ */
306
+ protected static $browsers = array(
307
+ // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
308
+ 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
309
+ 'Dolfin' => '\bDolfin\b',
310
+ 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
311
+ 'Skyfire' => 'Skyfire',
312
+ 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
313
+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
314
+ 'Bolt' => 'bolt',
315
+ 'TeaShark' => 'teashark',
316
+ 'Blazer' => 'Blazer',
317
+ // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
318
+ 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile',
319
+ // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser)
320
+ //'Midori' => 'midori',
321
+ 'Tizen' => 'Tizen',
322
+ 'UCBrowser' => 'UC.*Browser|UCWEB',
323
+ // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7
324
+ 'DiigoBrowser' => 'DiigoBrowser',
325
+ // http://www.puffinbrowser.com/index.php
326
+ 'Puffin' => 'Puffin',
327
+ // @ref: http://mercury-browser.com/index.html
328
+ 'Mercury' => '\bMercury\b',
329
+ // @reference: http://en.wikipedia.org/wiki/Minimo
330
+ // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
331
+ 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger'
332
+ );
333
+
334
+ /**
335
+ * Utilities.
336
+ *
337
+ * @var array
338
+ */
339
+ protected static $utilities = array(
340
+ // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
341
+ // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
342
+ // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
343
+ 'DesktopMode' => 'WPDesktop',
344
+ 'TV' => 'SonyDTV|HbbTV', // experimental
345
+ 'WebKit' => '(webkit)[ /]([\w.]+)',
346
+ 'Bot' => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
347
+ 'MobileBot' => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2',
348
+ 'Console' => '\b(Nintendo|Nintendo WiiU|PLAYSTATION|Xbox)\b',
349
+ 'Watch' => 'SM-V700',
350
+ );
351
+
352
+ /**
353
+ * The individual segments that could exist in a User-Agent string. VER refers to the regular
354
+ * expression defined in the constant self::VER.
355
+ *
356
+ * @var array
357
+ */
358
+ protected static $properties = array(
359
+
360
+ // Build
361
+ 'Mobile' => 'Mobile/[VER]',
362
+ 'Build' => 'Build/[VER]',
363
+ 'Version' => 'Version/[VER]',
364
+ 'VendorID' => 'VendorID/[VER]',
365
+
366
+ // Devices
367
+ 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
368
+ 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
369
+ 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
370
+ //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
371
+ 'Kindle' => 'Kindle/[VER]',
372
+
373
+ // Browser
374
+ 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
375
+ 'Coast' => array('Coast/[VER]'),
376
+ 'Dolfin' => 'Dolfin/[VER]',
377
+ // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
378
+ 'Firefox' => 'Firefox/[VER]',
379
+ 'Fennec' => 'Fennec/[VER]',
380
+ // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
381
+ 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),
382
+ // http://en.wikipedia.org/wiki/NetFront
383
+ 'NetFront' => 'NetFront/[VER]',
384
+ 'NokiaBrowser' => 'NokiaBrowser/[VER]',
385
+ 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
386
+ 'Opera Mini' => 'Opera Mini/[VER]',
387
+ 'Opera Mobi' => 'Version/[VER]',
388
+ 'UC Browser' => 'UC Browser[VER]',
389
+ 'MQQBrowser' => 'MQQBrowser/[VER]',
390
+ 'MicroMessenger' => 'MicroMessenger/[VER]',
391
+ // @note: Safari 7534.48.3 is actually Version 5.1.
392
+ // @note: On BlackBerry the Version is overwriten by the OS.
393
+ 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
394
+ 'Skyfire' => 'Skyfire/[VER]',
395
+ 'Tizen' => 'Tizen/[VER]',
396
+ 'Webkit' => 'webkit[ /][VER]',
397
+
398
+ // Engine
399
+ 'Gecko' => 'Gecko/[VER]',
400
+ 'Trident' => 'Trident/[VER]',
401
+ 'Presto' => 'Presto/[VER]',
402
+
403
+ // OS
404
+ 'iOS' => ' \bOS\b [VER] ',
405
+ 'Android' => 'Android [VER]',
406
+ 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
407
+ 'BREW' => 'BREW [VER]',
408
+ 'Java' => 'Java/[VER]',
409
+ // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
410
+ // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
411
+ 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
412
+ 'Windows Phone' => 'Windows Phone [VER]',
413
+ 'Windows CE' => 'Windows CE/[VER]',
414
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
415
+ 'Windows NT' => 'Windows NT [VER]',
416
+ 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
417
+ 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
418
+ );
419
+
420
+ /**
421
+ * Construct an instance of this class.
422
+ *
423
+ * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
424
+ * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
425
+ * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
426
+ * from the $headers array instead.
427
+ */
428
+ public function __construct(
429
+ array $headers = null,
430
+ $userAgent = null
431
+ ){
432
+ $this->setHttpHeaders($headers);
433
+ $this->setUserAgent($userAgent);
434
+ }
435
+
436
+ /**
437
+ * Get the current script version.
438
+ * This is useful for the demo.php file,
439
+ * so people can check on what version they are testing
440
+ * for mobile devices.
441
+ *
442
+ * @return string The version number in semantic version format.
443
+ */
444
+ public static function getScriptVersion()
445
+ {
446
+ return self::VERSION;
447
+ }
448
+
449
+ /**
450
+ * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
451
+ *
452
+ * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
453
+ * the headers. The default null is left for backwards compatibilty.
454
+ */
455
+ public function setHttpHeaders($httpHeaders = null)
456
+ {
457
+ //use global _SERVER if $httpHeaders aren't defined
458
+ if (!is_array($httpHeaders) || !count($httpHeaders)) {
459
+ $httpHeaders = $_SERVER;
460
+ }
461
+
462
+ //clear existing headers
463
+ $this->httpHeaders = array();
464
+
465
+ //Only save HTTP headers. In PHP land, that means only _SERVER vars that
466
+ //start with HTTP_.
467
+ foreach ($httpHeaders as $key => $value) {
468
+ if (substr($key,0,5) == 'HTTP_') {
469
+ $this->httpHeaders[$key] = $value;
470
+ }
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Retrieves the HTTP headers.
476
+ *
477
+ * @return array
478
+ */
479
+ public function getHttpHeaders()
480
+ {
481
+ return $this->httpHeaders;
482
+ }
483
+
484
+ /**
485
+ * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
486
+ * Simply null is returned.
487
+ *
488
+ * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
489
+ * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
490
+ * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
491
+ *
492
+ * @return string|null The value of the header.
493
+ */
494
+ public function getHttpHeader($header)
495
+ {
496
+ //are we using PHP-flavored headers?
497
+ if (strpos($header, '_') === false) {
498
+ $header = str_replace('-', '_', $header);
499
+ $header = strtoupper($header);
500
+ }
501
+
502
+ //test the alternate, too
503
+ $altHeader = 'HTTP_' . $header;
504
+
505
+ //Test both the regular and the HTTP_ prefix
506
+ if (isset($this->httpHeaders[$header])) {
507
+ return $this->httpHeaders[$header];
508
+ } elseif (isset($this->httpHeaders[$altHeader])) {
509
+ return $this->httpHeaders[$altHeader];
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Set the User-Agent to be used.
515
+ *
516
+ * @param string $userAgent The user agent string to set.
517
+ */
518
+ public function setUserAgent($userAgent = null)
519
+ {
520
+ if (!empty($userAgent)) {
521
+ $this->userAgent = $userAgent;
522
+ } else {
523
+ $this->userAgent = $this->getHttpHeader('User-Agent');
524
+
525
+ if (empty($this->userAgent)) {
526
+ $this->userAgent = $this->getHttpHeader('X-Device-User-Agent');
527
+ }
528
+
529
+ //Header can occur on devices using Opera Mini (can expose the real device type).
530
+ //Let's concatenate it (we need this extra info in the regexes).
531
+ if ($operaMiniUa = $this->getHttpHeader('X-OperaMini-Phone-UA')) {
532
+ $this->userAgent .= ' ' . $operaMiniUa;
533
+ }
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Retrieve the User-Agent.
539
+ *
540
+ * @return string|null The user agent if it's set.
541
+ */
542
+ public function getUserAgent()
543
+ {
544
+ return $this->userAgent;
545
+ }
546
+
547
+ /**
548
+ * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
549
+ * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
550
+ *
551
+ * @deprecated since version 2.6.9
552
+ *
553
+ * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
554
+ * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
555
+ */
556
+ public function setDetectionType($type = null)
557
+ {
558
+ if ($type === null) {
559
+ $type = self::DETECTION_TYPE_MOBILE;
560
+ }
561
+
562
+ if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {
563
+ return;
564
+ }
565
+
566
+ $this->detectionType = $type;
567
+ }
568
+
569
+ /**
570
+ * Retrieve the list of known phone devices.
571
+ *
572
+ * @return array List of phone devices.
573
+ */
574
+ public static function getPhoneDevices()
575
+ {
576
+ return self::$phoneDevices;
577
+ }
578
+
579
+ /**
580
+ * Retrieve the list of known tablet devices.
581
+ *
582
+ * @return array List of tablet devices.
583
+ */
584
+ public static function getTabletDevices()
585
+ {
586
+ return self::$tabletDevices;
587
+ }
588
+
589
+ /**
590
+ * Alias for getBrowsers() method.
591
+ *
592
+ * @return array List of user agents.
593
+ */
594
+ public static function getUserAgents()
595
+ {
596
+ return self::getBrowsers();
597
+ }
598
+
599
+ /**
600
+ * Retrieve the list of known browsers. Specifically, the user agents.
601
+ *
602
+ * @return array List of browsers / user agents.
603
+ */
604
+ public static function getBrowsers()
605
+ {
606
+ return self::$browsers;
607
+ }
608
+
609
+ /**
610
+ * Retrieve the list of known utilities.
611
+ *
612
+ * @return array List of utilities.
613
+ */
614
+ public static function getUtilities()
615
+ {
616
+ return self::$utilities;
617
+ }
618
+
619
+ /**
620
+ * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
621
+ *
622
+ * @deprecated since version 2.6.9
623
+ *
624
+ * @return array All the rules (but not extended).
625
+ */
626
+ public static function getMobileDetectionRules()
627
+ {
628
+ static $rules;
629
+
630
+ if (!$rules) {
631
+ $rules = array_merge(
632
+ self::$phoneDevices,
633
+ self::$tabletDevices,
634
+ self::$operatingSystems,
635
+ self::$browsers
636
+ );
637
+ }
638
+
639
+ return $rules;
640
+
641
+ }
642
+
643
+ /**
644
+ * Method gets the mobile detection rules + utilities.
645
+ * The reason this is separate is because utilities rules
646
+ * don't necessary imply mobile. This method is used inside
647
+ * the new $detect->is('stuff') method.
648
+ *
649
+ * @deprecated since version 2.6.9
650
+ *
651
+ * @return array All the rules + extended.
652
+ */
653
+ public function getMobileDetectionRulesExtended()
654
+ {
655
+ static $rules;
656
+
657
+ if (!$rules) {
658
+ // Merge all rules together.
659
+ $rules = array_merge(
660
+ self::$phoneDevices,
661
+ self::$tabletDevices,
662
+ self::$operatingSystems,
663
+ self::$browsers,
664
+ self::$utilities
665
+ );
666
+ }
667
+
668
+ return $rules;
669
+ }
670
+
671
+ /**
672
+ * Retrieve the current set of rules.
673
+ *
674
+ * @deprecated since version 2.6.9
675
+ *
676
+ * @return array
677
+ */
678
+ public function getRules()
679
+ {
680
+ if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
681
+ return self::getMobileDetectionRulesExtended();
682
+ } else {
683
+ return self::getMobileDetectionRules();
684
+ }
685
+ }
686
+
687
+ /**
688
+ * Check the HTTP headers for signs of mobile.
689
+ * This is the fastest mobile check possible; it's used
690
+ * inside isMobile() method.
691
+ *
692
+ * @return bool
693
+ */
694
+ public function checkHttpHeadersForMobile()
695
+ {
696
+ return(
697
+ isset($this->httpHeaders['HTTP_ACCEPT']) &&
698
+ (strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/x-obml2d') !== false || // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
699
+ strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.rim.html') !== false || // BlackBerry devices.
700
+ strpos($this->httpHeaders['HTTP_ACCEPT'], 'text/vnd.wap.wml') !== false ||
701
+ strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.wap.xhtml+xml') !== false) ||
702
+ isset($this->httpHeaders['HTTP_X_WAP_PROFILE']) || // @todo: validate
703
+ isset($this->httpHeaders['HTTP_X_WAP_CLIENTID']) ||
704
+ isset($this->httpHeaders['HTTP_WAP_CONNECTION']) ||
705
+ isset($this->httpHeaders['HTTP_PROFILE']) ||
706
+ isset($this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA']) || // Reported by Nokia devices (eg. C3)
707
+ isset($this->httpHeaders['HTTP_X_NOKIA_IPADDRESS']) ||
708
+ isset($this->httpHeaders['HTTP_X_NOKIA_GATEWAY_ID']) ||
709
+ isset($this->httpHeaders['HTTP_X_ORANGE_ID']) ||
710
+ isset($this->httpHeaders['HTTP_X_VODAFONE_3GPDPCONTEXT']) ||
711
+ isset($this->httpHeaders['HTTP_X_HUAWEI_USERID']) ||
712
+ isset($this->httpHeaders['HTTP_UA_OS']) || // Reported by Windows Smartphones.
713
+ isset($this->httpHeaders['HTTP_X_MOBILE_GATEWAY']) || // Reported by Verizon, Vodafone proxy system.
714
+ isset($this->httpHeaders['HTTP_X_ATT_DEVICEID']) || // Seen this on HTC Sensation. @ref: SensationXE_Beats_Z715e
715
+ //HTTP_X_NETWORK_TYPE = WIFI
716
+ ( isset($this->httpHeaders['HTTP_UA_CPU']) &&
717
+ $this->httpHeaders['HTTP_UA_CPU'] == 'ARM' // Seen this on a HTC.
718
+ )
719
+ );
720
+ }
721
+
722
+ /**
723
+ * Magic overloading method.
724
+ *
725
+ * @method boolean is[...]()
726
+ * @param string $name
727
+ * @param array $arguments
728
+ * @return mixed
729
+ * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
730
+ */
731
+ public function __call($name, $arguments)
732
+ {
733
+ //make sure the name starts with 'is', otherwise
734
+ if (substr($name, 0, 2) != 'is') {
735
+ throw new BadMethodCallException("No such method exists: $name");
736
+ }
737
+
738
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
739
+
740
+ $key = substr($name, 2);
741
+
742
+ return $this->matchUAAgainstKey($key);
743
+ }
744
+
745
+ /**
746
+ * Find a detection rule that matches the current User-agent.
747
+ *
748
+ * @param null $userAgent deprecated
749
+ * @return boolean
750
+ */
751
+ private function matchDetectionRulesAgainstUA($userAgent = null)
752
+ {
753
+ // Begin general search.
754
+ foreach ($this->getRules() as $_regex) {
755
+ if (empty($_regex)) {
756
+ continue;
757
+ }
758
+ if ($this->match($_regex, $userAgent)) {
759
+ return true;
760
+ }
761
+ }
762
+
763
+ return false;
764
+ }
765
+
766
+ /**
767
+ * Search for a certain key in the rules array.
768
+ * If the key is found the try to match the corresponding
769
+ * regex agains the User-Agent.
770
+ *
771
+ * @param string $key
772
+ * @param null $userAgent deprecated
773
+ * @return mixed
774
+ */
775
+ private function matchUAAgainstKey($key, $userAgent = null)
776
+ {
777
+ // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
778
+ $key = strtolower($key);
779
+
780
+ //change the keys to lower case
781
+ $_rules = array_change_key_case($this->getRules());
782
+
783
+ if (array_key_exists($key, $_rules)) {
784
+ if (empty($_rules[$key])) {
785
+ return null;
786
+ }
787
+
788
+ return $this->match($_rules[$key], $userAgent);
789
+ }
790
+
791
+ return false;
792
+ }
793
+
794
+ /**
795
+ * Check if the device is mobile.
796
+ * Returns true if any type of mobile device detected, including special ones
797
+ * @param null $userAgent deprecated
798
+ * @param null $httpHeaders deprecated
799
+ * @return bool
800
+ */
801
+ public function isMobile($userAgent = null, $httpHeaders = null)
802
+ {
803
+
804
+ if ($httpHeaders) {
805
+ $this->setHttpHeaders($httpHeaders);
806
+ }
807
+
808
+ if ($userAgent) {
809
+ $this->setUserAgent($userAgent);
810
+ }
811
+
812
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
813
+
814
+ if ($this->checkHttpHeadersForMobile()) {
815
+ return true;
816
+ } else {
817
+ return $this->matchDetectionRulesAgainstUA();
818
+ }
819
+
820
+ }
821
+
822
+ /**
823
+ * Check if the device is a tablet.
824
+ * Return true if any type of tablet device is detected.
825
+ *
826
+ * @param string $userAgent deprecated
827
+ * @param array $httpHeaders deprecated
828
+ * @return bool
829
+ */
830
+ public function isTablet($userAgent = null, $httpHeaders = null)
831
+ {
832
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
833
+
834
+ foreach (self::$tabletDevices as $_regex) {
835
+ if ($this->match($_regex, $userAgent)) {
836
+ return true;
837
+ }
838
+ }
839
+
840
+ return false;
841
+ }
842
+
843
+ /**
844
+ * This method checks for a certain property in the
845
+ * userAgent.
846
+ * @todo: The httpHeaders part is not yet used.
847
+ *
848
+ * @param $key
849
+ * @param string $userAgent deprecated
850
+ * @param string $httpHeaders deprecated
851
+ * @return bool|int|null
852
+ */
853
+ public function is($key, $userAgent = null, $httpHeaders = null)
854
+ {
855
+ // Set the UA and HTTP headers only if needed (eg. batch mode).
856
+ if ($httpHeaders) {
857
+ $this->setHttpHeaders($httpHeaders);
858
+ }
859
+
860
+ if ($userAgent) {
861
+ $this->setUserAgent($userAgent);
862
+ }
863
+
864
+ $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
865
+
866
+ return $this->matchUAAgainstKey($key);
867
+ }
868
+
869
+ /**
870
+ * Retrieve the list of mobile operating systems.
871
+ *
872
+ * @return array The list of mobile operating systems.
873
+ */
874
+ public static function getOperatingSystems()
875
+ {
876
+ return self::$operatingSystems;
877
+ }
878
+
879
+ /**
880
+ * Some detection rules are relative (not standard),
881
+ * because of the diversity of devices, vendors and
882
+ * their conventions in representing the User-Agent or
883
+ * the HTTP headers.
884
+ *
885
+ * This method will be used to check custom regexes against
886
+ * the User-Agent string.
887
+ *
888
+ * @param $regex
889
+ * @param string $userAgent
890
+ * @return bool
891
+ *
892
+ * @todo: search in the HTTP headers too.
893
+ */
894
+ public function match($regex, $userAgent = null)
895
+ {
896
+ // Escape the special character which is the delimiter.
897
+ $regex = str_replace('/', '\/', $regex);
898
+
899
+ return (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));
900
+ }
901
+
902
+ /**
903
+ * Get the properties array.
904
+ *
905
+ * @return array
906
+ */
907
+ public static function getProperties()
908
+ {
909
+ return self::$properties;
910
+ }
911
+
912
+ /**
913
+ * Prepare the version number.
914
+ *
915
+ * @todo Remove the error supression from str_replace() call.
916
+ *
917
+ * @param string $ver The string version, like "2.6.21.2152";
918
+ *
919
+ * @return float
920
+ */
921
+ public function prepareVersionNo($ver)
922
+ {
923
+ $ver = str_replace(array('_', ' ', '/'), '.', $ver);
924
+ $arrVer = explode('.', $ver, 2);
925
+
926
+ if (isset($arrVer[1])) {
927
+ $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
928
+ }
929
+
930
+ return (float) implode('.', $arrVer);
931
+ }
932
+
933
+ /**
934
+ * Check the version of the given property in the User-Agent.
935
+ * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
936
+ *
937
+ * @param string $propertyName The name of the property. See self::getProperties() array
938
+ * keys for all possible properties.
939
+ * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
940
+ * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
941
+ * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
942
+ * invalid parameter will default to the this type as well.
943
+ *
944
+ * @return string|float The version of the property we are trying to extract.
945
+ */
946
+ public function version($propertyName, $type = self::VERSION_TYPE_STRING)
947
+ {
948
+ if (empty($propertyName)) {
949
+ return false;
950
+ }
951
+
952
+ //set the $type to the default if we don't recognize the type
953
+ if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) {
954
+ $type = self::VERSION_TYPE_STRING;
955
+ }
956
+
957
+ $properties = self::getProperties();
958
+
959
+ // Check if the property exists in the properties array.
960
+ if (array_key_exists($propertyName, $properties)) {
961
+
962
+ // Prepare the pattern to be matched.
963
+ // Make sure we always deal with an array (string is converted).
964
+ $properties[$propertyName] = (array) $properties[$propertyName];
965
+
966
+ foreach ($properties[$propertyName] as $propertyMatchString) {
967
+
968
+ $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
969
+
970
+ // Escape the special character which is the delimiter.
971
+ $propertyPattern = str_replace('/', '\/', $propertyPattern);
972
+
973
+ // Identify and extract the version.
974
+ preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
975
+
976
+ if (!empty($match[1])) {
977
+ $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] );
978
+
979
+ return $version;
980
+ }
981
+
982
+ }
983
+
984
+ }
985
+
986
+ return false;
987
+ }
988
+
989
+ /**
990
+ * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
991
+ *
992
+ * @return string One of the self::MOBILE_GRADE_* constants.
993
+ */
994
+ public function mobileGrade()
995
+ {
996
+ $isMobile = $this->isMobile();
997
+
998
+ if (
999
+ // 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)
1000
+ $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 ||
1001
+ $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=3.1 ||
1002
+ $this->version('iPod', self::VERSION_TYPE_FLOAT)>=3.1 ||
1003
+
1004
+ // 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)
1005
+ // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1006
+ // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1007
+ // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1008
+ ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1009
+
1010
+ // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800
1011
+ $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.0 ||
1012
+
1013
+ // Blackberry 7 - Tested on BlackBerry® Torch 9810
1014
+ // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670
1015
+ $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 ||
1016
+ // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1017
+ $this->match('Playbook.*Tablet') ||
1018
+
1019
+ // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0)
1020
+ ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
1021
+ // Palm WebOS 3.0 - Tested on HP TouchPad
1022
+ $this->match('hp.*TouchPad') ||
1023
+
1024
+ // Firefox Mobile (12 Beta) - Tested on Android 2.3 device
1025
+ ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=12 ) ||
1026
+
1027
+ // Chrome for Android - Tested on Android 4.0, 4.1 device
1028
+ ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) ||
1029
+
1030
+ // Skyfire 4.1 - Tested on Android 2.3 device
1031
+ ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1032
+
1033
+ // Opera Mobile 11.5-12: Tested on Android 2.3
1034
+ ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>11 && $this->is('AndroidOS') ) ||
1035
+
1036
+ // Meego 1.2 - Tested on Nokia 950 and N9
1037
+ $this->is('MeeGoOS') ||
1038
+
1039
+ // Tizen (pre-release) - Tested on early hardware
1040
+ $this->is('Tizen') ||
1041
+
1042
+ // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1043
+ // @todo: more tests here!
1044
+ $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 ||
1045
+
1046
+ // UC Browser - Tested on Android 2.3 device
1047
+ ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1048
+
1049
+ // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1050
+ ( $this->match('Kindle Fire') ||
1051
+ $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) ||
1052
+
1053
+ // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1054
+ $this->is('AndroidOS') && $this->is('NookTablet') ||
1055
+
1056
+ // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7
1057
+ $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=11 && !$isMobile ||
1058
+
1059
+ // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7
1060
+ $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile ||
1061
+
1062
+ // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7
1063
+ $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=4.0 && !$isMobile ||
1064
+
1065
+ // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1066
+ $this->version('MSIE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile ||
1067
+
1068
+ // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1069
+ // @reference: http://my.opera.com/community/openweb/idopera/
1070
+ $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile
1071
+
1072
+ ){
1073
+ return self::MOBILE_GRADE_A;
1074
+ }
1075
+
1076
+ if (
1077
+ $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1078
+ $this->version('iPhone', self::VERSION_TYPE_FLOAT)<3.1 ||
1079
+ $this->version('iPod', self::VERSION_TYPE_FLOAT)<3.1 ||
1080
+
1081
+ // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1082
+ $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1083
+
1084
+ //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1085
+ ( $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=6.5 &&
1086
+ ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) ||
1087
+
1088
+ // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1089
+ $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1090
+
1091
+ // @todo: report this (tested on Nokia N71)
1092
+ $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS')
1093
+ ){
1094
+ return self::MOBILE_GRADE_B;
1095
+ }
1096
+
1097
+ if (
1098
+ // Blackberry 4.x - Tested on the Curve 8330
1099
+ $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<5.0 ||
1100
+ // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1101
+ $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2
1102
+
1103
+ ){
1104
+ return self::MOBILE_GRADE_C;
1105
+ }
1106
+
1107
+ //All older smartphone platforms and featurephones - Any device that doesn't support media queries
1108
+ //will receive the basic, C grade experience.
1109
+ return self::MOBILE_GRADE_C;
1110
+ }
1111
+ }
app/code/community/Optimiseweb/MobileDetect/etc/config.xml CHANGED
@@ -11,7 +11,7 @@
11
 
12
  <modules>
13
  <Optimiseweb_MobileDetect>
14
- <version>0.1.4</version>
15
  </Optimiseweb_MobileDetect>
16
  </modules>
17
 
11
 
12
  <modules>
13
  <Optimiseweb_MobileDetect>
14
+ <version>0.1.6</version>
15
  </Optimiseweb_MobileDetect>
16
  </modules>
17
 
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Optimiseweb_MobileDetect</name>
4
- <version>0.1.4</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Optimise Web's Magento helper to enable the usage of all functions provided by MobileDetect.net</summary>
10
  <description>MobileDetect.net is a lightweight PHP class for detecting mobile devices. Optimise Web's MobileDetect Magento extension allows using the mobile detection functions from within Magento.</description>
11
- <notes>Updated to Mobile_Detect 2.6.0</notes>
12
  <authors><author><name>Kathir Vel</name><user>OptimiseWeb</user><email>info@optimiseweb.co.uk</email></author></authors>
13
- <date>2013-05-11</date>
14
- <time>01:25:13</time>
15
- <contents><target name="magecommunity"><dir name="Optimiseweb"><dir name="MobileDetect"><dir name="Helper"><file name="Data.php" hash="0e6c5e046ffdee7d46cf77ff744b6dcf"/></dir><dir name="Library"><file name="Mobile_Detect.php" hash="dfbccd9e06f3d58545c113bf18a0762a"/></dir><dir name="etc"><file name="config.xml" hash="9e6c867e042c8fa75fd9b7815d0ccb83"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Optimiseweb_MobileDetect.xml" hash="b199a92a751991216ed19e1cf596a159"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Optimiseweb_MobileDetect</name>
4
+ <version>0.1.6</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Optimise Web's Magento helper to enable the usage of all functions provided by MobileDetect.net</summary>
10
  <description>MobileDetect.net is a lightweight PHP class for detecting mobile devices. Optimise Web's MobileDetect Magento extension allows using the mobile detection functions from within Magento.</description>
11
+ <notes>Updated to Mobile Detect 2.7.1</notes>
12
  <authors><author><name>Kathir Vel</name><user>OptimiseWeb</user><email>info@optimiseweb.co.uk</email></author></authors>
13
+ <date>2013-10-07</date>
14
+ <time>22:14:39</time>
15
+ <contents><target name="magecommunity"><dir name="Optimiseweb"><dir name="MobileDetect"><dir name="Helper"><file name="Data.php" hash="0e6c5e046ffdee7d46cf77ff744b6dcf"/></dir><dir name="Library"><file name="Mobile_Detect.php" hash="222ed9d9291dd3301cc2f928e4c01b20"/></dir><dir name="etc"><file name="config.xml" hash="90f1ad6482efc65788dca2b12ab5ce1f"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Optimiseweb_MobileDetect.xml" hash="b199a92a751991216ed19e1cf596a159"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>