| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
5
|
|
|
5
|
|
72346
|
use strict; |
|
|
5
|
|
|
|
|
29
|
|
|
|
5
|
|
|
|
|
145
|
|
|
2
|
5
|
|
|
5
|
|
27
|
use warnings; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
119
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
5
|
|
|
5
|
|
105
|
use 5.006; |
|
|
5
|
|
|
|
|
16
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package HTTP::BrowserDetect; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '3.38'; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Operating Systems |
|
11
|
|
|
|
|
|
|
our @OS_TESTS = qw( |
|
12
|
|
|
|
|
|
|
windows mac os2 |
|
13
|
|
|
|
|
|
|
unix linux vms |
|
14
|
|
|
|
|
|
|
bsd amiga brew |
|
15
|
|
|
|
|
|
|
bb10 rimtabletos |
|
16
|
|
|
|
|
|
|
chromeos ios |
|
17
|
|
|
|
|
|
|
firefoxos |
|
18
|
|
|
|
|
|
|
); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# More precise Windows |
|
21
|
|
|
|
|
|
|
our @WINDOWS_TESTS = qw( |
|
22
|
|
|
|
|
|
|
win16 win3x win31 |
|
23
|
|
|
|
|
|
|
win95 win98 winnt |
|
24
|
|
|
|
|
|
|
winme win32 win2k |
|
25
|
|
|
|
|
|
|
winxp win2k3 winvista |
|
26
|
|
|
|
|
|
|
win7 win8 win8_0 |
|
27
|
|
|
|
|
|
|
win8_1 win10 win10_0 |
|
28
|
|
|
|
|
|
|
wince winphone winphone7 |
|
29
|
|
|
|
|
|
|
winphone7_5 winphone8 winphone8_1 |
|
30
|
|
|
|
|
|
|
winphone10 |
|
31
|
|
|
|
|
|
|
); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# More precise Mac |
|
34
|
|
|
|
|
|
|
our @MAC_TESTS = qw( |
|
35
|
|
|
|
|
|
|
macosx mac68k macppc |
|
36
|
|
|
|
|
|
|
); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# More precise Unix |
|
39
|
|
|
|
|
|
|
our @UNIX_TESTS = qw( |
|
40
|
|
|
|
|
|
|
sun sun4 sun5 |
|
41
|
|
|
|
|
|
|
suni86 irix irix5 |
|
42
|
|
|
|
|
|
|
irix6 hpux hpux9 |
|
43
|
|
|
|
|
|
|
hpux10 aix aix1 |
|
44
|
|
|
|
|
|
|
aix2 aix3 aix4 |
|
45
|
|
|
|
|
|
|
sco unixware mpras |
|
46
|
|
|
|
|
|
|
reliant dec sinix |
|
47
|
|
|
|
|
|
|
); |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# More precise BSDs |
|
50
|
|
|
|
|
|
|
our @BSD_TESTS = qw( |
|
51
|
|
|
|
|
|
|
freebsd |
|
52
|
|
|
|
|
|
|
); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Gaming devices |
|
55
|
|
|
|
|
|
|
our @GAMING_TESTS = qw( |
|
56
|
|
|
|
|
|
|
ps3gameos pspgameos |
|
57
|
|
|
|
|
|
|
); |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Device related tests |
|
60
|
|
|
|
|
|
|
our @DEVICE_TESTS = qw( |
|
61
|
|
|
|
|
|
|
android audrey blackberry dsi iopener ipad |
|
62
|
|
|
|
|
|
|
iphone ipod kindle kindlefire n3ds palm ps3 psp wap webos |
|
63
|
|
|
|
|
|
|
mobile tablet |
|
64
|
|
|
|
|
|
|
); |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# Browsers |
|
67
|
|
|
|
|
|
|
our @BROWSER_TESTS = qw( |
|
68
|
|
|
|
|
|
|
mosaic netscape firefox |
|
69
|
|
|
|
|
|
|
chrome safari ie |
|
70
|
|
|
|
|
|
|
opera lynx links |
|
71
|
|
|
|
|
|
|
elinks neoplanet neoplanet2 |
|
72
|
|
|
|
|
|
|
avantgo emacs mozilla |
|
73
|
|
|
|
|
|
|
konqueror realplayer netfront |
|
74
|
|
|
|
|
|
|
mobile_safari obigo aol |
|
75
|
|
|
|
|
|
|
lotusnotes staroffice icab |
|
76
|
|
|
|
|
|
|
webtv browsex silk |
|
77
|
|
|
|
|
|
|
applecoremedia galeon seamonkey |
|
78
|
|
|
|
|
|
|
epiphany ucbrowser dalvik |
|
79
|
|
|
|
|
|
|
edge pubsub adm |
|
80
|
|
|
|
|
|
|
brave imagesearcherpro polaris |
|
81
|
|
|
|
|
|
|
edgelegacy samsung |
|
82
|
|
|
|
|
|
|
instagram |
|
83
|
|
|
|
|
|
|
yandex_browser |
|
84
|
|
|
|
|
|
|
); |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
our @IE_TESTS = qw( |
|
87
|
|
|
|
|
|
|
ie3 ie4 ie4up |
|
88
|
|
|
|
|
|
|
ie5 ie5up ie55 |
|
89
|
|
|
|
|
|
|
ie55up ie6 ie7 |
|
90
|
|
|
|
|
|
|
ie8 ie9 ie10 |
|
91
|
|
|
|
|
|
|
ie11 |
|
92
|
|
|
|
|
|
|
ie_compat_mode |
|
93
|
|
|
|
|
|
|
); |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
our @OPERA_TESTS = qw( |
|
96
|
|
|
|
|
|
|
opera3 opera4 opera5 |
|
97
|
|
|
|
|
|
|
opera6 opera7 |
|
98
|
|
|
|
|
|
|
); |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
our @AOL_TESTS = qw( |
|
101
|
|
|
|
|
|
|
aol3 aol4 |
|
102
|
|
|
|
|
|
|
aol5 aol6 |
|
103
|
|
|
|
|
|
|
); |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
our @NETSCAPE_TESTS = qw( |
|
106
|
|
|
|
|
|
|
nav2 nav3 nav4 |
|
107
|
|
|
|
|
|
|
nav4up nav45 nav45up |
|
108
|
|
|
|
|
|
|
nav6 nav6up navgold |
|
109
|
|
|
|
|
|
|
); |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Firefox variants |
|
112
|
|
|
|
|
|
|
our @FIREFOX_TESTS = qw( |
|
113
|
|
|
|
|
|
|
firebird iceweasel phoenix |
|
114
|
|
|
|
|
|
|
namoroka |
|
115
|
|
|
|
|
|
|
fxios |
|
116
|
|
|
|
|
|
|
); |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# Engine tests |
|
119
|
|
|
|
|
|
|
our @ENGINE_TESTS = qw( |
|
120
|
|
|
|
|
|
|
gecko trident webkit |
|
121
|
|
|
|
|
|
|
presto khtml edgehtml |
|
122
|
|
|
|
|
|
|
); |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# These bot names get turned into methods. Crazy, right? (I don't even think |
|
125
|
|
|
|
|
|
|
# this is documented anymore.) We'll leave this in place for back compat, but |
|
126
|
|
|
|
|
|
|
# we won't add any new methods moving forward. |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
my @OLD_ROBOT_TESTS = qw( |
|
129
|
|
|
|
|
|
|
ahrefs |
|
130
|
|
|
|
|
|
|
altavista |
|
131
|
|
|
|
|
|
|
apache |
|
132
|
|
|
|
|
|
|
askjeeves |
|
133
|
|
|
|
|
|
|
baidu |
|
134
|
|
|
|
|
|
|
bingbot |
|
135
|
|
|
|
|
|
|
curl |
|
136
|
|
|
|
|
|
|
facebook |
|
137
|
|
|
|
|
|
|
getright |
|
138
|
|
|
|
|
|
|
golib |
|
139
|
|
|
|
|
|
|
google |
|
140
|
|
|
|
|
|
|
googleadsbot |
|
141
|
|
|
|
|
|
|
googleadsense |
|
142
|
|
|
|
|
|
|
googlebotimage |
|
143
|
|
|
|
|
|
|
googlebotnews |
|
144
|
|
|
|
|
|
|
googlebotvideo |
|
145
|
|
|
|
|
|
|
googlefavicon |
|
146
|
|
|
|
|
|
|
googlemobile |
|
147
|
|
|
|
|
|
|
indy |
|
148
|
|
|
|
|
|
|
infoseek |
|
149
|
|
|
|
|
|
|
ipsagent |
|
150
|
|
|
|
|
|
|
java |
|
151
|
|
|
|
|
|
|
linkchecker |
|
152
|
|
|
|
|
|
|
linkexchange |
|
153
|
|
|
|
|
|
|
lwp |
|
154
|
|
|
|
|
|
|
lycos |
|
155
|
|
|
|
|
|
|
malware |
|
156
|
|
|
|
|
|
|
mj12bot |
|
157
|
|
|
|
|
|
|
msn |
|
158
|
|
|
|
|
|
|
msnmobile |
|
159
|
|
|
|
|
|
|
msoffice |
|
160
|
|
|
|
|
|
|
nutch |
|
161
|
|
|
|
|
|
|
phplib |
|
162
|
|
|
|
|
|
|
puf |
|
163
|
|
|
|
|
|
|
rubylib |
|
164
|
|
|
|
|
|
|
slurp |
|
165
|
|
|
|
|
|
|
specialarchiver |
|
166
|
|
|
|
|
|
|
wget |
|
167
|
|
|
|
|
|
|
yahoo |
|
168
|
|
|
|
|
|
|
yandex |
|
169
|
|
|
|
|
|
|
yandeximages |
|
170
|
|
|
|
|
|
|
headlesschrome |
|
171
|
|
|
|
|
|
|
); |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
our @ROBOT_TESTS = ( |
|
174
|
|
|
|
|
|
|
[ 'Applebot', 'apple' ], |
|
175
|
|
|
|
|
|
|
[ 'baiduspider', 'baidu' ], |
|
176
|
|
|
|
|
|
|
[ 'bitlybot', 'bitly' ], |
|
177
|
|
|
|
|
|
|
[ 'developers.google.com//web/snippet', 'google-plus-snippet' ], |
|
178
|
|
|
|
|
|
|
[ 'Discordbot', 'discordbot' ], |
|
179
|
|
|
|
|
|
|
[ 'embedly', 'embedly' ], |
|
180
|
|
|
|
|
|
|
[ 'facebookexternalhit', 'facebook' ], |
|
181
|
|
|
|
|
|
|
[ 'flipboard', 'flipboard' ], |
|
182
|
|
|
|
|
|
|
[ 'Google Page Speed', 'google-page-speed' ], |
|
183
|
|
|
|
|
|
|
[ 'ltx71', 'ltx71' ], |
|
184
|
|
|
|
|
|
|
[ 'linkedinbot', 'linkedin' ], |
|
185
|
|
|
|
|
|
|
[ 'nuzzel', 'nuzzel' ], |
|
186
|
|
|
|
|
|
|
[ 'outbrain', 'outbrain' ], |
|
187
|
|
|
|
|
|
|
[ 'pinterest/0.', 'pinterest' ], |
|
188
|
|
|
|
|
|
|
[ 'pinterestbot', 'pinterest' ], |
|
189
|
|
|
|
|
|
|
[ 'Pro-Sitemaps', 'pro-sitemaps' ], |
|
190
|
|
|
|
|
|
|
[ 'quora link preview', 'quora-link-preview' ], |
|
191
|
|
|
|
|
|
|
[ 'Qwantify', 'qwantify' ], |
|
192
|
|
|
|
|
|
|
[ 'redditbot', 'reddit', ], |
|
193
|
|
|
|
|
|
|
[ 'researchscan', 'researchscan' ], |
|
194
|
|
|
|
|
|
|
[ 'rogerbot', 'rogerbot' ], |
|
195
|
|
|
|
|
|
|
[ 'ShowyouBot', 'showyou' ], |
|
196
|
|
|
|
|
|
|
[ 'SkypeUriPreview', 'skype-uri-preview' ], |
|
197
|
|
|
|
|
|
|
[ 'slackbot', 'slack' ], |
|
198
|
|
|
|
|
|
|
[ 'Swiftbot', 'swiftbot' ], |
|
199
|
|
|
|
|
|
|
[ 'tumblr', 'tumblr' ], |
|
200
|
|
|
|
|
|
|
[ 'twitterbot', 'twitter' ], |
|
201
|
|
|
|
|
|
|
[ 'vkShare', 'vkshare' ], |
|
202
|
|
|
|
|
|
|
[ 'W3C_Validator', 'w3c-validator' ], |
|
203
|
|
|
|
|
|
|
[ 'WhatsApp', 'whatsapp' ], |
|
204
|
|
|
|
|
|
|
); |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
our @MISC_TESTS = qw( |
|
207
|
|
|
|
|
|
|
dotnet x11 |
|
208
|
|
|
|
|
|
|
webview |
|
209
|
|
|
|
|
|
|
meta_app |
|
210
|
|
|
|
|
|
|
); |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
our @ALL_TESTS = ( |
|
213
|
|
|
|
|
|
|
@OS_TESTS, @WINDOWS_TESTS, |
|
214
|
|
|
|
|
|
|
@MAC_TESTS, @UNIX_TESTS, |
|
215
|
|
|
|
|
|
|
@BSD_TESTS, @GAMING_TESTS, |
|
216
|
|
|
|
|
|
|
@DEVICE_TESTS, @BROWSER_TESTS, |
|
217
|
|
|
|
|
|
|
@IE_TESTS, @OPERA_TESTS, |
|
218
|
|
|
|
|
|
|
@AOL_TESTS, @NETSCAPE_TESTS, |
|
219
|
|
|
|
|
|
|
@FIREFOX_TESTS, @ENGINE_TESTS, |
|
220
|
|
|
|
|
|
|
@OLD_ROBOT_TESTS, @MISC_TESTS, |
|
221
|
|
|
|
|
|
|
); |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# https://support.google.com/webmasters/answer/1061943?hl=en |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
my %ROBOT_NAMES = ( |
|
226
|
|
|
|
|
|
|
ahrefs => 'Ahrefs', |
|
227
|
|
|
|
|
|
|
altavista => 'AltaVista', |
|
228
|
|
|
|
|
|
|
'apache-http-client' => 'Apache HttpClient', |
|
229
|
|
|
|
|
|
|
apple => 'Apple', |
|
230
|
|
|
|
|
|
|
'archive-org' => 'Internet Archive', |
|
231
|
|
|
|
|
|
|
askjeeves => 'AskJeeves', |
|
232
|
|
|
|
|
|
|
baidu => 'Baidu', |
|
233
|
|
|
|
|
|
|
baiduspider => 'Baidu Spider', |
|
234
|
|
|
|
|
|
|
bingbot => 'Bingbot', |
|
235
|
|
|
|
|
|
|
bitly => 'Bitly', |
|
236
|
|
|
|
|
|
|
curl => 'curl', |
|
237
|
|
|
|
|
|
|
discordbot => 'Discord', |
|
238
|
|
|
|
|
|
|
embedly => 'Embedly', |
|
239
|
|
|
|
|
|
|
facebook => 'Facebook', |
|
240
|
|
|
|
|
|
|
facebookexternalhit => 'Facebook', |
|
241
|
|
|
|
|
|
|
flipboard => 'Flipboard', |
|
242
|
|
|
|
|
|
|
getright => 'GetRight', |
|
243
|
|
|
|
|
|
|
golib => 'Go language http library', |
|
244
|
|
|
|
|
|
|
google => 'Googlebot', |
|
245
|
|
|
|
|
|
|
'google-adsbot' => 'Google AdsBot', |
|
246
|
|
|
|
|
|
|
'google-adsense' => 'Google AdSense', |
|
247
|
|
|
|
|
|
|
'googlebot' => 'Googlebot', |
|
248
|
|
|
|
|
|
|
'googlebot-image' => 'Googlebot Images', |
|
249
|
|
|
|
|
|
|
'googlebot-mobile' => 'Googlebot Mobile', |
|
250
|
|
|
|
|
|
|
'googlebot-news' => 'Googlebot News', |
|
251
|
|
|
|
|
|
|
'googlebot-video' => 'Googlebot Video', |
|
252
|
|
|
|
|
|
|
'google-favicon' => 'Google Favicon', |
|
253
|
|
|
|
|
|
|
'google-mobile' => 'Googlebot Mobile', |
|
254
|
|
|
|
|
|
|
'google-page-speed' => 'Google Page Speed', |
|
255
|
|
|
|
|
|
|
'google-plus-snippet' => 'Google+ Snippet', |
|
256
|
|
|
|
|
|
|
'indy-library' => 'Indy Library', |
|
257
|
|
|
|
|
|
|
infoseek => 'InfoSeek', |
|
258
|
|
|
|
|
|
|
java => 'Java', |
|
259
|
|
|
|
|
|
|
'libwww-perl' => 'LWP::UserAgent', |
|
260
|
|
|
|
|
|
|
linkchecker => 'LinkChecker', |
|
261
|
|
|
|
|
|
|
linkedin => 'LinkedIn', |
|
262
|
|
|
|
|
|
|
linkexchange => 'LinkExchange', |
|
263
|
|
|
|
|
|
|
ltx71 => 'ltx71', |
|
264
|
|
|
|
|
|
|
lycos => 'Lycos', |
|
265
|
|
|
|
|
|
|
malware => 'Malware / hack attempt', |
|
266
|
|
|
|
|
|
|
'microsoft-office' => 'Microsoft Office', |
|
267
|
|
|
|
|
|
|
mj12bot => 'Majestic-12 DSearch', |
|
268
|
|
|
|
|
|
|
msn => 'MSN', |
|
269
|
|
|
|
|
|
|
'msn-mobile' => 'MSN Mobile', |
|
270
|
|
|
|
|
|
|
nutch => 'Apache Nutch', |
|
271
|
|
|
|
|
|
|
nuzzel => 'Nuzzel', |
|
272
|
|
|
|
|
|
|
outbrain => 'Outbrain', |
|
273
|
|
|
|
|
|
|
phplib => 'PHP http library', |
|
274
|
|
|
|
|
|
|
pinterest => 'Pinterest', |
|
275
|
|
|
|
|
|
|
'pro-sitemaps' => 'Pro Sitemap Service', |
|
276
|
|
|
|
|
|
|
puf => 'puf', |
|
277
|
|
|
|
|
|
|
'quora-link-preview' => 'Quora Link Preview', |
|
278
|
|
|
|
|
|
|
qwantify => 'Qwantify', |
|
279
|
|
|
|
|
|
|
researchscan => 'Researchscan RWTH Aachen', |
|
280
|
|
|
|
|
|
|
reddit => 'Reddit', |
|
281
|
|
|
|
|
|
|
robot => 'robot', |
|
282
|
|
|
|
|
|
|
rogerbot => 'Moz', |
|
283
|
|
|
|
|
|
|
'ruby-http-library' => 'Ruby http library', |
|
284
|
|
|
|
|
|
|
showyou => 'Showyou', |
|
285
|
|
|
|
|
|
|
'skype-uri-preview' => 'Skype URI Preview', |
|
286
|
|
|
|
|
|
|
slack => 'slack', |
|
287
|
|
|
|
|
|
|
swiftbot => 'Swiftbot', |
|
288
|
|
|
|
|
|
|
tumblr => 'Tumblr', |
|
289
|
|
|
|
|
|
|
twitter => 'Twitter', |
|
290
|
|
|
|
|
|
|
unknown => 'Unknown Bot', |
|
291
|
|
|
|
|
|
|
'verisign-ips-agent' => 'Verisign ips-agent', |
|
292
|
|
|
|
|
|
|
vkshare => 'VK Share', |
|
293
|
|
|
|
|
|
|
'w3c-validator' => 'W3C Validator', |
|
294
|
|
|
|
|
|
|
wget => 'Wget', |
|
295
|
|
|
|
|
|
|
whatsapp => 'WhatsApp', |
|
296
|
|
|
|
|
|
|
yahoo => 'Yahoo', |
|
297
|
|
|
|
|
|
|
'yahoo-slurp' => 'Yahoo! Slurp', |
|
298
|
|
|
|
|
|
|
yandex => 'Yandex', |
|
299
|
|
|
|
|
|
|
'yandex-images' => 'YandexImages', |
|
300
|
|
|
|
|
|
|
'headless-chrome' => 'HeadlessChrome', |
|
301
|
|
|
|
|
|
|
); |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
my %ROBOT_IDS = ( |
|
304
|
|
|
|
|
|
|
ahrefs => 'ahrefs', |
|
305
|
|
|
|
|
|
|
altavista => 'altavista', |
|
306
|
|
|
|
|
|
|
apache => 'apache-http-client', |
|
307
|
|
|
|
|
|
|
askjeeves => 'askjeeves', |
|
308
|
|
|
|
|
|
|
baidu => 'baidu', |
|
309
|
|
|
|
|
|
|
baiduspider => 'baidu', |
|
310
|
|
|
|
|
|
|
bingbot => 'bingbot', |
|
311
|
|
|
|
|
|
|
curl => 'curl', |
|
312
|
|
|
|
|
|
|
facebook => 'facebook', |
|
313
|
|
|
|
|
|
|
getright => 'getright', |
|
314
|
|
|
|
|
|
|
golib => 'golib', |
|
315
|
|
|
|
|
|
|
google => 'googlebot', |
|
316
|
|
|
|
|
|
|
googleadsbot => 'google-adsbot', |
|
317
|
|
|
|
|
|
|
googleadsense => 'google-adsense', |
|
318
|
|
|
|
|
|
|
googlebotimage => 'googlebot-image', |
|
319
|
|
|
|
|
|
|
googlebotnews => 'googlebot-news', |
|
320
|
|
|
|
|
|
|
googlebotvideo => 'googlebot-video', |
|
321
|
|
|
|
|
|
|
googlefavicon => 'google-favicon', |
|
322
|
|
|
|
|
|
|
googlemobile => 'googlebot-mobile', |
|
323
|
|
|
|
|
|
|
indy => 'indy-library', |
|
324
|
|
|
|
|
|
|
infoseek => 'infoseek', |
|
325
|
|
|
|
|
|
|
ipsagent => 'verisign-ips-agent', |
|
326
|
|
|
|
|
|
|
java => 'java', |
|
327
|
|
|
|
|
|
|
linkchecker => 'linkchecker', |
|
328
|
|
|
|
|
|
|
linkexchange => 'linkexchange', |
|
329
|
|
|
|
|
|
|
ltx71 => 'ltx71', |
|
330
|
|
|
|
|
|
|
lwp => 'libwww-perl', |
|
331
|
|
|
|
|
|
|
lycos => 'lycos', |
|
332
|
|
|
|
|
|
|
malware => 'malware', |
|
333
|
|
|
|
|
|
|
mj12bot => 'mj12bot', |
|
334
|
|
|
|
|
|
|
msn => 'msn', |
|
335
|
|
|
|
|
|
|
msnmobile => 'msn-mobile', |
|
336
|
|
|
|
|
|
|
msoffice => 'microsoft-office', |
|
337
|
|
|
|
|
|
|
nutch => 'nutch', |
|
338
|
|
|
|
|
|
|
phplib => 'phplib', |
|
339
|
|
|
|
|
|
|
puf => 'puf', |
|
340
|
|
|
|
|
|
|
robot => 'robot', |
|
341
|
|
|
|
|
|
|
rubylib => 'ruby-http-library', |
|
342
|
|
|
|
|
|
|
researchscan => 'researchscan', |
|
343
|
|
|
|
|
|
|
slurp => 'yahoo-slurp', |
|
344
|
|
|
|
|
|
|
specialarchiver => 'archive-org', |
|
345
|
|
|
|
|
|
|
wget => 'wget', |
|
346
|
|
|
|
|
|
|
yahoo => 'yahoo', |
|
347
|
|
|
|
|
|
|
yandex => 'yandex', |
|
348
|
|
|
|
|
|
|
yandeximages => 'yandex-images', |
|
349
|
|
|
|
|
|
|
headlesschrome => 'headless-chrome', |
|
350
|
|
|
|
|
|
|
); |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
my %BROWSER_NAMES = ( |
|
353
|
|
|
|
|
|
|
adm => 'Android Download Manager', |
|
354
|
|
|
|
|
|
|
aol => 'AOL Browser', |
|
355
|
|
|
|
|
|
|
applecoremedia => 'AppleCoreMedia', |
|
356
|
|
|
|
|
|
|
blackberry => 'BlackBerry', |
|
357
|
|
|
|
|
|
|
brave => 'Brave', |
|
358
|
|
|
|
|
|
|
browsex => 'BrowseX', |
|
359
|
|
|
|
|
|
|
chrome => 'Chrome', |
|
360
|
|
|
|
|
|
|
curl => 'curl', |
|
361
|
|
|
|
|
|
|
dalvik => 'Dalvik', |
|
362
|
|
|
|
|
|
|
dsi => 'Nintendo DSi', |
|
363
|
|
|
|
|
|
|
edge => 'Edge', |
|
364
|
|
|
|
|
|
|
elinks => 'ELinks', |
|
365
|
|
|
|
|
|
|
epiphany => 'Epiphany', |
|
366
|
|
|
|
|
|
|
firefox => 'Firefox', |
|
367
|
|
|
|
|
|
|
galeon => 'Galeon', |
|
368
|
|
|
|
|
|
|
icab => 'iCab', |
|
369
|
|
|
|
|
|
|
iceweasel => 'IceWeasel', |
|
370
|
|
|
|
|
|
|
ie => 'MSIE', |
|
371
|
|
|
|
|
|
|
imagesearcherpro => 'ImageSearcherPro', |
|
372
|
|
|
|
|
|
|
instagram => 'Instagram', |
|
373
|
|
|
|
|
|
|
konqueror => 'Konqueror', |
|
374
|
|
|
|
|
|
|
links => 'Links', |
|
375
|
|
|
|
|
|
|
lotusnotes => 'Lotus Notes', |
|
376
|
|
|
|
|
|
|
lynx => 'Lynx', |
|
377
|
|
|
|
|
|
|
mobile_safari => 'Mobile Safari', |
|
378
|
|
|
|
|
|
|
mosaic => 'Mosaic', |
|
379
|
|
|
|
|
|
|
mozilla => 'Mozilla', |
|
380
|
|
|
|
|
|
|
n3ds => 'Nintendo 3DS', |
|
381
|
|
|
|
|
|
|
netfront => 'NetFront', |
|
382
|
|
|
|
|
|
|
netscape => 'Netscape', |
|
383
|
|
|
|
|
|
|
obigo => 'Obigo', |
|
384
|
|
|
|
|
|
|
opera => 'Opera', |
|
385
|
|
|
|
|
|
|
polaris => 'Polaris', |
|
386
|
|
|
|
|
|
|
pubsub => 'Safari RSS Reader', |
|
387
|
|
|
|
|
|
|
puf => 'puf', |
|
388
|
|
|
|
|
|
|
realplayer => 'RealPlayer', |
|
389
|
|
|
|
|
|
|
safari => 'Safari', |
|
390
|
|
|
|
|
|
|
samsung => 'Samsung', |
|
391
|
|
|
|
|
|
|
seamonkey => 'SeaMonkey', |
|
392
|
|
|
|
|
|
|
silk => 'Silk', |
|
393
|
|
|
|
|
|
|
staroffice => 'StarOffice', |
|
394
|
|
|
|
|
|
|
ucbrowser => 'UCBrowser', |
|
395
|
|
|
|
|
|
|
webtv => 'WebTV', |
|
396
|
|
|
|
|
|
|
yandex_browser => 'Yandex Browser', |
|
397
|
|
|
|
|
|
|
); |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
# Device names |
|
400
|
|
|
|
|
|
|
my %DEVICE_NAMES = ( |
|
401
|
|
|
|
|
|
|
android => 'Android', |
|
402
|
|
|
|
|
|
|
audrey => 'Audrey', |
|
403
|
|
|
|
|
|
|
blackberry => 'BlackBerry', |
|
404
|
|
|
|
|
|
|
dsi => 'Nintendo DSi', |
|
405
|
|
|
|
|
|
|
iopener => 'iopener', |
|
406
|
|
|
|
|
|
|
ipad => 'iPad', |
|
407
|
|
|
|
|
|
|
iphone => 'iPhone', |
|
408
|
|
|
|
|
|
|
ipod => 'iPod', |
|
409
|
|
|
|
|
|
|
kindle => 'Amazon Kindle', |
|
410
|
|
|
|
|
|
|
n3ds => 'Nintendo 3DS', |
|
411
|
|
|
|
|
|
|
palm => 'Palm', |
|
412
|
|
|
|
|
|
|
ps3 => 'Sony PlayStation 3', |
|
413
|
|
|
|
|
|
|
psp => 'Sony PlayStation Portable', |
|
414
|
|
|
|
|
|
|
wap => 'WAP capable phone', |
|
415
|
|
|
|
|
|
|
webos => 'webOS', |
|
416
|
|
|
|
|
|
|
); |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
my %OS_NAMES = ( |
|
419
|
|
|
|
|
|
|
amiga => 'Amiga', |
|
420
|
|
|
|
|
|
|
android => 'Android', |
|
421
|
|
|
|
|
|
|
bb10 => 'BlackBerry 10', |
|
422
|
|
|
|
|
|
|
brew => 'Brew', |
|
423
|
|
|
|
|
|
|
chromeos => 'Chrome OS', |
|
424
|
|
|
|
|
|
|
firefoxos => 'Firefox OS', |
|
425
|
|
|
|
|
|
|
ios => 'iOS', |
|
426
|
|
|
|
|
|
|
linux => 'Linux', |
|
427
|
|
|
|
|
|
|
mac => 'Mac', |
|
428
|
|
|
|
|
|
|
macosx => 'Mac OS X', |
|
429
|
|
|
|
|
|
|
os2 => 'OS/2', |
|
430
|
|
|
|
|
|
|
ps3gameos => 'Playstation 3 GameOS', |
|
431
|
|
|
|
|
|
|
pspgameos => 'Playstation Portable GameOS', |
|
432
|
|
|
|
|
|
|
rimtabletos => 'RIM Tablet OS', |
|
433
|
|
|
|
|
|
|
unix => 'Unix', |
|
434
|
|
|
|
|
|
|
vms => 'VMS', |
|
435
|
|
|
|
|
|
|
win2k => 'Win2k', |
|
436
|
|
|
|
|
|
|
win2k3 => 'Win2k3', |
|
437
|
|
|
|
|
|
|
win3x => 'Win3x', |
|
438
|
|
|
|
|
|
|
win7 => 'Win7', |
|
439
|
|
|
|
|
|
|
win8 => 'Win8', |
|
440
|
|
|
|
|
|
|
win8_0 => 'Win8.0', |
|
441
|
|
|
|
|
|
|
win8_1 => 'Win8.1', |
|
442
|
|
|
|
|
|
|
win10 => 'Win10', |
|
443
|
|
|
|
|
|
|
win10_0 => 'Win10.0', |
|
444
|
|
|
|
|
|
|
win95 => 'Win95', |
|
445
|
|
|
|
|
|
|
win98 => 'Win98', |
|
446
|
|
|
|
|
|
|
winme => 'WinME', |
|
447
|
|
|
|
|
|
|
winnt => 'WinNT', |
|
448
|
|
|
|
|
|
|
winphone => 'Windows Phone', |
|
449
|
|
|
|
|
|
|
winvista => 'WinVista', |
|
450
|
|
|
|
|
|
|
winxp => 'WinXP', |
|
451
|
|
|
|
|
|
|
); |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# Safari build -> version map for versions prior to 3.0 |
|
454
|
|
|
|
|
|
|
# (since then, version appears in the user-agent string) |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
my %safari_build_to_version = qw( |
|
457
|
|
|
|
|
|
|
48 0.8 |
|
458
|
|
|
|
|
|
|
51 0.8.1 |
|
459
|
|
|
|
|
|
|
60 0.8.2 |
|
460
|
|
|
|
|
|
|
73 0.9 |
|
461
|
|
|
|
|
|
|
74 1.0b2v74 |
|
462
|
|
|
|
|
|
|
85 1.0 |
|
463
|
|
|
|
|
|
|
85.7 1.0.2 |
|
464
|
|
|
|
|
|
|
85.8 1.0.3 |
|
465
|
|
|
|
|
|
|
100 1.1 |
|
466
|
|
|
|
|
|
|
100.1 1.1.1 |
|
467
|
|
|
|
|
|
|
125 1.2 |
|
468
|
|
|
|
|
|
|
125.1 1.2.1 |
|
469
|
|
|
|
|
|
|
125.7 1.2.2 |
|
470
|
|
|
|
|
|
|
125.9 1.2.3 |
|
471
|
|
|
|
|
|
|
125.11 1.2.4 |
|
472
|
|
|
|
|
|
|
312 1.3 |
|
473
|
|
|
|
|
|
|
312.3 1.3.1 |
|
474
|
|
|
|
|
|
|
312.5 1.3.2 |
|
475
|
|
|
|
|
|
|
412 2.0 |
|
476
|
|
|
|
|
|
|
412.5 2.0.1 |
|
477
|
|
|
|
|
|
|
416.12 2.0.2 |
|
478
|
|
|
|
|
|
|
417.8 2.0.3 |
|
479
|
|
|
|
|
|
|
419.3 2.0.4 |
|
480
|
|
|
|
|
|
|
); |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
####################################################################################################### |
|
483
|
|
|
|
|
|
|
# BROWSER OBJECT |
|
484
|
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
my $default = undef; |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
sub new { |
|
488
|
7247
|
|
|
7247
|
1
|
5257260
|
my ( $class, $user_agent ) = @_; |
|
489
|
|
|
|
|
|
|
|
|
490
|
7247
|
|
|
|
|
15176
|
my $self = {}; |
|
491
|
7247
|
|
|
|
|
15451
|
bless $self, $class; |
|
492
|
|
|
|
|
|
|
|
|
493
|
7247
|
100
|
|
|
|
21715
|
unless ( defined $user_agent ) { |
|
494
|
2
|
|
|
|
|
6
|
$user_agent = $ENV{'HTTP_USER_AGENT'}; |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
|
|
497
|
7247
|
100
|
|
|
|
23432
|
$self->{user_agent} = defined $user_agent ? $user_agent : q{}; |
|
498
|
7247
|
|
|
|
|
22671
|
$self->_init_core; |
|
499
|
|
|
|
|
|
|
|
|
500
|
7247
|
|
|
|
|
71544
|
return $self; |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
### Accessors for computed-on-demand test attributes |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
foreach my $test ( @ENGINE_TESTS, @MISC_TESTS ) { |
|
506
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
507
|
5
|
|
|
5
|
|
39
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
18
|
|
|
|
5
|
|
|
|
|
627
|
|
|
508
|
|
|
|
|
|
|
*{$test} = sub { |
|
509
|
25672
|
|
|
25672
|
|
1774949
|
my ($self) = @_; |
|
510
|
25672
|
|
100
|
|
|
96975
|
return $self->{tests}->{$test} || 0; |
|
511
|
|
|
|
|
|
|
}; |
|
512
|
|
|
|
|
|
|
} |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
foreach my $test ( |
|
515
|
|
|
|
|
|
|
@OS_TESTS, @WINDOWS_TESTS, @MAC_TESTS, @UNIX_TESTS, |
|
516
|
|
|
|
|
|
|
@BSD_TESTS, @GAMING_TESTS |
|
517
|
|
|
|
|
|
|
) { |
|
518
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
519
|
5
|
|
|
5
|
|
36
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
521
|
|
|
520
|
|
|
|
|
|
|
*{$test} = sub { |
|
521
|
50632
|
|
|
50632
|
|
8367630
|
my ($self) = @_; |
|
522
|
50632
|
100
|
|
|
|
128379
|
$self->_init_os() unless $self->{os_tests}; |
|
523
|
50632
|
|
100
|
|
|
179318
|
return $self->{os_tests}->{$test} || 0; |
|
524
|
|
|
|
|
|
|
}; |
|
525
|
|
|
|
|
|
|
} |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
foreach my $test ( @BROWSER_TESTS, @FIREFOX_TESTS ) { |
|
528
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
529
|
5
|
|
|
5
|
|
44
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
21
|
|
|
|
5
|
|
|
|
|
431
|
|
|
530
|
|
|
|
|
|
|
*{$test} = sub { |
|
531
|
61584
|
|
|
61584
|
|
5513786
|
my ($self) = @_; |
|
532
|
61584
|
|
100
|
|
|
245486
|
return $self->{browser_tests}->{$test} || 0; |
|
533
|
|
|
|
|
|
|
}; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
foreach my $test (@OLD_ROBOT_TESTS) { |
|
537
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
538
|
5
|
|
|
5
|
|
32
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
12
|
|
|
|
5
|
|
|
|
|
622
|
|
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# For the 'robot' test, we return undef instead of 0 if it's |
|
541
|
|
|
|
|
|
|
# false, to match os() and browser() and the like. |
|
542
|
|
|
|
|
|
|
my $false_result = ( $test eq 'robot' ? undef : 0 ); |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
*{$test} = sub { |
|
545
|
30674
|
|
|
30674
|
|
4199719
|
my ($self) = @_; |
|
546
|
30674
|
100
|
|
|
|
74731
|
$self->_init_robots() unless $self->{robot_tests}; |
|
547
|
30674
|
|
66
|
|
|
112379
|
return $self->{robot_tests}->{$test} || $false_result; |
|
548
|
|
|
|
|
|
|
}; |
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
foreach my $test ( |
|
552
|
|
|
|
|
|
|
@NETSCAPE_TESTS, @IE_TESTS, @AOL_TESTS, |
|
553
|
|
|
|
|
|
|
@OPERA_TESTS |
|
554
|
|
|
|
|
|
|
) { |
|
555
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
556
|
5
|
|
|
5
|
|
34
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
11
|
|
|
|
5
|
|
|
|
|
551
|
|
|
557
|
|
|
|
|
|
|
*{$test} = sub { |
|
558
|
24362
|
|
|
24362
|
|
4011634
|
my ($self) = @_; |
|
559
|
24362
|
100
|
|
|
|
62823
|
$self->_init_version() unless $self->{version_tests}; |
|
560
|
24362
|
|
100
|
|
|
88362
|
return $self->{version_tests}->{$test} || 0; |
|
561
|
|
|
|
|
|
|
}; |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
foreach my $test (@DEVICE_TESTS) { |
|
565
|
|
|
|
|
|
|
## no critic (TestingAndDebugging::ProhibitNoStrict) |
|
566
|
5
|
|
|
5
|
|
34
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
79811
|
|
|
567
|
|
|
|
|
|
|
*{$test} = sub { |
|
568
|
22335
|
|
|
22335
|
|
2274103
|
my ($self) = @_; |
|
569
|
22335
|
100
|
|
|
|
63207
|
$self->_init_device() unless $self->{device_tests}; |
|
570
|
22335
|
|
100
|
|
|
106463
|
return $self->{device_tests}->{$test} || 0; |
|
571
|
|
|
|
|
|
|
}; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub user_agent { |
|
575
|
1
|
|
|
1
|
1
|
7
|
my ( $self, $user_agent ) = @_; |
|
576
|
1
|
50
|
|
|
|
6
|
if ( defined($user_agent) ) { |
|
577
|
0
|
|
|
|
|
0
|
die |
|
578
|
|
|
|
|
|
|
'Calling HTTP::BrowserDetect::user_agent() with an argument is no longer allowed; please use new().'; |
|
579
|
|
|
|
|
|
|
} |
|
580
|
|
|
|
|
|
|
else { |
|
581
|
1
|
|
|
|
|
11
|
return $self->{user_agent}; |
|
582
|
|
|
|
|
|
|
} |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
### Code for initializing various pieces of the object. Since it would |
|
586
|
|
|
|
|
|
|
### be needlessly slow if we examined every user agent for every piece |
|
587
|
|
|
|
|
|
|
### of information we might possibly need, we only initialize things |
|
588
|
|
|
|
|
|
|
### when they're actually queried about. Specifically: |
|
589
|
|
|
|
|
|
|
### |
|
590
|
|
|
|
|
|
|
### _init_core() sets up: |
|
591
|
|
|
|
|
|
|
### $self->{browser_tests} |
|
592
|
|
|
|
|
|
|
### $self->{browser} |
|
593
|
|
|
|
|
|
|
### $self->{browser_string} |
|
594
|
|
|
|
|
|
|
### $self->{tests} |
|
595
|
|
|
|
|
|
|
### $self->{engine_version} |
|
596
|
|
|
|
|
|
|
### $self->{realplayer_version} |
|
597
|
|
|
|
|
|
|
### |
|
598
|
|
|
|
|
|
|
### _init_version() sets up: |
|
599
|
|
|
|
|
|
|
### $self->{version_tests} |
|
600
|
|
|
|
|
|
|
### $self->{major} |
|
601
|
|
|
|
|
|
|
### $self->{minor} |
|
602
|
|
|
|
|
|
|
### $self->{beta} |
|
603
|
|
|
|
|
|
|
### $self->{realplayer_version} |
|
604
|
|
|
|
|
|
|
### |
|
605
|
|
|
|
|
|
|
### _init_os() sets up: |
|
606
|
|
|
|
|
|
|
### $self->{os} |
|
607
|
|
|
|
|
|
|
### $self->{os_string} |
|
608
|
|
|
|
|
|
|
### $self->{os_tests} |
|
609
|
|
|
|
|
|
|
### $self->{os_version} |
|
610
|
|
|
|
|
|
|
### |
|
611
|
|
|
|
|
|
|
### _init_os_version() sets up: |
|
612
|
|
|
|
|
|
|
### $self->{os_version} |
|
613
|
|
|
|
|
|
|
### |
|
614
|
|
|
|
|
|
|
### _init_device() sets up: |
|
615
|
|
|
|
|
|
|
### $self->{device_tests} |
|
616
|
|
|
|
|
|
|
### $self->{device} |
|
617
|
|
|
|
|
|
|
### $self->{device_string} |
|
618
|
|
|
|
|
|
|
### |
|
619
|
|
|
|
|
|
|
### _init_robots() sets up: |
|
620
|
|
|
|
|
|
|
### $self->{robot} |
|
621
|
|
|
|
|
|
|
### $self->{robot_tests} |
|
622
|
|
|
|
|
|
|
### $self->{robot_string} |
|
623
|
|
|
|
|
|
|
### $self->{robot_version} |
|
624
|
|
|
|
|
|
|
### |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# Private method -- Set up the basics (browser and misc attributes) |
|
627
|
|
|
|
|
|
|
# for a new user-agent string |
|
628
|
|
|
|
|
|
|
sub _init_core { |
|
629
|
7247
|
|
|
7247
|
|
14517
|
my ( $self, $new_ua ) = @_; |
|
630
|
|
|
|
|
|
|
|
|
631
|
7247
|
|
|
|
|
21263
|
my $ua = lc $self->{user_agent}; |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
# any UA via Google Translate gets this appended |
|
634
|
7247
|
|
|
|
|
17465
|
$ua =~ s{,gzip\(gfe\)\z}{}; |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
# These get filled in immediately |
|
637
|
7247
|
|
|
|
|
15478
|
$self->{tests} = {}; |
|
638
|
7247
|
|
|
|
|
15164
|
$self->{browser_tests} = {}; |
|
639
|
|
|
|
|
|
|
|
|
640
|
7247
|
|
|
|
|
13612
|
my $tests = $self->{tests}; |
|
641
|
7247
|
|
|
|
|
13810
|
my $browser_tests = $self->{browser_tests}; |
|
642
|
7247
|
|
|
|
|
11923
|
my $browser = undef; |
|
643
|
7247
|
|
|
|
|
11808
|
my $browser_string = undef; |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# Detect engine |
|
646
|
7247
|
|
|
|
|
13025
|
$self->{engine_version} = undef; |
|
647
|
|
|
|
|
|
|
|
|
648
|
7247
|
100
|
100
|
|
|
73689
|
if ( $ua =~ m{edge/([\d\.]+)} ) { |
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
649
|
30
|
|
|
|
|
90
|
$tests->{edgehtml} = 1; |
|
650
|
30
|
|
|
|
|
92
|
$self->{engine_version} = $1; |
|
651
|
|
|
|
|
|
|
} |
|
652
|
|
|
|
|
|
|
elsif ( $ua =~ /trident\/([\w\.\d]*)/ ) { |
|
653
|
944
|
|
|
|
|
2356
|
$tests->{trident} = 1; |
|
654
|
944
|
|
|
|
|
2946
|
$self->{engine_version} = $1; |
|
655
|
|
|
|
|
|
|
} |
|
656
|
|
|
|
|
|
|
elsif ( index( $ua, 'gecko' ) != -1 && index( $ua, 'like gecko' ) == -1 ) |
|
657
|
|
|
|
|
|
|
{ |
|
658
|
732
|
|
|
|
|
1889
|
$tests->{gecko} = 1; |
|
659
|
732
|
100
|
|
|
|
4843
|
if ( $ua =~ /\([^)]*rv:([\w.\d]*)/ ) { |
|
660
|
660
|
|
|
|
|
2402
|
$self->{engine_version} = $1; |
|
661
|
|
|
|
|
|
|
} |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
elsif ( $ua =~ m{applewebkit/([\d.\+]+)} && not $tests->{edgehtml} ) { |
|
664
|
2628
|
|
|
|
|
7022
|
$tests->{webkit} = 1; |
|
665
|
2628
|
|
|
|
|
8248
|
$self->{engine_version} = $1; |
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
elsif ( $ua =~ m{presto/([\d.]+)} ) { |
|
668
|
138
|
|
|
|
|
355
|
$tests->{presto} = 1; |
|
669
|
138
|
|
|
|
|
422
|
$self->{engine_version} = $1; |
|
670
|
|
|
|
|
|
|
} |
|
671
|
|
|
|
|
|
|
elsif ( $ua =~ m{khtml/([\d.]+)} ) { |
|
672
|
12
|
|
|
|
|
34
|
$tests->{khtml} = 1; |
|
673
|
12
|
|
|
|
|
37
|
$self->{engine_version} = $1; |
|
674
|
|
|
|
|
|
|
} |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
# Detect browser |
|
677
|
|
|
|
|
|
|
|
|
678
|
7247
|
100
|
100
|
|
|
176967
|
if ( index( $ua, 'galeon' ) != -1 ) { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
# Needs to go above firefox |
|
681
|
|
|
|
|
|
|
|
|
682
|
12
|
|
|
|
|
30
|
$browser = 'galeon'; |
|
683
|
12
|
|
|
|
|
30
|
$browser_tests->{galeon} = 1; |
|
684
|
|
|
|
|
|
|
} |
|
685
|
|
|
|
|
|
|
elsif ( index( $ua, 'epiphany' ) != -1 ) { |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# Needs to go above firefox + mozilla |
|
688
|
|
|
|
|
|
|
|
|
689
|
6
|
|
|
|
|
15
|
$browser = 'epiphany'; |
|
690
|
6
|
|
|
|
|
15
|
$browser_tests->{epiphany} = 1; |
|
691
|
|
|
|
|
|
|
} |
|
692
|
|
|
|
|
|
|
elsif ( $ua =~ m{(?:edg|edga|edgios)/[\d.]+} ) { |
|
693
|
24
|
|
|
|
|
53
|
$browser = 'edge'; |
|
694
|
24
|
|
|
|
|
53
|
$browser_string = 'Edge'; |
|
695
|
|
|
|
|
|
|
|
|
696
|
24
|
|
|
|
|
54
|
$browser_tests->{edge} = 1; |
|
697
|
|
|
|
|
|
|
} |
|
698
|
|
|
|
|
|
|
elsif ( $ua =~ m{edge/[\d.]+} ) { |
|
699
|
30
|
|
|
|
|
57
|
$browser = 'edge'; |
|
700
|
30
|
|
|
|
|
61
|
$browser_string = 'Edge'; |
|
701
|
|
|
|
|
|
|
|
|
702
|
30
|
|
|
|
|
60
|
$browser_tests->{edgelegacy} = 1; |
|
703
|
|
|
|
|
|
|
} |
|
704
|
|
|
|
|
|
|
elsif ( |
|
705
|
|
|
|
|
|
|
$ua =~ m{ |
|
706
|
|
|
|
|
|
|
(firebird|iceweasel|phoenix|namoroka|firefox|fxios) |
|
707
|
|
|
|
|
|
|
\/ |
|
708
|
|
|
|
|
|
|
( [^.]* ) # Major version number is everything before first dot |
|
709
|
|
|
|
|
|
|
\. # The first dot |
|
710
|
|
|
|
|
|
|
( [\d]* ) # Minor version nnumber is digits after first dot |
|
711
|
|
|
|
|
|
|
}xo |
|
712
|
|
|
|
|
|
|
&& index( $ua, 'not firefox' ) == -1 |
|
713
|
|
|
|
|
|
|
) # Hack for Yahoo Slurp |
|
714
|
|
|
|
|
|
|
{ |
|
715
|
|
|
|
|
|
|
# Browser is Firefox, possibly under an alternate name |
|
716
|
|
|
|
|
|
|
|
|
717
|
636
|
|
|
|
|
1461
|
$browser = 'firefox'; |
|
718
|
636
|
100
|
|
|
|
2762
|
$browser_string = ucfirst( $1 eq 'fxios' ? $browser : $1 ); |
|
719
|
|
|
|
|
|
|
|
|
720
|
636
|
|
|
|
|
1694
|
$browser_tests->{$1} = 1; |
|
721
|
636
|
|
|
|
|
1183
|
$browser_tests->{firefox} = 1; |
|
722
|
|
|
|
|
|
|
} |
|
723
|
|
|
|
|
|
|
elsif ( $self->{user_agent} =~ m{ \[ FB (?: AN | _IAB ) }x ) { |
|
724
|
78
|
|
50
|
|
|
471
|
$browser_string = $self->_match( |
|
725
|
|
|
|
|
|
|
[ 'Facebook', '[FB_IAB/FB4A', '[FBAN/FBIOS' ], |
|
726
|
|
|
|
|
|
|
[ 'Facebook Lite', '[FBAN/EMA' ], |
|
727
|
|
|
|
|
|
|
[ |
|
728
|
|
|
|
|
|
|
'Facebook Messenger', '[FB_IAB/Orca-Android', |
|
729
|
|
|
|
|
|
|
'[FB_IAB/MESSENGER', '[FBAN/MessengerForiOS' |
|
730
|
|
|
|
|
|
|
], |
|
731
|
|
|
|
|
|
|
[ |
|
732
|
|
|
|
|
|
|
'Facebook Messenger Lite', '[FBAN/mLite', |
|
733
|
|
|
|
|
|
|
'[FBAN/MessengerLiteForiOS' |
|
734
|
|
|
|
|
|
|
], |
|
735
|
|
|
|
|
|
|
) || 'Meta App'; |
|
736
|
78
|
|
|
|
|
289
|
$browser = lc $browser_string; |
|
737
|
78
|
|
|
|
|
209
|
$browser =~ tr/ /_/; |
|
738
|
78
|
|
|
|
|
172
|
$tests->{meta_app} = 1; |
|
739
|
|
|
|
|
|
|
} |
|
740
|
|
|
|
|
|
|
elsif ( $ua =~ m{opera|opr\/} ) { |
|
741
|
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
# Browser is Opera |
|
743
|
|
|
|
|
|
|
|
|
744
|
264
|
|
|
|
|
600
|
$browser = 'opera'; |
|
745
|
264
|
|
|
|
|
549
|
$browser_tests->{opera} = 1; |
|
746
|
|
|
|
|
|
|
} |
|
747
|
|
|
|
|
|
|
elsif ($tests->{trident} |
|
748
|
|
|
|
|
|
|
|| index( $ua, 'msie' ) != -1 |
|
749
|
|
|
|
|
|
|
|| index( $ua, 'microsoft internet explorer' ) != -1 ) { |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
# Browser is MSIE (possibly AOL branded) |
|
752
|
|
|
|
|
|
|
|
|
753
|
1730
|
|
|
|
|
3635
|
$browser = 'ie'; |
|
754
|
1730
|
|
|
|
|
3532
|
$browser_tests->{ie} = 1; |
|
755
|
|
|
|
|
|
|
|
|
756
|
1730
|
100
|
100
|
|
|
9023
|
if ( index( $ua, 'aol' ) != -1 |
|
757
|
|
|
|
|
|
|
|| index( $ua, 'america online browser' ) != -1 ) { |
|
758
|
42
|
|
|
|
|
71
|
$browser_string = 'AOL Browser'; |
|
759
|
42
|
|
|
|
|
87
|
$browser_tests->{aol} = 1; |
|
760
|
|
|
|
|
|
|
} |
|
761
|
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# Disabled for now -- need to figure out how to deal with version numbers |
|
763
|
|
|
|
|
|
|
#elsif ( index ( $ua, 'acoobrowser' ) != -1 ) { |
|
764
|
|
|
|
|
|
|
# $browser_string = 'Acoo Browser'; |
|
765
|
|
|
|
|
|
|
#} |
|
766
|
|
|
|
|
|
|
#elsif ( index( $ua, 'avant' ) != -1 ) { |
|
767
|
|
|
|
|
|
|
# $browser_string = 'Avant Browser'; |
|
768
|
|
|
|
|
|
|
#} |
|
769
|
|
|
|
|
|
|
#elsif ( index( $ua, 'crazy browser' ) != -1 ) { |
|
770
|
|
|
|
|
|
|
# $browser_string = 'Crazy Browser'; |
|
771
|
|
|
|
|
|
|
#} |
|
772
|
|
|
|
|
|
|
#elsif ( index( $ua, 'deepnet explorer' ) != -1 ) { |
|
773
|
|
|
|
|
|
|
# $browser_string = 'Deepnet Explorer'; |
|
774
|
|
|
|
|
|
|
#} |
|
775
|
|
|
|
|
|
|
#elsif ( index( $ua, 'maxthon' ) != -1 ) { |
|
776
|
|
|
|
|
|
|
# $browser_string = 'Maxthon'; |
|
777
|
|
|
|
|
|
|
#} |
|
778
|
|
|
|
|
|
|
} |
|
779
|
|
|
|
|
|
|
elsif ( 0 < index $self->{user_agent}, ' Instagram ' ) { |
|
780
|
12
|
|
|
|
|
30
|
$browser = 'instagram'; |
|
781
|
12
|
|
|
|
|
31
|
$browser_tests->{$browser} = 1; |
|
782
|
|
|
|
|
|
|
} |
|
783
|
|
|
|
|
|
|
elsif ( index( $ua, 'brave' ) != -1 ) { |
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# Has to go above Chrome, it includes 'like Chrome/' |
|
786
|
|
|
|
|
|
|
|
|
787
|
12
|
|
|
|
|
27
|
$browser = 'brave'; |
|
788
|
12
|
|
|
|
|
31
|
$browser_tests->{$browser} = 1; |
|
789
|
|
|
|
|
|
|
} |
|
790
|
|
|
|
|
|
|
elsif ( index( $ua, 'silk' ) != -1 ) { |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
# Has to go above Chrome, it includes 'like Chrome/' |
|
793
|
|
|
|
|
|
|
|
|
794
|
72
|
|
|
|
|
160
|
$browser = 'silk'; |
|
795
|
72
|
|
|
|
|
188
|
$browser_tests->{$browser} = 1; |
|
796
|
|
|
|
|
|
|
} |
|
797
|
|
|
|
|
|
|
elsif ( index( $ua, 'samsungbrowser' ) != -1 ) { |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
# Has to go above Chrome, it includes 'Chrome/' |
|
800
|
6
|
|
|
|
|
15
|
$browser = 'samsung'; |
|
801
|
6
|
|
|
|
|
15
|
$browser_tests->{$browser} = 1; |
|
802
|
|
|
|
|
|
|
} |
|
803
|
|
|
|
|
|
|
elsif ( index( $ua, 'ucbrowser' ) != -1 ) { |
|
804
|
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
# Has to go above Safari, Mozilla and Chrome |
|
806
|
|
|
|
|
|
|
|
|
807
|
336
|
|
|
|
|
700
|
$browser = 'ucbrowser'; |
|
808
|
336
|
|
|
|
|
756
|
$browser_tests->{$browser} = 1; |
|
809
|
|
|
|
|
|
|
} |
|
810
|
|
|
|
|
|
|
elsif ( 0 < index $self->{user_agent}, ' YaBrowser/' ) { |
|
811
|
36
|
|
|
|
|
81
|
$browser = 'yandex_browser'; |
|
812
|
36
|
|
|
|
|
86
|
$browser_tests->{$browser} = 1; |
|
813
|
|
|
|
|
|
|
} |
|
814
|
|
|
|
|
|
|
elsif (index( $ua, 'chrome/' ) != -1 |
|
815
|
|
|
|
|
|
|
|| index( $ua, 'crios' ) != -1 ) { |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
# Browser is Chrome |
|
818
|
|
|
|
|
|
|
|
|
819
|
1344
|
|
|
|
|
3002
|
$browser = 'chrome'; |
|
820
|
1344
|
|
|
|
|
2690
|
$browser_tests->{chrome} = 1; |
|
821
|
|
|
|
|
|
|
|
|
822
|
1344
|
100
|
|
|
|
4025
|
if ( index( $ua, 'chromium' ) != -1 ) { |
|
823
|
12
|
|
|
|
|
23
|
$browser_string = 'Chromium'; |
|
824
|
|
|
|
|
|
|
} |
|
825
|
|
|
|
|
|
|
} |
|
826
|
|
|
|
|
|
|
elsif (index( $ua, 'blackberry' ) != -1 |
|
827
|
|
|
|
|
|
|
|| index( $ua, 'bb10' ) != -1 |
|
828
|
|
|
|
|
|
|
|| index( $ua, 'rim tablet os' ) != -1 ) { |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
# Has to go above Safari |
|
831
|
42
|
|
|
|
|
102
|
$browser = 'blackberry'; # test gets set during device check |
|
832
|
|
|
|
|
|
|
} |
|
833
|
|
|
|
|
|
|
elsif (( index( $ua, 'safari' ) != -1 ) |
|
834
|
|
|
|
|
|
|
|| ( index( $ua, 'applewebkit' ) != -1 ) ) { |
|
835
|
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
# Browser is Safari |
|
837
|
|
|
|
|
|
|
|
|
838
|
960
|
|
|
|
|
2643
|
$browser_tests->{safari} = 1; |
|
839
|
960
|
|
|
|
|
1868
|
$browser = 'safari'; |
|
840
|
960
|
100
|
100
|
|
|
4415
|
if ( index( $ua, ' mobile safari/' ) != -1 |
|
841
|
|
|
|
|
|
|
|| index( $ua, 'mobilesafari' ) != -1 ) { |
|
842
|
276
|
|
|
|
|
527
|
$browser_string = 'Mobile Safari'; |
|
843
|
276
|
|
|
|
|
533
|
$browser_tests->{mobile_safari} = 1; |
|
844
|
|
|
|
|
|
|
} |
|
845
|
960
|
100
|
|
|
|
3110
|
if ( index( $ua, 'puffin' ) != -1 ) { |
|
846
|
18
|
|
|
|
|
40
|
$browser_string = 'Puffin'; |
|
847
|
|
|
|
|
|
|
} |
|
848
|
|
|
|
|
|
|
} |
|
849
|
|
|
|
|
|
|
elsif ( index( $ua, 'neoplanet' ) != -1 ) { |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
# Browser is Neoplanet |
|
852
|
|
|
|
|
|
|
|
|
853
|
0
|
|
|
|
|
0
|
$browser = 'ie'; |
|
854
|
0
|
|
|
|
|
0
|
$browser_tests->{$browser} = 1; |
|
855
|
0
|
|
|
|
|
0
|
$browser_tests->{neoplanet} = 1; |
|
856
|
0
|
0
|
|
|
|
0
|
$browser_tests->{neoplanet2} = 1 if ( index( $ua, '2.' ) != -1 ); |
|
857
|
|
|
|
|
|
|
} |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
## The following browsers all need to be tested for *before* |
|
860
|
|
|
|
|
|
|
## Mozilla, otherwise we'll think they are Mozilla because they |
|
861
|
|
|
|
|
|
|
## look very much like it. |
|
862
|
|
|
|
|
|
|
elsif ( index( $ua, 'webtv' ) != -1 ) { |
|
863
|
0
|
|
|
|
|
0
|
$browser = 'webtv'; |
|
864
|
0
|
|
|
|
|
0
|
$browser_tests->{$browser} = 1; |
|
865
|
|
|
|
|
|
|
} |
|
866
|
|
|
|
|
|
|
elsif ( index( $ua, 'nintendo 3ds' ) != -1 ) { |
|
867
|
6
|
|
|
|
|
14
|
$browser = 'n3ds'; # Test gets set during device check |
|
868
|
|
|
|
|
|
|
} |
|
869
|
|
|
|
|
|
|
elsif ( index( $ua, 'nintendo dsi' ) != -1 ) { |
|
870
|
0
|
|
|
|
|
0
|
$browser = 'dsi'; # Test gets set during device check |
|
871
|
|
|
|
|
|
|
} |
|
872
|
|
|
|
|
|
|
elsif (index( $ua, 'playstation 3' ) != -1 |
|
873
|
|
|
|
|
|
|
|| index( $ua, 'playstation portable' ) != -1 |
|
874
|
|
|
|
|
|
|
|| index( $ua, 'netfront' ) != -1 ) { |
|
875
|
42
|
|
|
|
|
107
|
$browser = 'netfront'; |
|
876
|
42
|
|
|
|
|
107
|
$browser_tests->{$browser} = 1; |
|
877
|
|
|
|
|
|
|
} |
|
878
|
|
|
|
|
|
|
elsif ( index( $ua, 'browsex' ) != -1 ) { |
|
879
|
6
|
|
|
|
|
16
|
$browser = 'browsex'; |
|
880
|
6
|
|
|
|
|
16
|
$browser_tests->{$browser} = 1; |
|
881
|
|
|
|
|
|
|
} |
|
882
|
|
|
|
|
|
|
elsif ( index( $ua, 'polaris' ) != -1 ) { |
|
883
|
18
|
|
|
|
|
44
|
$browser = 'polaris'; |
|
884
|
18
|
|
|
|
|
48
|
$browser_tests->{$browser} = 1; |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
## At this point if it looks like Mozilla but we haven't found |
|
888
|
|
|
|
|
|
|
## anything else for it to be, it's probably Mozilla. |
|
889
|
|
|
|
|
|
|
elsif (index( $ua, 'mozilla' ) != -1 |
|
890
|
|
|
|
|
|
|
&& index( $ua, 'compatible' ) == -1 ) { |
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
# Browser is a Gecko-powered Netscape (i.e. Mozilla) version |
|
893
|
|
|
|
|
|
|
|
|
894
|
168
|
|
|
|
|
426
|
$browser = 'mozilla'; |
|
895
|
168
|
100
|
100
|
|
|
984
|
if ( index( $ua, 'netscape' ) != -1 |
|
|
|
100
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
|| !$tests->{gecko} ) { |
|
897
|
108
|
|
|
|
|
231
|
$browser = 'netscape'; |
|
898
|
|
|
|
|
|
|
} |
|
899
|
|
|
|
|
|
|
elsif ( index( $ua, 'seamonkey' ) != -1 ) { |
|
900
|
6
|
|
|
|
|
154
|
$browser = 'seamonkey'; |
|
901
|
|
|
|
|
|
|
} |
|
902
|
168
|
|
|
|
|
469
|
$browser_tests->{$browser} = 1; |
|
903
|
168
|
|
|
|
|
316
|
$browser_tests->{netscape} = 1; |
|
904
|
168
|
|
|
|
|
321
|
$browser_tests->{mozilla} = ( $tests->{gecko} ); |
|
905
|
|
|
|
|
|
|
} |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
## Long series of unlikely browsers (ones that don't look like Mozilla) |
|
908
|
|
|
|
|
|
|
elsif ( index( $ua, 'staroffice' ) != -1 ) { |
|
909
|
12
|
|
|
|
|
28
|
$browser = 'staroffice'; |
|
910
|
12
|
|
|
|
|
33
|
$browser_tests->{$browser} = 1; |
|
911
|
|
|
|
|
|
|
} |
|
912
|
|
|
|
|
|
|
elsif ( index( $ua, 'icab' ) != -1 ) { |
|
913
|
6
|
|
|
|
|
14
|
$browser = 'icab'; |
|
914
|
6
|
|
|
|
|
20
|
$browser_tests->{$browser} = 1; |
|
915
|
|
|
|
|
|
|
} |
|
916
|
|
|
|
|
|
|
elsif ( index( $ua, 'lotus-notes' ) != -1 ) { |
|
917
|
6
|
|
|
|
|
16
|
$browser = 'lotusnotes'; |
|
918
|
6
|
|
|
|
|
18
|
$browser_tests->{$browser} = 1; |
|
919
|
|
|
|
|
|
|
} |
|
920
|
|
|
|
|
|
|
elsif ( index( $ua, 'konqueror' ) != -1 ) { |
|
921
|
24
|
|
|
|
|
60
|
$browser = 'konqueror'; |
|
922
|
24
|
|
|
|
|
59
|
$browser_tests->{$browser} = 1; |
|
923
|
|
|
|
|
|
|
} |
|
924
|
|
|
|
|
|
|
elsif ( index( $ua, 'lynx' ) != -1 ) { |
|
925
|
6
|
|
|
|
|
15
|
$browser = 'lynx'; |
|
926
|
6
|
|
|
|
|
17
|
$browser_tests->{$browser} = 1; |
|
927
|
|
|
|
|
|
|
} |
|
928
|
|
|
|
|
|
|
elsif ( index( $ua, 'elinks' ) != -1 ) { |
|
929
|
6
|
|
|
|
|
15
|
$browser = 'elinks'; |
|
930
|
6
|
|
|
|
|
15
|
$browser_tests->{$browser} = 1; |
|
931
|
|
|
|
|
|
|
} |
|
932
|
|
|
|
|
|
|
elsif ( index( $ua, 'links' ) != -1 ) { |
|
933
|
12
|
|
|
|
|
26
|
$browser = 'links'; |
|
934
|
12
|
|
|
|
|
31
|
$browser_tests->{$browser} = 1; |
|
935
|
|
|
|
|
|
|
} |
|
936
|
|
|
|
|
|
|
elsif ( index( $ua, 'mosaic' ) != -1 ) { |
|
937
|
0
|
|
|
|
|
0
|
$browser = 'mosaic'; |
|
938
|
0
|
|
|
|
|
0
|
$browser_tests->{$browser} = 1; |
|
939
|
|
|
|
|
|
|
} |
|
940
|
|
|
|
|
|
|
elsif ( index( $ua, 'emacs' ) != -1 ) { |
|
941
|
6
|
|
|
|
|
14
|
$browser = 'emacs'; |
|
942
|
6
|
|
|
|
|
15
|
$browser_tests->{$browser} = 1; |
|
943
|
|
|
|
|
|
|
} |
|
944
|
|
|
|
|
|
|
elsif ( index( $ua, 'obigo' ) != -1 ) { |
|
945
|
30
|
|
|
|
|
67
|
$browser = 'obigo'; |
|
946
|
30
|
|
|
|
|
87
|
$browser_tests->{$browser} = 1; |
|
947
|
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
elsif ( index( $ua, 'teleca' ) != -1 ) { |
|
949
|
54
|
|
|
|
|
125
|
$browser = 'obigo'; |
|
950
|
54
|
|
|
|
|
82
|
$browser_string = 'Teleca'; |
|
951
|
54
|
|
|
|
|
137
|
$browser_tests->{$browser} = 1; |
|
952
|
|
|
|
|
|
|
} |
|
953
|
|
|
|
|
|
|
elsif ( index( $ua, 'libcurl' ) != -1 || $ua =~ /^curl/ ) { |
|
954
|
36
|
|
|
|
|
88
|
$browser = 'curl'; # Test gets set during robot check |
|
955
|
|
|
|
|
|
|
} |
|
956
|
|
|
|
|
|
|
elsif ( index( $ua, 'puf/' ) != -1 ) { |
|
957
|
6
|
|
|
|
|
16
|
$browser = 'puf'; # Test gets set during robot check |
|
958
|
|
|
|
|
|
|
} |
|
959
|
|
|
|
|
|
|
elsif ( index( $ua, 'applecoremedia/' ) != -1 ) { |
|
960
|
6
|
|
|
|
|
127
|
$browser = 'applecoremedia'; |
|
961
|
6
|
|
|
|
|
23
|
$browser_tests->{$browser} = 1; |
|
962
|
|
|
|
|
|
|
} |
|
963
|
|
|
|
|
|
|
elsif ( index( $ua, 'androiddownloadmanager' ) != -1 ) { |
|
964
|
6
|
|
|
|
|
17
|
$browser = 'adm'; |
|
965
|
6
|
|
|
|
|
16
|
$browser_tests->{$browser} = 1; |
|
966
|
|
|
|
|
|
|
} |
|
967
|
|
|
|
|
|
|
elsif ( index( $ua, 'dalvik' ) != -1 ) { |
|
968
|
12
|
|
|
|
|
28
|
$browser = 'dalvik'; |
|
969
|
12
|
|
|
|
|
28
|
$browser_tests->{$browser} = 1; |
|
970
|
|
|
|
|
|
|
} |
|
971
|
|
|
|
|
|
|
elsif ( index( $ua, 'apple-pubsub' ) != -1 ) { |
|
972
|
6
|
|
|
|
|
32
|
$browser = 'pubsub'; |
|
973
|
6
|
|
|
|
|
23
|
$browser_tests->{$browser} = 1; |
|
974
|
|
|
|
|
|
|
} |
|
975
|
|
|
|
|
|
|
elsif ( index( $ua, 'imagesearcherpro' ) != -1 ) { |
|
976
|
6
|
|
|
|
|
14
|
$browser = 'imagesearcherpro'; |
|
977
|
6
|
|
|
|
|
14
|
$browser_tests->{$browser} = 1; |
|
978
|
|
|
|
|
|
|
} |
|
979
|
|
|
|
|
|
|
|
|
980
|
7247
|
|
|
|
|
15125
|
$self->{browser} = $browser; |
|
981
|
7247
|
100
|
100
|
|
|
31741
|
$self->{browser_string} = $browser_string || $BROWSER_NAMES{$browser} |
|
982
|
|
|
|
|
|
|
if defined $browser; |
|
983
|
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
# Other random tests |
|
985
|
|
|
|
|
|
|
|
|
986
|
7247
|
100
|
|
|
|
18789
|
$tests->{x11} = 1 if index( $ua, 'x11' ) != -1; |
|
987
|
7247
|
100
|
|
|
|
17998
|
$tests->{dotnet} = 1 if index( $ua, '.net clr' ) != -1; |
|
988
|
|
|
|
|
|
|
|
|
989
|
7247
|
100
|
|
|
|
15813
|
if ( index( $ua, 'realplayer' ) != -1 ) { |
|
990
|
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
# Hack for Realplayer -- fix the version and 'real' browser |
|
992
|
|
|
|
|
|
|
|
|
993
|
18
|
|
|
|
|
61
|
$self->_init_version; # Set appropriate tests for whatever the 'real' |
|
994
|
|
|
|
|
|
|
# browser is. |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
# Now set the browser to Realplayer. |
|
997
|
18
|
|
|
|
|
35
|
$self->{browser} = 'realplayer'; |
|
998
|
18
|
|
|
|
|
30
|
$self->{browser_string} = 'RealPlayer'; |
|
999
|
18
|
|
|
|
|
35
|
$browser_tests->{realplayer} = 1; |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
# Now override the version with the Realplayer version (but leave |
|
1002
|
|
|
|
|
|
|
# alone the tests we already set, which might have been based on the |
|
1003
|
|
|
|
|
|
|
# 'real' browser's version). |
|
1004
|
18
|
|
|
|
|
37
|
$self->{realplayer_version} = undef; |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
18
|
100
|
|
|
|
96
|
if ( $ua =~ /realplayer\/([\d+\.]+)/ ) { |
|
|
|
50
|
|
|
|
|
|
|
1007
|
12
|
|
|
|
|
35
|
$self->{realplayer_version} = $1; |
|
1008
|
|
|
|
|
|
|
( $self->{major}, $self->{minor} ) |
|
1009
|
12
|
|
|
|
|
44
|
= split( /\./, $self->{realplayer_version} ); |
|
1010
|
12
|
50
|
|
|
|
46
|
$self->{minor} = ".$self->{minor}" if defined $self->{minor}; |
|
1011
|
|
|
|
|
|
|
} |
|
1012
|
|
|
|
|
|
|
elsif ( $ua =~ /realplayer\s(\w+)/ ) { |
|
1013
|
6
|
|
|
|
|
124
|
$self->{realplayer_version} = $1; |
|
1014
|
|
|
|
|
|
|
} |
|
1015
|
|
|
|
|
|
|
} |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
7247
|
100
|
|
|
|
18507
|
if ( index( $ua, '(r1 ' ) != -1 ) { |
|
1018
|
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
# Realplayer plugin -- don't override browser but do set property |
|
1020
|
18
|
|
|
|
|
41
|
$browser_tests->{realplayer} = 1; |
|
1021
|
|
|
|
|
|
|
} |
|
1022
|
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
# Details: https://developer.chrome.com/multidevice/user-agent#webview_user_agent |
|
1024
|
7247
|
100
|
100
|
|
|
16541
|
if ( ( $self->android && index( $ua, '; wv)' ) > 0 ) |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
|| ( $self->chrome && $self->android && $self->browser_major >= 30 ) ) |
|
1026
|
|
|
|
|
|
|
{ |
|
1027
|
480
|
|
|
|
|
1259
|
$tests->{webview} = 1; |
|
1028
|
|
|
|
|
|
|
} |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
} |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
# match strings or regexps against user_agent |
|
1033
|
|
|
|
|
|
|
# pass specs as list of [ 'thing to return', …tests… ] |
|
1034
|
|
|
|
|
|
|
sub _match { |
|
1035
|
78
|
|
|
78
|
|
232
|
my ( $self, @specs ) = @_; |
|
1036
|
78
|
|
|
|
|
188
|
for my $spec (@specs) { |
|
1037
|
156
|
|
|
|
|
241
|
my ( $ret, @tests ) = @{$spec}; |
|
|
156
|
|
|
|
|
385
|
|
|
1038
|
156
|
|
|
|
|
338
|
for my $m (@tests) { |
|
1039
|
264
|
100
|
66
|
|
|
1312
|
return $ret if !ref $m && 0 < index $self->{user_agent}, $m; |
|
1040
|
186
|
50
|
33
|
|
|
519
|
return $ret if 'Regexp' eq ref $m && $self->{user_agent} =~ $m; |
|
1041
|
|
|
|
|
|
|
} |
|
1042
|
|
|
|
|
|
|
} |
|
1043
|
|
|
|
|
|
|
} |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
# Any of these fragments within a user-agent generally indicates it's |
|
1046
|
|
|
|
|
|
|
# a robot. |
|
1047
|
|
|
|
|
|
|
my @ROBOT_FRAGMENTS = qw( |
|
1048
|
|
|
|
|
|
|
agent |
|
1049
|
|
|
|
|
|
|
analy |
|
1050
|
|
|
|
|
|
|
appender |
|
1051
|
|
|
|
|
|
|
babya |
|
1052
|
|
|
|
|
|
|
checker |
|
1053
|
|
|
|
|
|
|
bot |
|
1054
|
|
|
|
|
|
|
copy |
|
1055
|
|
|
|
|
|
|
crawl |
|
1056
|
|
|
|
|
|
|
explorador |
|
1057
|
|
|
|
|
|
|
fetch |
|
1058
|
|
|
|
|
|
|
find |
|
1059
|
|
|
|
|
|
|
ia_archive |
|
1060
|
|
|
|
|
|
|
index |
|
1061
|
|
|
|
|
|
|
netcraft |
|
1062
|
|
|
|
|
|
|
reap |
|
1063
|
|
|
|
|
|
|
resolver |
|
1064
|
|
|
|
|
|
|
sleuth |
|
1065
|
|
|
|
|
|
|
scan |
|
1066
|
|
|
|
|
|
|
service |
|
1067
|
|
|
|
|
|
|
spider |
|
1068
|
|
|
|
|
|
|
thumbtack-thunderdome |
|
1069
|
|
|
|
|
|
|
tiscali |
|
1070
|
|
|
|
|
|
|
validator |
|
1071
|
|
|
|
|
|
|
verif |
|
1072
|
|
|
|
|
|
|
webcapture |
|
1073
|
|
|
|
|
|
|
worm |
|
1074
|
|
|
|
|
|
|
zyborg |
|
1075
|
|
|
|
|
|
|
); |
|
1076
|
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
my %ROBOT_FRAGMENT_EXCEPTIONS = ( |
|
1078
|
|
|
|
|
|
|
bot => ['cubot'], |
|
1079
|
|
|
|
|
|
|
); |
|
1080
|
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
sub _init_robots { |
|
1082
|
8787
|
|
|
8787
|
|
15112
|
my $self = shift; |
|
1083
|
|
|
|
|
|
|
|
|
1084
|
8787
|
|
|
|
|
21848
|
my $ua = lc $self->{user_agent}; |
|
1085
|
8787
|
|
|
|
|
15032
|
my $tests = $self->{tests}; |
|
1086
|
8787
|
|
|
|
|
13628
|
my $browser_tests = $self->{browser_tests}; |
|
1087
|
|
|
|
|
|
|
|
|
1088
|
8787
|
|
|
|
|
23201
|
my $robot_tests = $self->{robot_tests} = {}; |
|
1089
|
8787
|
|
|
|
|
21915
|
my $id; |
|
1090
|
|
|
|
|
|
|
my $r; |
|
1091
|
|
|
|
|
|
|
|
|
1092
|
8787
|
|
|
|
|
0
|
my $robot_fragment; # The text that indicates it's a robot (we'll |
|
1093
|
|
|
|
|
|
|
# use this later to detect robot version, and |
|
1094
|
|
|
|
|
|
|
# maybe robot_string) |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
8787
|
100
|
66
|
|
|
347145
|
if ( index( $ua, 'libwww-perl' ) != -1 || index( $ua, 'lwp-' ) != -1 ) { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1097
|
18
|
|
|
|
|
38
|
$r = 'lwp'; |
|
1098
|
18
|
|
|
|
|
44
|
$robot_tests->{lib} = 1; |
|
1099
|
18
|
50
|
|
|
|
58
|
$robot_fragment = ( |
|
1100
|
|
|
|
|
|
|
( index( $ua, 'libwww-perl' ) != -1 ) ? 'libwww-perl' : 'lwp-' ); |
|
1101
|
|
|
|
|
|
|
} |
|
1102
|
|
|
|
|
|
|
elsif ( index( $ua, 'slurp' ) != -1 ) { |
|
1103
|
12
|
|
|
|
|
23
|
$r = 'slurp'; |
|
1104
|
12
|
|
|
|
|
28
|
$robot_tests->{yahoo} = 1; |
|
1105
|
|
|
|
|
|
|
} |
|
1106
|
|
|
|
|
|
|
elsif (index( $ua, 'yahoo' ) != -1 |
|
1107
|
|
|
|
|
|
|
&& index( $ua, 'jp.co.yahoo' ) == -1 ) { |
|
1108
|
6
|
|
|
|
|
15
|
$r = 'yahoo'; |
|
1109
|
|
|
|
|
|
|
} |
|
1110
|
|
|
|
|
|
|
elsif ( index( $ua, 'msnbot-mobile' ) != -1 ) { |
|
1111
|
6
|
|
|
|
|
16
|
$r = 'msnmobile'; |
|
1112
|
6
|
|
|
|
|
16
|
$robot_tests->{msn} = 1; |
|
1113
|
6
|
|
|
|
|
9
|
$robot_fragment = 'msnbot'; |
|
1114
|
|
|
|
|
|
|
} |
|
1115
|
|
|
|
|
|
|
elsif ( index( $ua, 'bingbot-mobile' ) != -1 ) { |
|
1116
|
0
|
|
|
|
|
0
|
$r = 'bingbot'; |
|
1117
|
0
|
|
|
|
|
0
|
$robot_tests->{bingbot} = 1; |
|
1118
|
0
|
|
|
|
|
0
|
$robot_fragment = 'bingbot'; |
|
1119
|
|
|
|
|
|
|
} |
|
1120
|
|
|
|
|
|
|
elsif ( index( $ua, 'msnbot' ) != -1 ) { |
|
1121
|
6
|
|
|
|
|
11
|
$r = 'msn'; |
|
1122
|
6
|
|
|
|
|
12
|
$robot_fragment = 'msnbot'; |
|
1123
|
|
|
|
|
|
|
} |
|
1124
|
|
|
|
|
|
|
elsif (index( $ua, 'binglocalsearch' ) != -1 |
|
1125
|
|
|
|
|
|
|
|| index( $ua, 'bingbot' ) != -1 |
|
1126
|
|
|
|
|
|
|
|| index( $ua, 'bingpreview' ) != -1 ) { |
|
1127
|
30
|
|
|
|
|
61
|
$r = 'bingbot'; |
|
1128
|
30
|
|
|
|
|
74
|
$robot_tests->{bingbot} = 1; |
|
1129
|
30
|
|
|
|
|
55
|
$robot_fragment = 'bingbot'; |
|
1130
|
|
|
|
|
|
|
} |
|
1131
|
|
|
|
|
|
|
elsif ( index( $ua, 'microsoft office existence discovery' ) != -1 ) { |
|
1132
|
6
|
|
|
|
|
13
|
$r = 'msoffice'; |
|
1133
|
6
|
|
|
|
|
11
|
$robot_fragment = 'office'; |
|
1134
|
|
|
|
|
|
|
} |
|
1135
|
|
|
|
|
|
|
elsif ( index( $ua, 'ahrefsbot' ) != -1 ) { |
|
1136
|
6
|
|
|
|
|
14
|
$r = 'ahrefs'; |
|
1137
|
|
|
|
|
|
|
} |
|
1138
|
|
|
|
|
|
|
elsif ( index( $ua, 'altavista' ) != -1 ) { |
|
1139
|
0
|
|
|
|
|
0
|
$r = 'altavista'; |
|
1140
|
|
|
|
|
|
|
} |
|
1141
|
|
|
|
|
|
|
elsif ( index( $ua, 'apache-httpclient' ) != -1 ) { |
|
1142
|
12
|
|
|
|
|
26
|
$r = 'apache'; |
|
1143
|
|
|
|
|
|
|
} |
|
1144
|
|
|
|
|
|
|
elsif ( $ua =~ m{\( *\) *\{ *\: *\; *} ) { |
|
1145
|
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
# Shellcode for spawning a process, i.e. (){:;} with some kind of whitespace interleaved |
|
1147
|
6
|
|
|
|
|
23
|
$r = 'malware'; |
|
1148
|
|
|
|
|
|
|
} |
|
1149
|
|
|
|
|
|
|
elsif ( index( $ua, 'ask jeeves/teoma' ) != -1 ) { |
|
1150
|
0
|
|
|
|
|
0
|
$r = 'askjeeves'; |
|
1151
|
0
|
|
|
|
|
0
|
$robot_fragment = 'teoma'; |
|
1152
|
|
|
|
|
|
|
} |
|
1153
|
|
|
|
|
|
|
elsif ( index( $ua, 'baiduspider' ) != -1 ) { |
|
1154
|
18
|
|
|
|
|
48
|
$r = 'baidu'; |
|
1155
|
|
|
|
|
|
|
} |
|
1156
|
|
|
|
|
|
|
elsif ( index( $ua, 'libcurl' ) != -1 || $ua =~ /^curl/ ) { |
|
1157
|
36
|
|
|
|
|
73
|
$r = 'curl'; |
|
1158
|
36
|
|
|
|
|
90
|
$robot_tests->{lib} = 1; |
|
1159
|
|
|
|
|
|
|
} |
|
1160
|
|
|
|
|
|
|
elsif ( index( $ua, 'facebookexternalhit' ) != -1 ) { |
|
1161
|
6
|
|
|
|
|
14
|
$r = 'facebook'; |
|
1162
|
|
|
|
|
|
|
} |
|
1163
|
|
|
|
|
|
|
elsif ( index( $ua, 'getright' ) != -1 ) { |
|
1164
|
6
|
|
|
|
|
12
|
$r = 'getright'; |
|
1165
|
|
|
|
|
|
|
} |
|
1166
|
|
|
|
|
|
|
elsif ( index( $ua, 'adsbot-google' ) != -1 ) { |
|
1167
|
12
|
|
|
|
|
26
|
$r = 'googleadsbot'; |
|
1168
|
12
|
|
|
|
|
28
|
$robot_tests->{google} = 1; |
|
1169
|
12
|
|
|
|
|
22
|
$robot_fragment = 'adsbot-google'; |
|
1170
|
|
|
|
|
|
|
} |
|
1171
|
|
|
|
|
|
|
elsif ( index( $ua, 'mediapartners-google' ) != -1 ) { |
|
1172
|
6
|
|
|
|
|
12
|
$r = 'googleadsense'; |
|
1173
|
6
|
|
|
|
|
17
|
$robot_tests->{google} = 1; |
|
1174
|
6
|
|
|
|
|
11
|
$robot_fragment = 'mediapartners-google'; |
|
1175
|
|
|
|
|
|
|
} |
|
1176
|
|
|
|
|
|
|
elsif ( index( $ua, 'google favicon' ) != -1 ) { |
|
1177
|
6
|
|
|
|
|
18
|
$r = 'googlefavicon'; |
|
1178
|
6
|
|
|
|
|
15
|
$robot_tests->{google} = 1; |
|
1179
|
6
|
|
|
|
|
13
|
$robot_fragment = 'favicon'; |
|
1180
|
|
|
|
|
|
|
} |
|
1181
|
|
|
|
|
|
|
elsif ( index( $ua, 'googlebot-image' ) != -1 ) { |
|
1182
|
6
|
|
|
|
|
14
|
$r = 'googlebotimage'; |
|
1183
|
6
|
|
|
|
|
14
|
$robot_tests->{google} = 1; |
|
1184
|
6
|
|
|
|
|
12
|
$robot_fragment = 'googlebot-image'; |
|
1185
|
|
|
|
|
|
|
} |
|
1186
|
|
|
|
|
|
|
elsif ( index( $ua, 'googlebot-news' ) != -1 ) { |
|
1187
|
6
|
|
|
|
|
12
|
$r = 'googlebotnews'; |
|
1188
|
6
|
|
|
|
|
16
|
$robot_tests->{google} = 1; |
|
1189
|
6
|
|
|
|
|
12
|
$robot_fragment = 'googlebot-news'; |
|
1190
|
|
|
|
|
|
|
} |
|
1191
|
|
|
|
|
|
|
elsif ( index( $ua, 'googlebot-video' ) != -1 ) { |
|
1192
|
6
|
|
|
|
|
17
|
$r = 'googlebotvideo'; |
|
1193
|
6
|
|
|
|
|
15
|
$robot_tests->{google} = 1; |
|
1194
|
6
|
|
|
|
|
14
|
$robot_fragment = 'googlebot-video'; |
|
1195
|
|
|
|
|
|
|
} |
|
1196
|
|
|
|
|
|
|
elsif ( index( $ua, 'googlebot-mobile' ) != -1 ) { |
|
1197
|
18
|
|
|
|
|
47
|
$r = 'googlemobile'; |
|
1198
|
18
|
|
|
|
|
48
|
$robot_tests->{google} = 1; |
|
1199
|
18
|
|
|
|
|
43
|
$robot_fragment = 'googlebot-mobile'; |
|
1200
|
|
|
|
|
|
|
} |
|
1201
|
|
|
|
|
|
|
elsif ( index( $ua, 'googlebot' ) != -1 ) { |
|
1202
|
36
|
|
|
|
|
85
|
$r = 'google'; |
|
1203
|
|
|
|
|
|
|
} |
|
1204
|
|
|
|
|
|
|
elsif ( $ua =~ m{go.*package http} ) { |
|
1205
|
6
|
|
|
|
|
14
|
$r = 'golib'; |
|
1206
|
6
|
|
|
|
|
17
|
$robot_tests->{lib} = 1; |
|
1207
|
6
|
|
|
|
|
14
|
$robot_fragment = 'package'; |
|
1208
|
|
|
|
|
|
|
} |
|
1209
|
|
|
|
|
|
|
elsif ( $ua =~ m{^http_request} ) { |
|
1210
|
6
|
|
|
|
|
16
|
$r = 'phplib'; |
|
1211
|
6
|
|
|
|
|
17
|
$robot_tests->{lib} = 1; |
|
1212
|
6
|
|
|
|
|
11
|
$robot_fragment = 'http_request'; |
|
1213
|
|
|
|
|
|
|
} |
|
1214
|
|
|
|
|
|
|
elsif ( $ua =~ m{^http_request} ) { |
|
1215
|
0
|
|
|
|
|
0
|
$r = 'phplib'; |
|
1216
|
0
|
|
|
|
|
0
|
$robot_tests->{lib} = 1; |
|
1217
|
|
|
|
|
|
|
} |
|
1218
|
|
|
|
|
|
|
elsif ( index( $ua, 'indy library' ) != -1 ) { |
|
1219
|
6
|
|
|
|
|
9
|
$r = 'indy'; |
|
1220
|
6
|
|
|
|
|
18
|
$robot_tests->{lib} = 1; |
|
1221
|
|
|
|
|
|
|
} |
|
1222
|
|
|
|
|
|
|
elsif ( index( $ua, 'infoseek' ) != -1 ) { |
|
1223
|
0
|
|
|
|
|
0
|
$r = 'infoseek'; |
|
1224
|
|
|
|
|
|
|
} |
|
1225
|
|
|
|
|
|
|
elsif ( index( $ua, 'ips-agent' ) != -1 ) { |
|
1226
|
6
|
|
|
|
|
14
|
$r = 'ipsagent'; |
|
1227
|
6
|
|
|
|
|
12
|
$robot_fragment = 'ips-agent'; |
|
1228
|
|
|
|
|
|
|
} |
|
1229
|
|
|
|
|
|
|
elsif ( index( $ua, 'lecodechecker' ) != -1 ) { |
|
1230
|
0
|
|
|
|
|
0
|
$r = 'linkexchange'; |
|
1231
|
0
|
|
|
|
|
0
|
$robot_fragment = 'lecodechecker'; |
|
1232
|
|
|
|
|
|
|
} |
|
1233
|
|
|
|
|
|
|
elsif ( index( $ua, 'linkchecker' ) != -1 ) { |
|
1234
|
12
|
|
|
|
|
30
|
$r = 'linkchecker'; |
|
1235
|
|
|
|
|
|
|
} |
|
1236
|
|
|
|
|
|
|
elsif ( index( $ua, 'lycos' ) != -1 ) { |
|
1237
|
0
|
|
|
|
|
0
|
$r = 'lycos'; |
|
1238
|
|
|
|
|
|
|
} |
|
1239
|
|
|
|
|
|
|
elsif ( index( $ua, 'mechanize' ) != -1 ) { |
|
1240
|
12
|
|
|
|
|
27
|
$r = 'rubylib'; |
|
1241
|
12
|
|
|
|
|
29
|
$robot_tests->{lib} = 1; |
|
1242
|
12
|
|
|
|
|
22
|
$robot_fragment = 'mechanize'; |
|
1243
|
|
|
|
|
|
|
} |
|
1244
|
|
|
|
|
|
|
elsif ( index( $ua, 'mj12bot/' ) != -1 ) { |
|
1245
|
6
|
|
|
|
|
18
|
$r = 'mj12bot'; |
|
1246
|
|
|
|
|
|
|
} |
|
1247
|
|
|
|
|
|
|
elsif ( index( $ua, 'nutch' ) != -1 ) { |
|
1248
|
18
|
|
|
|
|
40
|
$r = 'nutch'; |
|
1249
|
|
|
|
|
|
|
} |
|
1250
|
|
|
|
|
|
|
elsif ( index( $ua, 'puf/' ) != -1 ) { |
|
1251
|
6
|
|
|
|
|
16
|
$r = 'puf'; |
|
1252
|
6
|
|
|
|
|
16
|
$robot_tests->{lib} = 1; |
|
1253
|
|
|
|
|
|
|
} |
|
1254
|
|
|
|
|
|
|
elsif ( index( $ua, 'scooter' ) != -1 ) { |
|
1255
|
0
|
|
|
|
|
0
|
$r = 'scooter'; |
|
1256
|
|
|
|
|
|
|
} |
|
1257
|
|
|
|
|
|
|
elsif ( index( $ua, 'special_archiver' ) != -1 ) { |
|
1258
|
6
|
|
|
|
|
16
|
$r = 'specialarchiver'; |
|
1259
|
6
|
|
|
|
|
15
|
$robot_fragment = 'special_archiver'; |
|
1260
|
|
|
|
|
|
|
} |
|
1261
|
|
|
|
|
|
|
elsif ( index( $ua, 'wget' ) == 0 ) { |
|
1262
|
12
|
|
|
|
|
30
|
$r = 'wget'; |
|
1263
|
|
|
|
|
|
|
} |
|
1264
|
|
|
|
|
|
|
elsif ( index( $ua, 'yandexbot' ) != -1 ) { |
|
1265
|
6
|
|
|
|
|
14
|
$r = 'yandex'; |
|
1266
|
|
|
|
|
|
|
} |
|
1267
|
|
|
|
|
|
|
elsif ( index( $ua, 'yandeximages' ) != -1 ) { |
|
1268
|
6
|
|
|
|
|
16
|
$r = 'yandeximages'; |
|
1269
|
|
|
|
|
|
|
} |
|
1270
|
|
|
|
|
|
|
elsif ( index( $ua, 'headlesschrome' ) != -1 ) { |
|
1271
|
6
|
|
|
|
|
28
|
$r = 'headlesschrome'; |
|
1272
|
|
|
|
|
|
|
} |
|
1273
|
|
|
|
|
|
|
elsif ( $ua =~ m{^java} && !$self->{browser} ) { |
|
1274
|
42
|
|
|
|
|
99
|
$r = 'java'; |
|
1275
|
42
|
|
|
|
|
92
|
$robot_tests->{lib} = 1; |
|
1276
|
|
|
|
|
|
|
} |
|
1277
|
|
|
|
|
|
|
elsif ( index( $ua, 'jdk' ) != -1 ) { |
|
1278
|
0
|
|
|
|
|
0
|
$r = 'java'; |
|
1279
|
0
|
|
|
|
|
0
|
$robot_tests->{lib} = 1; |
|
1280
|
0
|
|
|
|
|
0
|
$robot_fragment = 'jdk'; |
|
1281
|
|
|
|
|
|
|
} |
|
1282
|
|
|
|
|
|
|
elsif ( index( $ua, 'jakarta commons-httpclient' ) != -1 ) { |
|
1283
|
6
|
|
|
|
|
16
|
$r = 'java'; |
|
1284
|
6
|
|
|
|
|
15
|
$robot_tests->{lib} = 1; |
|
1285
|
6
|
|
|
|
|
12
|
$robot_fragment = 'jakarta'; |
|
1286
|
|
|
|
|
|
|
} |
|
1287
|
|
|
|
|
|
|
elsif ( index( $ua, 'google-http-java-client' ) != -1 ) { |
|
1288
|
6
|
|
|
|
|
16
|
$r = 'java'; |
|
1289
|
6
|
|
|
|
|
16
|
$robot_tests->{lib} = 1; |
|
1290
|
6
|
|
|
|
|
14
|
$robot_fragment = 'google'; |
|
1291
|
|
|
|
|
|
|
} |
|
1292
|
|
|
|
|
|
|
elsif ( index( $ua, 'researchscan.comsys.rwth-aachen.de' ) != -1 ) { |
|
1293
|
6
|
|
|
|
|
16
|
$r = 'researchscan'; |
|
1294
|
|
|
|
|
|
|
} |
|
1295
|
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
# These @ROBOT_TESTS were added in 3.15. Some of them may need more |
|
1297
|
|
|
|
|
|
|
# individualized treatment, but get them identified as bots for now. |
|
1298
|
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
# XXX |
|
1300
|
|
|
|
|
|
|
else { |
|
1301
|
|
|
|
|
|
|
TEST: |
|
1302
|
8343
|
|
|
|
|
22169
|
for my $set (@ROBOT_TESTS) { |
|
1303
|
249498
|
|
|
|
|
388671
|
my $match = lc $set->[0]; |
|
1304
|
|
|
|
|
|
|
|
|
1305
|
249498
|
100
|
|
|
|
561868
|
if ( index( $ua, lc($match) ) != -1 ) { |
|
1306
|
48
|
|
|
|
|
114
|
$id = $set->[1]; |
|
1307
|
48
|
|
|
|
|
92
|
$r = $id; |
|
1308
|
48
|
|
|
|
|
99
|
$robot_fragment = lc $match; |
|
1309
|
48
|
|
|
|
|
135
|
last TEST; |
|
1310
|
|
|
|
|
|
|
} |
|
1311
|
|
|
|
|
|
|
} |
|
1312
|
|
|
|
|
|
|
} |
|
1313
|
|
|
|
|
|
|
|
|
1314
|
8787
|
100
|
100
|
|
|
46799
|
if ( $browser_tests->{applecoremedia} |
|
|
|
|
100
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
|| $browser_tests->{dalvik} |
|
1316
|
|
|
|
|
|
|
|| $browser_tests->{adm} ) { |
|
1317
|
28
|
|
|
|
|
68
|
$robot_tests->{lib} = 1; |
|
1318
|
|
|
|
|
|
|
} |
|
1319
|
|
|
|
|
|
|
|
|
1320
|
8787
|
100
|
|
|
|
52116
|
if ($r) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
# Got a named robot |
|
1323
|
492
|
|
|
|
|
1026
|
$robot_tests->{$r} = 1; |
|
1324
|
492
|
100
|
|
|
|
1195
|
if ( !$id ) { |
|
1325
|
444
|
|
|
|
|
1096
|
$id = $ROBOT_IDS{$r}; |
|
1326
|
|
|
|
|
|
|
} |
|
1327
|
|
|
|
|
|
|
|
|
1328
|
492
|
50
|
|
|
|
1217
|
if ( !exists $robot_tests->{robot_id} ) { |
|
1329
|
492
|
|
|
|
|
965
|
$robot_tests->{robot_id} = $id; |
|
1330
|
|
|
|
|
|
|
} |
|
1331
|
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
# This isn't all keyed on ids (yet) |
|
1333
|
492
|
|
33
|
|
|
1913
|
$self->{robot_string} = $ROBOT_NAMES{$id} || $ROBOT_NAMES{$r}; |
|
1334
|
492
|
|
|
|
|
967
|
$robot_tests->{robot} = $r; |
|
1335
|
492
|
100
|
|
|
|
1123
|
$robot_fragment = $r if !defined $robot_fragment; |
|
1336
|
|
|
|
|
|
|
} |
|
1337
|
|
|
|
|
|
|
elsif ( $ua =~ /seek (?! mo (?: toolbar )? \s+ \d+\.\d+ )/x ) { |
|
1338
|
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
# Store the fragment for later, to determine full name |
|
1340
|
0
|
|
|
|
|
0
|
$robot_fragment = 'seek'; |
|
1341
|
0
|
|
|
|
|
0
|
$robot_tests->{robot} = 'unknown'; |
|
1342
|
|
|
|
|
|
|
} |
|
1343
|
|
|
|
|
|
|
elsif ( $ua =~ /search (?! [\w\s]* toolbar \b | bar \b | erpro \b )/x ) { |
|
1344
|
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
# Store the fragment for later, to determine full name |
|
1346
|
42
|
|
|
|
|
103
|
$robot_fragment = 'search'; |
|
1347
|
42
|
|
|
|
|
126
|
$robot_tests->{robot} = 'unknown'; |
|
1348
|
|
|
|
|
|
|
} |
|
1349
|
|
|
|
|
|
|
elsif ( $self->{user_agent} =~ /([\w \/\.\-]+)[ \;\(\)]*\+https?\:/i ) { |
|
1350
|
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
# Something followed by +http |
|
1352
|
246
|
|
|
|
|
1122
|
$self->{robot_string} = $1; |
|
1353
|
246
|
|
|
|
|
2575
|
$self->{robot_string} =~ s/^ *(.+?)[ \;\(\)]*?( *\/[\d\.]+ *)?$/$1/; |
|
1354
|
246
|
|
|
|
|
701
|
$robot_fragment = $1; |
|
1355
|
246
|
|
|
|
|
666
|
$robot_tests->{robot} = 'unknown'; |
|
1356
|
|
|
|
|
|
|
} |
|
1357
|
|
|
|
|
|
|
else { |
|
1358
|
|
|
|
|
|
|
# See if we have a simple fragment |
|
1359
|
|
|
|
|
|
|
FRAGMENT: |
|
1360
|
8007
|
|
|
|
|
15713
|
for my $fragment (@ROBOT_FRAGMENTS) { |
|
1361
|
211078
|
100
|
|
|
|
362391
|
if ( $ROBOT_FRAGMENT_EXCEPTIONS{$fragment} ) { |
|
1362
|
7965
|
|
|
|
|
11847
|
for my $exception ( |
|
1363
|
7965
|
50
|
|
|
|
21402
|
@{ $ROBOT_FRAGMENT_EXCEPTIONS{$fragment} || [] } ) { |
|
1364
|
7965
|
100
|
|
|
|
20552
|
if ( index( $ua, $exception ) != -1 ) { |
|
1365
|
7
|
|
|
|
|
26
|
next FRAGMENT; |
|
1366
|
|
|
|
|
|
|
} |
|
1367
|
|
|
|
|
|
|
} |
|
1368
|
|
|
|
|
|
|
} |
|
1369
|
|
|
|
|
|
|
|
|
1370
|
211071
|
100
|
|
|
|
428422
|
if ( index( $ua, $fragment ) != -1 ) { |
|
1371
|
311
|
|
|
|
|
715
|
$robot_fragment = $fragment; |
|
1372
|
311
|
|
|
|
|
848
|
$robot_tests->{robot} = 'unknown'; |
|
1373
|
311
|
|
|
|
|
707
|
last; |
|
1374
|
|
|
|
|
|
|
} |
|
1375
|
|
|
|
|
|
|
} |
|
1376
|
|
|
|
|
|
|
} |
|
1377
|
|
|
|
|
|
|
|
|
1378
|
8787
|
100
|
100
|
|
|
23627
|
if ( exists $robot_tests->{robot} && $robot_tests->{robot} eq 'unknown' ) |
|
1379
|
|
|
|
|
|
|
{ |
|
1380
|
599
|
|
|
|
|
1303
|
$robot_tests->{robot_id} = 'unknown'; |
|
1381
|
|
|
|
|
|
|
} |
|
1382
|
|
|
|
|
|
|
|
|
1383
|
8787
|
100
|
|
|
|
18805
|
if ( defined $robot_fragment ) { |
|
1384
|
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
# Examine what surrounds the fragment; that leads us to the |
|
1386
|
|
|
|
|
|
|
# version and the string (if we haven't explicitly set one). |
|
1387
|
|
|
|
|
|
|
|
|
1388
|
1091
|
100
|
|
|
|
73464
|
if ( |
|
1389
|
|
|
|
|
|
|
$self->{user_agent} =~ m{\s* # Beginning whitespace |
|
1390
|
|
|
|
|
|
|
([\w .:,\-\@\/]* # Words before fragment |
|
1391
|
|
|
|
|
|
|
$robot_fragment # Match the fragment |
|
1392
|
|
|
|
|
|
|
[\w .:,\-\@\/]*) # Words after fragment |
|
1393
|
|
|
|
|
|
|
}ix |
|
1394
|
|
|
|
|
|
|
) { |
|
1395
|
1019
|
|
|
|
|
3561
|
my $full_string = $1; |
|
1396
|
1019
|
|
|
|
|
5886
|
$full_string =~ s/ *$//; # Trim whitespace at end |
|
1397
|
1019
|
100
|
100
|
|
|
6189
|
if ( |
|
|
|
|
66
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
$self->{user_agent} eq $full_string |
|
1399
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m{\/.*\/} |
|
1400
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m{ |
|
1401
|
|
|
|
|
|
|
([\w]* # Words before fragment |
|
1402
|
|
|
|
|
|
|
$robot_fragment # Match the fragment |
|
1403
|
|
|
|
|
|
|
(\/[\d\.]+)? # Version |
|
1404
|
|
|
|
|
|
|
[\w]*) # Beta stuff |
|
1405
|
|
|
|
|
|
|
}ix |
|
1406
|
|
|
|
|
|
|
) { |
|
1407
|
|
|
|
|
|
|
# We matched the whole string, but it seems to |
|
1408
|
|
|
|
|
|
|
# make more sense as whitespace-separated |
|
1409
|
|
|
|
|
|
|
# 'thing/ver' tokens |
|
1410
|
36
|
|
|
|
|
117
|
$full_string = $1; |
|
1411
|
|
|
|
|
|
|
} |
|
1412
|
|
|
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
# Figure out robot version based on the string |
|
1414
|
1019
|
100
|
66
|
|
|
10906
|
if ( $full_string |
|
1415
|
|
|
|
|
|
|
and $full_string =~ s/[\/ \.v]*(\d+)(\.\d+)?([\.\w]*)$// ) { |
|
1416
|
654
|
|
|
|
|
3066
|
$self->{robot_version} = [ $1, $2, $3 ]; |
|
1417
|
|
|
|
|
|
|
} |
|
1418
|
|
|
|
|
|
|
else { |
|
1419
|
365
|
|
|
|
|
972
|
$self->{robot_version} = undef; |
|
1420
|
|
|
|
|
|
|
} |
|
1421
|
|
|
|
|
|
|
|
|
1422
|
|
|
|
|
|
|
# Set robot_string, if we don't already have an explictly set |
|
1423
|
|
|
|
|
|
|
# one |
|
1424
|
1019
|
100
|
|
|
|
3221
|
if ( !defined $self->{robot_string} ) { |
|
1425
|
353
|
|
|
|
|
998
|
$self->{robot_string} = $full_string; |
|
1426
|
|
|
|
|
|
|
} |
|
1427
|
|
|
|
|
|
|
} |
|
1428
|
|
|
|
|
|
|
} |
|
1429
|
|
|
|
|
|
|
|
|
1430
|
8787
|
100
|
|
|
|
22587
|
if ( !exists( $self->{robot_version} ) ) { |
|
1431
|
6210
|
|
|
|
|
15497
|
$self->{robot_version} = undef; |
|
1432
|
|
|
|
|
|
|
} |
|
1433
|
|
|
|
|
|
|
} |
|
1434
|
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
### OS tests, only run on demand |
|
1436
|
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
sub _init_os { |
|
1438
|
7242
|
|
|
7242
|
|
12040
|
my $self = shift; |
|
1439
|
|
|
|
|
|
|
|
|
1440
|
7242
|
|
|
|
|
11492
|
my $tests = $self->{tests}; |
|
1441
|
7242
|
|
|
|
|
11531
|
my $browser_tests = $self->{browser_tests}; |
|
1442
|
7242
|
|
|
|
|
16959
|
my $ua = lc $self->{user_agent}; |
|
1443
|
|
|
|
|
|
|
|
|
1444
|
7242
|
|
|
|
|
16683
|
my $os_tests = $self->{os_tests} = {}; |
|
1445
|
7242
|
|
|
|
|
12471
|
my $os = undef; |
|
1446
|
7242
|
|
|
|
|
10877
|
my $os_string = undef; |
|
1447
|
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
# Windows |
|
1449
|
|
|
|
|
|
|
|
|
1450
|
7242
|
50
|
|
|
|
20914
|
if ( index( $ua, '16bit' ) != -1 ) { |
|
1451
|
0
|
|
|
|
|
0
|
$os = 'windows'; |
|
1452
|
0
|
|
|
|
|
0
|
$os_string = '16-bit Windows'; |
|
1453
|
0
|
|
|
|
|
0
|
$os_tests->{win16} = $os_tests->{windows} = 1; |
|
1454
|
|
|
|
|
|
|
} |
|
1455
|
|
|
|
|
|
|
|
|
1456
|
7242
|
100
|
|
|
|
16772
|
if ( index( $ua, 'win' ) != -1 ) { |
|
1457
|
2964
|
100
|
66
|
|
|
47835
|
if ( index( $ua, 'win16' ) != -1 |
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
|| index( $ua, 'windows 3' ) != -1 |
|
1459
|
|
|
|
|
|
|
|| index( $ua, 'windows 16-bit' ) != -1 ) { |
|
1460
|
12
|
|
|
|
|
35
|
$os_tests->{win16} = 1; |
|
1461
|
12
|
|
|
|
|
24
|
$os_tests->{win3x} = 1; |
|
1462
|
12
|
|
|
|
|
23
|
$os = 'windows'; |
|
1463
|
12
|
100
|
|
|
|
39
|
if ( index( $ua, 'windows 3.1' ) != -1 ) { |
|
1464
|
6
|
|
|
|
|
10
|
$os_tests->{win31} = 1; |
|
1465
|
6
|
|
|
|
|
13
|
$os_string = 'Win3x'; # FIXME bug compatibility |
|
1466
|
|
|
|
|
|
|
} |
|
1467
|
|
|
|
|
|
|
else { |
|
1468
|
6
|
|
|
|
|
10
|
$os_string = 'Win3x'; |
|
1469
|
|
|
|
|
|
|
} |
|
1470
|
|
|
|
|
|
|
} |
|
1471
|
|
|
|
|
|
|
elsif (index( $ua, 'win95' ) != -1 |
|
1472
|
|
|
|
|
|
|
|| index( $ua, 'windows 95' ) != -1 ) { |
|
1473
|
72
|
|
|
|
|
131
|
$os = 'windows'; |
|
1474
|
72
|
|
|
|
|
110
|
$os_string = 'Win95'; |
|
1475
|
72
|
|
|
|
|
208
|
$os_tests->{win95} = $os_tests->{win32} = 1; |
|
1476
|
|
|
|
|
|
|
} |
|
1477
|
|
|
|
|
|
|
elsif ( |
|
1478
|
|
|
|
|
|
|
index( $ua, 'win 9x 4.90' ) != -1 # whatever |
|
1479
|
|
|
|
|
|
|
|| index( $ua, 'windows me' ) != -1 |
|
1480
|
|
|
|
|
|
|
) { |
|
1481
|
30
|
|
|
|
|
53
|
$os = 'windows'; |
|
1482
|
30
|
|
|
|
|
53
|
$os_string = 'WinME'; |
|
1483
|
30
|
|
|
|
|
89
|
$os_tests->{winme} = $os_tests->{win32} = 1; |
|
1484
|
|
|
|
|
|
|
} |
|
1485
|
|
|
|
|
|
|
elsif (index( $ua, 'win98' ) != -1 |
|
1486
|
|
|
|
|
|
|
|| index( $ua, 'windows 98' ) != -1 ) { |
|
1487
|
24
|
|
|
|
|
54
|
$os = 'windows'; |
|
1488
|
24
|
|
|
|
|
39
|
$os_string = 'Win98'; |
|
1489
|
24
|
|
|
|
|
74
|
$os_tests->{win98} = $os_tests->{win32} = 1; |
|
1490
|
|
|
|
|
|
|
} |
|
1491
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows 2000' ) != -1 ) { |
|
1492
|
12
|
|
|
|
|
26
|
$os = 'windows'; |
|
1493
|
12
|
|
|
|
|
19
|
$os_string = 'Win2k'; |
|
1494
|
12
|
|
|
|
|
38
|
$os_tests->{win2k} = $os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1495
|
|
|
|
|
|
|
} |
|
1496
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows ce' ) != -1 ) { |
|
1497
|
12
|
|
|
|
|
28
|
$os = 'windows'; |
|
1498
|
12
|
|
|
|
|
20
|
$os_string = 'WinCE'; |
|
1499
|
12
|
|
|
|
|
33
|
$os_tests->{wince} = 1; |
|
1500
|
|
|
|
|
|
|
} |
|
1501
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows phone' ) != -1 ) { |
|
1502
|
54
|
|
|
|
|
108
|
$os = 'winphone'; |
|
1503
|
54
|
|
|
|
|
128
|
$os_tests->{winphone} = 1; |
|
1504
|
|
|
|
|
|
|
|
|
1505
|
54
|
100
|
|
|
|
286
|
if ( index( $ua, 'windows phone os 7.0' ) != -1 ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1506
|
6
|
|
|
|
|
14
|
$os_tests->{winphone7} = 1; |
|
1507
|
|
|
|
|
|
|
} |
|
1508
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows phone os 7.5' ) != -1 ) { |
|
1509
|
12
|
|
|
|
|
28
|
$os_tests->{winphone7_5} = 1; |
|
1510
|
|
|
|
|
|
|
} |
|
1511
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows phone 8.0' ) != -1 ) { |
|
1512
|
12
|
|
|
|
|
26
|
$os_tests->{winphone8} = 1; |
|
1513
|
|
|
|
|
|
|
} |
|
1514
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows phone 8.1' ) != -1 ) { |
|
1515
|
18
|
|
|
|
|
39
|
$os_tests->{winphone8_1} = 1; |
|
1516
|
|
|
|
|
|
|
} |
|
1517
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows phone 10.0' ) != -1 ) { |
|
1518
|
6
|
|
|
|
|
17
|
$os_tests->{winphone10} = 1; |
|
1519
|
|
|
|
|
|
|
} |
|
1520
|
|
|
|
|
|
|
} |
|
1521
|
|
|
|
|
|
|
} |
|
1522
|
|
|
|
|
|
|
|
|
1523
|
7242
|
100
|
|
|
|
17961
|
if ( index( $ua, 'nt' ) != -1 ) { |
|
1524
|
3804
|
100
|
66
|
|
|
37440
|
if ( index( $ua, 'nt 5.0' ) != -1 |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
|| index( $ua, 'nt5' ) != -1 ) { |
|
1526
|
90
|
|
|
|
|
173
|
$os = 'windows'; |
|
1527
|
90
|
|
|
|
|
160
|
$os_string = 'Win2k'; |
|
1528
|
90
|
|
|
|
|
278
|
$os_tests->{win2k} = $os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1529
|
|
|
|
|
|
|
} |
|
1530
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 5.1' ) != -1 ) { |
|
1531
|
984
|
|
|
|
|
1764
|
$os = 'windows'; |
|
1532
|
984
|
|
|
|
|
1538
|
$os_string = 'WinXP'; |
|
1533
|
984
|
|
|
|
|
2847
|
$os_tests->{winxp} = $os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1534
|
|
|
|
|
|
|
} |
|
1535
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 5.2' ) != -1 ) { |
|
1536
|
126
|
|
|
|
|
217
|
$os = 'windows'; |
|
1537
|
126
|
|
|
|
|
200
|
$os_string = 'Win2k3'; |
|
1538
|
126
|
|
|
|
|
361
|
$os_tests->{win2k3} = $os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1539
|
|
|
|
|
|
|
} |
|
1540
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 6.0' ) != -1 ) { |
|
1541
|
204
|
|
|
|
|
399
|
$os = 'windows'; |
|
1542
|
204
|
|
|
|
|
334
|
$os_string = 'WinVista'; |
|
1543
|
|
|
|
|
|
|
$os_tests->{winvista} = $os_tests->{winnt} = $os_tests->{win32} |
|
1544
|
204
|
|
|
|
|
654
|
= 1; |
|
1545
|
|
|
|
|
|
|
} |
|
1546
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 6.1' ) != -1 ) { |
|
1547
|
966
|
|
|
|
|
1929
|
$os = 'windows'; |
|
1548
|
966
|
|
|
|
|
1507
|
$os_string = 'Win7'; |
|
1549
|
966
|
|
|
|
|
2910
|
$os_tests->{win7} = $os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1550
|
|
|
|
|
|
|
} |
|
1551
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 6.2' ) != -1 ) { |
|
1552
|
96
|
|
|
|
|
194
|
$os = 'windows'; |
|
1553
|
96
|
|
|
|
|
158
|
$os_string = 'Win8.0'; |
|
1554
|
|
|
|
|
|
|
$os_tests->{win8_0} = $os_tests->{win8} = $os_tests->{winnt} |
|
1555
|
96
|
|
|
|
|
334
|
= $os_tests->{win32} = 1; |
|
1556
|
|
|
|
|
|
|
} |
|
1557
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 6.3' ) != -1 ) { |
|
1558
|
78
|
|
|
|
|
157
|
$os = 'windows'; |
|
1559
|
78
|
|
|
|
|
153
|
$os_string = 'Win8.1'; |
|
1560
|
|
|
|
|
|
|
$os_tests->{win8_1} = $os_tests->{win8} = $os_tests->{winnt} |
|
1561
|
78
|
|
|
|
|
269
|
= $os_tests->{win32} = 1; |
|
1562
|
|
|
|
|
|
|
} |
|
1563
|
|
|
|
|
|
|
elsif ( index( $ua, 'nt 10.0' ) != -1 ) { |
|
1564
|
36
|
|
|
|
|
75
|
$os = 'windows'; |
|
1565
|
36
|
|
|
|
|
49
|
$os_string = 'Win10.0'; |
|
1566
|
|
|
|
|
|
|
$os_tests->{win10_0} = $os_tests->{win10} = $os_tests->{winnt} |
|
1567
|
36
|
|
|
|
|
116
|
= $os_tests->{win32} = 1; |
|
1568
|
|
|
|
|
|
|
} |
|
1569
|
|
|
|
|
|
|
elsif (index( $ua, 'winnt' ) != -1 |
|
1570
|
|
|
|
|
|
|
|| index( $ua, 'windows nt' ) != -1 |
|
1571
|
|
|
|
|
|
|
|| index( $ua, 'nt4' ) != -1 |
|
1572
|
|
|
|
|
|
|
|| index( $ua, 'nt3' ) != -1 ) { |
|
1573
|
54
|
|
|
|
|
100
|
$os = 'windows'; |
|
1574
|
54
|
|
|
|
|
88
|
$os_string = 'WinNT'; |
|
1575
|
54
|
|
|
|
|
154
|
$os_tests->{winnt} = $os_tests->{win32} = 1; |
|
1576
|
|
|
|
|
|
|
} |
|
1577
|
|
|
|
|
|
|
} |
|
1578
|
|
|
|
|
|
|
|
|
1579
|
7242
|
100
|
100
|
|
|
117445
|
if ($os) { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
# windows, set through some path above |
|
1582
|
2850
|
|
|
|
|
5914
|
$os_tests->{windows} = 1; |
|
1583
|
2850
|
50
|
|
|
|
7437
|
$os_tests->{win32} = 1 if index( $ua, 'win32' ) != -1; |
|
1584
|
|
|
|
|
|
|
} |
|
1585
|
|
|
|
|
|
|
elsif ( index( $ua, 'macintosh' ) != -1 || index( $ua, 'mac_' ) != -1 ) { |
|
1586
|
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
# Mac operating systems |
|
1588
|
462
|
|
|
|
|
1064
|
$os_tests->{mac} = 1; |
|
1589
|
462
|
100
|
|
|
|
1108
|
if ( index( $ua, 'mac os x' ) != -1 ) { |
|
1590
|
438
|
|
|
|
|
726
|
$os = 'macosx'; |
|
1591
|
438
|
|
|
|
|
851
|
$os_tests->{$os} = 1; |
|
1592
|
|
|
|
|
|
|
} |
|
1593
|
|
|
|
|
|
|
else { |
|
1594
|
24
|
|
|
|
|
47
|
$os = 'mac'; |
|
1595
|
|
|
|
|
|
|
} |
|
1596
|
462
|
50
|
33
|
|
|
3051
|
if ( index( $ua, '68k' ) != -1 || index( $ua, '68000' ) != -1 ) { |
|
|
|
100
|
100
|
|
|
|
|
|
1597
|
0
|
|
|
|
|
0
|
$os_tests->{mac68k} = 1; |
|
1598
|
|
|
|
|
|
|
} |
|
1599
|
|
|
|
|
|
|
elsif ( index( $ua, 'ppc' ) != -1 || index( $ua, 'powerpc' ) != -1 ) { |
|
1600
|
126
|
|
|
|
|
264
|
$os_tests->{macppc} = 1; |
|
1601
|
|
|
|
|
|
|
} |
|
1602
|
|
|
|
|
|
|
} |
|
1603
|
|
|
|
|
|
|
elsif (index( $ua, 'ipod' ) != -1 |
|
1604
|
|
|
|
|
|
|
|| index( $ua, 'iphone' ) != -1 |
|
1605
|
|
|
|
|
|
|
|| index( $ua, 'ipad' ) != -1 ) { |
|
1606
|
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
# iOS |
|
1608
|
420
|
|
|
|
|
748
|
$os = 'ios'; |
|
1609
|
420
|
|
|
|
|
1028
|
$os_tests->{$os} = 1; |
|
1610
|
|
|
|
|
|
|
} |
|
1611
|
|
|
|
|
|
|
elsif ( index( $ua, 'android' ) != -1 ) { |
|
1612
|
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
# Android |
|
1614
|
1008
|
|
|
|
|
1871
|
$os = 'android'; # Test gets set in the device testing |
|
1615
|
|
|
|
|
|
|
} |
|
1616
|
|
|
|
|
|
|
elsif ( index( $ua, 'inux' ) != -1 ) { |
|
1617
|
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
# Linux |
|
1619
|
498
|
|
|
|
|
875
|
$os = 'linux'; |
|
1620
|
498
|
|
|
|
|
1316
|
$os_tests->{linux} = $os_tests->{unix} = 1; |
|
1621
|
|
|
|
|
|
|
} |
|
1622
|
|
|
|
|
|
|
elsif ( $tests->{x11} && index( $ua, 'cros' ) != -1 ) { |
|
1623
|
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
# ChromeOS |
|
1625
|
42
|
|
|
|
|
108
|
$os = 'chromeos'; |
|
1626
|
42
|
|
|
|
|
97
|
$os_tests->{chromeos} = 1; |
|
1627
|
|
|
|
|
|
|
} |
|
1628
|
|
|
|
|
|
|
## Long series of unlikely OSs |
|
1629
|
|
|
|
|
|
|
elsif ( index( $ua, 'amiga' ) != -1 ) { |
|
1630
|
6
|
|
|
|
|
10
|
$os = 'amiga'; |
|
1631
|
6
|
|
|
|
|
16
|
$os_tests->{$os} = 1; |
|
1632
|
|
|
|
|
|
|
} |
|
1633
|
|
|
|
|
|
|
elsif ( index( $ua, 'os/2' ) != -1 ) { |
|
1634
|
6
|
|
|
|
|
14
|
$os = 'os2'; |
|
1635
|
6
|
|
|
|
|
15
|
$os_tests->{$os} = 1; |
|
1636
|
|
|
|
|
|
|
} |
|
1637
|
|
|
|
|
|
|
elsif ( index( $ua, 'solaris' ) != -1 ) { |
|
1638
|
6
|
|
|
|
|
14
|
$os = 'unix'; |
|
1639
|
6
|
|
|
|
|
8
|
$os_string = 'Solaris'; |
|
1640
|
6
|
|
|
|
|
20
|
$os_tests->{sun} = $os_tests->{unix} = 1; |
|
1641
|
|
|
|
|
|
|
} |
|
1642
|
|
|
|
|
|
|
elsif ( index( $ua, 'samsung' ) == -1 && index( $ua, 'sun' ) != -1 ) { |
|
1643
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1644
|
0
|
|
|
|
|
0
|
$os_string = 'SunOS'; |
|
1645
|
0
|
|
|
|
|
0
|
$os_tests->{sun} = $os_tests->{unix} = 1; |
|
1646
|
0
|
0
|
|
|
|
0
|
$os_tests->{suni86} = 1 if index( $ua, 'i86' ) != -1; |
|
1647
|
0
|
0
|
|
|
|
0
|
$os_tests->{sun4} = 1 if index( $ua, 'sunos 4' ) != -1; |
|
1648
|
0
|
0
|
|
|
|
0
|
$os_tests->{sun5} = 1 if index( $ua, 'sunos 5' ) != -1; |
|
1649
|
|
|
|
|
|
|
} |
|
1650
|
|
|
|
|
|
|
elsif ( index( $ua, 'irix' ) != -1 ) { |
|
1651
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1652
|
0
|
|
|
|
|
0
|
$os_string = 'Irix'; |
|
1653
|
0
|
|
|
|
|
0
|
$os_tests->{irix} = $os_tests->{unix} = 1; |
|
1654
|
0
|
0
|
|
|
|
0
|
$os_tests->{irix5} = 1 if ( index( $ua, 'irix5' ) != -1 ); |
|
1655
|
0
|
0
|
|
|
|
0
|
$os_tests->{irix6} = 1 if ( index( $ua, 'irix6' ) != -1 ); |
|
1656
|
|
|
|
|
|
|
} |
|
1657
|
|
|
|
|
|
|
elsif ( index( $ua, 'hp-ux' ) != -1 ) { |
|
1658
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1659
|
0
|
|
|
|
|
0
|
$os_string = 'HP-UX'; |
|
1660
|
0
|
|
|
|
|
0
|
$os_tests->{hpux} = $os_tests->{unix} = 1; |
|
1661
|
0
|
0
|
|
|
|
0
|
$os_tests->{hpux9} = 1 if index( $ua, '09.' ) != -1; |
|
1662
|
0
|
0
|
|
|
|
0
|
$os_tests->{hpux10} = 1 if index( $ua, '10.' ) != -1; |
|
1663
|
|
|
|
|
|
|
} |
|
1664
|
|
|
|
|
|
|
elsif ( index( $ua, 'aix' ) != -1 ) { |
|
1665
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1666
|
0
|
|
|
|
|
0
|
$os_string = 'AIX'; |
|
1667
|
0
|
|
|
|
|
0
|
$os_tests->{aix} = $os_tests->{unix} = 1; |
|
1668
|
0
|
0
|
|
|
|
0
|
$os_tests->{aix1} = 1 if ( index( $ua, 'aix 1' ) != -1 ); |
|
1669
|
0
|
0
|
|
|
|
0
|
$os_tests->{aix2} = 1 if ( index( $ua, 'aix 2' ) != -1 ); |
|
1670
|
0
|
0
|
|
|
|
0
|
$os_tests->{aix3} = 1 if ( index( $ua, 'aix 3' ) != -1 ); |
|
1671
|
0
|
0
|
|
|
|
0
|
$os_tests->{aix4} = 1 if ( index( $ua, 'aix 4' ) != -1 ); |
|
1672
|
|
|
|
|
|
|
} |
|
1673
|
|
|
|
|
|
|
elsif ( $ua =~ m{\bsco\b} || index( $ua, 'unix_sv' ) != -1 ) { |
|
1674
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1675
|
0
|
|
|
|
|
0
|
$os_string = 'SCO Unix'; |
|
1676
|
0
|
|
|
|
|
0
|
$os_tests->{sco} = $os_tests->{unix} = 1; |
|
1677
|
|
|
|
|
|
|
} |
|
1678
|
|
|
|
|
|
|
elsif ( index( $ua, 'unix_system_v' ) != -1 ) { |
|
1679
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1680
|
0
|
|
|
|
|
0
|
$os_string = 'System V Unix'; |
|
1681
|
0
|
|
|
|
|
0
|
$os_tests->{unixware} = $os_tests->{unix} = 1; |
|
1682
|
|
|
|
|
|
|
} |
|
1683
|
|
|
|
|
|
|
elsif ( $ua =~ m{\bncr\b} ) { |
|
1684
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1685
|
0
|
|
|
|
|
0
|
$os_string = 'NCR Unix'; |
|
1686
|
0
|
|
|
|
|
0
|
$os_tests->{mpras} = $os_tests->{unix} = 1; |
|
1687
|
|
|
|
|
|
|
} |
|
1688
|
|
|
|
|
|
|
elsif ( index( $ua, 'reliantunix' ) != -1 ) { |
|
1689
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1690
|
0
|
|
|
|
|
0
|
$os_string = 'Reliant Unix'; |
|
1691
|
0
|
|
|
|
|
0
|
$os_tests->{reliant} = $os_tests->{unix} = 1; |
|
1692
|
|
|
|
|
|
|
} |
|
1693
|
|
|
|
|
|
|
elsif (index( $ua, 'dec' ) != -1 |
|
1694
|
|
|
|
|
|
|
|| index( $ua, 'osf1' ) != -1 |
|
1695
|
|
|
|
|
|
|
|| index( $ua, 'declpha' ) != -1 |
|
1696
|
|
|
|
|
|
|
|| index( $ua, 'alphaserver' ) != -1 |
|
1697
|
|
|
|
|
|
|
|| index( $ua, 'ultrix' ) != -1 |
|
1698
|
|
|
|
|
|
|
|| index( $ua, 'alphastation' ) != -1 ) { |
|
1699
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1700
|
0
|
|
|
|
|
0
|
$os_tests->{dec} = $os_tests->{unix} = 1; |
|
1701
|
|
|
|
|
|
|
} |
|
1702
|
|
|
|
|
|
|
elsif ( index( $ua, 'sinix' ) != -1 ) { |
|
1703
|
0
|
|
|
|
|
0
|
$os = 'unix'; |
|
1704
|
0
|
|
|
|
|
0
|
$os_tests->{sinix} = $os_tests->{unix} = 1; |
|
1705
|
|
|
|
|
|
|
} |
|
1706
|
|
|
|
|
|
|
elsif ( index( $ua, 'bsd' ) != -1 ) { |
|
1707
|
30
|
|
|
|
|
70
|
$os = 'unix'; |
|
1708
|
30
|
50
|
|
|
|
257
|
if ( $self->{user_agent} =~ m{(\w*bsd\w*)}i ) { |
|
1709
|
30
|
|
|
|
|
100
|
$os_string = $1; |
|
1710
|
|
|
|
|
|
|
} |
|
1711
|
30
|
|
|
|
|
94
|
$os_tests->{bsd} = $os_tests->{unix} = 1; |
|
1712
|
30
|
50
|
|
|
|
111
|
$os_tests->{freebsd} = 1 if index( $ua, 'freebsd' ) != -1; |
|
1713
|
|
|
|
|
|
|
} |
|
1714
|
|
|
|
|
|
|
elsif ( $tests->{x11} ) { |
|
1715
|
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
# Some Unix we didn't identify |
|
1717
|
12
|
|
|
|
|
33
|
$os = 'unix'; |
|
1718
|
12
|
|
|
|
|
34
|
$os_tests->{unix} = 1; |
|
1719
|
|
|
|
|
|
|
} |
|
1720
|
|
|
|
|
|
|
elsif ( index( $ua, 'vax' ) != -1 || index( $ua, 'openvms' ) != -1 ) { |
|
1721
|
|
|
|
|
|
|
|
|
1722
|
0
|
|
|
|
|
0
|
$os = 'vms'; |
|
1723
|
0
|
|
|
|
|
0
|
$os_tests->{vms} = 1; |
|
1724
|
|
|
|
|
|
|
} |
|
1725
|
|
|
|
|
|
|
elsif ( index( $ua, 'bb10' ) != -1 ) { |
|
1726
|
12
|
|
|
|
|
27
|
$os = 'bb10'; |
|
1727
|
12
|
|
|
|
|
28
|
$os_tests->{bb10} = 1; |
|
1728
|
|
|
|
|
|
|
} |
|
1729
|
|
|
|
|
|
|
elsif ( index( $ua, 'rim tablet os' ) != -1 ) { |
|
1730
|
6
|
|
|
|
|
13
|
$os = 'rimtabletos'; |
|
1731
|
6
|
|
|
|
|
16
|
$os_tests->{rimtabletos} = 1; |
|
1732
|
|
|
|
|
|
|
} |
|
1733
|
|
|
|
|
|
|
elsif ( index( $ua, 'playstation 3' ) != -1 ) { |
|
1734
|
6
|
|
|
|
|
14
|
$os = 'ps3gameos'; |
|
1735
|
6
|
|
|
|
|
17
|
$os_tests->{ps3gameos} = 1; |
|
1736
|
|
|
|
|
|
|
} |
|
1737
|
|
|
|
|
|
|
elsif ( index( $ua, 'playstation portable' ) != -1 ) { |
|
1738
|
6
|
|
|
|
|
14
|
$os = 'pspgameos'; |
|
1739
|
6
|
|
|
|
|
15
|
$os_tests->{pspgameos} = 1; |
|
1740
|
|
|
|
|
|
|
} |
|
1741
|
|
|
|
|
|
|
elsif ( index( $ua, 'windows' ) != -1 ) { |
|
1742
|
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
# Windows again, the super generic version |
|
1744
|
54
|
|
|
|
|
169
|
$os_tests->{windows} = 1; |
|
1745
|
|
|
|
|
|
|
} |
|
1746
|
|
|
|
|
|
|
elsif ( index( $ua, 'win32' ) != -1 ) { |
|
1747
|
18
|
|
|
|
|
62
|
$os_tests->{win32} = $os_tests->{windows} = 1; |
|
1748
|
|
|
|
|
|
|
} |
|
1749
|
|
|
|
|
|
|
elsif ( $self->{user_agent} =~ m{(brew)|(\bbmp\b)}i ) { |
|
1750
|
144
|
|
|
|
|
347
|
$os = 'brew'; |
|
1751
|
144
|
100
|
|
|
|
473
|
if ($1) { |
|
1752
|
102
|
|
|
|
|
183
|
$os_string = 'Brew'; |
|
1753
|
|
|
|
|
|
|
} |
|
1754
|
|
|
|
|
|
|
else { |
|
1755
|
42
|
|
|
|
|
71
|
$os_string = 'Brew MP'; |
|
1756
|
|
|
|
|
|
|
} |
|
1757
|
144
|
|
|
|
|
374
|
$os_tests->{brew} = 1; |
|
1758
|
|
|
|
|
|
|
} |
|
1759
|
|
|
|
|
|
|
else { |
|
1760
|
1656
|
|
|
|
|
3564
|
$os = undef; |
|
1761
|
|
|
|
|
|
|
} |
|
1762
|
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
# To deal with FirefoxOS we seem to have to load-on-demand devices |
|
1764
|
|
|
|
|
|
|
# also, by calling ->mobile and ->tablet. We have to be careful; |
|
1765
|
|
|
|
|
|
|
# if we ever created a loop back from _init_devices to _init_os |
|
1766
|
|
|
|
|
|
|
# we'd run forever. |
|
1767
|
7242
|
100
|
100
|
|
|
19623
|
if ( !$os |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
&& $browser_tests->{firefox} |
|
1769
|
|
|
|
|
|
|
&& index( $ua, 'fennec' ) == -1 |
|
1770
|
|
|
|
|
|
|
&& ( $self->mobile || $self->tablet ) ) { |
|
1771
|
12
|
|
|
|
|
27
|
$os = 'firefoxos'; |
|
1772
|
12
|
|
|
|
|
31
|
$os_tests->{firefoxos} = 1; |
|
1773
|
|
|
|
|
|
|
} |
|
1774
|
|
|
|
|
|
|
|
|
1775
|
7242
|
|
|
|
|
15856
|
$self->{os} = $os; |
|
1776
|
7242
|
100
|
100
|
|
|
22901
|
if ( $os and !$os_string ) { |
|
1777
|
2550
|
|
|
|
|
5748
|
$os_string = $OS_NAMES{$os}; |
|
1778
|
|
|
|
|
|
|
} |
|
1779
|
7242
|
|
|
|
|
18371
|
$self->{os_string} = $os_string; |
|
1780
|
|
|
|
|
|
|
} |
|
1781
|
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
sub _init_os_version { |
|
1783
|
2574
|
|
|
2574
|
|
5118
|
my ($self) = @_; |
|
1784
|
|
|
|
|
|
|
|
|
1785
|
2574
|
|
|
|
|
6407
|
my $os = $self->os; |
|
1786
|
2574
|
|
|
|
|
7013
|
my $os_string = $self->os_string; |
|
1787
|
2574
|
|
|
|
|
8276
|
my $ua = lc $self->{user_agent}; |
|
1788
|
|
|
|
|
|
|
|
|
1789
|
2574
|
|
|
|
|
4436
|
my $os_version = undef; |
|
1790
|
|
|
|
|
|
|
|
|
1791
|
2574
|
100
|
|
|
|
14816
|
if ( !defined $os ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1792
|
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
# Nothing is going to work if we have no OS. Skip everything. |
|
1794
|
|
|
|
|
|
|
} |
|
1795
|
|
|
|
|
|
|
elsif ( $os eq 'winphone' ) { |
|
1796
|
22
|
50
|
|
|
|
198
|
if ( $ua =~ m{windows phone (?:os )?(\d+)(\.?\d*)([\.\d]*)} ) { |
|
1797
|
22
|
|
|
|
|
115
|
$os_version = [ $1, $2, $3 ]; |
|
1798
|
|
|
|
|
|
|
} |
|
1799
|
|
|
|
|
|
|
} |
|
1800
|
|
|
|
|
|
|
elsif ( $os eq 'macosx' ) { |
|
1801
|
194
|
100
|
|
|
|
1324
|
if ( $ua =~ m{os x (\d+)[\._](\d+)[\._]?(\d*)} ) { |
|
1802
|
155
|
100
|
|
|
|
1073
|
$os_version = [ $1, ".$2", length($3) ? ".$3" : q{} ]; |
|
1803
|
|
|
|
|
|
|
} |
|
1804
|
|
|
|
|
|
|
} |
|
1805
|
|
|
|
|
|
|
elsif ( $os eq 'ios' ) { |
|
1806
|
185
|
100
|
|
|
|
1394
|
if ( $ua =~ m{ os (\d+)[\._ ](\d+)[\._ ]?(\d*)} ) { |
|
1807
|
184
|
100
|
|
|
|
1309
|
$os_version = [ $1, ".$2", length($3) ? ".$3" : q{} ]; |
|
1808
|
|
|
|
|
|
|
} |
|
1809
|
|
|
|
|
|
|
} |
|
1810
|
|
|
|
|
|
|
elsif ( $os eq 'chromeos' ) { |
|
1811
|
20
|
50
|
|
|
|
186
|
if ( $ua =~ m{ cros \S* (\d+)(\.?\d*)([\.\d]*)} ) { |
|
1812
|
20
|
|
|
|
|
92
|
$os_version = [ $1, $2, $3 ]; |
|
1813
|
|
|
|
|
|
|
} |
|
1814
|
|
|
|
|
|
|
} |
|
1815
|
|
|
|
|
|
|
elsif ( $os eq 'android' ) { |
|
1816
|
479
|
100
|
|
|
|
3838
|
if ( $ua =~ m{android (\d+)(\.?\d*)([\w\-\.]*)[\;\)]} ) { |
|
1817
|
464
|
|
|
|
|
2128
|
$os_version = [ $1, $2, $3 ]; |
|
1818
|
|
|
|
|
|
|
} |
|
1819
|
|
|
|
|
|
|
} |
|
1820
|
|
|
|
|
|
|
elsif ( $os eq 'firefoxos' ) { |
|
1821
|
5
|
50
|
|
|
|
42
|
if ( $ua =~ m{firefox/(\d+)(\.?\d*)([\.\d]*)} ) { |
|
1822
|
5
|
|
|
|
|
26
|
$os_version = [ $1, $2, $3 ]; |
|
1823
|
|
|
|
|
|
|
} |
|
1824
|
|
|
|
|
|
|
} |
|
1825
|
|
|
|
|
|
|
elsif ( $os eq 'brew' ) { |
|
1826
|
68
|
100
|
|
|
|
644
|
if ( $ua =~ m{(brew|\bbmp) (\d+)(\.?\d*)([\.\d]*)} ) { |
|
1827
|
47
|
|
|
|
|
239
|
$os_version = [ $2, $3, $4 ]; |
|
1828
|
|
|
|
|
|
|
} |
|
1829
|
|
|
|
|
|
|
} |
|
1830
|
|
|
|
|
|
|
|
|
1831
|
|
|
|
|
|
|
# Set the version. It might be set to undef, in which case we know |
|
1832
|
|
|
|
|
|
|
# not to go through this next time. |
|
1833
|
2574
|
|
|
|
|
6436
|
$self->{os_version} = $os_version; |
|
1834
|
|
|
|
|
|
|
} |
|
1835
|
|
|
|
|
|
|
|
|
1836
|
|
|
|
|
|
|
### Version determination, only run on demand |
|
1837
|
|
|
|
|
|
|
|
|
1838
|
|
|
|
|
|
|
sub _init_version { |
|
1839
|
7201
|
|
|
7201
|
|
11923
|
my ($self) = @_; |
|
1840
|
|
|
|
|
|
|
|
|
1841
|
7201
|
|
|
|
|
20922
|
my $ua = lc $self->{user_agent}; |
|
1842
|
7201
|
|
|
|
|
12360
|
my $tests = $self->{tests}; |
|
1843
|
7201
|
|
|
|
|
10729
|
my $browser_tests = $self->{browser_tests}; |
|
1844
|
7201
|
|
|
|
|
11511
|
my $browser = $self->{browser}; |
|
1845
|
|
|
|
|
|
|
|
|
1846
|
7201
|
|
|
|
|
14930
|
$self->{version_tests} = {}; |
|
1847
|
7201
|
|
|
|
|
11683
|
my $version_tests = $self->{version_tests}; |
|
1848
|
|
|
|
|
|
|
|
|
1849
|
7201
|
|
|
|
|
12218
|
my ( $major, $minor, $beta ); |
|
1850
|
|
|
|
|
|
|
|
|
1851
|
|
|
|
|
|
|
### First figure out version numbers. First, we test if we're |
|
1852
|
|
|
|
|
|
|
### using a browser that needs some special method to determine |
|
1853
|
|
|
|
|
|
|
### the version. |
|
1854
|
|
|
|
|
|
|
|
|
1855
|
7201
|
100
|
100
|
|
|
94843
|
if ( defined $browser && $browser eq 'opera' ) { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1856
|
|
|
|
|
|
|
|
|
1857
|
|
|
|
|
|
|
# Opera has a 'compatible; ' section, but lies sometimes. It needs |
|
1858
|
|
|
|
|
|
|
# special handling. |
|
1859
|
|
|
|
|
|
|
|
|
1860
|
|
|
|
|
|
|
# http://dev.opera.com/articles/view/opera-ua-string-changes/ |
|
1861
|
|
|
|
|
|
|
# http://my.opera.com/community/openweb/idopera/ |
|
1862
|
|
|
|
|
|
|
# Opera/9.80 (S60; SymbOS; Opera Mobi/320; U; sv) Presto/2.4.15 Version/10.00 |
|
1863
|
|
|
|
|
|
|
# Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.100 |
|
1864
|
|
|
|
|
|
|
|
|
1865
|
264
|
100
|
|
|
|
3138
|
if ( $ua =~ m{\AOpera.*\sVersion/(\d*)\.(\d*)\z}i ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1866
|
90
|
|
|
|
|
296
|
$major = $1; |
|
1867
|
90
|
|
|
|
|
199
|
$minor = $2; |
|
1868
|
|
|
|
|
|
|
} |
|
1869
|
|
|
|
|
|
|
elsif ( $ua =~ m{\bOPR/(\d+)\.(\d+)}i ) { |
|
1870
|
48
|
|
|
|
|
168
|
$major = $1; |
|
1871
|
48
|
|
|
|
|
105
|
$minor = $2; |
|
1872
|
|
|
|
|
|
|
} |
|
1873
|
|
|
|
|
|
|
elsif ( $ua =~ m{Opera[ /](\d+).(\d+)}i ) { |
|
1874
|
126
|
|
|
|
|
363
|
$major = $1; |
|
1875
|
126
|
|
|
|
|
268
|
$minor = $2; |
|
1876
|
|
|
|
|
|
|
} |
|
1877
|
|
|
|
|
|
|
} |
|
1878
|
|
|
|
|
|
|
elsif ( $ua |
|
1879
|
|
|
|
|
|
|
=~ m{\b compatible; \s* [\w\-]* [/\s] ( [0-9]+ ) (?: .([0-9]+) (\S*) )? ;}x |
|
1880
|
|
|
|
|
|
|
) { |
|
1881
|
|
|
|
|
|
|
# MSIE and some others use a 'compatible' format |
|
1882
|
1883
|
|
|
|
|
7969
|
( $major, $minor, $beta ) = ( $1, $2, $3 ); |
|
1883
|
|
|
|
|
|
|
} |
|
1884
|
|
|
|
|
|
|
elsif ( !$browser ) { |
|
1885
|
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
# Nothing else is going to work if $browser isn't defined; skip the |
|
1887
|
|
|
|
|
|
|
# specific approaches and go straight to the generic ones. |
|
1888
|
|
|
|
|
|
|
} |
|
1889
|
|
|
|
|
|
|
elsif ( $browser_tests->{edge} ) { |
|
1890
|
24
|
|
|
|
|
119
|
( $major, $minor, $beta ) |
|
1891
|
|
|
|
|
|
|
= $ua =~ m{Edge/(\d+)(?:\.(\d+))?([\.\d]+)?}i; |
|
1892
|
24
|
50
|
|
|
|
325
|
( $major, $minor, $beta ) |
|
1893
|
|
|
|
|
|
|
= $ua =~ m{(?:Edg|EdgA|EdgiOS)/(\d+)(?:\.(\d+))?([\.\d]+)?}i |
|
1894
|
|
|
|
|
|
|
unless defined $major; |
|
1895
|
|
|
|
|
|
|
} |
|
1896
|
|
|
|
|
|
|
elsif ( $browser_tests->{safari} ) { |
|
1897
|
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
# Safari Version |
|
1899
|
|
|
|
|
|
|
|
|
1900
|
940
|
100
|
|
|
|
6592
|
if ( |
|
|
|
100
|
|
|
|
|
|
|
1901
|
|
|
|
|
|
|
0 |
|
1902
|
|
|
|
|
|
|
&& $ua =~ m{ # Disabled for bug compatibility |
|
1903
|
|
|
|
|
|
|
version/ |
|
1904
|
|
|
|
|
|
|
( \d+ ) # Major version number is everything before first dot |
|
1905
|
|
|
|
|
|
|
\. # First dot |
|
1906
|
|
|
|
|
|
|
( \d+ )? # Minor version number follows dot |
|
1907
|
|
|
|
|
|
|
}x |
|
1908
|
|
|
|
|
|
|
) { |
|
1909
|
|
|
|
|
|
|
# Safari starting with version 3.0 provides its own public version |
|
1910
|
|
|
|
|
|
|
( $major, $minor ) = ( $1, $2, undef ); |
|
1911
|
|
|
|
|
|
|
} |
|
1912
|
0
|
|
|
|
|
0
|
elsif ( $ua =~ m{ safari/ ( \d+ (?: \.\d+ )* ) }x ) { |
|
1913
|
875
|
50
|
|
|
|
5416
|
if ( my ( $safari_build, $safari_minor ) = split /\./, $1 ) { |
|
1914
|
875
|
|
|
|
|
2840
|
$major = int( $safari_build / 100 ); |
|
1915
|
875
|
|
|
|
|
1806
|
$minor = int( $safari_build % 100 ); |
|
1916
|
875
|
100
|
|
|
|
2678
|
$beta = ".$safari_minor" if defined $safari_minor; |
|
1917
|
|
|
|
|
|
|
} |
|
1918
|
|
|
|
|
|
|
} |
|
1919
|
|
|
|
|
|
|
elsif ( $ua =~ m{applewebkit\/([\d\.]{1,})}xi ) { |
|
1920
|
53
|
50
|
|
|
|
351
|
if ( my ( $safari_build, $safari_minor ) = split /\./, $1 ) { |
|
1921
|
53
|
|
|
|
|
187
|
$major = int( $safari_build / 100 ); |
|
1922
|
53
|
|
|
|
|
132
|
$minor = int( $safari_build % 100 ); |
|
1923
|
53
|
100
|
|
|
|
207
|
$beta = ".$safari_minor" if $safari_minor; |
|
1924
|
|
|
|
|
|
|
} |
|
1925
|
|
|
|
|
|
|
} |
|
1926
|
|
|
|
|
|
|
} |
|
1927
|
|
|
|
|
|
|
elsif ( $browser_tests->{fxios} ) { |
|
1928
|
6
|
|
|
|
|
51
|
( $major, $minor ) = $ua =~ m{ \b fxios/ (\d+) [.] (\d+) }x; |
|
1929
|
|
|
|
|
|
|
} |
|
1930
|
|
|
|
|
|
|
elsif ( $tests->{meta_app} ) { |
|
1931
|
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
# init. in order to avoid guessing downstream |
|
1933
|
78
|
|
|
|
|
279
|
( $major, $minor, $beta ) = (q{}) x 3; |
|
1934
|
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
# get version only from FBAV/ part |
|
1936
|
78
|
100
|
|
|
|
515
|
if ( $ua =~ m{ \b fbav/ ([^;]*) }x ) { |
|
1937
|
60
|
|
|
|
|
343
|
( $major, $minor, $beta ) = split /[.]/, $1, 3; |
|
1938
|
60
|
50
|
|
|
|
185
|
if ($beta) { |
|
1939
|
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
# "minor" forcibly gets a "." prepended at the end of _init_version |
|
1941
|
|
|
|
|
|
|
# while "beta" does not - yet it is documented to include the "." |
|
1942
|
60
|
|
|
|
|
165
|
$beta = q{.} . $beta; |
|
1943
|
|
|
|
|
|
|
} |
|
1944
|
|
|
|
|
|
|
} |
|
1945
|
|
|
|
|
|
|
} |
|
1946
|
|
|
|
|
|
|
elsif ( $browser_tests->{instagram} ) { |
|
1947
|
12
|
|
|
|
|
44
|
( $major, $minor, $beta ) = (q{}) x 3; # don't guess downstream |
|
1948
|
12
|
50
|
|
|
|
96
|
if ( $self->{user_agent} =~ m{ \b Instagram [ ]+ ([0-9.]+) [ ] }x ) { |
|
1949
|
12
|
|
|
|
|
62
|
( $major, $minor, $beta ) = split /[.]/, $1, 3; |
|
1950
|
12
|
50
|
|
|
|
37
|
if ($beta) { |
|
1951
|
12
|
|
|
|
|
35
|
$beta = q{.} . $beta; |
|
1952
|
|
|
|
|
|
|
} |
|
1953
|
|
|
|
|
|
|
} |
|
1954
|
|
|
|
|
|
|
} |
|
1955
|
|
|
|
|
|
|
elsif ( $browser_tests->{ie} ) { |
|
1956
|
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
# MSIE |
|
1958
|
|
|
|
|
|
|
|
|
1959
|
100
|
100
|
|
|
|
775
|
if ( $ua =~ m{\b msie \s ( [0-9\.]+ ) (?: [a-z]+ [a-z0-9]* )? ;}x ) { |
|
|
|
100
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
|
|
1961
|
|
|
|
|
|
|
# Internet Explorer |
|
1962
|
18
|
|
|
|
|
93
|
( $major, $minor, $beta ) = split /\./, $1; |
|
1963
|
|
|
|
|
|
|
} |
|
1964
|
|
|
|
|
|
|
elsif ( $ua =~ m{\b rv: ( [0-9\.]+ ) \b}x ) { |
|
1965
|
|
|
|
|
|
|
|
|
1966
|
|
|
|
|
|
|
# MSIE masking as Gecko really well ;) |
|
1967
|
71
|
|
|
|
|
353
|
( $major, $minor, $beta ) = split /\./, $1; |
|
1968
|
|
|
|
|
|
|
} |
|
1969
|
|
|
|
|
|
|
} |
|
1970
|
|
|
|
|
|
|
elsif ( $browser eq 'n3ds' ) { |
|
1971
|
6
|
50
|
|
|
|
50
|
if ( $ua =~ m{Nintendo 3DS;.*\sVersion/(\d*)\.(\d*)}i ) { |
|
1972
|
6
|
|
|
|
|
17
|
$major = $1; |
|
1973
|
6
|
|
|
|
|
16
|
$minor = $2; |
|
1974
|
|
|
|
|
|
|
} |
|
1975
|
|
|
|
|
|
|
} |
|
1976
|
|
|
|
|
|
|
elsif ( $browser eq 'browsex' ) { |
|
1977
|
6
|
50
|
|
|
|
53
|
if ( $ua =~ m{BrowseX \((\d+)\.(\d+)([\d.]*)}i ) { |
|
1978
|
6
|
|
|
|
|
17
|
$major = $1; |
|
1979
|
6
|
|
|
|
|
14
|
$minor = $2; |
|
1980
|
6
|
|
|
|
|
13
|
$beta = $3; |
|
1981
|
|
|
|
|
|
|
} |
|
1982
|
|
|
|
|
|
|
} |
|
1983
|
|
|
|
|
|
|
elsif ( $ua =~ m{netscape6/(\d+)\.(\d+)([\d.]*)} ) { |
|
1984
|
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
# Other cases get handled below, we just need this to skip the '6' |
|
1986
|
6
|
|
|
|
|
23
|
$major = $1; |
|
1987
|
6
|
|
|
|
|
15
|
$minor = $2; |
|
1988
|
6
|
|
|
|
|
13
|
$beta = $3; |
|
1989
|
|
|
|
|
|
|
} |
|
1990
|
|
|
|
|
|
|
elsif ( $browser eq 'brave' ) { |
|
1991
|
|
|
|
|
|
|
|
|
1992
|
|
|
|
|
|
|
# Note: since 0.7.10, Brave has changed the branding |
|
1993
|
|
|
|
|
|
|
# of GitHub's 'Electron' (http://electron.atom.io/) to 'Brave'. |
|
1994
|
|
|
|
|
|
|
# This means the browser string has both 'brave/' (the browser) |
|
1995
|
|
|
|
|
|
|
# and 'Brave/' (re-branded Electron) in it. |
|
1996
|
|
|
|
|
|
|
# The generic section below looks at $self->{browser_string}, which is 'Brave' |
|
1997
|
|
|
|
|
|
|
# (Electron) and not $self->{browser} which is 'brave'. |
|
1998
|
|
|
|
|
|
|
# Caveat parser. |
|
1999
|
12
|
50
|
|
|
|
92
|
if ( $ua =~ m{brave/(\d+)\.(\d+)([\d.]*)} ) { |
|
2000
|
12
|
|
|
|
|
34
|
$major = $1; |
|
2001
|
12
|
|
|
|
|
26
|
$minor = $2; |
|
2002
|
12
|
|
|
|
|
25
|
$beta = $3; |
|
2003
|
|
|
|
|
|
|
} |
|
2004
|
|
|
|
|
|
|
} |
|
2005
|
|
|
|
|
|
|
elsif ($browser eq 'chrome' |
|
2006
|
|
|
|
|
|
|
&& $ua =~ m{crios/(\d+)\.(\d+)([\d.]*)} ) { |
|
2007
|
18
|
|
|
|
|
57
|
$major = $1; |
|
2008
|
18
|
|
|
|
|
34
|
$minor = $2; |
|
2009
|
18
|
|
|
|
|
187
|
$beta = $3; |
|
2010
|
|
|
|
|
|
|
} |
|
2011
|
|
|
|
|
|
|
elsif ($browser eq 'pubsub' |
|
2012
|
|
|
|
|
|
|
&& $ua =~ m{apple-pubsub/(\d+)\.?(\d+)?([\d.]*)} ) { |
|
2013
|
6
|
|
|
|
|
21
|
$major = $1; |
|
2014
|
6
|
|
|
|
|
15
|
$minor = $2; |
|
2015
|
6
|
|
|
|
|
11
|
$beta = $3; |
|
2016
|
|
|
|
|
|
|
} |
|
2017
|
|
|
|
|
|
|
elsif ($browser eq 'obigo' |
|
2018
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m{(obigo[\w\-]*|teleca)[\/ ]\w(\d+)(\w*)}i ) |
|
2019
|
|
|
|
|
|
|
{ |
|
2020
|
78
|
|
|
|
|
268
|
$major = $2; |
|
2021
|
78
|
|
|
|
|
160
|
$minor = q{}; |
|
2022
|
78
|
|
|
|
|
166
|
$beta = $3; |
|
2023
|
|
|
|
|
|
|
} |
|
2024
|
|
|
|
|
|
|
elsif ($browser eq 'polaris' |
|
2025
|
|
|
|
|
|
|
&& $ua =~ m{polaris[ \/](\d+)\.?(\d+)?([\d\.]*)} ) { |
|
2026
|
6
|
|
|
|
|
21
|
$major = $1; |
|
2027
|
6
|
|
|
|
|
14
|
$minor = $2; |
|
2028
|
6
|
|
|
|
|
11
|
$beta = $3; |
|
2029
|
|
|
|
|
|
|
} |
|
2030
|
|
|
|
|
|
|
elsif ($browser eq 'ucbrowser' |
|
2031
|
|
|
|
|
|
|
&& $ua =~ m{ucbrowser[\/ ]*(\d+)\.?(\d+)?([\d\.]*)} ) { |
|
2032
|
336
|
|
|
|
|
1049
|
$major = $1; |
|
2033
|
336
|
|
|
|
|
672
|
$minor = $2; |
|
2034
|
336
|
|
|
|
|
704
|
$beta = $3; |
|
2035
|
|
|
|
|
|
|
} |
|
2036
|
|
|
|
|
|
|
elsif ( $browser eq 'samsung' && $ua =~ m{samsungbrowser/(\d+)\.(\d+)\s} ) |
|
2037
|
|
|
|
|
|
|
{ |
|
2038
|
6
|
|
|
|
|
19
|
$major = $1; |
|
2039
|
6
|
|
|
|
|
15
|
$minor = $2; |
|
2040
|
|
|
|
|
|
|
} |
|
2041
|
|
|
|
|
|
|
elsif ( $browser_tests->{yandex_browser} ) { |
|
2042
|
36
|
|
|
|
|
142
|
( $major, $minor, $beta ) = (q{}) x 3; # don't guess downstream |
|
2043
|
36
|
50
|
|
|
|
279
|
if ( $self->{user_agent} =~ m{ \b YaBrowser / ([0-9.]+) [ ] }x ) { |
|
2044
|
36
|
|
|
|
|
197
|
( $major, $minor, $beta ) = split /[.]/, $1, 3; |
|
2045
|
36
|
50
|
|
|
|
106
|
if ($beta) { |
|
2046
|
36
|
|
|
|
|
105
|
$beta = q{.} . $beta; |
|
2047
|
|
|
|
|
|
|
} |
|
2048
|
|
|
|
|
|
|
} |
|
2049
|
|
|
|
|
|
|
} |
|
2050
|
|
|
|
|
|
|
|
|
2051
|
|
|
|
|
|
|
# If we didn't match a browser-specific test, we look for |
|
2052
|
|
|
|
|
|
|
# '$browser/x.y.z' |
|
2053
|
7201
|
100
|
100
|
|
|
23211
|
if ( !defined $major && defined $self->{browser_string} ) { |
|
2054
|
2440
|
|
|
|
|
8001
|
my $version_index = index( $ua, lc "$self->{browser_string}/" ); |
|
2055
|
2440
|
100
|
|
|
|
5903
|
if ( $version_index != -1 ) { |
|
2056
|
2243
|
|
|
|
|
6177
|
my $version_str |
|
2057
|
|
|
|
|
|
|
= substr( $ua, $version_index + length($browser) ); |
|
2058
|
2243
|
100
|
|
|
|
13883
|
if ( $version_str =~ m{/(\d+)\.(\d+)([\w.]*)} ) { |
|
2059
|
2232
|
|
|
|
|
5702
|
$major = $1; |
|
2060
|
2232
|
|
|
|
|
4407
|
$minor = $2; |
|
2061
|
2232
|
|
|
|
|
5018
|
$beta = $3; |
|
2062
|
|
|
|
|
|
|
} |
|
2063
|
|
|
|
|
|
|
} |
|
2064
|
|
|
|
|
|
|
} |
|
2065
|
|
|
|
|
|
|
|
|
2066
|
|
|
|
|
|
|
# If that didn't work, we try 'Version/x.y.z' |
|
2067
|
7201
|
100
|
|
|
|
16275
|
if ( !defined $major ) { |
|
2068
|
1169
|
100
|
|
|
|
3359
|
if ( $ua =~ m{version/(\d+)\.(\d+)([\w.]*)} ) { |
|
2069
|
24
|
|
|
|
|
71
|
$major = $1; |
|
2070
|
24
|
|
|
|
|
53
|
$minor = $2; |
|
2071
|
24
|
|
|
|
|
50
|
$beta = $3; |
|
2072
|
|
|
|
|
|
|
} |
|
2073
|
|
|
|
|
|
|
} |
|
2074
|
|
|
|
|
|
|
|
|
2075
|
|
|
|
|
|
|
# If that didn't work, we start guessing. Just grab |
|
2076
|
|
|
|
|
|
|
# anything after a word and a slash. |
|
2077
|
7201
|
100
|
|
|
|
15989
|
if ( !defined $major ) { |
|
2078
|
|
|
|
|
|
|
|
|
2079
|
1145
|
|
|
|
|
7638
|
( $major, $minor, $beta ) = ( |
|
2080
|
|
|
|
|
|
|
$ua =~ m{ |
|
2081
|
|
|
|
|
|
|
\S+ # Greedily catch anything leading up to forward slash. |
|
2082
|
|
|
|
|
|
|
\/ # Version starts with a slash |
|
2083
|
|
|
|
|
|
|
[A-Za-z]* # Eat any letters before the major version |
|
2084
|
|
|
|
|
|
|
( [0-9]+ ) # Major version number is everything before the first dot |
|
2085
|
|
|
|
|
|
|
\. # The first dot |
|
2086
|
|
|
|
|
|
|
([\d]* ) # Minor version number is every digit after the first dot |
|
2087
|
|
|
|
|
|
|
# Throw away remaining numbers and dots |
|
2088
|
|
|
|
|
|
|
( [^\s]* ) # Beta version string is up to next space |
|
2089
|
|
|
|
|
|
|
}x |
|
2090
|
|
|
|
|
|
|
); |
|
2091
|
|
|
|
|
|
|
} |
|
2092
|
|
|
|
|
|
|
|
|
2093
|
|
|
|
|
|
|
# If that didn't work, try even more generic. |
|
2094
|
7201
|
100
|
|
|
|
15025
|
if ( !defined $major ) { |
|
2095
|
|
|
|
|
|
|
|
|
2096
|
324
|
50
|
|
|
|
1190
|
if ( $ua =~ /[A-Za-z]+\/(\d+)\;/ ) { |
|
2097
|
0
|
|
|
|
|
0
|
$major = $1; |
|
2098
|
0
|
|
|
|
|
0
|
$minor = 0; |
|
2099
|
|
|
|
|
|
|
} |
|
2100
|
|
|
|
|
|
|
} |
|
2101
|
|
|
|
|
|
|
|
|
2102
|
|
|
|
|
|
|
# If that didn't work, give up. |
|
2103
|
7201
|
100
|
|
|
|
14891
|
$major = 0 if !$major; |
|
2104
|
7201
|
100
|
|
|
|
13797
|
$minor = 0 if !$minor; |
|
2105
|
7201
|
100
|
100
|
|
|
24388
|
$beta = undef if ( defined $beta && $beta eq q{} ); |
|
2106
|
|
|
|
|
|
|
|
|
2107
|
|
|
|
|
|
|
# Now set version tests |
|
2108
|
|
|
|
|
|
|
|
|
2109
|
7201
|
100
|
|
|
|
15994
|
if ( $browser_tests->{netscape} ) { |
|
2110
|
|
|
|
|
|
|
|
|
2111
|
|
|
|
|
|
|
# Netscape browsers |
|
2112
|
168
|
100
|
|
|
|
540
|
$version_tests->{nav2} = 1 if $major == 2; |
|
2113
|
168
|
100
|
|
|
|
480
|
$version_tests->{nav3} = 1 if $major == 3; |
|
2114
|
168
|
100
|
|
|
|
434
|
$version_tests->{nav4} = 1 if $major == 4; |
|
2115
|
168
|
100
|
|
|
|
550
|
$version_tests->{nav4up} = 1 if $major >= 4; |
|
2116
|
168
|
100
|
100
|
|
|
538
|
$version_tests->{nav45} = 1 if $major == 4 && $minor == 5; |
|
2117
|
168
|
100
|
100
|
|
|
866
|
$version_tests->{nav45up} = 1 |
|
|
|
|
100
|
|
|
|
|
|
2118
|
|
|
|
|
|
|
if ( $major == 4 && ".$minor" >= .5 ) |
|
2119
|
|
|
|
|
|
|
|| $major >= 5; |
|
2120
|
168
|
100
|
100
|
|
|
591
|
$version_tests->{navgold} = 1 |
|
2121
|
|
|
|
|
|
|
if defined $beta && ( index( $beta, 'gold' ) != -1 ); |
|
2122
|
168
|
100
|
100
|
|
|
590
|
$version_tests->{nav6} = 1 |
|
2123
|
|
|
|
|
|
|
if ( $major == 5 || $major == 6 ); # go figure |
|
2124
|
168
|
100
|
|
|
|
438
|
$version_tests->{nav6up} = 1 if $major >= 5; |
|
2125
|
|
|
|
|
|
|
|
|
2126
|
168
|
100
|
|
|
|
428
|
if ( $browser eq 'seamonkey' ) { |
|
2127
|
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
# Ugh, seamonkey versions started back at 1. |
|
2129
|
6
|
|
|
|
|
13
|
$version_tests->{nav2} = 0; |
|
2130
|
6
|
|
|
|
|
14
|
$version_tests->{nav4up} = 1; |
|
2131
|
6
|
|
|
|
|
16
|
$version_tests->{nav45up} = 1; |
|
2132
|
6
|
|
|
|
|
13
|
$version_tests->{nav6} = 1; |
|
2133
|
6
|
|
|
|
|
18
|
$version_tests->{nav6up} = 1; |
|
2134
|
|
|
|
|
|
|
} |
|
2135
|
|
|
|
|
|
|
} |
|
2136
|
|
|
|
|
|
|
|
|
2137
|
7201
|
100
|
|
|
|
16009
|
if ( $browser_tests->{ie} ) { |
|
2138
|
1708
|
100
|
|
|
|
4465
|
$version_tests->{ie3} = 1 if ( $major == 3 ); |
|
2139
|
1708
|
100
|
|
|
|
3717
|
$version_tests->{ie4} = 1 if ( $major == 4 ); |
|
2140
|
1708
|
100
|
|
|
|
4889
|
$version_tests->{ie4up} = 1 if ( $major >= 4 ); |
|
2141
|
1708
|
100
|
|
|
|
3851
|
$version_tests->{ie5} = 1 if ( $major == 5 ); |
|
2142
|
1708
|
100
|
|
|
|
4101
|
$version_tests->{ie5up} = 1 if ( $major >= 5 ); |
|
2143
|
1708
|
100
|
100
|
|
|
4359
|
$version_tests->{ie55} = 1 if ( $major == 5 && $minor == 5 ); |
|
2144
|
1708
|
100
|
100
|
|
|
10320
|
$version_tests->{ie55up} = 1 if ( ".$minor" >= .5 || $major >= 6 ); |
|
2145
|
1708
|
100
|
|
|
|
4253
|
$version_tests->{ie6} = 1 if ( $major == 6 ); |
|
2146
|
1708
|
100
|
|
|
|
3588
|
$version_tests->{ie7} = 1 if ( $major == 7 ); |
|
2147
|
1708
|
100
|
|
|
|
3293
|
$version_tests->{ie8} = 1 if ( $major == 8 ); |
|
2148
|
1708
|
100
|
|
|
|
3288
|
$version_tests->{ie9} = 1 if ( $major == 9 ); |
|
2149
|
1708
|
100
|
|
|
|
3463
|
$version_tests->{ie10} = 1 if ( $major == 10 ); |
|
2150
|
1708
|
100
|
|
|
|
3323
|
$version_tests->{ie11} = 1 if ( $major == 11 ); |
|
2151
|
|
|
|
|
|
|
|
|
2152
|
|
|
|
|
|
|
$version_tests->{ie_compat_mode} |
|
2153
|
|
|
|
|
|
|
= ( $version_tests->{ie7} |
|
2154
|
|
|
|
|
|
|
&& $tests->{trident} |
|
2155
|
1708
|
|
100
|
|
|
5038
|
&& defined $self->engine_version |
|
2156
|
|
|
|
|
|
|
&& $self->engine_version >= 4 ); |
|
2157
|
|
|
|
|
|
|
} |
|
2158
|
|
|
|
|
|
|
|
|
2159
|
7201
|
100
|
|
|
|
15322
|
if ( $browser_tests->{aol} ) { |
|
2160
|
|
|
|
|
|
|
$version_tests->{aol3} = 1 |
|
2161
|
|
|
|
|
|
|
if ( index( $ua, 'aol 3.0' ) != -1 |
|
2162
|
41
|
100
|
66
|
|
|
238
|
|| $version_tests->{ie3} ); |
|
2163
|
|
|
|
|
|
|
$version_tests->{aol4} = 1 |
|
2164
|
|
|
|
|
|
|
if ( index( $ua, 'aol 4.0' ) != -1 ) |
|
2165
|
41
|
50
|
33
|
|
|
196
|
|| $version_tests->{ie4}; |
|
2166
|
41
|
50
|
|
|
|
121
|
$version_tests->{aol5} = 1 if index( $ua, 'aol 5.0' ) != -1; |
|
2167
|
41
|
100
|
|
|
|
111
|
$version_tests->{aol6} = 1 if index( $ua, 'aol 6.0' ) != -1; |
|
2168
|
41
|
50
|
|
|
|
113
|
$version_tests->{aoltv} = 1 if index( $ua, 'navio' ) != -1; |
|
2169
|
|
|
|
|
|
|
} |
|
2170
|
|
|
|
|
|
|
|
|
2171
|
7201
|
100
|
|
|
|
15955
|
if ( $browser_tests->{opera} ) { |
|
2172
|
264
|
100
|
66
|
|
|
1407
|
$version_tests->{opera3} = 1 |
|
2173
|
|
|
|
|
|
|
if index( $ua, 'opera 3' ) != -1 || index( $ua, 'opera/3' ) != -1; |
|
2174
|
264
|
50
|
66
|
|
|
1222
|
$version_tests->{opera4} = 1 |
|
|
|
|
33
|
|
|
|
|
|
2175
|
|
|
|
|
|
|
if ( index( $ua, 'opera 4' ) != -1 ) |
|
2176
|
|
|
|
|
|
|
|| ( index( $ua, 'opera/4' ) != -1 |
|
2177
|
|
|
|
|
|
|
&& ( index( $ua, 'nintendo dsi' ) == -1 ) ); |
|
2178
|
264
|
50
|
33
|
|
|
1132
|
$version_tests->{opera5} = 1 |
|
2179
|
|
|
|
|
|
|
if ( index( $ua, 'opera 5' ) != -1 ) |
|
2180
|
|
|
|
|
|
|
|| ( index( $ua, 'opera/5' ) != -1 ); |
|
2181
|
264
|
100
|
66
|
|
|
1119
|
$version_tests->{opera6} = 1 |
|
2182
|
|
|
|
|
|
|
if ( index( $ua, 'opera 6' ) != -1 ) |
|
2183
|
|
|
|
|
|
|
|| ( index( $ua, 'opera/6' ) != -1 ); |
|
2184
|
264
|
100
|
100
|
|
|
1074
|
$version_tests->{opera7} = 1 |
|
2185
|
|
|
|
|
|
|
if ( index( $ua, 'opera 7' ) != -1 ) |
|
2186
|
|
|
|
|
|
|
|| ( index( $ua, 'opera/7' ) != -1 ); |
|
2187
|
|
|
|
|
|
|
|
|
2188
|
|
|
|
|
|
|
} |
|
2189
|
|
|
|
|
|
|
|
|
2190
|
7201
|
|
|
|
|
15938
|
$minor = ".$minor"; |
|
2191
|
|
|
|
|
|
|
|
|
2192
|
7201
|
|
|
|
|
18780
|
$self->{major} = $major; |
|
2193
|
7201
|
|
|
|
|
17111
|
$self->{minor} = $minor; |
|
2194
|
7201
|
|
|
|
|
18423
|
$self->{beta} = $beta; |
|
2195
|
|
|
|
|
|
|
} |
|
2196
|
|
|
|
|
|
|
|
|
2197
|
|
|
|
|
|
|
### Device tests, only run on demand |
|
2198
|
|
|
|
|
|
|
|
|
2199
|
|
|
|
|
|
|
sub _init_device { |
|
2200
|
8311
|
|
|
8311
|
|
14205
|
my ($self) = @_; |
|
2201
|
|
|
|
|
|
|
|
|
2202
|
8311
|
|
|
|
|
19848
|
my $ua = lc $self->{user_agent}; |
|
2203
|
8311
|
|
|
|
|
13597
|
my $browser_tests = $self->{browser_tests}; |
|
2204
|
8311
|
|
|
|
|
13277
|
my $tests = $self->{tests}; |
|
2205
|
|
|
|
|
|
|
|
|
2206
|
8311
|
|
|
|
|
12858
|
my ( $device, $device_string ); |
|
2207
|
8311
|
|
|
|
|
19514
|
my $device_tests = $self->{device_tests} = {}; |
|
2208
|
|
|
|
|
|
|
|
|
2209
|
8311
|
100
|
100
|
|
|
270640
|
if ( index( $ua, 'windows phone' ) != -1 ) { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
2210
|
54
|
|
|
|
|
119
|
$device = 'winphone'; |
|
2211
|
|
|
|
|
|
|
|
|
2212
|
|
|
|
|
|
|
# Test is set in _init_os() |
|
2213
|
|
|
|
|
|
|
} |
|
2214
|
|
|
|
|
|
|
elsif (index( $ua, 'android' ) != -1 |
|
2215
|
|
|
|
|
|
|
|| index( $ua, 'silk-accelerated' ) != -1 ) { |
|
2216
|
|
|
|
|
|
|
|
|
2217
|
|
|
|
|
|
|
# Silk-accelerated indicates a 1st generation Kindle Fire, |
|
2218
|
|
|
|
|
|
|
# which may not have other indications of being an Android |
|
2219
|
|
|
|
|
|
|
# device. |
|
2220
|
1014
|
|
|
|
|
1765
|
$device = 'android'; |
|
2221
|
1014
|
|
|
|
|
2313
|
$device_tests->{$device} = 1; |
|
2222
|
|
|
|
|
|
|
} |
|
2223
|
|
|
|
|
|
|
elsif (index( $ua, 'blackberry' ) != -1 |
|
2224
|
|
|
|
|
|
|
|| index( $ua, 'bb10' ) != -1 |
|
2225
|
|
|
|
|
|
|
|| index( $ua, 'rim tablet os' ) != -1 ) { |
|
2226
|
42
|
|
|
|
|
75
|
$device = 'blackberry'; |
|
2227
|
42
|
|
|
|
|
111
|
$device_tests->{$device} = 1; |
|
2228
|
|
|
|
|
|
|
} |
|
2229
|
|
|
|
|
|
|
elsif ( index( $ua, 'ipod' ) != -1 ) { |
|
2230
|
18
|
|
|
|
|
32
|
$device = 'ipod'; |
|
2231
|
18
|
|
|
|
|
44
|
$device_tests->{$device} = 1; |
|
2232
|
|
|
|
|
|
|
} |
|
2233
|
|
|
|
|
|
|
elsif ( index( $ua, 'ipad' ) != -1 ) { |
|
2234
|
162
|
|
|
|
|
306
|
$device = 'ipad'; |
|
2235
|
162
|
|
|
|
|
401
|
$device_tests->{$device} = 1; |
|
2236
|
|
|
|
|
|
|
} |
|
2237
|
|
|
|
|
|
|
elsif ( index( $ua, 'iphone' ) != -1 ) { |
|
2238
|
240
|
|
|
|
|
413
|
$device = 'iphone'; |
|
2239
|
240
|
|
|
|
|
573
|
$device_tests->{$device} = 1; |
|
2240
|
|
|
|
|
|
|
} |
|
2241
|
|
|
|
|
|
|
elsif ( index( $ua, 'webos' ) != -1 ) { |
|
2242
|
6
|
|
|
|
|
12
|
$device = 'webos'; |
|
2243
|
6
|
|
|
|
|
19
|
$device_tests->{$device} = 1; |
|
2244
|
|
|
|
|
|
|
} |
|
2245
|
|
|
|
|
|
|
elsif ( index( $ua, 'kindle' ) != -1 ) { |
|
2246
|
12
|
|
|
|
|
25
|
$device = 'kindle'; |
|
2247
|
12
|
|
|
|
|
28
|
$device_tests->{$device} = 1; |
|
2248
|
|
|
|
|
|
|
} |
|
2249
|
|
|
|
|
|
|
elsif ( index( $ua, 'audrey' ) != -1 ) { |
|
2250
|
0
|
|
|
|
|
0
|
$device = 'audrey'; |
|
2251
|
0
|
|
|
|
|
0
|
$device_tests->{$device} = 1; |
|
2252
|
|
|
|
|
|
|
} |
|
2253
|
|
|
|
|
|
|
elsif ( index( $ua, 'i-opener' ) != -1 ) { |
|
2254
|
0
|
|
|
|
|
0
|
$device = 'iopener'; |
|
2255
|
0
|
|
|
|
|
0
|
$device_tests->{$device} = 1; |
|
2256
|
|
|
|
|
|
|
} |
|
2257
|
|
|
|
|
|
|
elsif ( index( $ua, 'avantgo' ) != -1 ) { |
|
2258
|
0
|
|
|
|
|
0
|
$device = 'avantgo'; |
|
2259
|
0
|
|
|
|
|
0
|
$device_tests->{$device} = 1; |
|
2260
|
0
|
|
|
|
|
0
|
$device_tests->{palm} = 1; |
|
2261
|
|
|
|
|
|
|
} |
|
2262
|
|
|
|
|
|
|
elsif ( index( $ua, 'palmos' ) != -1 ) { |
|
2263
|
0
|
|
|
|
|
0
|
$device = 'palm'; |
|
2264
|
0
|
|
|
|
|
0
|
$device_tests->{$device} = 1; |
|
2265
|
|
|
|
|
|
|
} |
|
2266
|
|
|
|
|
|
|
elsif ( index( $ua, 'playstation 3' ) != -1 ) { |
|
2267
|
6
|
|
|
|
|
15
|
$device = 'ps3'; |
|
2268
|
6
|
|
|
|
|
16
|
$device_tests->{$device} = 1; |
|
2269
|
|
|
|
|
|
|
} |
|
2270
|
|
|
|
|
|
|
elsif ( index( $ua, 'playstation portable' ) != -1 ) { |
|
2271
|
6
|
|
|
|
|
10
|
$device = 'psp'; |
|
2272
|
6
|
|
|
|
|
16
|
$device_tests->{$device} = 1; |
|
2273
|
|
|
|
|
|
|
} |
|
2274
|
|
|
|
|
|
|
elsif ( index( $ua, 'nintendo dsi' ) != -1 ) { |
|
2275
|
6
|
|
|
|
|
13
|
$device = 'dsi'; |
|
2276
|
6
|
|
|
|
|
22
|
$device_tests->{$device} = 1; |
|
2277
|
|
|
|
|
|
|
} |
|
2278
|
|
|
|
|
|
|
elsif ( index( $ua, 'nintendo 3ds' ) != -1 ) { |
|
2279
|
6
|
|
|
|
|
14
|
$device = 'n3ds'; |
|
2280
|
6
|
|
|
|
|
16
|
$device_tests->{$device} = 1; |
|
2281
|
|
|
|
|
|
|
} |
|
2282
|
|
|
|
|
|
|
elsif ( |
|
2283
|
|
|
|
|
|
|
$browser_tests->{obigo} |
|
2284
|
|
|
|
|
|
|
|| $browser_tests->{ucbrowser} |
|
2285
|
|
|
|
|
|
|
|| index( $ua, 'up.browser' ) != -1 |
|
2286
|
|
|
|
|
|
|
|| ( index( $ua, 'nokia' ) != -1 |
|
2287
|
|
|
|
|
|
|
&& index( $ua, 'windows phone' ) == -1 ) |
|
2288
|
|
|
|
|
|
|
|| index( $ua, 'alcatel' ) != -1 |
|
2289
|
|
|
|
|
|
|
|| $ua =~ m{\bbrew\b} |
|
2290
|
|
|
|
|
|
|
|| $ua =~ m{\bbmp\b} |
|
2291
|
|
|
|
|
|
|
|| index( $ua, 'ericsson' ) != -1 |
|
2292
|
|
|
|
|
|
|
|| index( $ua, 'sie-' ) == 0 |
|
2293
|
|
|
|
|
|
|
|| index( $ua, 'wmlib' ) != -1 |
|
2294
|
|
|
|
|
|
|
|| index( $ua, ' wap' ) != -1 |
|
2295
|
|
|
|
|
|
|
|| index( $ua, 'wap ' ) != -1 |
|
2296
|
|
|
|
|
|
|
|| index( $ua, 'wap/' ) != -1 |
|
2297
|
|
|
|
|
|
|
|| index( $ua, '-wap' ) != -1 |
|
2298
|
|
|
|
|
|
|
|| index( $ua, 'wap-' ) != -1 |
|
2299
|
|
|
|
|
|
|
|| index( $ua, 'wap' ) == 0 |
|
2300
|
|
|
|
|
|
|
|| index( $ua, 'wapper' ) != -1 |
|
2301
|
|
|
|
|
|
|
|| index( $ua, 'zetor' ) != -1 |
|
2302
|
|
|
|
|
|
|
) { |
|
2303
|
582
|
|
|
|
|
1205
|
$device = 'wap'; |
|
2304
|
582
|
|
|
|
|
1339
|
$device_tests->{$device} = 1; |
|
2305
|
|
|
|
|
|
|
} |
|
2306
|
|
|
|
|
|
|
|
|
2307
|
|
|
|
|
|
|
$device_tests->{tablet} = ( |
|
2308
|
|
|
|
|
|
|
index( $ua, 'ipad' ) != -1 |
|
2309
|
|
|
|
|
|
|
|| ( $browser_tests->{ie} |
|
2310
|
|
|
|
|
|
|
&& index( $ua, 'windows phone' ) == -1 |
|
2311
|
|
|
|
|
|
|
&& index( $ua, 'arm' ) != -1 ) |
|
2312
|
|
|
|
|
|
|
|| ( index( $ua, 'android' ) != -1 |
|
2313
|
|
|
|
|
|
|
&& index( $ua, 'mobile' ) == -1 |
|
2314
|
|
|
|
|
|
|
&& index( $ua, 'safari' ) != -1 ) |
|
2315
|
8311
|
|
66
|
|
|
304450
|
|| ( $browser_tests->{firefox} && index( $ua, 'tablet' ) != -1 ) |
|
2316
|
|
|
|
|
|
|
|| index( $ua, 'an10bg3' ) != -1 |
|
2317
|
|
|
|
|
|
|
|| index( $ua, 'an10bg3dt' ) != -1 |
|
2318
|
|
|
|
|
|
|
|| index( $ua, 'an10g2' ) != -1 |
|
2319
|
|
|
|
|
|
|
|| index( $ua, 'an7bg3' ) != -1 |
|
2320
|
|
|
|
|
|
|
|| index( $ua, 'an7dg3' ) != -1 |
|
2321
|
|
|
|
|
|
|
|| index( $ua, 'an7dg3childpad' ) != -1 |
|
2322
|
|
|
|
|
|
|
|| index( $ua, 'an7dg3st' ) != -1 |
|
2323
|
|
|
|
|
|
|
|| index( $ua, 'an7fg3' ) != -1 |
|
2324
|
|
|
|
|
|
|
|| index( $ua, 'an7g3' ) != -1 |
|
2325
|
|
|
|
|
|
|
|| index( $ua, 'an8cg3' ) != -1 |
|
2326
|
|
|
|
|
|
|
|| index( $ua, 'an8g3' ) != -1 |
|
2327
|
|
|
|
|
|
|
|| index( $ua, 'an9g3' ) != -1 |
|
2328
|
|
|
|
|
|
|
|| index( $ua, 'flyer' ) != -1 |
|
2329
|
|
|
|
|
|
|
|| index( $ua, 'hp-tablet' ) != -1 |
|
2330
|
|
|
|
|
|
|
|| index( $ua, 'jetstream' ) != -1 |
|
2331
|
|
|
|
|
|
|
|| index( $ua, 'kindle' ) != -1 |
|
2332
|
|
|
|
|
|
|
|| index( $ua, 'novo7' ) != -1 |
|
2333
|
|
|
|
|
|
|
|| index( $ua, 'opera tablet' ) != -1 |
|
2334
|
|
|
|
|
|
|
|| index( $ua, 'rim tablet' ) != -1 |
|
2335
|
|
|
|
|
|
|
|| index( $ua, 'transformer' ) != -1 |
|
2336
|
|
|
|
|
|
|
|| index( $ua, 'xoom' ) != -1 |
|
2337
|
|
|
|
|
|
|
); |
|
2338
|
|
|
|
|
|
|
|
|
2339
|
8311
|
100
|
|
|
|
19932
|
if ( !$device_tests->{tablet} ) { |
|
2340
|
|
|
|
|
|
|
$device_tests->{mobile} = ( |
|
2341
|
|
|
|
|
|
|
( $browser_tests->{firefox} && index( $ua, 'mobile' ) != -1 ) |
|
2342
|
|
|
|
|
|
|
|| ( $browser_tests->{ie} |
|
2343
|
|
|
|
|
|
|
&& index( $ua, 'windows phone' ) == -1 |
|
2344
|
|
|
|
|
|
|
&& index( $ua, 'arm' ) != -1 ) |
|
2345
|
|
|
|
|
|
|
|| index( $ua, 'windows phone' ) != -1 |
|
2346
|
|
|
|
|
|
|
|| index( $ua, 'up.browser' ) != -1 |
|
2347
|
|
|
|
|
|
|
|| index( $ua, 'nokia' ) != -1 |
|
2348
|
|
|
|
|
|
|
|| index( $ua, 'alcatel' ) != -1 |
|
2349
|
|
|
|
|
|
|
|| index( $ua, 'ericsson' ) != -1 |
|
2350
|
|
|
|
|
|
|
|| index( $ua, 'sie-' ) == 0 |
|
2351
|
|
|
|
|
|
|
|| index( $ua, 'wmlib' ) != -1 |
|
2352
|
|
|
|
|
|
|
|| index( $ua, ' wap' ) != -1 |
|
2353
|
|
|
|
|
|
|
|| index( $ua, 'wap ' ) != -1 |
|
2354
|
|
|
|
|
|
|
|| index( $ua, 'wap/' ) != -1 |
|
2355
|
|
|
|
|
|
|
|| index( $ua, '-wap' ) != -1 |
|
2356
|
|
|
|
|
|
|
|| index( $ua, 'wap-' ) != -1 |
|
2357
|
|
|
|
|
|
|
|| index( $ua, 'wap' ) == 0 |
|
2358
|
|
|
|
|
|
|
|| index( $ua, 'wapper' ) != -1 |
|
2359
|
|
|
|
|
|
|
|| index( $ua, 'blackberry' ) != -1 |
|
2360
|
|
|
|
|
|
|
|| index( $ua, 'mobile' ) != -1 |
|
2361
|
|
|
|
|
|
|
|| index( $ua, 'palm' ) != -1 |
|
2362
|
|
|
|
|
|
|
|| index( $ua, 'smartphone' ) != -1 |
|
2363
|
|
|
|
|
|
|
|| index( $ua, 'windows ce' ) != -1 |
|
2364
|
|
|
|
|
|
|
|| index( $ua, 'palmsource' ) != -1 |
|
2365
|
|
|
|
|
|
|
|| index( $ua, 'iphone' ) != -1 |
|
2366
|
|
|
|
|
|
|
|| index( $ua, 'ipod' ) != -1 |
|
2367
|
|
|
|
|
|
|
|| index( $ua, 'ipad' ) != -1 |
|
2368
|
|
|
|
|
|
|
|| ( index( $ua, 'opera mini' ) != -1 |
|
2369
|
|
|
|
|
|
|
&& index( $ua, 'tablet' ) == -1 ) |
|
2370
|
|
|
|
|
|
|
|| index( $ua, 'htc_' ) != -1 |
|
2371
|
|
|
|
|
|
|
|| index( $ua, 'symbian' ) != -1 |
|
2372
|
|
|
|
|
|
|
|| index( $ua, 'webos' ) != -1 |
|
2373
|
|
|
|
|
|
|
|| index( $ua, 'samsung' ) != -1 |
|
2374
|
|
|
|
|
|
|
|| index( $ua, 'zetor' ) != -1 |
|
2375
|
|
|
|
|
|
|
|| index( $ua, 'android' ) != -1 |
|
2376
|
|
|
|
|
|
|
|| index( $ua, 'symbos' ) != -1 |
|
2377
|
|
|
|
|
|
|
|| index( $ua, 'opera mobi' ) != -1 |
|
2378
|
|
|
|
|
|
|
|| index( $ua, 'fennec' ) != -1 |
|
2379
|
|
|
|
|
|
|
|| $ua =~ m{\bbrew\b} |
|
2380
|
|
|
|
|
|
|
|| index( $ua, 'obigo' ) != -1 |
|
2381
|
|
|
|
|
|
|
|| index( $ua, 'teleca' ) != -1 |
|
2382
|
|
|
|
|
|
|
|| index( $ua, 'polaris' ) != -1 |
|
2383
|
|
|
|
|
|
|
|| index( $ua, 'opera tablet' ) != -1 |
|
2384
|
|
|
|
|
|
|
|| index( $ua, 'rim tablet' ) != -1 |
|
2385
|
|
|
|
|
|
|
|| ( index( $ua, 'bb10' ) != -1 |
|
2386
|
|
|
|
|
|
|
&& index( $ua, 'mobile' ) != -1 ) |
|
2387
|
|
|
|
|
|
|
|| $device_tests->{psp} |
|
2388
|
|
|
|
|
|
|
|| $device_tests->{dsi} |
|
2389
|
7970
|
|
100
|
|
|
402307
|
|| $device_tests->{'n3ds'} |
|
2390
|
|
|
|
|
|
|
); |
|
2391
|
|
|
|
|
|
|
} |
|
2392
|
|
|
|
|
|
|
|
|
2393
|
8311
|
100
|
100
|
|
|
194420
|
if ( $browser_tests->{ucbrowser} |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
&& $self->{user_agent} |
|
2395
|
|
|
|
|
|
|
=~ m{ucweb/2.0\s*\(([^\;\)]*\;){3,4}\s*([^\;\)]*?)\s*\)}i ) { |
|
2396
|
276
|
|
|
|
|
966
|
$device_string = $2; |
|
2397
|
|
|
|
|
|
|
} |
|
2398
|
|
|
|
|
|
|
elsif ( $ua =~ /^(\bmot-[^ \/]+)/ ) { |
|
2399
|
12
|
|
|
|
|
52
|
$device_string = substr $self->{user_agent}, 0, length $1; |
|
2400
|
12
|
|
|
|
|
51
|
$device_string =~ s/^MOT-/Motorola /i; |
|
2401
|
|
|
|
|
|
|
} |
|
2402
|
|
|
|
|
|
|
elsif ( ( $browser_tests->{obigo} || index( $ua, 'brew' ) != -1 ) |
|
2403
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m{\d+x\d+ ([\d\w\- ]+?)( \S+\/\S+)*$}i ) { |
|
2404
|
108
|
|
|
|
|
359
|
$device_string = $1; |
|
2405
|
|
|
|
|
|
|
} |
|
2406
|
|
|
|
|
|
|
elsif ( |
|
2407
|
|
|
|
|
|
|
$ua =~ /windows phone os [^\)]+ iemobile\/[^;]+; ([^;]+; [^;\)]+)/g ) |
|
2408
|
|
|
|
|
|
|
{ |
|
2409
|
|
|
|
|
|
|
# windows phone 7.x |
|
2410
|
|
|
|
|
|
|
$device_string = substr $self->{user_agent}, |
|
2411
|
18
|
|
|
|
|
100
|
pos($ua) - length $1, length $1; |
|
2412
|
18
|
|
|
|
|
75
|
$device_string =~ s/; / /; |
|
2413
|
|
|
|
|
|
|
} |
|
2414
|
|
|
|
|
|
|
elsif ( $ua |
|
2415
|
|
|
|
|
|
|
=~ /windows phone [^\)]+ iemobile\/[^;]+; arm; touch; ([^;]+; [^;\)]+)/g |
|
2416
|
|
|
|
|
|
|
) { |
|
2417
|
|
|
|
|
|
|
# windows phone 8.0 |
|
2418
|
|
|
|
|
|
|
$device_string = substr $self->{user_agent}, |
|
2419
|
12
|
|
|
|
|
57
|
pos($ua) - length $1, length $1; |
|
2420
|
12
|
|
|
|
|
45
|
$device_string =~ s/; / /; |
|
2421
|
|
|
|
|
|
|
} |
|
2422
|
|
|
|
|
|
|
elsif ( |
|
2423
|
|
|
|
|
|
|
$ua =~ /windows phone 8[^\)]+ iemobile\/[^;]+; ([^;]+; [^;\)]+)/g ) { |
|
2424
|
|
|
|
|
|
|
|
|
2425
|
|
|
|
|
|
|
# windows phone 8.1 |
|
2426
|
|
|
|
|
|
|
$device_string = substr $self->{user_agent}, |
|
2427
|
18
|
|
|
|
|
91
|
pos($ua) - length $1, length $1; |
|
2428
|
18
|
|
|
|
|
73
|
$device_string =~ s/; / /; |
|
2429
|
|
|
|
|
|
|
} |
|
2430
|
|
|
|
|
|
|
elsif ( $ua =~ /bb10; ([^;\)]+)/g ) { |
|
2431
|
|
|
|
|
|
|
$device_string = 'BlackBerry ' . substr $self->{user_agent}, |
|
2432
|
12
|
|
|
|
|
67
|
pos($ua) - length $1, length $1; |
|
2433
|
12
|
|
|
|
|
36
|
$device_string =~ s/Kbd/Q10/; |
|
2434
|
|
|
|
|
|
|
} |
|
2435
|
|
|
|
|
|
|
elsif ( $ua =~ /blackberry ([\w.]+)/ ) { |
|
2436
|
6
|
|
|
|
|
25
|
$device_string = "BlackBerry $1"; |
|
2437
|
|
|
|
|
|
|
} |
|
2438
|
|
|
|
|
|
|
elsif ( $ua =~ /blackberry(\d+)\// ) { |
|
2439
|
18
|
|
|
|
|
71
|
$device_string = "BlackBerry $1"; |
|
2440
|
|
|
|
|
|
|
} |
|
2441
|
|
|
|
|
|
|
elsif ( $ua =~ /silk-accelerated/ ) { |
|
2442
|
|
|
|
|
|
|
|
|
2443
|
|
|
|
|
|
|
# Only first generation Kindle Fires have that string |
|
2444
|
12
|
|
|
|
|
29
|
$device_string = 'Kindle Fire'; |
|
2445
|
12
|
|
|
|
|
28
|
$device_tests->{kindlefire} = 1; |
|
2446
|
|
|
|
|
|
|
} |
|
2447
|
|
|
|
|
|
|
elsif ( $self->{user_agent} =~ /android .*\; ([^;]*) build/i ) { |
|
2448
|
942
|
|
|
|
|
3153
|
my $model = $1; |
|
2449
|
942
|
100
|
100
|
|
|
4632
|
if ( $model =~ m{^KF} || $model =~ m{kindle fire}i ) { |
|
|
|
100
|
|
|
|
|
|
|
2450
|
|
|
|
|
|
|
|
|
2451
|
|
|
|
|
|
|
# We might hit this even if tablet() is false, if we have |
|
2452
|
|
|
|
|
|
|
# a Kindle Fire masquerading as a mobile device. |
|
2453
|
54
|
|
|
|
|
117
|
$device_string = 'Kindle Fire'; |
|
2454
|
54
|
|
|
|
|
137
|
$device_tests->{kindlefire} = 1; |
|
2455
|
|
|
|
|
|
|
} |
|
2456
|
|
|
|
|
|
|
elsif ( $device_tests->{tablet} ) { |
|
2457
|
78
|
|
|
|
|
259
|
$device_string = "Android tablet ($model)"; |
|
2458
|
|
|
|
|
|
|
} |
|
2459
|
|
|
|
|
|
|
else { |
|
2460
|
810
|
|
|
|
|
2521
|
$device_string = "Android ($model)"; |
|
2461
|
|
|
|
|
|
|
} |
|
2462
|
|
|
|
|
|
|
} |
|
2463
|
|
|
|
|
|
|
elsif ( $self->{user_agent} |
|
2464
|
|
|
|
|
|
|
=~ /\b((alcatel|huawei|lg|nokia|samsung|sonyericsson)[\w\-]*)\//i ) { |
|
2465
|
114
|
|
|
|
|
430
|
$device_string = $1; |
|
2466
|
|
|
|
|
|
|
} |
|
2467
|
|
|
|
|
|
|
elsif ( $self->{user_agent} =~ /CrKey/ ) { |
|
2468
|
6
|
|
|
|
|
23
|
$device = 'chromecast'; |
|
2469
|
6
|
|
|
|
|
10
|
$device_string = 'Chromecast'; |
|
2470
|
|
|
|
|
|
|
} |
|
2471
|
|
|
|
|
|
|
elsif ($device) { |
|
2472
|
606
|
|
|
|
|
1788
|
$device_string = $DEVICE_NAMES{$device}; |
|
2473
|
|
|
|
|
|
|
} |
|
2474
|
|
|
|
|
|
|
else { |
|
2475
|
6151
|
|
|
|
|
13024
|
$device_string = undef; |
|
2476
|
|
|
|
|
|
|
} |
|
2477
|
|
|
|
|
|
|
|
|
2478
|
8311
|
100
|
|
|
|
14488
|
if ($device) { |
|
2479
|
2160
|
|
|
|
|
7398
|
$self->{device} = $device; |
|
2480
|
|
|
|
|
|
|
} |
|
2481
|
|
|
|
|
|
|
else { |
|
2482
|
|
|
|
|
|
|
$self->{device} |
|
2483
|
6151
|
|
|
|
|
16911
|
= undef; # Means we cache the fact that we found nothing |
|
2484
|
|
|
|
|
|
|
} |
|
2485
|
|
|
|
|
|
|
|
|
2486
|
8311
|
100
|
|
|
|
22813
|
if ($device_string) { |
|
2487
|
2154
|
|
|
|
|
5962
|
$self->{device_string} = $device_string; |
|
2488
|
|
|
|
|
|
|
} |
|
2489
|
|
|
|
|
|
|
} |
|
2490
|
|
|
|
|
|
|
|
|
2491
|
|
|
|
|
|
|
### Now a big block of public accessors for tests and information |
|
2492
|
|
|
|
|
|
|
|
|
2493
|
|
|
|
|
|
|
sub browser { |
|
2494
|
1726
|
|
|
1726
|
1
|
912734
|
my ($self) = @_; |
|
2495
|
1726
|
50
|
|
|
|
5664
|
return undef unless defined $self->{user_agent}; |
|
2496
|
1726
|
|
|
|
|
7624
|
return $self->{browser}; |
|
2497
|
|
|
|
|
|
|
} |
|
2498
|
|
|
|
|
|
|
|
|
2499
|
|
|
|
|
|
|
sub browser_string { |
|
2500
|
1695
|
|
|
1695
|
1
|
837757
|
my ($self) = @_; |
|
2501
|
1695
|
50
|
|
|
|
5782
|
return undef unless defined $self->{user_agent}; |
|
2502
|
1695
|
|
|
|
|
6955
|
return $self->{browser_string}; |
|
2503
|
|
|
|
|
|
|
} |
|
2504
|
|
|
|
|
|
|
|
|
2505
|
|
|
|
|
|
|
sub robot { |
|
2506
|
2254
|
|
|
2254
|
1
|
2396541
|
my $self = shift; |
|
2507
|
|
|
|
|
|
|
|
|
2508
|
2254
|
100
|
|
|
|
11427
|
$self->_init_robots unless exists( $self->{robot_string} ); |
|
2509
|
2254
|
|
|
|
|
8742
|
return $self->{robot_tests}->{robot}; |
|
2510
|
|
|
|
|
|
|
} |
|
2511
|
|
|
|
|
|
|
|
|
2512
|
|
|
|
|
|
|
sub robot_string { |
|
2513
|
934
|
|
|
934
|
1
|
142616
|
my $self = shift; |
|
2514
|
|
|
|
|
|
|
|
|
2515
|
934
|
100
|
|
|
|
3875
|
$self->_init_robots unless exists( $self->{robot_string} ); |
|
2516
|
934
|
|
|
|
|
3238
|
return $self->{robot_string}; |
|
2517
|
|
|
|
|
|
|
} |
|
2518
|
|
|
|
|
|
|
|
|
2519
|
|
|
|
|
|
|
sub robot_name { |
|
2520
|
140
|
|
|
140
|
0
|
101120
|
my $self = shift; |
|
2521
|
140
|
|
|
|
|
447
|
return $self->robot_string; |
|
2522
|
|
|
|
|
|
|
} |
|
2523
|
|
|
|
|
|
|
|
|
2524
|
|
|
|
|
|
|
sub robot_id { |
|
2525
|
546
|
|
|
546
|
1
|
1696
|
my $self = shift; |
|
2526
|
|
|
|
|
|
|
return |
|
2527
|
|
|
|
|
|
|
$self->{robot_tests}->{robot_id} ? $self->{robot_tests}->{robot_id} |
|
2528
|
546
|
0
|
|
|
|
2128
|
: $self->robot ? $ROBOT_IDS{ $self->robot } |
|
|
|
50
|
|
|
|
|
|
|
2529
|
|
|
|
|
|
|
: undef; |
|
2530
|
|
|
|
|
|
|
} |
|
2531
|
|
|
|
|
|
|
|
|
2532
|
|
|
|
|
|
|
sub _robot_version { |
|
2533
|
415
|
|
|
415
|
|
788
|
my ($self) = @_; |
|
2534
|
415
|
50
|
|
|
|
1244
|
$self->_init_robots unless exists( $self->{robot_string} ); |
|
2535
|
415
|
50
|
|
|
|
1170
|
if ( $self->{robot_version} ) { |
|
2536
|
415
|
|
|
|
|
650
|
return @{ $self->{robot_version} }; |
|
|
415
|
|
|
|
|
1988
|
|
|
2537
|
|
|
|
|
|
|
} |
|
2538
|
|
|
|
|
|
|
else { |
|
2539
|
0
|
|
|
|
|
0
|
return ( undef, undef, undef ); |
|
2540
|
|
|
|
|
|
|
} |
|
2541
|
|
|
|
|
|
|
} |
|
2542
|
|
|
|
|
|
|
|
|
2543
|
|
|
|
|
|
|
sub robot_version { |
|
2544
|
106
|
|
|
106
|
1
|
74337
|
my ($self) = @_; |
|
2545
|
106
|
|
|
|
|
339
|
my ( $major, $minor, $beta ) = $self->_robot_version; |
|
2546
|
106
|
50
|
|
|
|
425
|
if ( defined $major ) { |
|
2547
|
106
|
100
|
|
|
|
268
|
if ( defined $minor ) { |
|
2548
|
105
|
|
|
|
|
640
|
return "$major$minor"; |
|
2549
|
|
|
|
|
|
|
} |
|
2550
|
|
|
|
|
|
|
else { |
|
2551
|
1
|
|
|
|
|
7
|
return $major; |
|
2552
|
|
|
|
|
|
|
} |
|
2553
|
|
|
|
|
|
|
} |
|
2554
|
|
|
|
|
|
|
else { |
|
2555
|
0
|
|
|
|
|
0
|
return undef; |
|
2556
|
|
|
|
|
|
|
} |
|
2557
|
|
|
|
|
|
|
} |
|
2558
|
|
|
|
|
|
|
|
|
2559
|
|
|
|
|
|
|
sub robot_major { |
|
2560
|
102
|
|
|
102
|
1
|
57043
|
my ($self) = @_; |
|
2561
|
102
|
|
|
|
|
364
|
my ( $major, $minor, $beta ) = $self->_robot_version; |
|
2562
|
102
|
|
|
|
|
521
|
return $major; |
|
2563
|
|
|
|
|
|
|
} |
|
2564
|
|
|
|
|
|
|
|
|
2565
|
|
|
|
|
|
|
sub robot_minor { |
|
2566
|
101
|
|
|
101
|
1
|
53482
|
my ($self) = @_; |
|
2567
|
101
|
|
|
|
|
334
|
my ( $major, $minor, $beta ) = $self->_robot_version; |
|
2568
|
101
|
|
|
|
|
495
|
return $minor; |
|
2569
|
|
|
|
|
|
|
} |
|
2570
|
|
|
|
|
|
|
|
|
2571
|
|
|
|
|
|
|
sub robot_beta { |
|
2572
|
106
|
|
|
106
|
1
|
77887
|
my ($self) = @_; |
|
2573
|
106
|
|
|
|
|
341
|
my ( $major, $minor, $beta ) = $self->_robot_version; |
|
2574
|
106
|
|
|
|
|
556
|
return $beta; |
|
2575
|
|
|
|
|
|
|
} |
|
2576
|
|
|
|
|
|
|
|
|
2577
|
|
|
|
|
|
|
sub os { |
|
2578
|
4225
|
|
|
4225
|
1
|
776080
|
my ($self) = @_; |
|
2579
|
|
|
|
|
|
|
|
|
2580
|
4225
|
50
|
|
|
|
11496
|
return undef unless defined $self->{user_agent}; |
|
2581
|
4225
|
100
|
|
|
|
12609
|
$self->_init_os unless $self->{os_tests}; |
|
2582
|
4225
|
|
|
|
|
11424
|
return $self->{os}; |
|
2583
|
|
|
|
|
|
|
} |
|
2584
|
|
|
|
|
|
|
|
|
2585
|
|
|
|
|
|
|
sub os_string { |
|
2586
|
4199
|
|
|
4199
|
1
|
759439
|
my ($self) = @_; |
|
2587
|
|
|
|
|
|
|
|
|
2588
|
4199
|
50
|
|
|
|
11357
|
return undef unless defined $self->{user_agent}; |
|
2589
|
4199
|
100
|
|
|
|
11207
|
$self->_init_os unless $self->{os_tests}; |
|
2590
|
4199
|
|
|
|
|
11057
|
return $self->{os_string}; |
|
2591
|
|
|
|
|
|
|
} |
|
2592
|
|
|
|
|
|
|
|
|
2593
|
|
|
|
|
|
|
sub _os_version { |
|
2594
|
4011
|
|
|
4011
|
|
6986
|
my ($self) = @_; |
|
2595
|
4011
|
100
|
|
|
|
14297
|
$self->_init_os_version if !exists( $self->{os_version} ); |
|
2596
|
4011
|
100
|
|
|
|
9752
|
if ( $self->{os_version} ) { |
|
2597
|
1947
|
|
|
|
|
3147
|
return @{ $self->{os_version} }; |
|
|
1947
|
|
|
|
|
9341
|
|
|
2598
|
|
|
|
|
|
|
} |
|
2599
|
|
|
|
|
|
|
else { |
|
2600
|
2064
|
|
|
|
|
6329
|
return ( undef, undef, undef ); |
|
2601
|
|
|
|
|
|
|
} |
|
2602
|
|
|
|
|
|
|
} |
|
2603
|
|
|
|
|
|
|
|
|
2604
|
|
|
|
|
|
|
sub os_version { |
|
2605
|
998
|
|
|
998
|
1
|
302384
|
my ($self) = @_; |
|
2606
|
998
|
|
|
|
|
3276
|
my ( $major, $minor, $beta ) = $self->_os_version; |
|
2607
|
998
|
100
|
|
|
|
4753
|
return defined $major ? "$major$minor" : undef; |
|
2608
|
|
|
|
|
|
|
} |
|
2609
|
|
|
|
|
|
|
|
|
2610
|
|
|
|
|
|
|
sub os_major { |
|
2611
|
950
|
|
|
950
|
1
|
286607
|
my ($self) = @_; |
|
2612
|
950
|
|
|
|
|
2915
|
my ( $major, $minor, $beta ) = $self->_os_version; |
|
2613
|
950
|
|
|
|
|
3068
|
return $major; |
|
2614
|
|
|
|
|
|
|
} |
|
2615
|
|
|
|
|
|
|
|
|
2616
|
|
|
|
|
|
|
sub os_minor { |
|
2617
|
1029
|
|
|
1029
|
1
|
269086
|
my ($self) = @_; |
|
2618
|
1029
|
|
|
|
|
3274
|
my ( $major, $minor, $beta ) = $self->_os_version; |
|
2619
|
1029
|
|
|
|
|
3335
|
return $minor; |
|
2620
|
|
|
|
|
|
|
} |
|
2621
|
|
|
|
|
|
|
|
|
2622
|
|
|
|
|
|
|
sub os_beta { |
|
2623
|
1034
|
|
|
1034
|
1
|
334854
|
my ($self) = @_; |
|
2624
|
1034
|
|
|
|
|
3505
|
my ( $major, $minor, $beta ) = $self->_os_version; |
|
2625
|
1034
|
|
|
|
|
3985
|
return $beta; |
|
2626
|
|
|
|
|
|
|
} |
|
2627
|
|
|
|
|
|
|
|
|
2628
|
|
|
|
|
|
|
sub _realplayer_version { |
|
2629
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
|
2630
|
|
|
|
|
|
|
|
|
2631
|
0
|
0
|
|
|
|
0
|
$self->_init_version unless $self->{version_tests}; |
|
2632
|
0
|
|
0
|
|
|
0
|
return $self->{realplayer_version} || 0; |
|
2633
|
|
|
|
|
|
|
} |
|
2634
|
|
|
|
|
|
|
|
|
2635
|
|
|
|
|
|
|
sub realplayer_browser { |
|
2636
|
740
|
|
|
740
|
1
|
106373
|
my ($self) = @_; |
|
2637
|
740
|
|
100
|
|
|
4806
|
return defined( $self->{browser} ) && $self->{browser} eq 'realplayer'; |
|
2638
|
|
|
|
|
|
|
} |
|
2639
|
|
|
|
|
|
|
|
|
2640
|
|
|
|
|
|
|
sub gecko_version { |
|
2641
|
684
|
|
|
684
|
1
|
90447
|
my ($self) = @_; |
|
2642
|
|
|
|
|
|
|
|
|
2643
|
684
|
100
|
|
|
|
2049
|
if ( $self->gecko ) { |
|
2644
|
74
|
|
|
|
|
270
|
return $self->{engine_version}; |
|
2645
|
|
|
|
|
|
|
} |
|
2646
|
|
|
|
|
|
|
else { |
|
2647
|
610
|
|
|
|
|
1629
|
return undef; |
|
2648
|
|
|
|
|
|
|
} |
|
2649
|
|
|
|
|
|
|
} |
|
2650
|
|
|
|
|
|
|
|
|
2651
|
|
|
|
|
|
|
sub version { |
|
2652
|
893
|
|
|
893
|
1
|
217008
|
my ($self) = @_; |
|
2653
|
893
|
100
|
|
|
|
3673
|
$self->_init_version() unless $self->{version_tests}; |
|
2654
|
|
|
|
|
|
|
|
|
2655
|
893
|
50
|
|
|
|
4741
|
return defined $self->{major} ? "$self->{major}$self->{minor}" : undef; |
|
2656
|
|
|
|
|
|
|
} |
|
2657
|
|
|
|
|
|
|
|
|
2658
|
|
|
|
|
|
|
sub major { |
|
2659
|
1174
|
|
|
1174
|
1
|
213164
|
my ($self) = @_; |
|
2660
|
1174
|
100
|
|
|
|
3948
|
$self->_init_version() unless $self->{version_tests}; |
|
2661
|
|
|
|
|
|
|
|
|
2662
|
1174
|
|
|
|
|
2760
|
my ($version) = $self->{major}; |
|
2663
|
1174
|
|
|
|
|
3652
|
return $version; |
|
2664
|
|
|
|
|
|
|
} |
|
2665
|
|
|
|
|
|
|
|
|
2666
|
|
|
|
|
|
|
sub minor { |
|
2667
|
964
|
|
|
964
|
1
|
216472
|
my ($self) = @_; |
|
2668
|
964
|
100
|
|
|
|
3897
|
$self->_init_version() unless $self->{version_tests}; |
|
2669
|
|
|
|
|
|
|
|
|
2670
|
964
|
|
|
|
|
3019
|
my ($version) = $self->{minor}; |
|
2671
|
964
|
|
|
|
|
2929
|
return $version; |
|
2672
|
|
|
|
|
|
|
} |
|
2673
|
|
|
|
|
|
|
|
|
2674
|
|
|
|
|
|
|
sub public_version { |
|
2675
|
883
|
|
|
883
|
1
|
209823
|
my ($self) = @_; |
|
2676
|
883
|
|
|
|
|
3235
|
my ( $major, $minor ) = $self->_public; |
|
2677
|
|
|
|
|
|
|
|
|
2678
|
883
|
|
50
|
|
|
2782
|
$minor ||= q{}; |
|
2679
|
883
|
50
|
|
|
|
4490
|
return defined $major ? "$major$minor" : undef; |
|
2680
|
|
|
|
|
|
|
} |
|
2681
|
|
|
|
|
|
|
|
|
2682
|
|
|
|
|
|
|
sub public_major { |
|
2683
|
836
|
|
|
836
|
1
|
196202
|
my ($self) = @_; |
|
2684
|
836
|
|
|
|
|
2785
|
my ( $major, $minor ) = $self->_public; |
|
2685
|
|
|
|
|
|
|
|
|
2686
|
836
|
|
|
|
|
2847
|
return $major; |
|
2687
|
|
|
|
|
|
|
} |
|
2688
|
|
|
|
|
|
|
|
|
2689
|
|
|
|
|
|
|
sub public_minor { |
|
2690
|
934
|
|
|
934
|
1
|
192449
|
my ($self) = @_; |
|
2691
|
934
|
|
|
|
|
3132
|
my ( $major, $minor ) = $self->_public; |
|
2692
|
|
|
|
|
|
|
|
|
2693
|
934
|
|
|
|
|
3453
|
return $minor; |
|
2694
|
|
|
|
|
|
|
} |
|
2695
|
|
|
|
|
|
|
|
|
2696
|
|
|
|
|
|
|
sub public_beta { |
|
2697
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
|
2698
|
0
|
|
|
|
|
0
|
my ( $major, $minor, $beta ) = $self->_public; |
|
2699
|
|
|
|
|
|
|
|
|
2700
|
0
|
|
|
|
|
0
|
return $beta; |
|
2701
|
|
|
|
|
|
|
} |
|
2702
|
|
|
|
|
|
|
|
|
2703
|
|
|
|
|
|
|
sub browser_version { |
|
2704
|
22
|
|
|
22
|
1
|
16524
|
my ($self) = @_; |
|
2705
|
22
|
|
|
|
|
81
|
my ( $major, $minor ) = $self->_public; |
|
2706
|
22
|
|
100
|
|
|
105
|
$minor ||= q{}; |
|
2707
|
|
|
|
|
|
|
|
|
2708
|
22
|
100
|
|
|
|
175
|
return defined $major ? "$major$minor" : undef; |
|
2709
|
|
|
|
|
|
|
} |
|
2710
|
|
|
|
|
|
|
|
|
2711
|
|
|
|
|
|
|
sub browser_major { |
|
2712
|
1451
|
|
|
1451
|
1
|
673467
|
my ($self) = @_; |
|
2713
|
1451
|
|
|
|
|
4464
|
my ( $major, $minor ) = $self->_public; |
|
2714
|
|
|
|
|
|
|
|
|
2715
|
1451
|
|
|
|
|
8166
|
return $major; |
|
2716
|
|
|
|
|
|
|
} |
|
2717
|
|
|
|
|
|
|
|
|
2718
|
|
|
|
|
|
|
sub browser_minor { |
|
2719
|
911
|
|
|
911
|
1
|
655662
|
my ($self) = @_; |
|
2720
|
911
|
|
|
|
|
2851
|
my ( $major, $minor ) = $self->_public; |
|
2721
|
|
|
|
|
|
|
|
|
2722
|
911
|
|
|
|
|
4592
|
return $minor; |
|
2723
|
|
|
|
|
|
|
} |
|
2724
|
|
|
|
|
|
|
|
|
2725
|
|
|
|
|
|
|
sub browser_beta { |
|
2726
|
369
|
|
|
369
|
1
|
278191
|
my ($self) = @_; |
|
2727
|
369
|
|
|
|
|
1206
|
my ( $major, $minor, $beta ) = $self->_public; |
|
2728
|
|
|
|
|
|
|
|
|
2729
|
369
|
|
|
|
|
2100
|
return $beta; |
|
2730
|
|
|
|
|
|
|
} |
|
2731
|
|
|
|
|
|
|
|
|
2732
|
|
|
|
|
|
|
sub _public { |
|
2733
|
5406
|
|
|
5406
|
|
10697
|
my ($self) = @_; |
|
2734
|
|
|
|
|
|
|
|
|
2735
|
|
|
|
|
|
|
# Return Public version of Safari. See RT #48727. |
|
2736
|
5406
|
100
|
|
|
|
13083
|
if ( $self->safari ) { |
|
2737
|
657
|
|
|
|
|
2454
|
my $ua = lc $self->{user_agent}; |
|
2738
|
|
|
|
|
|
|
|
|
2739
|
|
|
|
|
|
|
# Safari starting with version 3.0 provides its own public version |
|
2740
|
657
|
100
|
|
|
|
4255
|
if ( |
|
2741
|
|
|
|
|
|
|
$ua =~ m{ |
|
2742
|
|
|
|
|
|
|
version/ |
|
2743
|
|
|
|
|
|
|
( \d+ ) # Major version number is everything before first dot |
|
2744
|
|
|
|
|
|
|
( \. \d+ )? # Minor version number is first dot and following digits |
|
2745
|
|
|
|
|
|
|
}x |
|
2746
|
|
|
|
|
|
|
) { |
|
2747
|
473
|
|
|
|
|
2981
|
return ( $1, $2, undef ); |
|
2748
|
|
|
|
|
|
|
} |
|
2749
|
|
|
|
|
|
|
|
|
2750
|
|
|
|
|
|
|
# Safari before version 3.0 had only build numbers; use a lookup table |
|
2751
|
|
|
|
|
|
|
# provided by Apple to convert to version numbers |
|
2752
|
|
|
|
|
|
|
|
|
2753
|
184
|
100
|
|
|
|
1217
|
if ( $ua =~ m{ safari/ ( \d+ (?: \.\d+ )* ) }x ) { |
|
2754
|
152
|
|
|
|
|
463
|
my $build = $1; |
|
2755
|
152
|
|
|
|
|
341
|
my $version = $safari_build_to_version{$build}; |
|
2756
|
152
|
100
|
|
|
|
392
|
unless ($version) { |
|
2757
|
|
|
|
|
|
|
|
|
2758
|
|
|
|
|
|
|
# if exact build -> version mapping doesn't exist, find next |
|
2759
|
|
|
|
|
|
|
# lower build |
|
2760
|
|
|
|
|
|
|
|
|
2761
|
111
|
|
|
|
|
1037
|
for my $maybe_build ( |
|
2762
|
8941
|
|
|
|
|
14672
|
sort { $self->_cmp_versions( $b, $a ) } |
|
2763
|
|
|
|
|
|
|
keys %safari_build_to_version |
|
2764
|
|
|
|
|
|
|
) { |
|
2765
|
510
|
100
|
|
|
|
1012
|
$version = $safari_build_to_version{$maybe_build}, last |
|
2766
|
|
|
|
|
|
|
if $self->_cmp_versions( $build, $maybe_build ) >= 0; |
|
2767
|
|
|
|
|
|
|
} |
|
2768
|
|
|
|
|
|
|
|
|
2769
|
|
|
|
|
|
|
# Special case for specific worm that uses a malformed user agent |
|
2770
|
111
|
100
|
|
|
|
613
|
return ( '1', '.2', undef ) if $ua =~ m{safari/12x}; |
|
2771
|
|
|
|
|
|
|
} |
|
2772
|
|
|
|
|
|
|
|
|
2773
|
148
|
100
|
|
|
|
407
|
return ( undef, undef, undef ) unless defined $version; |
|
2774
|
141
|
|
|
|
|
550
|
my ( $major, $minor ) = split /\./, $version; |
|
2775
|
141
|
|
|
|
|
272
|
my $beta; |
|
2776
|
141
|
100
|
|
|
|
503
|
$minor =~ s/(\D.*)// and $beta = $1; |
|
2777
|
141
|
|
|
|
|
344
|
$minor = ( '.' . $minor ); |
|
2778
|
141
|
100
|
|
|
|
815
|
return ( $major, $minor, ( $beta ? 1 : undef ) ); |
|
2779
|
|
|
|
|
|
|
} |
|
2780
|
|
|
|
|
|
|
} |
|
2781
|
|
|
|
|
|
|
|
|
2782
|
4781
|
100
|
|
|
|
15802
|
$self->_init_version() unless $self->{version_tests}; |
|
2783
|
4781
|
|
|
|
|
19940
|
return ( $self->{major}, $self->{minor}, $self->{beta} ); |
|
2784
|
|
|
|
|
|
|
} |
|
2785
|
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
sub _cmp_versions { |
|
2787
|
9451
|
|
|
9451
|
|
15517
|
my ( $self, $a, $b ) = @_; |
|
2788
|
|
|
|
|
|
|
|
|
2789
|
9451
|
|
|
|
|
17733
|
my @a = split /\./, $a; |
|
2790
|
9451
|
|
|
|
|
15234
|
my @b = split /\./, $b; |
|
2791
|
|
|
|
|
|
|
|
|
2792
|
9451
|
|
|
|
|
16429
|
while (@b) { |
|
2793
|
10920
|
100
|
100
|
|
|
37713
|
return -1 if @a == 0 || $a[0] < $b[0]; |
|
2794
|
5537
|
100
|
66
|
|
|
19855
|
return 1 if @b == 0 || $b[0] < $a[0]; |
|
2795
|
1783
|
|
|
|
|
2449
|
shift @a; |
|
2796
|
1783
|
|
|
|
|
3411
|
shift @b; |
|
2797
|
|
|
|
|
|
|
} |
|
2798
|
|
|
|
|
|
|
|
|
2799
|
314
|
|
|
|
|
679
|
return @a <=> @b; |
|
2800
|
|
|
|
|
|
|
} |
|
2801
|
|
|
|
|
|
|
|
|
2802
|
|
|
|
|
|
|
sub engine { |
|
2803
|
1584
|
|
|
1584
|
1
|
743703
|
my ($self) = @_; |
|
2804
|
|
|
|
|
|
|
|
|
2805
|
|
|
|
|
|
|
return |
|
2806
|
1584
|
100
|
|
|
|
4862
|
!$self->engine_string ? undef |
|
|
|
100
|
|
|
|
|
|
|
2807
|
|
|
|
|
|
|
: $self->engine_string eq 'MSIE' ? 'ie' |
|
2808
|
|
|
|
|
|
|
: lc( $self->engine_string ); |
|
2809
|
|
|
|
|
|
|
} |
|
2810
|
|
|
|
|
|
|
|
|
2811
|
|
|
|
|
|
|
sub engine_string { |
|
2812
|
5671
|
|
|
5671
|
1
|
679240
|
my ($self) = @_; |
|
2813
|
|
|
|
|
|
|
|
|
2814
|
5671
|
100
|
|
|
|
12406
|
if ( $self->gecko ) { |
|
2815
|
750
|
|
|
|
|
3236
|
return 'Gecko'; |
|
2816
|
|
|
|
|
|
|
} |
|
2817
|
|
|
|
|
|
|
|
|
2818
|
4921
|
100
|
|
|
|
10913
|
if ( $self->trident ) { |
|
2819
|
1016
|
|
|
|
|
4374
|
return 'Trident'; |
|
2820
|
|
|
|
|
|
|
} |
|
2821
|
|
|
|
|
|
|
|
|
2822
|
3905
|
100
|
|
|
|
8299
|
if ( $self->ie ) { |
|
2823
|
576
|
|
|
|
|
2715
|
return 'MSIE'; |
|
2824
|
|
|
|
|
|
|
} |
|
2825
|
|
|
|
|
|
|
|
|
2826
|
3329
|
100
|
|
|
|
7658
|
if ( $self->edgelegacy ) { |
|
2827
|
31
|
|
|
|
|
142
|
return 'EdgeHTML'; |
|
2828
|
|
|
|
|
|
|
} |
|
2829
|
|
|
|
|
|
|
|
|
2830
|
3298
|
100
|
|
|
|
7039
|
if ( $self->webkit ) { |
|
2831
|
2727
|
|
|
|
|
12969
|
return 'WebKit'; |
|
2832
|
|
|
|
|
|
|
} |
|
2833
|
|
|
|
|
|
|
|
|
2834
|
571
|
100
|
|
|
|
1501
|
if ( $self->presto ) { |
|
2835
|
147
|
|
|
|
|
697
|
return 'Presto'; |
|
2836
|
|
|
|
|
|
|
} |
|
2837
|
|
|
|
|
|
|
|
|
2838
|
424
|
100
|
|
|
|
1077
|
if ( $self->netfront ) { |
|
2839
|
45
|
|
|
|
|
199
|
return 'NetFront'; |
|
2840
|
|
|
|
|
|
|
} |
|
2841
|
|
|
|
|
|
|
|
|
2842
|
379
|
100
|
|
|
|
920
|
if ( $self->khtml ) { |
|
2843
|
11
|
|
|
|
|
53
|
return 'KHTML'; |
|
2844
|
|
|
|
|
|
|
} |
|
2845
|
|
|
|
|
|
|
|
|
2846
|
368
|
|
|
|
|
1066
|
return undef; |
|
2847
|
|
|
|
|
|
|
} |
|
2848
|
|
|
|
|
|
|
|
|
2849
|
|
|
|
|
|
|
sub engine_version { |
|
2850
|
1574
|
|
|
1574
|
1
|
526365
|
my ($self) = @_; |
|
2851
|
|
|
|
|
|
|
|
|
2852
|
|
|
|
|
|
|
return $self->{engine_version} |
|
2853
|
1574
|
100
|
100
|
|
|
18394
|
&& $self->{engine_version} =~ m{^(\d+(\.\d+)?)} ? $1 : undef; |
|
2854
|
|
|
|
|
|
|
} |
|
2855
|
|
|
|
|
|
|
|
|
2856
|
|
|
|
|
|
|
sub engine_major { |
|
2857
|
2224
|
|
|
2224
|
1
|
618544
|
my ($self) = @_; |
|
2858
|
|
|
|
|
|
|
|
|
2859
|
|
|
|
|
|
|
return $self->{engine_version} |
|
2860
|
2224
|
100
|
100
|
|
|
20076
|
&& $self->{engine_version} =~ m{^(\d+)} ? $1 : undef; |
|
2861
|
|
|
|
|
|
|
} |
|
2862
|
|
|
|
|
|
|
|
|
2863
|
|
|
|
|
|
|
sub engine_minor { |
|
2864
|
2112
|
|
|
2112
|
1
|
574960
|
my ($self) = @_; |
|
2865
|
|
|
|
|
|
|
|
|
2866
|
|
|
|
|
|
|
return $self->{engine_version} |
|
2867
|
2112
|
100
|
100
|
|
|
20023
|
&& $self->{engine_version} =~ m{^\d+(\.\d+)} ? $1 : undef; |
|
2868
|
|
|
|
|
|
|
} |
|
2869
|
|
|
|
|
|
|
|
|
2870
|
|
|
|
|
|
|
sub engine_beta { |
|
2871
|
1424
|
|
|
1424
|
1
|
614612
|
my ($self) = @_; |
|
2872
|
|
|
|
|
|
|
|
|
2873
|
|
|
|
|
|
|
return $self->{engine_version} |
|
2874
|
1424
|
100
|
100
|
|
|
17352
|
&& $self->{engine_version} =~ m{^\d+\.\d+([\.\d\+]*)} ? $1 : undef; |
|
2875
|
|
|
|
|
|
|
} |
|
2876
|
|
|
|
|
|
|
|
|
2877
|
|
|
|
|
|
|
sub beta { |
|
2878
|
732
|
|
|
732
|
1
|
98976
|
my ($self) = @_; |
|
2879
|
|
|
|
|
|
|
|
|
2880
|
732
|
100
|
|
|
|
2872
|
$self->_init_version unless $self->{version_tests}; |
|
2881
|
|
|
|
|
|
|
|
|
2882
|
732
|
|
|
|
|
2735
|
my ($version) = $self->{beta}; |
|
2883
|
732
|
|
|
|
|
1993
|
return $version; |
|
2884
|
|
|
|
|
|
|
} |
|
2885
|
|
|
|
|
|
|
|
|
2886
|
|
|
|
|
|
|
sub language { |
|
2887
|
1133
|
|
|
1133
|
1
|
350615
|
my ($self) = @_; |
|
2888
|
|
|
|
|
|
|
|
|
2889
|
1133
|
|
|
|
|
3338
|
my $parsed = $self->_language_country(); |
|
2890
|
1133
|
|
|
|
|
4932
|
return $parsed->{'language'}; |
|
2891
|
|
|
|
|
|
|
} |
|
2892
|
|
|
|
|
|
|
|
|
2893
|
|
|
|
|
|
|
sub country { |
|
2894
|
719
|
|
|
719
|
1
|
96711
|
my ($self) = @_; |
|
2895
|
|
|
|
|
|
|
|
|
2896
|
719
|
|
|
|
|
2042
|
my $parsed = $self->_language_country(); |
|
2897
|
719
|
|
|
|
|
2607
|
return $parsed->{'country'}; |
|
2898
|
|
|
|
|
|
|
} |
|
2899
|
|
|
|
|
|
|
|
|
2900
|
|
|
|
|
|
|
sub device { |
|
2901
|
4166
|
|
|
4166
|
1
|
803794
|
my ($self) = @_; |
|
2902
|
|
|
|
|
|
|
|
|
2903
|
4166
|
50
|
|
|
|
10762
|
$self->_init_device if !exists( $self->{device} ); |
|
2904
|
4166
|
|
|
|
|
11984
|
return $self->{device}; |
|
2905
|
|
|
|
|
|
|
} |
|
2906
|
|
|
|
|
|
|
|
|
2907
|
|
|
|
|
|
|
sub device_string { |
|
2908
|
1837
|
|
|
1837
|
1
|
361151
|
my ($self) = @_; |
|
2909
|
|
|
|
|
|
|
|
|
2910
|
1837
|
100
|
|
|
|
7800
|
$self->_init_device if !exists( $self->{device_string} ); |
|
2911
|
1837
|
|
|
|
|
6721
|
return $self->{device_string}; |
|
2912
|
|
|
|
|
|
|
} |
|
2913
|
|
|
|
|
|
|
|
|
2914
|
|
|
|
|
|
|
sub device_name { |
|
2915
|
682
|
|
|
682
|
1
|
91306
|
my ($self) = @_; |
|
2916
|
682
|
|
|
|
|
1916
|
return $self->device_string; |
|
2917
|
|
|
|
|
|
|
} |
|
2918
|
|
|
|
|
|
|
|
|
2919
|
|
|
|
|
|
|
sub _language_country { |
|
2920
|
1852
|
|
|
1852
|
|
3370
|
my ($self) = @_; |
|
2921
|
|
|
|
|
|
|
|
|
2922
|
1852
|
100
|
|
|
|
4172
|
if ( $self->safari ) { |
|
2923
|
267
|
100
|
66
|
|
|
859
|
if ( $self->major == 1 |
|
2924
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m/\s ( [a-z]{2} ) \)/xms ) { |
|
2925
|
8
|
|
|
|
|
59
|
return { language => uc $1 }; |
|
2926
|
|
|
|
|
|
|
} |
|
2927
|
259
|
100
|
|
|
|
1600
|
if ( $self->{user_agent} =~ m/\s ([a-z]{2})-([A-Za-z]{2})/xms ) { |
|
2928
|
149
|
|
|
|
|
1049
|
return { language => uc $1, country => uc $2 }; |
|
2929
|
|
|
|
|
|
|
} |
|
2930
|
|
|
|
|
|
|
} |
|
2931
|
|
|
|
|
|
|
|
|
2932
|
1695
|
100
|
100
|
|
|
5041
|
if ( $self->aol |
|
2933
|
|
|
|
|
|
|
&& $self->{user_agent} =~ m/;([A-Z]{2})_([A-Z]{2})\)/ ) { |
|
2934
|
3
|
|
|
|
|
21
|
return { language => $1, country => $2 }; |
|
2935
|
|
|
|
|
|
|
} |
|
2936
|
|
|
|
|
|
|
|
|
2937
|
1692
|
100
|
100
|
|
|
4955
|
if ( $self->meta_app |
|
2938
|
|
|
|
|
|
|
&& $self->{user_agent} |
|
2939
|
|
|
|
|
|
|
=~ m{ ;FBLC/ ([a-z]{2}) (?: [_-] ([A-Z]{2}) )? }x ) { |
|
2940
|
12
|
100
|
|
|
|
115
|
return { language => uc $1, $2 ? ( country => $2 ) : () }; |
|
2941
|
|
|
|
|
|
|
} |
|
2942
|
|
|
|
|
|
|
|
|
2943
|
1680
|
100
|
66
|
|
|
4609
|
if ( $self->instagram |
|
2944
|
|
|
|
|
|
|
&& $self->{user_agent} |
|
2945
|
|
|
|
|
|
|
=~ m{ (?: [(] | ;[ ] ) ([a-z]{2}) [_-] ([A-Z]{2}) [;)] }x ) { |
|
2946
|
4
|
50
|
|
|
|
43
|
return { language => uc $1, $2 ? ( country => $2 ) : () }; |
|
2947
|
|
|
|
|
|
|
} |
|
2948
|
|
|
|
|
|
|
|
|
2949
|
1676
|
100
|
|
|
|
8385
|
if ( $self->{user_agent} =~ m/\b([a-z]{2})-([A-Za-z]{2})\b/xms ) { |
|
2950
|
338
|
|
|
|
|
2529
|
return { language => uc $1, country => uc $2 }; |
|
2951
|
|
|
|
|
|
|
} |
|
2952
|
|
|
|
|
|
|
|
|
2953
|
1338
|
100
|
|
|
|
4287
|
if ( $self->{user_agent} =~ m/\[([a-z]{2})\]/xms ) { |
|
2954
|
28
|
|
|
|
|
173
|
return { language => uc $1 }; |
|
2955
|
|
|
|
|
|
|
} |
|
2956
|
|
|
|
|
|
|
|
|
2957
|
1310
|
100
|
|
|
|
7326
|
if ( $self->{user_agent} =~ m/\(([^)]+)\)/xms ) { |
|
2958
|
1156
|
|
|
|
|
6006
|
my @parts = split( /;/, $1 ); |
|
2959
|
1156
|
|
|
|
|
2879
|
foreach my $part (@parts) { |
|
2960
|
|
|
|
|
|
|
|
|
2961
|
|
|
|
|
|
|
# 'wv' for WebView is not language code. Details here: https://developer.chrome.com/multidevice/user-agent#webview_user_agent |
|
2962
|
4850
|
100
|
66
|
|
|
16465
|
if ( $part =~ /^\s*([a-z]{2})\s*$/ |
|
|
|
|
100
|
|
|
|
|
|
2963
|
|
|
|
|
|
|
&& !( $self->webview && $1 eq 'wv' ) ) { |
|
2964
|
144
|
|
|
|
|
979
|
return { language => uc $1 }; |
|
2965
|
|
|
|
|
|
|
} |
|
2966
|
|
|
|
|
|
|
} |
|
2967
|
|
|
|
|
|
|
} |
|
2968
|
|
|
|
|
|
|
|
|
2969
|
1166
|
|
|
|
|
4572
|
return { language => undef, country => undef }; |
|
2970
|
|
|
|
|
|
|
} |
|
2971
|
|
|
|
|
|
|
|
|
2972
|
|
|
|
|
|
|
sub browser_properties { |
|
2973
|
1938
|
|
|
1938
|
1
|
528683
|
my ($self) = @_; |
|
2974
|
|
|
|
|
|
|
|
|
2975
|
1938
|
|
|
|
|
3969
|
my @browser_properties; |
|
2976
|
|
|
|
|
|
|
|
|
2977
|
1938
|
|
|
|
|
4546
|
my ( $test, $value ); |
|
2978
|
|
|
|
|
|
|
|
|
2979
|
1938
|
|
|
|
|
4131
|
while ( ( $test, $value ) = each %{ $self->{tests} } ) { |
|
|
3709
|
|
|
|
|
15578
|
|
|
2980
|
1771
|
50
|
|
|
|
5667
|
push @browser_properties, $test if $value; |
|
2981
|
|
|
|
|
|
|
} |
|
2982
|
1938
|
|
|
|
|
4096
|
while ( ( $test, $value ) = each %{ $self->{browser_tests} } ) { |
|
|
3677
|
|
|
|
|
12169
|
|
|
2983
|
1739
|
100
|
|
|
|
5537
|
push @browser_properties, $test if $value; |
|
2984
|
|
|
|
|
|
|
} |
|
2985
|
|
|
|
|
|
|
|
|
2986
|
1938
|
50
|
|
|
|
5435
|
$self->_init_device unless $self->{device_tests}; |
|
2987
|
1938
|
100
|
|
|
|
6357
|
$self->_init_os unless $self->{os_tests}; |
|
2988
|
1938
|
100
|
|
|
|
6631
|
$self->_init_robots unless $self->{robot_tests}; |
|
2989
|
1938
|
100
|
|
|
|
5512
|
$self->_init_version unless $self->{version_tests}; |
|
2990
|
|
|
|
|
|
|
|
|
2991
|
1938
|
|
|
|
|
3540
|
while ( ( $test, $value ) = each %{ $self->{device_tests} } ) { |
|
|
6296
|
|
|
|
|
19358
|
|
|
2992
|
4358
|
100
|
|
|
|
9991
|
push @browser_properties, $test if $value; |
|
2993
|
|
|
|
|
|
|
} |
|
2994
|
1938
|
|
|
|
|
3688
|
while ( ( $test, $value ) = each %{ $self->{os_tests} } ) { |
|
|
5794
|
|
|
|
|
15813
|
|
|
2995
|
3856
|
50
|
|
|
|
8903
|
push @browser_properties, $test if $value; |
|
2996
|
|
|
|
|
|
|
} |
|
2997
|
1938
|
|
|
|
|
3620
|
while ( ( $test, $value ) = each %{ $self->{robot_tests} } ) { |
|
|
2709
|
|
|
|
|
9188
|
|
|
2998
|
771
|
50
|
|
|
|
1890
|
push @browser_properties, $test if $value; |
|
2999
|
|
|
|
|
|
|
} |
|
3000
|
1938
|
|
|
|
|
3783
|
while ( ( $test, $value ) = each %{ $self->{version_tests} } ) { |
|
|
4371
|
|
|
|
|
12096
|
|
|
3001
|
2433
|
100
|
|
|
|
6947
|
push @browser_properties, $test if $value; |
|
3002
|
|
|
|
|
|
|
} |
|
3003
|
|
|
|
|
|
|
|
|
3004
|
|
|
|
|
|
|
# devices are a property too but it's not stored in %tests |
|
3005
|
|
|
|
|
|
|
# so I explicitly test for it and add it |
|
3006
|
1938
|
100
|
|
|
|
6182
|
push @browser_properties, 'device' if ( $self->device() ); |
|
3007
|
|
|
|
|
|
|
|
|
3008
|
1938
|
|
|
|
|
11647
|
@browser_properties = sort @browser_properties; |
|
3009
|
1938
|
|
|
|
|
7301
|
return @browser_properties; |
|
3010
|
|
|
|
|
|
|
} |
|
3011
|
|
|
|
|
|
|
|
|
3012
|
|
|
|
|
|
|
sub lib { |
|
3013
|
28
|
|
|
28
|
1
|
20656
|
my $self = shift; |
|
3014
|
28
|
100
|
|
|
|
112
|
$self->_init_robots() unless $self->{robot_tests}; |
|
3015
|
28
|
|
|
|
|
114
|
return $self->{robot_tests}->{lib}; |
|
3016
|
|
|
|
|
|
|
} |
|
3017
|
|
|
|
|
|
|
|
|
3018
|
|
|
|
|
|
|
sub all_robot_ids { |
|
3019
|
2
|
|
|
2
|
1
|
112
|
my $self = shift; |
|
3020
|
2
|
|
|
|
|
47
|
return keys %ROBOT_NAMES; |
|
3021
|
|
|
|
|
|
|
} |
|
3022
|
|
|
|
|
|
|
|
|
3023
|
|
|
|
|
|
|
# The list of U2F supported browsers is expected to increase: |
|
3024
|
|
|
|
|
|
|
# https://www.bit-tech.net/news/tech/software/w3c-adopts-fidos-webauthn-standard/1/ |
|
3025
|
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
sub u2f { |
|
3027
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
3028
|
|
|
|
|
|
|
|
|
3029
|
|
|
|
|
|
|
# Chrome version 41 and up can U2F |
|
3030
|
0
|
0
|
0
|
|
|
0
|
return 1 |
|
|
|
|
0
|
|
|
|
|
|
3031
|
|
|
|
|
|
|
if $self->chrome |
|
3032
|
|
|
|
|
|
|
&& $self->browser_major |
|
3033
|
|
|
|
|
|
|
&& $self->browser_major >= 41; |
|
3034
|
|
|
|
|
|
|
|
|
3035
|
|
|
|
|
|
|
# Opera versions 40 and >= 42 can U2F |
|
3036
|
0
|
0
|
0
|
|
|
0
|
return 1 |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
3037
|
|
|
|
|
|
|
if $self->opera |
|
3038
|
|
|
|
|
|
|
&& $self->browser_major |
|
3039
|
|
|
|
|
|
|
&& ( $self->browser_major == 40 |
|
3040
|
|
|
|
|
|
|
|| $self->browser_major >= 42 ); |
|
3041
|
|
|
|
|
|
|
|
|
3042
|
0
|
|
|
|
|
0
|
return undef; |
|
3043
|
|
|
|
|
|
|
} |
|
3044
|
|
|
|
|
|
|
|
|
3045
|
|
|
|
|
|
|
# These method are only used by the test suite. |
|
3046
|
|
|
|
|
|
|
sub _all_tests { |
|
3047
|
1
|
|
|
1
|
|
6703425
|
return @ALL_TESTS; |
|
3048
|
|
|
|
|
|
|
} |
|
3049
|
|
|
|
|
|
|
|
|
3050
|
|
|
|
|
|
|
sub _robot_names { |
|
3051
|
1
|
|
|
1
|
|
84
|
return %ROBOT_NAMES; |
|
3052
|
|
|
|
|
|
|
} |
|
3053
|
|
|
|
|
|
|
|
|
3054
|
|
|
|
|
|
|
sub _robot_tests { |
|
3055
|
2
|
|
|
2
|
|
7098186
|
return @ROBOT_TESTS; |
|
3056
|
|
|
|
|
|
|
} |
|
3057
|
|
|
|
|
|
|
|
|
3058
|
|
|
|
|
|
|
sub _robot_ids { |
|
3059
|
1
|
|
|
1
|
|
28
|
return %ROBOT_IDS; |
|
3060
|
|
|
|
|
|
|
} |
|
3061
|
|
|
|
|
|
|
|
|
3062
|
|
|
|
|
|
|
1; |
|
3063
|
|
|
|
|
|
|
|
|
3064
|
|
|
|
|
|
|
# ABSTRACT: Determine Web browser, version, and platform from an HTTP user agent string |
|
3065
|
|
|
|
|
|
|
|
|
3066
|
|
|
|
|
|
|
__END__ |