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__ |