use
5.006;
our
$VERSION
=
'3.41'
;
our
@OS_TESTS
=
qw(
windows mac os2
unix linux vms
bsd amiga brew
bb10 rimtabletos
chromeos ios
firefoxos
)
;
our
@WINDOWS_TESTS
=
qw(
win16 win3x win31
win95 win98 winnt
winme win32 win2k
winxp win2k3 winvista
win7 win8 win8_0
win8_1 win10 win10_0
wince winphone winphone7
winphone7_5 winphone8 winphone8_1
winphone10
)
;
our
@MAC_TESTS
=
qw(
macosx mac68k macppc
)
;
our
@UNIX_TESTS
=
qw(
sun sun4 sun5
suni86 irix irix5
irix6 hpux hpux9
hpux10 aix aix1
aix2 aix3 aix4
sco unixware mpras
reliant dec sinix
)
;
our
@BSD_TESTS
=
qw(
freebsd
)
;
our
@GAMING_TESTS
=
qw(
ps3gameos pspgameos
)
;
our
@DEVICE_TESTS
=
qw(
android audrey blackberry dsi iopener ipad
iphone ipod kindle kindlefire n3ds palm ps3 psp wap webos
mobile tablet
)
;
our
@BROWSER_TESTS
=
qw(
mosaic netscape firefox
chrome safari ie
opera lynx links
elinks neoplanet neoplanet2
avantgo emacs mozilla
konqueror realplayer netfront
mobile_safari obigo aol
lotusnotes staroffice icab
webtv browsex silk
applecoremedia galeon seamonkey
epiphany ucbrowser dalvik
edge pubsub adm
brave imagesearcherpro polaris
edgelegacy samsung
instagram
yandex_browser
)
;
our
@IE_TESTS
=
qw(
ie3 ie4 ie4up
ie5 ie5up ie55
ie55up ie6 ie7
ie8 ie9 ie10
ie11
ie_compat_mode
)
;
our
@OPERA_TESTS
=
qw(
opera3 opera4 opera5
opera6 opera7
)
;
our
@AOL_TESTS
=
qw(
aol3 aol4
aol5 aol6
)
;
our
@NETSCAPE_TESTS
=
qw(
nav2 nav3 nav4
nav4up nav45 nav45up
nav6 nav6up navgold
)
;
our
@FIREFOX_TESTS
=
qw(
firebird iceweasel phoenix
namoroka
fxios
)
;
our
@ENGINE_TESTS
=
qw(
gecko trident webkit
presto khtml edgehtml
)
;
my
@OLD_ROBOT_TESTS
=
qw(
ahrefs
altavista
amazonbot
apache
askjeeves
baidu
bingbot
curl
facebook
getright
golib
google
googleadsbot
googleadsense
googlebotimage
googlebotnews
googlebotvideo
googlefavicon
googlemobile
indy
infoseek
ipsagent
java
linkchecker
linkexchange
lwp
lycos
malware
mj12bot
msn
msnmobile
msoffice
nutch
phplib
puf
rubylib
slurp
specialarchiver
wget
yahoo
yandex
yandeximages
headlesschrome
)
;
our
@ROBOT_TESTS
= (
[
'Applebot'
,
'apple'
],
[
'baiduspider'
,
'baidu'
],
[
'bitlybot'
,
'bitly'
],
[
'developers.google.com//web/snippet'
,
'google-plus-snippet'
],
[
'Discordbot'
,
'discordbot'
],
[
'embedly'
,
'embedly'
],
[
'facebookexternalhit'
,
'facebook'
],
[
'flipboard'
,
'flipboard'
],
[
'Google Page Speed'
,
'google-page-speed'
],
[
'ltx71'
,
'ltx71'
],
[
'linkedinbot'
,
'linkedin'
],
[
'nuzzel'
,
'nuzzel'
],
[
'outbrain'
,
'outbrain'
],
[
'pinterest/0.'
,
'pinterest'
],
[
'pinterestbot'
,
'pinterest'
],
[
'Pro-Sitemaps'
,
'pro-sitemaps'
],
[
'quora link preview'
,
'quora-link-preview'
],
[
'Qwantify'
,
'qwantify'
],
[
'redditbot'
,
'reddit'
, ],
[
'researchscan'
,
'researchscan'
],
[
'rogerbot'
,
'rogerbot'
],
[
'ShowyouBot'
,
'showyou'
],
[
'SkypeUriPreview'
,
'skype-uri-preview'
],
[
'slackbot'
,
'slack'
],
[
'Swiftbot'
,
'swiftbot'
],
[
'tumblr'
,
'tumblr'
],
[
'twitterbot'
,
'twitter'
],
[
'vkShare'
,
'vkshare'
],
[
'W3C_Validator'
,
'w3c-validator'
],
[
'WhatsApp'
,
'whatsapp'
],
[
'Amazonbot'
,
'amazonbot'
],
);
our
@MISC_TESTS
=
qw(
dotnet x11
webview
meta_app
)
;
our
@ALL_TESTS
= (
@OS_TESTS
,
@WINDOWS_TESTS
,
@MAC_TESTS
,
@UNIX_TESTS
,
@BSD_TESTS
,
@GAMING_TESTS
,
@DEVICE_TESTS
,
@BROWSER_TESTS
,
@IE_TESTS
,
@OPERA_TESTS
,
@AOL_TESTS
,
@NETSCAPE_TESTS
,
@FIREFOX_TESTS
,
@ENGINE_TESTS
,
@OLD_ROBOT_TESTS
,
@MISC_TESTS
,
);
my
%ROBOT_NAMES
= (
ahrefs
=>
'Ahrefs'
,
altavista
=>
'AltaVista'
,
amazonbot
=>
'Amazonbot'
,
'apache-http-client'
=>
'Apache HttpClient'
,
apple
=>
'Apple'
,
'archive-org'
=>
'Internet Archive'
,
askjeeves
=>
'AskJeeves'
,
baidu
=>
'Baidu'
,
baiduspider
=>
'Baidu Spider'
,
bingbot
=>
'Bingbot'
,
bitly
=>
'Bitly'
,
curl
=>
'curl'
,
discordbot
=>
'Discord'
,
embedly
=>
'Embedly'
,
facebook
=>
'Facebook'
,
facebookexternalhit
=>
'Facebook'
,
flipboard
=>
'Flipboard'
,
getright
=>
'GetRight'
,
golib
=>
'Go language http library'
,
google
=>
'Googlebot'
,
'google-adsbot'
=>
'Google AdsBot'
,
'google-adsense'
=>
'Google AdSense'
,
'googlebot'
=>
'Googlebot'
,
'googlebot-image'
=>
'Googlebot Images'
,
'googlebot-mobile'
=>
'Googlebot Mobile'
,
'googlebot-news'
=>
'Googlebot News'
,
'googlebot-video'
=>
'Googlebot Video'
,
'google-favicon'
=>
'Google Favicon'
,
'google-mobile'
=>
'Googlebot Mobile'
,
'google-page-speed'
=>
'Google Page Speed'
,
'google-plus-snippet'
=>
'Google+ Snippet'
,
'indy-library'
=>
'Indy Library'
,
infoseek
=>
'InfoSeek'
,
java
=>
'Java'
,
'libwww-perl'
=>
'LWP::UserAgent'
,
linkchecker
=>
'LinkChecker'
,
linkedin
=>
'LinkedIn'
,
linkexchange
=>
'LinkExchange'
,
ltx71
=>
'ltx71'
,
lycos
=>
'Lycos'
,
malware
=>
'Malware / hack attempt'
,
'microsoft-office'
=>
'Microsoft Office'
,
mj12bot
=>
'Majestic-12 DSearch'
,
msn
=>
'MSN'
,
'msn-mobile'
=>
'MSN Mobile'
,
nutch
=>
'Apache Nutch'
,
nuzzel
=>
'Nuzzel'
,
outbrain
=>
'Outbrain'
,
phplib
=>
'PHP http library'
,
pinterest
=>
'Pinterest'
,
'pro-sitemaps'
=>
'Pro Sitemap Service'
,
puf
=>
'puf'
,
'quora-link-preview'
=>
'Quora Link Preview'
,
qwantify
=>
'Qwantify'
,
researchscan
=>
'Researchscan RWTH Aachen'
,
reddit
=>
'Reddit'
,
robot
=>
'robot'
,
rogerbot
=>
'Moz'
,
'ruby-http-library'
=>
'Ruby http library'
,
showyou
=>
'Showyou'
,
'skype-uri-preview'
=>
'Skype URI Preview'
,
slack
=>
'slack'
,
swiftbot
=>
'Swiftbot'
,
tumblr
=>
'Tumblr'
,
twitter
=>
'Twitter'
,
unknown
=>
'Unknown Bot'
,
'verisign-ips-agent'
=>
'Verisign ips-agent'
,
vkshare
=>
'VK Share'
,
'w3c-validator'
=>
'W3C Validator'
,
wget
=>
'Wget'
,
whatsapp
=>
'WhatsApp'
,
yahoo
=>
'Yahoo'
,
'yahoo-slurp'
=>
'Yahoo! Slurp'
,
yandex
=>
'Yandex'
,
'yandex-images'
=>
'YandexImages'
,
'headless-chrome'
=>
'HeadlessChrome'
,
);
my
%ROBOT_IDS
= (
ahrefs
=>
'ahrefs'
,
altavista
=>
'altavista'
,
apache
=>
'apache-http-client'
,
askjeeves
=>
'askjeeves'
,
baidu
=>
'baidu'
,
baiduspider
=>
'baidu'
,
bingbot
=>
'bingbot'
,
curl
=>
'curl'
,
facebook
=>
'facebook'
,
getright
=>
'getright'
,
golib
=>
'golib'
,
google
=>
'googlebot'
,
googleadsbot
=>
'google-adsbot'
,
googleadsense
=>
'google-adsense'
,
googlebotimage
=>
'googlebot-image'
,
googlebotnews
=>
'googlebot-news'
,
googlebotvideo
=>
'googlebot-video'
,
googlefavicon
=>
'google-favicon'
,
googlemobile
=>
'googlebot-mobile'
,
indy
=>
'indy-library'
,
infoseek
=>
'infoseek'
,
ipsagent
=>
'verisign-ips-agent'
,
java
=>
'java'
,
linkchecker
=>
'linkchecker'
,
linkexchange
=>
'linkexchange'
,
ltx71
=>
'ltx71'
,
lwp
=>
'libwww-perl'
,
lycos
=>
'lycos'
,
malware
=>
'malware'
,
mj12bot
=>
'mj12bot'
,
msn
=>
'msn'
,
msnmobile
=>
'msn-mobile'
,
msoffice
=>
'microsoft-office'
,
nutch
=>
'nutch'
,
phplib
=>
'phplib'
,
puf
=>
'puf'
,
robot
=>
'robot'
,
rubylib
=>
'ruby-http-library'
,
researchscan
=>
'researchscan'
,
slurp
=>
'yahoo-slurp'
,
specialarchiver
=>
'archive-org'
,
wget
=>
'wget'
,
yahoo
=>
'yahoo'
,
yandex
=>
'yandex'
,
yandeximages
=>
'yandex-images'
,
headlesschrome
=>
'headless-chrome'
,
amazonbot
=>
'amazonbot'
,
);
my
%BROWSER_NAMES
= (
adm
=>
'Android Download Manager'
,
aol
=>
'AOL Browser'
,
applecoremedia
=>
'AppleCoreMedia'
,
blackberry
=>
'BlackBerry'
,
brave
=>
'Brave'
,
browsex
=>
'BrowseX'
,
chrome
=>
'Chrome'
,
curl
=>
'curl'
,
dalvik
=>
'Dalvik'
,
dsi
=>
'Nintendo DSi'
,
edge
=>
'Edge'
,
elinks
=>
'ELinks'
,
epiphany
=>
'Epiphany'
,
firefox
=>
'Firefox'
,
galeon
=>
'Galeon'
,
icab
=>
'iCab'
,
iceweasel
=>
'IceWeasel'
,
ie
=>
'MSIE'
,
imagesearcherpro
=>
'ImageSearcherPro'
,
instagram
=>
'Instagram'
,
konqueror
=>
'Konqueror'
,
links
=>
'Links'
,
lotusnotes
=>
'Lotus Notes'
,
lynx
=>
'Lynx'
,
mobile_safari
=>
'Mobile Safari'
,
mosaic
=>
'Mosaic'
,
mozilla
=>
'Mozilla'
,
n3ds
=>
'Nintendo 3DS'
,
netfront
=>
'NetFront'
,
netscape
=>
'Netscape'
,
obigo
=>
'Obigo'
,
opera
=>
'Opera'
,
polaris
=>
'Polaris'
,
pubsub
=>
'Safari RSS Reader'
,
puf
=>
'puf'
,
realplayer
=>
'RealPlayer'
,
safari
=>
'Safari'
,
samsung
=>
'Samsung'
,
seamonkey
=>
'SeaMonkey'
,
silk
=>
'Silk'
,
staroffice
=>
'StarOffice'
,
ucbrowser
=>
'UCBrowser'
,
webtv
=>
'WebTV'
,
yandex_browser
=>
'Yandex Browser'
,
);
my
%DEVICE_NAMES
= (
android
=>
'Android'
,
audrey
=>
'Audrey'
,
blackberry
=>
'BlackBerry'
,
dsi
=>
'Nintendo DSi'
,
iopener
=>
'iopener'
,
ipad
=>
'iPad'
,
iphone
=>
'iPhone'
,
ipod
=>
'iPod'
,
kindle
=>
'Amazon Kindle'
,
n3ds
=>
'Nintendo 3DS'
,
palm
=>
'Palm'
,
ps3
=>
'Sony PlayStation 3'
,
psp
=>
'Sony PlayStation Portable'
,
wap
=>
'WAP capable phone'
,
webos
=>
'webOS'
,
);
my
%OS_NAMES
= (
amiga
=>
'Amiga'
,
android
=>
'Android'
,
bb10
=>
'BlackBerry 10'
,
brew
=>
'Brew'
,
chromeos
=>
'Chrome OS'
,
firefoxos
=>
'Firefox OS'
,
ios
=>
'iOS'
,
linux
=>
'Linux'
,
mac
=>
'Mac'
,
macosx
=>
'Mac OS X'
,
os2
=>
'OS/2'
,
ps3gameos
=>
'Playstation 3 GameOS'
,
pspgameos
=>
'Playstation Portable GameOS'
,
rimtabletos
=>
'RIM Tablet OS'
,
unix
=>
'Unix'
,
vms
=>
'VMS'
,
win2k
=>
'Win2k'
,
win2k3
=>
'Win2k3'
,
win3x
=>
'Win3x'
,
win7
=>
'Win7'
,
win8
=>
'Win8'
,
win8_0
=>
'Win8.0'
,
win8_1
=>
'Win8.1'
,
win10
=>
'Win10'
,
win10_0
=>
'Win10.0'
,
win95
=>
'Win95'
,
win98
=>
'Win98'
,
winme
=>
'WinME'
,
winnt
=>
'WinNT'
,
winphone
=>
'Windows Phone'
,
winvista
=>
'WinVista'
,
winxp
=>
'WinXP'
,
);
my
%safari_build_to_version
=
qw(
48 0.8
51 0.8.1
60 0.8.2
73 0.9
74 1.0b2v74
85 1.0
85.7 1.0.2
85.8 1.0.3
100 1.1
100.1 1.1.1
125 1.2
125.1 1.2.1
125.7 1.2.2
125.9 1.2.3
125.11 1.2.4
312 1.3
312.3 1.3.1
312.5 1.3.2
412 2.0
412.5 2.0.1
416.12 2.0.2
417.8 2.0.3
419.3 2.0.4
)
;
my
$default
=
undef
;
sub
new {
my
(
$class
,
$user_agent
) =
@_
;
my
$self
= {};
bless
$self
,
$class
;
unless
(
defined
$user_agent
) {
$user_agent
=
$ENV
{
'HTTP_USER_AGENT'
};
}
$self
->{user_agent} =
defined
$user_agent
?
$user_agent
:
q{}
;
$self
->_init_core;
return
$self
;
}
foreach
my
$test
(
@ENGINE_TESTS
,
@MISC_TESTS
) {
no
strict
'refs'
;
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
return
$self
->{tests}->{
$test
} || 0;
};
}
foreach
my
$test
(
@OS_TESTS
,
@WINDOWS_TESTS
,
@MAC_TESTS
,
@UNIX_TESTS
,
@BSD_TESTS
,
@GAMING_TESTS
) {
no
strict
'refs'
;
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
$self
->_init_os()
unless
$self
->{os_tests};
return
$self
->{os_tests}->{
$test
} || 0;
};
}
foreach
my
$test
(
@BROWSER_TESTS
,
@FIREFOX_TESTS
) {
no
strict
'refs'
;
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
return
$self
->{browser_tests}->{
$test
} || 0;
};
}
foreach
my
$test
(
@OLD_ROBOT_TESTS
) {
no
strict
'refs'
;
my
$false_result
= (
$test
eq
'robot'
?
undef
: 0 );
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
$self
->_init_robots()
unless
$self
->{robot_tests};
return
$self
->{robot_tests}->{
$test
} ||
$false_result
;
};
}
foreach
my
$test
(
@NETSCAPE_TESTS
,
@IE_TESTS
,
@AOL_TESTS
,
@OPERA_TESTS
) {
no
strict
'refs'
;
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
$self
->_init_version()
unless
$self
->{version_tests};
return
$self
->{version_tests}->{
$test
} || 0;
};
}
foreach
my
$test
(
@DEVICE_TESTS
) {
no
strict
'refs'
;
*{
$test
} =
sub
{
my
(
$self
) =
@_
;
$self
->_init_device()
unless
$self
->{device_tests};
return
$self
->{device_tests}->{
$test
} || 0;
};
}
sub
user_agent {
my
(
$self
,
$user_agent
) =
@_
;
if
(
defined
(
$user_agent
) ) {
die
'Calling HTTP::BrowserDetect::user_agent() with an argument is no longer allowed; please use new().'
;
}
else
{
return
$self
->{user_agent};
}
}
sub
_init_core {
my
(
$self
,
$new_ua
) =
@_
;
my
$ua
=
lc
$self
->{user_agent};
$ua
=~ s{,gzip\(gfe\)\z}{};
$self
->{tests} = {};
$self
->{browser_tests} = {};
my
$tests
=
$self
->{tests};
my
$browser_tests
=
$self
->{browser_tests};
my
$browser
=
undef
;
my
$browser_string
=
undef
;
$self
->{engine_version} =
undef
;
if
(
$ua
=~ m{edge/([\d\.]+)} ) {
$tests
->{edgehtml} = 1;
$self
->{engine_version} = $1;
}
elsif
(
$ua
=~ /trident\/([\w\.\d]*)/ ) {
$tests
->{trident} = 1;
$self
->{engine_version} = $1;
}
elsif
(
index
(
$ua
,
'gecko'
) != -1 &&
index
(
$ua
,
'like gecko'
) == -1 )
{
$tests
->{gecko} = 1;
if
(
$ua
=~ /\([^)]
*rv
:([\w.\d]*)/ ) {
$self
->{engine_version} = $1;
}
}
elsif
(
$ua
=~ m{applewebkit/([\d.\+]+)} && not
$tests
->{edgehtml} ) {
$tests
->{webkit} = 1;
$self
->{engine_version} = $1;
}
elsif
(
$ua
=~ m{presto/([\d.]+)} ) {
$tests
->{presto} = 1;
$self
->{engine_version} = $1;
}
elsif
(
$ua
=~ m{khtml/([\d.]+)} ) {
$tests
->{khtml} = 1;
$self
->{engine_version} = $1;
}
if
(
index
(
$ua
,
'galeon'
) != -1 ) {
$browser
=
'galeon'
;
$browser_tests
->{galeon} = 1;
}
elsif
(
index
(
$ua
,
'epiphany'
) != -1 ) {
$browser
=
'epiphany'
;
$browser_tests
->{epiphany} = 1;
}
elsif
(
$ua
=~ m{(?:edg|edga|edgios)/[\d.]+} ) {
$browser
=
'edge'
;
$browser_string
=
'Edge'
;
$browser_tests
->{edge} = 1;
}
elsif
(
$ua
=~ m{edge/[\d.]+} ) {
$browser
=
'edge'
;
$browser_string
=
'Edge'
;
$browser_tests
->{edgelegacy} = 1;
}
elsif
(
$ua
=~ m{
(firebird|iceweasel|phoenix|namoroka|firefox|fxios)
\/
( [^.]* )
\.
( [\d]* )
}xo
&&
index
(
$ua
,
'not firefox'
) == -1
)
{
$browser
=
'firefox'
;
$browser_string
=
ucfirst
( $1 eq
'fxios'
?
$browser
: $1 );
$browser_tests
->{$1} = 1;
$browser_tests
->{firefox} = 1;
}
elsif
(
$self
->{user_agent} =~ m{ \[ FB (?: AN | _IAB ) }x ) {
$browser_string
=
$self
->_match(
[
'Facebook'
,
'[FB_IAB/FB4A'
,
'[FBAN/FBIOS'
],
[
'Facebook Lite'
,
'[FBAN/EMA'
],
[
'Facebook Messenger'
,
'[FB_IAB/Orca-Android'
,
'[FB_IAB/MESSENGER'
,
'[FBAN/MessengerForiOS'
],
[
'Facebook Messenger Lite'
,
'[FBAN/mLite'
,
'[FBAN/MessengerLiteForiOS'
],
) ||
'Meta App'
;
$browser
=
lc
$browser_string
;
$browser
=~
tr
/ /_/;
$tests
->{meta_app} = 1;
}
elsif
(
$ua
=~ m{opera|opr\/} ) {
$browser
=
'opera'
;
$browser_tests
->{opera} = 1;
}
elsif
(
$tests
->{trident}
||
index
(
$ua
,
'msie'
) != -1
||
index
(
$ua
,
'microsoft internet explorer'
) != -1 ) {
$browser
=
'ie'
;
$browser_tests
->{ie} = 1;
if
(
index
(
$ua
,
'aol'
) != -1
||
index
(
$ua
,
'america online browser'
) != -1 ) {
$browser_string
=
'AOL Browser'
;
$browser_tests
->{aol} = 1;
}
}
elsif
( 0 <
index
$self
->{user_agent},
' Instagram '
) {
$browser
=
'instagram'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'brave'
) != -1 ) {
$browser
=
'brave'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'silk'
) != -1 ) {
$browser
=
'silk'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'samsungbrowser'
) != -1 ) {
$browser
=
'samsung'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'ucbrowser'
) != -1 ) {
$browser
=
'ucbrowser'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
( 0 <
index
$self
->{user_agent},
' YaBrowser/'
) {
$browser
=
'yandex_browser'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'chrome/'
) != -1
||
index
(
$ua
,
'crios'
) != -1 ) {
$browser
=
'chrome'
;
$browser_tests
->{chrome} = 1;
if
(
index
(
$ua
,
'chromium'
) != -1 ) {
$browser_string
=
'Chromium'
;
}
}
elsif
(
index
(
$ua
,
'blackberry'
) != -1
||
index
(
$ua
,
'bb10'
) != -1
||
index
(
$ua
,
'rim tablet os'
) != -1 ) {
$browser
=
'blackberry'
;
}
elsif
((
index
(
$ua
,
'safari'
) != -1 )
|| (
index
(
$ua
,
'applewebkit'
) != -1 ) ) {
$browser_tests
->{safari} = 1;
$browser
=
'safari'
;
if
(
index
(
$ua
,
' mobile safari/'
) != -1
||
index
(
$ua
,
'mobilesafari'
) != -1 ) {
$browser_string
=
'Mobile Safari'
;
$browser_tests
->{mobile_safari} = 1;
}
if
(
index
(
$ua
,
'puffin'
) != -1 ) {
$browser_string
=
'Puffin'
;
}
}
elsif
(
index
(
$ua
,
'neoplanet'
) != -1 ) {
$browser
=
'ie'
;
$browser_tests
->{
$browser
} = 1;
$browser_tests
->{neoplanet} = 1;
$browser_tests
->{neoplanet2} = 1
if
(
index
(
$ua
,
'2.'
) != -1 );
}
elsif
(
index
(
$ua
,
'webtv'
) != -1 ) {
$browser
=
'webtv'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'nintendo 3ds'
) != -1 ) {
$browser
=
'n3ds'
;
}
elsif
(
index
(
$ua
,
'nintendo dsi'
) != -1 ) {
$browser
=
'dsi'
;
}
elsif
(
index
(
$ua
,
'playstation 3'
) != -1
||
index
(
$ua
,
'playstation portable'
) != -1
||
index
(
$ua
,
'netfront'
) != -1 ) {
$browser
=
'netfront'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'browsex'
) != -1 ) {
$browser
=
'browsex'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'polaris'
) != -1 ) {
$browser
=
'polaris'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'mozilla'
) != -1
&&
index
(
$ua
,
'compatible'
) == -1 ) {
$browser
=
'mozilla'
;
if
(
index
(
$ua
,
'netscape'
) != -1
|| !
$tests
->{gecko} ) {
$browser
=
'netscape'
;
}
elsif
(
index
(
$ua
,
'seamonkey'
) != -1 ) {
$browser
=
'seamonkey'
;
}
$browser_tests
->{
$browser
} = 1;
$browser_tests
->{netscape} = 1;
$browser_tests
->{mozilla} = (
$tests
->{gecko} );
}
elsif
(
index
(
$ua
,
'staroffice'
) != -1 ) {
$browser
=
'staroffice'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'icab'
) != -1 ) {
$browser
=
'icab'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'lotus-notes'
) != -1 ) {
$browser
=
'lotusnotes'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'konqueror'
) != -1 ) {
$browser
=
'konqueror'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'lynx'
) != -1 ) {
$browser
=
'lynx'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'elinks'
) != -1 ) {
$browser
=
'elinks'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'links'
) != -1 ) {
$browser
=
'links'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'mosaic'
) != -1 ) {
$browser
=
'mosaic'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'emacs'
) != -1 ) {
$browser
=
'emacs'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'obigo'
) != -1 ) {
$browser
=
'obigo'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'teleca'
) != -1 ) {
$browser
=
'obigo'
;
$browser_string
=
'Teleca'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'libcurl'
) != -1 ||
$ua
=~ /^curl/ ) {
$browser
=
'curl'
;
}
elsif
(
index
(
$ua
,
'puf/'
) != -1 ) {
$browser
=
'puf'
;
}
elsif
(
index
(
$ua
,
'applecoremedia/'
) != -1 ) {
$browser
=
'applecoremedia'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'androiddownloadmanager'
) != -1 ) {
$browser
=
'adm'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'dalvik'
) != -1 ) {
$browser
=
'dalvik'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'apple-pubsub'
) != -1 ) {
$browser
=
'pubsub'
;
$browser_tests
->{
$browser
} = 1;
}
elsif
(
index
(
$ua
,
'imagesearcherpro'
) != -1 ) {
$browser
=
'imagesearcherpro'
;
$browser_tests
->{
$browser
} = 1;
}
$self
->{browser} =
$browser
;
$self
->{browser_string} =
$browser_string
||
$BROWSER_NAMES
{
$browser
}
if
defined
$browser
;
$tests
->{x11} = 1
if
index
(
$ua
,
'x11'
) != -1;
$tests
->{dotnet} = 1
if
index
(
$ua
,
'.net clr'
) != -1;
if
(
index
(
$ua
,
'realplayer'
) != -1 ) {
$self
->_init_version;
$self
->{browser} =
'realplayer'
;
$self
->{browser_string} =
'RealPlayer'
;
$browser_tests
->{realplayer} = 1;
$self
->{realplayer_version} =
undef
;
if
(
$ua
=~ /realplayer\/([\d+\.]+)/ ) {
$self
->{realplayer_version} = $1;
(
$self
->{major},
$self
->{minor} )
=
split
( /\./,
$self
->{realplayer_version} );
$self
->{minor} =
".$self->{minor}"
if
defined
$self
->{minor};
}
elsif
(
$ua
=~ /realplayer\s(\w+)/ ) {
$self
->{realplayer_version} = $1;
}
}
if
(
index
(
$ua
,
'(r1 '
) != -1 ) {
$browser_tests
->{realplayer} = 1;
}
if
( (
$self
->android &&
index
(
$ua
,
'; wv)'
) > 0 )
|| (
$self
->chrome &&
$self
->android &&
$self
->browser_major >= 30 ) )
{
$tests
->{webview} = 1;
}
}
sub
_match {
my
(
$self
,
@specs
) =
@_
;
for
my
$spec
(
@specs
) {
my
(
$ret
,
@tests
) = @{
$spec
};
for
my
$m
(
@tests
) {
return
$ret
if
!
ref
$m
&& 0 <
index
$self
->{user_agent},
$m
;
return
$ret
if
'Regexp'
eq
ref
$m
&&
$self
->{user_agent} =~
$m
;
}
}
}
my
@ROBOT_FRAGMENTS
=
qw(
agent
analy
appender
babya
checker
bot
copy
crawl
explorador
fetch
find
ia_archive
index
netcraft
reap
resolver
sleuth
scan
service
spider
thumbtack-thunderdome
tiscali
validator
verif
webcapture
worm
zyborg
)
;
my
%ROBOT_FRAGMENT_EXCEPTIONS
= (
bot
=> [
'cubot'
],
);
sub
_init_robots {
my
$self
=
shift
;
my
$ua
=
lc
$self
->{user_agent};
my
$tests
=
$self
->{tests};
my
$browser_tests
=
$self
->{browser_tests};
my
$robot_tests
=
$self
->{robot_tests} = {};
my
$id
;
my
$r
;
my
$robot_fragment
;
if
(
index
(
$ua
,
'libwww-perl'
) != -1 ||
index
(
$ua
,
'lwp-'
) != -1 ) {
$r
=
'lwp'
;
$robot_tests
->{lib} = 1;
$robot_fragment
= (
(
index
(
$ua
,
'libwww-perl'
) != -1 ) ?
'libwww-perl'
:
'lwp-'
);
}
elsif
(
index
(
$ua
,
'slurp'
) != -1 ) {
$r
=
'slurp'
;
$robot_tests
->{yahoo} = 1;
}
elsif
(
index
(
$ua
,
'yahoo'
) != -1
&&
index
(
$ua
,
'jp.co.yahoo'
) == -1 ) {
$r
=
'yahoo'
;
}
elsif
(
index
(
$ua
,
'msnbot-mobile'
) != -1 ) {
$r
=
'msnmobile'
;
$robot_tests
->{msn} = 1;
$robot_fragment
=
'msnbot'
;
}
elsif
(
index
(
$ua
,
'bingbot-mobile'
) != -1 ) {
$r
=
'bingbot'
;
$robot_tests
->{bingbot} = 1;
$robot_fragment
=
'bingbot'
;
}
elsif
(
index
(
$ua
,
'msnbot'
) != -1 ) {
$r
=
'msn'
;
$robot_fragment
=
'msnbot'
;
}
elsif
(
index
(
$ua
,
'binglocalsearch'
) != -1
||
index
(
$ua
,
'bingbot'
) != -1
||
index
(
$ua
,
'bingpreview'
) != -1 ) {
$r
=
'bingbot'
;
$robot_tests
->{bingbot} = 1;
$robot_fragment
=
'bingbot'
;
}
elsif
(
index
(
$ua
,
'microsoft office existence discovery'
) != -1 ) {
$r
=
'msoffice'
;
$robot_fragment
=
'office'
;
}
elsif
(
index
(
$ua
,
'ahrefsbot'
) != -1 ) {
$r
=
'ahrefs'
;
}
elsif
(
index
(
$ua
,
'altavista'
) != -1 ) {
$r
=
'altavista'
;
}
elsif
(
index
(
$ua
,
'apache-httpclient'
) != -1 ) {
$r
=
'apache'
;
}
elsif
(
$ua
=~ m{\( *\) *\{ *\: *\; *} ) {
$r
=
'malware'
;
}
elsif
(
index
(
$ua
,
'ask jeeves/teoma'
) != -1 ) {
$r
=
'askjeeves'
;
$robot_fragment
=
'teoma'
;
}
elsif
(
index
(
$ua
,
'baiduspider'
) != -1 ) {
$r
=
'baidu'
;
}
elsif
(
index
(
$ua
,
'libcurl'
) != -1 ||
$ua
=~ /^curl/ ) {
$r
=
'curl'
;
$robot_tests
->{lib} = 1;
}
elsif
(
index
(
$ua
,
'facebookexternalhit'
) != -1 ) {
$r
=
'facebook'
;
}
elsif
(
index
(
$ua
,
'getright'
) != -1 ) {
$r
=
'getright'
;
}
elsif
(
index
(
$ua
,
'adsbot-google'
) != -1 ) {
$r
=
'googleadsbot'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'adsbot-google'
;
}
elsif
(
index
(
$ua
,
'mediapartners-google'
) != -1 ) {
$r
=
'googleadsense'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'mediapartners-google'
;
}
elsif
(
index
(
$ua
,
'google favicon'
) != -1 ) {
$r
=
'googlefavicon'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'favicon'
;
}
elsif
(
index
(
$ua
,
'googlebot-image'
) != -1 ) {
$r
=
'googlebotimage'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'googlebot-image'
;
}
elsif
(
index
(
$ua
,
'googlebot-news'
) != -1 ) {
$r
=
'googlebotnews'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'googlebot-news'
;
}
elsif
(
index
(
$ua
,
'googlebot-video'
) != -1 ) {
$r
=
'googlebotvideo'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'googlebot-video'
;
}
elsif
(
index
(
$ua
,
'googlebot-mobile'
) != -1 ) {
$r
=
'googlemobile'
;
$robot_tests
->{google} = 1;
$robot_fragment
=
'googlebot-mobile'
;
}
elsif
(
index
(
$ua
,
'googlebot'
) != -1 ) {
$r
=
'google'
;
}
elsif
(
$ua
=~ m{go.
*package
http} ) {
$r
=
'golib'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'package'
;
}
elsif
(
$ua
=~ m{^http_request} ) {
$r
=
'phplib'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'http_request'
;
}
elsif
(
$ua
=~ m{^http_request} ) {
$r
=
'phplib'
;
$robot_tests
->{lib} = 1;
}
elsif
(
index
(
$ua
,
'indy library'
) != -1 ) {
$r
=
'indy'
;
$robot_tests
->{lib} = 1;
}
elsif
(
index
(
$ua
,
'infoseek'
) != -1 ) {
$r
=
'infoseek'
;
}
elsif
(
index
(
$ua
,
'ips-agent'
) != -1 ) {
$r
=
'ipsagent'
;
$robot_fragment
=
'ips-agent'
;
}
elsif
(
index
(
$ua
,
'lecodechecker'
) != -1 ) {
$r
=
'linkexchange'
;
$robot_fragment
=
'lecodechecker'
;
}
elsif
(
index
(
$ua
,
'linkchecker'
) != -1 ) {
$r
=
'linkchecker'
;
}
elsif
(
index
(
$ua
,
'lycos'
) != -1 ) {
$r
=
'lycos'
;
}
elsif
(
index
(
$ua
,
'mechanize'
) != -1 ) {
$r
=
'rubylib'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'mechanize'
;
}
elsif
(
index
(
$ua
,
'mj12bot/'
) != -1 ) {
$r
=
'mj12bot'
;
}
elsif
(
index
(
$ua
,
'nutch'
) != -1 ) {
$r
=
'nutch'
;
}
elsif
(
index
(
$ua
,
'puf/'
) != -1 ) {
$r
=
'puf'
;
$robot_tests
->{lib} = 1;
}
elsif
(
index
(
$ua
,
'scooter'
) != -1 ) {
$r
=
'scooter'
;
}
elsif
(
index
(
$ua
,
'special_archiver'
) != -1 ) {
$r
=
'specialarchiver'
;
$robot_fragment
=
'special_archiver'
;
}
elsif
(
index
(
$ua
,
'wget'
) == 0 ) {
$r
=
'wget'
;
}
elsif
(
index
(
$ua
,
'yandexbot'
) != -1 ) {
$r
=
'yandex'
;
}
elsif
(
index
(
$ua
,
'yandeximages'
) != -1 ) {
$r
=
'yandeximages'
;
}
elsif
(
index
(
$ua
,
'headlesschrome'
) != -1 ) {
$r
=
'headlesschrome'
;
}
elsif
(
$ua
=~ m{^java} && !
$self
->{browser} ) {
$r
=
'java'
;
$robot_tests
->{lib} = 1;
}
elsif
(
index
(
$ua
,
'jdk'
) != -1 ) {
$r
=
'java'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'jdk'
;
}
elsif
(
index
(
$ua
,
'jakarta commons-httpclient'
) != -1 ) {
$r
=
'java'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'jakarta'
;
}
elsif
(
index
(
$ua
,
'google-http-java-client'
) != -1 ) {
$r
=
'java'
;
$robot_tests
->{lib} = 1;
$robot_fragment
=
'google'
;
}
elsif
(
index
(
$ua
,
'researchscan.comsys.rwth-aachen.de'
) != -1 ) {
$r
=
'researchscan'
;
}
else
{
TEST:
for
my
$set
(
@ROBOT_TESTS
) {
my
$match
=
lc
$set
->[0];
if
(
index
(
$ua
,
lc
(
$match
) ) != -1 ) {
$id
=
$set
->[1];
$r
=
$id
;
$robot_fragment
=
lc
$match
;
last
TEST;
}
}
}
if
(
$browser_tests
->{applecoremedia}
||
$browser_tests
->{dalvik}
||
$browser_tests
->{adm} ) {
$robot_tests
->{lib} = 1;
}
if
(
$r
) {
$robot_tests
->{
$r
} = 1;
if
( !
$id
) {
$id
=
$ROBOT_IDS
{
$r
};
}
if
( !
exists
$robot_tests
->{robot_id} ) {
$robot_tests
->{robot_id} =
$id
;
}
$self
->{robot_string} =
$ROBOT_NAMES
{
$id
} ||
$ROBOT_NAMES
{
$r
};
$robot_tests
->{robot} =
$r
;
$robot_fragment
=
$r
if
!
defined
$robot_fragment
;
}
elsif
(
$ua
=~ /
seek
(?! mo (?: toolbar )? \s+ \d+\.\d+ )/x ) {
$robot_fragment
=
'seek'
;
$robot_tests
->{robot} =
'unknown'
;
}
elsif
(
$ua
=~ /search (?! [\w\s]* toolbar \b | bar \b | erpro \b )/x ) {
$robot_fragment
=
'search'
;
$robot_tests
->{robot} =
'unknown'
;
}
elsif
(
$self
->{user_agent} =~ /([\w \/\.\-]+)[ \;\(\)]*\+https?\:/i ) {
$self
->{robot_string} = $1;
$self
->{robot_string} =~ s/^ *(.+?)[ \;\(\)]*?( *\/[\d\.]+ *)?$/$1/;
$robot_fragment
= $1;
$robot_tests
->{robot} =
'unknown'
;
}
else
{
FRAGMENT:
for
my
$fragment
(
@ROBOT_FRAGMENTS
) {
if
(
$ROBOT_FRAGMENT_EXCEPTIONS
{
$fragment
} ) {
for
my
$exception
(
@{
$ROBOT_FRAGMENT_EXCEPTIONS
{
$fragment
} || [] } ) {
if
(
index
(
$ua
,
$exception
) != -1 ) {
next
FRAGMENT;
}
}
}
if
(
index
(
$ua
,
$fragment
) != -1 ) {
$robot_fragment
=
$fragment
;
$robot_tests
->{robot} =
'unknown'
;
last
;
}
}
}
if
(
exists
$robot_tests
->{robot} &&
$robot_tests
->{robot} eq
'unknown'
)
{
$robot_tests
->{robot_id} =
'unknown'
;
}
if
(
defined
$robot_fragment
) {
if
(
$self
->{user_agent} =~ m{\s*
([\w .:,\-\@\/]*
$robot_fragment
[\w .:,\-\@\/]*)
}ix
) {
my
$full_string
= $1;
$full_string
=~ s/ *$//;
if
(
$self
->{user_agent} eq
$full_string
&&
$self
->{user_agent} =~ m{\/.*\/}
&&
$self
->{user_agent} =~ m{
([\w]*
$robot_fragment
(\/[\d\.]+)?
[\w]*)
}ix
) {
$full_string
= $1;
}
if
(
$full_string
and
$full_string
=~ s/[\/ \.v]*(\d+)(\.\d+)?([\.\w]*)$// ) {
$self
->{robot_version} = [ $1, $2, $3 ];
}
else
{
$self
->{robot_version} =
undef
;
}
if
( !
defined
$self
->{robot_string} ) {
$self
->{robot_string} =
$full_string
;
}
}
}
if
( !
exists
(
$self
->{robot_version} ) ) {
$self
->{robot_version} =
undef
;
}
}
sub
_init_os {
my
$self
=
shift
;
my
$tests
=
$self
->{tests};
my
$browser_tests
=
$self
->{browser_tests};
my
$ua
=
lc
$self
->{user_agent};
my
$os_tests
=
$self
->{os_tests} = {};
my
$os
=
undef
;
my
$os_string
=
undef
;
if
(
index
(
$ua
,
'16bit'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'16-bit Windows'
;
$os_tests
->{win16} =
$os_tests
->{windows} = 1;
}
if
(
index
(
$ua
,
'win'
) != -1 ) {
if
(
index
(
$ua
,
'win16'
) != -1
||
index
(
$ua
,
'windows 3'
) != -1
||
index
(
$ua
,
'windows 16-bit'
) != -1 ) {
$os_tests
->{win16} = 1;
$os_tests
->{win3x} = 1;
$os
=
'windows'
;
if
(
index
(
$ua
,
'windows 3.1'
) != -1 ) {
$os_tests
->{win31} = 1;
$os_string
=
'Win3x'
;
}
else
{
$os_string
=
'Win3x'
;
}
}
elsif
(
index
(
$ua
,
'win95'
) != -1
||
index
(
$ua
,
'windows 95'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win95'
;
$os_tests
->{win95} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'win 9x 4.90'
) != -1
||
index
(
$ua
,
'windows me'
) != -1
) {
$os
=
'windows'
;
$os_string
=
'WinME'
;
$os_tests
->{winme} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'win98'
) != -1
||
index
(
$ua
,
'windows 98'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win98'
;
$os_tests
->{win98} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'windows 2000'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win2k'
;
$os_tests
->{win2k} =
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'windows ce'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'WinCE'
;
$os_tests
->{wince} = 1;
}
elsif
(
index
(
$ua
,
'windows phone'
) != -1 ) {
$os
=
'winphone'
;
$os_tests
->{winphone} = 1;
if
(
index
(
$ua
,
'windows phone os 7.0'
) != -1 ) {
$os_tests
->{winphone7} = 1;
}
elsif
(
index
(
$ua
,
'windows phone os 7.5'
) != -1 ) {
$os_tests
->{winphone7_5} = 1;
}
elsif
(
index
(
$ua
,
'windows phone 8.0'
) != -1 ) {
$os_tests
->{winphone8} = 1;
}
elsif
(
index
(
$ua
,
'windows phone 8.1'
) != -1 ) {
$os_tests
->{winphone8_1} = 1;
}
elsif
(
index
(
$ua
,
'windows phone 10.0'
) != -1 ) {
$os_tests
->{winphone10} = 1;
}
}
}
if
(
index
(
$ua
,
'nt'
) != -1 ) {
if
(
index
(
$ua
,
'nt 5.0'
) != -1
||
index
(
$ua
,
'nt5'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win2k'
;
$os_tests
->{win2k} =
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 5.1'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'WinXP'
;
$os_tests
->{winxp} =
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 5.2'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win2k3'
;
$os_tests
->{win2k3} =
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 6.0'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'WinVista'
;
$os_tests
->{winvista} =
$os_tests
->{winnt} =
$os_tests
->{win32}
= 1;
}
elsif
(
index
(
$ua
,
'nt 6.1'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win7'
;
$os_tests
->{win7} =
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 6.2'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win8.0'
;
$os_tests
->{win8_0} =
$os_tests
->{win8} =
$os_tests
->{winnt}
=
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 6.3'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win8.1'
;
$os_tests
->{win8_1} =
$os_tests
->{win8} =
$os_tests
->{winnt}
=
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'nt 10.0'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'Win10.0'
;
$os_tests
->{win10_0} =
$os_tests
->{win10} =
$os_tests
->{winnt}
=
$os_tests
->{win32} = 1;
}
elsif
(
index
(
$ua
,
'winnt'
) != -1
||
index
(
$ua
,
'windows nt'
) != -1
||
index
(
$ua
,
'nt4'
) != -1
||
index
(
$ua
,
'nt3'
) != -1 ) {
$os
=
'windows'
;
$os_string
=
'WinNT'
;
$os_tests
->{winnt} =
$os_tests
->{win32} = 1;
}
}
if
(
$os
) {
$os_tests
->{windows} = 1;
$os_tests
->{win32} = 1
if
index
(
$ua
,
'win32'
) != -1;
}
elsif
(
index
(
$ua
,
'macintosh'
) != -1 ||
index
(
$ua
,
'mac_'
) != -1 ) {
$os_tests
->{mac} = 1;
if
(
index
(
$ua
,
'mac os x'
) != -1 ) {
$os
=
'macosx'
;
$os_tests
->{
$os
} = 1;
}
else
{
$os
=
'mac'
;
}
if
(
index
(
$ua
,
'68k'
) != -1 ||
index
(
$ua
,
'68000'
) != -1 ) {
$os_tests
->{mac68k} = 1;
}
elsif
(
index
(
$ua
,
'ppc'
) != -1 ||
index
(
$ua
,
'powerpc'
) != -1 ) {
$os_tests
->{macppc} = 1;
}
}
elsif
(
$ua
=~ m{\b(ipad|iphone|ipod)\b} ) {
$os
=
'ios'
;
$os_tests
->{
$os
} = 1;
}
elsif
(
index
(
$ua
,
'android'
) != -1 ) {
$os
=
'android'
;
}
elsif
(
index
(
$ua
,
'inux'
) != -1 ) {
$os
=
'linux'
;
$os_tests
->{linux} =
$os_tests
->{unix} = 1;
}
elsif
(
$tests
->{x11} &&
index
(
$ua
,
'cros'
) != -1 ) {
$os
=
'chromeos'
;
$os_tests
->{chromeos} = 1;
}
elsif
(
index
(
$ua
,
'amiga'
) != -1 ) {
$os
=
'amiga'
;
$os_tests
->{
$os
} = 1;
}
elsif
(
index
(
$ua
,
'os/2'
) != -1 ) {
$os
=
'os2'
;
$os_tests
->{
$os
} = 1;
}
elsif
(
index
(
$ua
,
'solaris'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'Solaris'
;
$os_tests
->{sun} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'samsung'
) == -1 &&
index
(
$ua
,
'sun'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'SunOS'
;
$os_tests
->{sun} =
$os_tests
->{unix} = 1;
$os_tests
->{suni86} = 1
if
index
(
$ua
,
'i86'
) != -1;
$os_tests
->{sun4} = 1
if
index
(
$ua
,
'sunos 4'
) != -1;
$os_tests
->{sun5} = 1
if
index
(
$ua
,
'sunos 5'
) != -1;
}
elsif
(
index
(
$ua
,
'irix'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'Irix'
;
$os_tests
->{irix} =
$os_tests
->{unix} = 1;
$os_tests
->{irix5} = 1
if
(
index
(
$ua
,
'irix5'
) != -1 );
$os_tests
->{irix6} = 1
if
(
index
(
$ua
,
'irix6'
) != -1 );
}
elsif
(
index
(
$ua
,
'hp-ux'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'HP-UX'
;
$os_tests
->{hpux} =
$os_tests
->{unix} = 1;
$os_tests
->{hpux9} = 1
if
index
(
$ua
,
'09.'
) != -1;
$os_tests
->{hpux10} = 1
if
index
(
$ua
,
'10.'
) != -1;
}
elsif
(
index
(
$ua
,
'aix'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'AIX'
;
$os_tests
->{aix} =
$os_tests
->{unix} = 1;
$os_tests
->{aix1} = 1
if
(
index
(
$ua
,
'aix 1'
) != -1 );
$os_tests
->{aix2} = 1
if
(
index
(
$ua
,
'aix 2'
) != -1 );
$os_tests
->{aix3} = 1
if
(
index
(
$ua
,
'aix 3'
) != -1 );
$os_tests
->{aix4} = 1
if
(
index
(
$ua
,
'aix 4'
) != -1 );
}
elsif
(
$ua
=~ m{\bsco\b} ||
index
(
$ua
,
'unix_sv'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'SCO Unix'
;
$os_tests
->{sco} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'unix_system_v'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'System V Unix'
;
$os_tests
->{unixware} =
$os_tests
->{unix} = 1;
}
elsif
(
$ua
=~ m{\bncr\b} ) {
$os
=
'unix'
;
$os_string
=
'NCR Unix'
;
$os_tests
->{mpras} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'reliantunix'
) != -1 ) {
$os
=
'unix'
;
$os_string
=
'Reliant Unix'
;
$os_tests
->{reliant} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'dec'
) != -1
||
index
(
$ua
,
'osf1'
) != -1
||
index
(
$ua
,
'declpha'
) != -1
||
index
(
$ua
,
'alphaserver'
) != -1
||
index
(
$ua
,
'ultrix'
) != -1
||
index
(
$ua
,
'alphastation'
) != -1 ) {
$os
=
'unix'
;
$os_tests
->{dec} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'sinix'
) != -1 ) {
$os
=
'unix'
;
$os_tests
->{sinix} =
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'bsd'
) != -1 ) {
$os
=
'unix'
;
if
(
$self
->{user_agent} =~ m{(\w
*bsd
\w*)}i ) {
$os_string
= $1;
}
$os_tests
->{bsd} =
$os_tests
->{unix} = 1;
$os_tests
->{freebsd} = 1
if
index
(
$ua
,
'freebsd'
) != -1;
}
elsif
(
$tests
->{x11} ) {
$os
=
'unix'
;
$os_tests
->{unix} = 1;
}
elsif
(
index
(
$ua
,
'vax'
) != -1 ||
index
(
$ua
,
'openvms'
) != -1 ) {
$os
=
'vms'
;
$os_tests
->{vms} = 1;
}
elsif
(
index
(
$ua
,
'bb10'
) != -1 ) {
$os
=
'bb10'
;
$os_tests
->{bb10} = 1;
}
elsif
(
index
(
$ua
,
'rim tablet os'
) != -1 ) {
$os
=
'rimtabletos'
;
$os_tests
->{rimtabletos} = 1;
}
elsif
(
index
(
$ua
,
'playstation 3'
) != -1 ) {
$os
=
'ps3gameos'
;
$os_tests
->{ps3gameos} = 1;
}
elsif
(
index
(
$ua
,
'playstation portable'
) != -1 ) {
$os
=
'pspgameos'
;
$os_tests
->{pspgameos} = 1;
}
elsif
(
index
(
$ua
,
'windows'
) != -1 ) {
$os_tests
->{windows} = 1;
}
elsif
(
index
(
$ua
,
'win32'
) != -1 ) {
$os_tests
->{win32} =
$os_tests
->{windows} = 1;
}
elsif
(
$self
->{user_agent} =~ m{(brew)|(\bbmp\b)}i ) {
$os
=
'brew'
;
if
($1) {
$os_string
=
'Brew'
;
}
else
{
$os_string
=
'Brew MP'
;
}
$os_tests
->{brew} = 1;
}
else
{
$os
=
undef
;
}
if
( !
$os
&&
$browser_tests
->{firefox}
&&
index
(
$ua
,
'fennec'
) == -1
&& (
$self
->mobile ||
$self
->tablet ) ) {
$os
=
'firefoxos'
;
$os_tests
->{firefoxos} = 1;
}
$self
->{os} =
$os
;
if
(
$os
and !
$os_string
) {
$os_string
=
$OS_NAMES
{
$os
};
}
$self
->{os_string} =
$os_string
;
}
sub
_init_os_version {
my
(
$self
) =
@_
;
my
$os
=
$self
->os;
my
$os_string
=
$self
->os_string;
my
$ua
=
lc
$self
->{user_agent};
my
$os_version
=
undef
;
if
( !
defined
$os
) {
}
elsif
(
$os
eq
'winphone'
) {
if
(
$ua
=~ m{windows phone (?:os )?(\d+)(\.?\d*)([\.\d]*)} ) {
$os_version
= [ $1, $2, $3 ];
}
}
elsif
(
$os
eq
'macosx'
) {
if
(
$ua
=~ m{os x (\d+)[\._](\d+)[\._]?(\d*)} ) {
$os_version
= [ $1,
".$2"
,
length
($3) ?
".$3"
:
q{}
];
}
}
elsif
(
$os
eq
'ios'
) {
if
(
$ua
=~ m{ os (\d+)[\._ ](\d+)[\._ ]?(\d*)} ) {
$os_version
= [ $1,
".$2"
,
length
($3) ?
".$3"
:
q{}
];
}
}
elsif
(
$os
eq
'chromeos'
) {
if
(
$ua
=~ m{ cros \S* (\d+)(\.?\d*)([\.\d]*)} ) {
$os_version
= [ $1, $2, $3 ];
}
}
elsif
(
$os
eq
'android'
) {
if
(
$ua
=~ m{android (\d+)(\.?\d*)([\w\-\.]*)[\;\)]} ) {
$os_version
= [ $1, $2, $3 ];
}
}
elsif
(
$os
eq
'firefoxos'
) {
if
(
$ua
=~ m{firefox/(\d+)(\.?\d*)([\.\d]*)} ) {
$os_version
= [ $1, $2, $3 ];
}
}
elsif
(
$os
eq
'brew'
) {
if
(
$ua
=~ m{(brew|\bbmp) (\d+)(\.?\d*)([\.\d]*)} ) {
$os_version
= [ $2, $3, $4 ];
}
}
$self
->{os_version} =
$os_version
;
}
sub
_init_version {
my
(
$self
) =
@_
;
my
$ua
=
lc
$self
->{user_agent};
my
$tests
=
$self
->{tests};
my
$browser_tests
=
$self
->{browser_tests};
my
$browser
=
$self
->{browser};
$self
->{version_tests} = {};
my
$version_tests
=
$self
->{version_tests};
my
(
$major
,
$minor
,
$beta
);
if
(
defined
$browser
&&
$browser
eq
'opera'
) {
if
(
$ua
=~ m{\AOpera.*\sVersion/(\d*)\.(\d*)\z}i ) {
$major
= $1;
$minor
= $2;
}
elsif
(
$ua
=~ m{\bOPR/(\d+)\.(\d+)}i ) {
$major
= $1;
$minor
= $2;
}
elsif
(
$ua
=~ m{Opera[ /](\d+).(\d+)}i ) {
$major
= $1;
$minor
= $2;
}
}
elsif
(
$ua
=~ m{\b compatible; \s* [\w\-]* [/\s] ( [0-9]+ ) (?: .([0-9]+) (\S*) )? ;}x
) {
(
$major
,
$minor
,
$beta
) = ( $1, $2, $3 );
}
elsif
( !
$browser
) {
}
elsif
(
$browser_tests
->{edge} ) {
(
$major
,
$minor
,
$beta
)
=
$ua
=~ m{Edge/(\d+)(?:\.(\d+))?([\.\d]+)?}i;
(
$major
,
$minor
,
$beta
)
=
$ua
=~ m{(?:Edg|EdgA|EdgiOS)/(\d+)(?:\.(\d+))?([\.\d]+)?}i
unless
defined
$major
;
}
elsif
(
$browser_tests
->{safari} ) {
if
(
0
&&
$ua
=~ m{
version/
( \d+ )
\.
( \d+ )?
}x
) {
(
$major
,
$minor
) = ( $1, $2,
undef
);
}
elsif
(
$ua
=~ m{ safari/ ( \d+ (?: \.\d+ )* ) }x ) {
if
(
my
(
$safari_build
,
$safari_minor
) =
split
/\./, $1 ) {
$major
=
int
(
$safari_build
/ 100 );
$minor
=
int
(
$safari_build
% 100 );
$beta
=
".$safari_minor"
if
defined
$safari_minor
;
}
}
elsif
(
$ua
=~ m{applewebkit\/([\d\.]{1,})}xi ) {
if
(
my
(
$safari_build
,
$safari_minor
) =
split
/\./, $1 ) {
$major
=
int
(
$safari_build
/ 100 );
$minor
=
int
(
$safari_build
% 100 );
$beta
=
".$safari_minor"
if
$safari_minor
;
}
}
}
elsif
(
$browser_tests
->{fxios} ) {
(
$major
,
$minor
) =
$ua
=~ m{ \b fxios/ (\d+) [.] (\d+) }x;
}
elsif
(
$tests
->{meta_app} ) {
(
$major
,
$minor
,
$beta
) = (
q{}
) x 3;
if
(
$ua
=~ m{ \b fbav/ ([^;]*) }x ) {
(
$major
,
$minor
,
$beta
) =
split
/[.]/, $1, 3;
if
(
$beta
) {
$beta
=
q{.}
.
$beta
;
}
}
}
elsif
(
$browser_tests
->{instagram} ) {
(
$major
,
$minor
,
$beta
) = (
q{}
) x 3;
if
(
$self
->{user_agent} =~ m{ \b Instagram [ ]+ ([0-9.]+) [ ] }x ) {
(
$major
,
$minor
,
$beta
) =
split
/[.]/, $1, 3;
if
(
$beta
) {
$beta
=
q{.}
.
$beta
;
}
}
}
elsif
(
$browser_tests
->{ie} ) {
if
(
$ua
=~ m{\b msie \s ( [0-9\.]+ ) (?: [a-z]+ [a-z0-9]* )? ;}x ) {
(
$major
,
$minor
,
$beta
) =
split
/\./, $1;
}
elsif
(
$ua
=~ m{\b rv: ( [0-9\.]+ ) \b}x ) {
(
$major
,
$minor
,
$beta
) =
split
/\./, $1;
}
}
elsif
(
$browser
eq
'n3ds'
) {
if
(
$ua
=~ m{Nintendo 3DS;.*\sVersion/(\d*)\.(\d*)}i ) {
$major
= $1;
$minor
= $2;
}
}
elsif
(
$browser
eq
'browsex'
) {
if
(
$ua
=~ m{BrowseX \((\d+)\.(\d+)([\d.]*)}i ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
}
elsif
(
$ua
=~ m{netscape6/(\d+)\.(\d+)([\d.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
elsif
(
$browser
eq
'brave'
) {
if
(
$ua
=~ m{brave/(\d+)\.(\d+)([\d.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
}
elsif
(
$browser
eq
'chrome'
&&
$ua
=~ m{crios/(\d+)\.(\d+)([\d.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
elsif
(
$browser
eq
'pubsub'
&&
$ua
=~ m{apple-pubsub/(\d+)\.?(\d+)?([\d.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
elsif
(
$browser
eq
'obigo'
&&
$self
->{user_agent} =~ m{(obigo[\w\-]*|teleca)[\/ ]\w(\d+)(\w*)}i )
{
$major
= $2;
$minor
=
q{}
;
$beta
= $3;
}
elsif
(
$browser
eq
'polaris'
&&
$ua
=~ m{polaris[ \/](\d+)\.?(\d+)?([\d\.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
elsif
(
$browser
eq
'ucbrowser'
&&
$ua
=~ m{ucbrowser[\/ ]*(\d+)\.?(\d+)?([\d\.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
elsif
(
$browser
eq
'samsung'
&&
$ua
=~ m{samsungbrowser/(\d+)\.(\d+)\s} )
{
$major
= $1;
$minor
= $2;
}
elsif
(
$browser_tests
->{yandex_browser} ) {
(
$major
,
$minor
,
$beta
) = (
q{}
) x 3;
if
(
$self
->{user_agent} =~ m{ \b YaBrowser / ([0-9.]+) [ ] }x ) {
(
$major
,
$minor
,
$beta
) =
split
/[.]/, $1, 3;
if
(
$beta
) {
$beta
=
q{.}
.
$beta
;
}
}
}
if
( !
defined
$major
&&
defined
$self
->{browser_string} ) {
my
$version_index
=
index
(
$ua
,
lc
"$self->{browser_string}/"
);
if
(
$version_index
!= -1 ) {
my
$version_str
=
substr
(
$ua
,
$version_index
+
length
(
$browser
) );
if
(
$version_str
=~ m{/(\d+)\.(\d+)([\w.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
}
}
if
( !
defined
$major
) {
if
(
$ua
=~ m{version/(\d+)\.(\d+)([\w.]*)} ) {
$major
= $1;
$minor
= $2;
$beta
= $3;
}
}
if
( !
defined
$major
) {
(
$major
,
$minor
,
$beta
) = (
$ua
=~ m{
\S+
\/
[A-Za-z]*
( [0-9]+ )
\.
([\d]* )
( [^\s]* )
}x
);
}
if
( !
defined
$major
) {
if
(
$ua
=~ /[A-Za-z]+\/(\d+)\;/ ) {
$major
= $1;
$minor
= 0;
}
}
$major
= 0
if
!
$major
;
$minor
= 0
if
!
$minor
;
$beta
=
undef
if
(
defined
$beta
&&
$beta
eq
q{}
);
if
(
$browser_tests
->{netscape} ) {
$version_tests
->{nav2} = 1
if
$major
== 2;
$version_tests
->{nav3} = 1
if
$major
== 3;
$version_tests
->{nav4} = 1
if
$major
== 4;
$version_tests
->{nav4up} = 1
if
$major
>= 4;
$version_tests
->{nav45} = 1
if
$major
== 4 &&
$minor
== 5;
$version_tests
->{nav45up} = 1
if
(
$major
== 4 &&
".$minor"
>= .5 )
||
$major
>= 5;
$version_tests
->{navgold} = 1
if
defined
$beta
&& (
index
(
$beta
,
'gold'
) != -1 );
$version_tests
->{nav6} = 1
if
(
$major
== 5 ||
$major
== 6 );
$version_tests
->{nav6up} = 1
if
$major
>= 5;
if
(
$browser
eq
'seamonkey'
) {
$version_tests
->{nav2} = 0;
$version_tests
->{nav4up} = 1;
$version_tests
->{nav45up} = 1;
$version_tests
->{nav6} = 1;
$version_tests
->{nav6up} = 1;
}
}
if
(
$browser_tests
->{ie} ) {
$version_tests
->{ie3} = 1
if
(
$major
== 3 );
$version_tests
->{ie4} = 1
if
(
$major
== 4 );
$version_tests
->{ie4up} = 1
if
(
$major
>= 4 );
$version_tests
->{ie5} = 1
if
(
$major
== 5 );
$version_tests
->{ie5up} = 1
if
(
$major
>= 5 );
$version_tests
->{ie55} = 1
if
(
$major
== 5 &&
$minor
== 5 );
$version_tests
->{ie55up} = 1
if
(
".$minor"
>= .5 ||
$major
>= 6 );
$version_tests
->{ie6} = 1
if
(
$major
== 6 );
$version_tests
->{ie7} = 1
if
(
$major
== 7 );
$version_tests
->{ie8} = 1
if
(
$major
== 8 );
$version_tests
->{ie9} = 1
if
(
$major
== 9 );
$version_tests
->{ie10} = 1
if
(
$major
== 10 );
$version_tests
->{ie11} = 1
if
(
$major
== 11 );
$version_tests
->{ie_compat_mode}
= (
$version_tests
->{ie7}
&&
$tests
->{trident}
&&
defined
$self
->engine_version
&&
$self
->engine_version >= 4 );
}
if
(
$browser_tests
->{aol} ) {
$version_tests
->{aol3} = 1
if
(
index
(
$ua
,
'aol 3.0'
) != -1
||
$version_tests
->{ie3} );
$version_tests
->{aol4} = 1
if
(
index
(
$ua
,
'aol 4.0'
) != -1 )
||
$version_tests
->{ie4};
$version_tests
->{aol5} = 1
if
index
(
$ua
,
'aol 5.0'
) != -1;
$version_tests
->{aol6} = 1
if
index
(
$ua
,
'aol 6.0'
) != -1;
$version_tests
->{aoltv} = 1
if
index
(
$ua
,
'navio'
) != -1;
}
if
(
$browser_tests
->{opera} ) {
$version_tests
->{opera3} = 1
if
index
(
$ua
,
'opera 3'
) != -1 ||
index
(
$ua
,
'opera/3'
) != -1;
$version_tests
->{opera4} = 1
if
(
index
(
$ua
,
'opera 4'
) != -1 )
|| (
index
(
$ua
,
'opera/4'
) != -1
&& (
index
(
$ua
,
'nintendo dsi'
) == -1 ) );
$version_tests
->{opera5} = 1
if
(
index
(
$ua
,
'opera 5'
) != -1 )
|| (
index
(
$ua
,
'opera/5'
) != -1 );
$version_tests
->{opera6} = 1
if
(
index
(
$ua
,
'opera 6'
) != -1 )
|| (
index
(
$ua
,
'opera/6'
) != -1 );
$version_tests
->{opera7} = 1
if
(
index
(
$ua
,
'opera 7'
) != -1 )
|| (
index
(
$ua
,
'opera/7'
) != -1 );
}
$minor
=
".$minor"
;
$self
->{major} =
$major
;
$self
->{minor} =
$minor
;
$self
->{beta} =
$beta
;
}
sub
_init_device {
my
(
$self
) =
@_
;
my
$ua
=
lc
$self
->{user_agent};
my
$browser_tests
=
$self
->{browser_tests};
my
$tests
=
$self
->{tests};
my
(
$device
,
$device_string
);
my
$device_tests
=
$self
->{device_tests} = {};
if
(
index
(
$ua
,
'windows phone'
) != -1 ) {
$device
=
'winphone'
;
}
elsif
(
index
(
$ua
,
'android'
) != -1
||
index
(
$ua
,
'silk-accelerated'
) != -1 ) {
$device
=
'android'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'blackberry'
) != -1
||
index
(
$ua
,
'bb10'
) != -1
||
index
(
$ua
,
'rim tablet os'
) != -1 ) {
$device
=
'blackberry'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'ipod'
) != -1 ) {
$device
=
'ipod'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'ipad'
) != -1 ) {
$device
=
'ipad'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'iphone'
) != -1 ) {
$device
=
'iphone'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'webos'
) != -1 ) {
$device
=
'webos'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'kindle'
) != -1 ) {
$device
=
'kindle'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'audrey'
) != -1 ) {
$device
=
'audrey'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'i-opener'
) != -1 ) {
$device
=
'iopener'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'avantgo'
) != -1 ) {
$device
=
'avantgo'
;
$device_tests
->{
$device
} = 1;
$device_tests
->{palm} = 1;
}
elsif
(
index
(
$ua
,
'palmos'
) != -1 ) {
$device
=
'palm'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'playstation 3'
) != -1 ) {
$device
=
'ps3'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'playstation portable'
) != -1 ) {
$device
=
'psp'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'nintendo dsi'
) != -1 ) {
$device
=
'dsi'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
index
(
$ua
,
'nintendo 3ds'
) != -1 ) {
$device
=
'n3ds'
;
$device_tests
->{
$device
} = 1;
}
elsif
(
$browser_tests
->{obigo}
||
$browser_tests
->{ucbrowser}
||
index
(
$ua
,
'up.browser'
) != -1
|| (
index
(
$ua
,
'nokia'
) != -1
&&
index
(
$ua
,
'windows phone'
) == -1 )
||
index
(
$ua
,
'alcatel'
) != -1
||
$ua
=~ m{\bbrew\b}
||
$ua
=~ m{\bbmp\b}
||
index
(
$ua
,
'ericsson'
) != -1
||
index
(
$ua
,
'sie-'
) == 0
||
index
(
$ua
,
'wmlib'
) != -1
||
index
(
$ua
,
' wap'
) != -1
||
index
(
$ua
,
'wap '
) != -1
||
index
(
$ua
,
'wap/'
) != -1
||
index
(
$ua
,
'-wap'
) != -1
||
index
(
$ua
,
'wap-'
) != -1
||
index
(
$ua
,
'wap'
) == 0
||
index
(
$ua
,
'wapper'
) != -1
||
index
(
$ua
,
'zetor'
) != -1
) {
$device
=
'wap'
;
$device_tests
->{
$device
} = 1;
}
$device_tests
->{tablet} = (
index
(
$ua
,
'ipad'
) != -1
|| (
$browser_tests
->{ie}
&&
index
(
$ua
,
'windows phone'
) == -1
&&
index
(
$ua
,
'arm'
) != -1 )
|| (
index
(
$ua
,
'android'
) != -1
&&
index
(
$ua
,
'mobile'
) == -1
&&
index
(
$ua
,
'safari'
) != -1 )
|| (
$browser_tests
->{firefox} &&
index
(
$ua
,
'tablet'
) != -1 )
||
index
(
$ua
,
'an10bg3'
) != -1
||
index
(
$ua
,
'an10bg3dt'
) != -1
||
index
(
$ua
,
'an10g2'
) != -1
||
index
(
$ua
,
'an7bg3'
) != -1
||
index
(
$ua
,
'an7dg3'
) != -1
||
index
(
$ua
,
'an7dg3childpad'
) != -1
||
index
(
$ua
,
'an7dg3st'
) != -1
||
index
(
$ua
,
'an7fg3'
) != -1
||
index
(
$ua
,
'an7g3'
) != -1
||
index
(
$ua
,
'an8cg3'
) != -1
||
index
(
$ua
,
'an8g3'
) != -1
||
index
(
$ua
,
'an9g3'
) != -1
||
index
(
$ua
,
'flyer'
) != -1
||
index
(
$ua
,
'hp-tablet'
) != -1
||
index
(
$ua
,
'jetstream'
) != -1
||
index
(
$ua
,
'kindle'
) != -1
||
index
(
$ua
,
'novo7'
) != -1
||
index
(
$ua
,
'opera tablet'
) != -1
||
index
(
$ua
,
'rim tablet'
) != -1
||
index
(
$ua
,
'transformer'
) != -1
||
index
(
$ua
,
'xoom'
) != -1
);
if
( !
$device_tests
->{tablet} ) {
$device_tests
->{mobile} = (
(
$browser_tests
->{firefox} &&
index
(
$ua
,
'mobile'
) != -1 )
|| (
$browser_tests
->{ie}
&&
index
(
$ua
,
'windows phone'
) == -1
&&
index
(
$ua
,
'arm'
) != -1 )
||
index
(
$ua
,
'windows phone'
) != -1
||
index
(
$ua
,
'up.browser'
) != -1
||
index
(
$ua
,
'nokia'
) != -1
||
index
(
$ua
,
'alcatel'
) != -1
||
index
(
$ua
,
'ericsson'
) != -1
||
index
(
$ua
,
'sie-'
) == 0
||
index
(
$ua
,
'wmlib'
) != -1
||
index
(
$ua
,
' wap'
) != -1
||
index
(
$ua
,
'wap '
) != -1
||
index
(
$ua
,
'wap/'
) != -1
||
index
(
$ua
,
'-wap'
) != -1
||
index
(
$ua
,
'wap-'
) != -1
||
index
(
$ua
,
'wap'
) == 0
||
index
(
$ua
,
'wapper'
) != -1
||
index
(
$ua
,
'blackberry'
) != -1
||
index
(
$ua
,
'mobile'
) != -1
||
index
(
$ua
,
'palm'
) != -1
||
index
(
$ua
,
'smartphone'
) != -1
||
index
(
$ua
,
'windows ce'
) != -1
||
index
(
$ua
,
'palmsource'
) != -1
||
index
(
$ua
,
'iphone'
) != -1
||
index
(
$ua
,
'ipod'
) != -1
||
index
(
$ua
,
'ipad'
) != -1
|| (
index
(
$ua
,
'opera mini'
) != -1
&&
index
(
$ua
,
'tablet'
) == -1 )
||
index
(
$ua
,
'htc_'
) != -1
||
index
(
$ua
,
'symbian'
) != -1
||
index
(
$ua
,
'webos'
) != -1
||
index
(
$ua
,
'samsung'
) != -1
||
index
(
$ua
,
'zetor'
) != -1
||
index
(
$ua
,
'android'
) != -1
||
index
(
$ua
,
'symbos'
) != -1
||
index
(
$ua
,
'opera mobi'
) != -1
||
index
(
$ua
,
'fennec'
) != -1
||
$ua
=~ m{\bbrew\b}
||
index
(
$ua
,
'obigo'
) != -1
||
index
(
$ua
,
'teleca'
) != -1
||
index
(
$ua
,
'polaris'
) != -1
||
index
(
$ua
,
'opera tablet'
) != -1
||
index
(
$ua
,
'rim tablet'
) != -1
|| (
index
(
$ua
,
'bb10'
) != -1
&&
index
(
$ua
,
'mobile'
) != -1 )
||
$device_tests
->{psp}
||
$device_tests
->{dsi}
||
$device_tests
->{
'n3ds'
}
);
}
if
(
$browser_tests
->{ucbrowser}
&&
$self
->{user_agent}
=~ m{ucweb/2.0\s*\(([^\;\)]*\;){3,4}\s*([^\;\)]*?)\s*\)}i ) {
$device_string
= $2;
}
elsif
(
$ua
=~ /^(\bmot-[^ \/]+)/ ) {
$device_string
=
substr
$self
->{user_agent}, 0,
length
$1;
$device_string
=~ s/^MOT-/Motorola /i;
}
elsif
( (
$browser_tests
->{obigo} ||
index
(
$ua
,
'brew'
) != -1 )
&&
$self
->{user_agent} =~ m{\d+x\d+ ([\d\w\- ]+?)( \S+\/\S+)*$}i ) {
$device_string
= $1;
}
elsif
(
$ua
=~ /windows phone os [^\)]+ iemobile\/[^;]+; ([^;]+; [^;\)]+)/g )
{
$device_string
=
substr
$self
->{user_agent},
pos
(
$ua
) -
length
$1,
length
$1;
$device_string
=~ s/; / /;
}
elsif
(
$ua
=~ /windows phone [^\)]+ iemobile\/[^;]+; arm; touch; ([^;]+; [^;\)]+)/g
) {
$device_string
=
substr
$self
->{user_agent},
pos
(
$ua
) -
length
$1,
length
$1;
$device_string
=~ s/; / /;
}
elsif
(
$ua
=~ /windows phone 8[^\)]+ iemobile\/[^;]+; ([^;]+; [^;\)]+)/g ) {
$device_string
=
substr
$self
->{user_agent},
pos
(
$ua
) -
length
$1,
length
$1;
$device_string
=~ s/; / /;
}
elsif
(
$ua
=~ /bb10; ([^;\)]+)/g ) {
$device_string
=
'BlackBerry '
.
substr
$self
->{user_agent},
pos
(
$ua
) -
length
$1,
length
$1;
$device_string
=~ s/Kbd/Q10/;
}
elsif
(
$ua
=~ /blackberry ([\w.]+)/ ) {
$device_string
=
"BlackBerry $1"
;
}
elsif
(
$ua
=~ /blackberry(\d+)\// ) {
$device_string
=
"BlackBerry $1"
;
}
elsif
(
$ua
=~ /silk-accelerated/ ) {
$device_string
=
'Kindle Fire'
;
$device_tests
->{kindlefire} = 1;
}
elsif
(
$self
->{user_agent} =~ /android .*\; ([^;]*) build/i ) {
my
$model
= $1;
if
(
$model
=~ m{^KF} ||
$model
=~ m{kindle fire}i ) {
$device_string
=
'Kindle Fire'
;
$device_tests
->{kindlefire} = 1;
}
elsif
(
$device_tests
->{tablet} ) {
$device_string
=
"Android tablet ($model)"
;
}
else
{
$device_string
=
"Android ($model)"
;
}
}
elsif
(
$self
->{user_agent}
=~ /\b((alcatel|huawei|lg|nokia|samsung|sonyericsson)[\w\-]*)\//i ) {
$device_string
= $1;
}
elsif
(
$self
->{user_agent} =~ /CrKey/ ) {
$device
=
'chromecast'
;
$device_string
=
'Chromecast'
;
}
elsif
(
$device
) {
$device_string
=
$DEVICE_NAMES
{
$device
};
}
else
{
$device_string
=
undef
;
}
if
(
$device
) {
$self
->{device} =
$device
;
}
else
{
$self
->{device}
=
undef
;
}
if
(
$device_string
) {
$self
->{device_string} =
$device_string
;
}
}
sub
browser {
my
(
$self
) =
@_
;
return
undef
unless
defined
$self
->{user_agent};
return
$self
->{browser};
}
sub
browser_string {
my
(
$self
) =
@_
;
return
undef
unless
defined
$self
->{user_agent};
return
$self
->{browser_string};
}
sub
robot {
my
$self
=
shift
;
$self
->_init_robots
unless
exists
(
$self
->{robot_string} );
return
$self
->{robot_tests}->{robot};
}
sub
robot_string {
my
$self
=
shift
;
$self
->_init_robots
unless
exists
(
$self
->{robot_string} );
return
$self
->{robot_string};
}
sub
robot_name {
my
$self
=
shift
;
return
$self
->robot_string;
}
sub
robot_id {
my
$self
=
shift
;
return
$self
->{robot_tests}->{robot_id} ?
$self
->{robot_tests}->{robot_id}
:
$self
->robot ?
$ROBOT_IDS
{
$self
->robot }
:
undef
;
}
sub
_robot_version {
my
(
$self
) =
@_
;
$self
->_init_robots
unless
exists
(
$self
->{robot_string} );
if
(
$self
->{robot_version} ) {
return
@{
$self
->{robot_version} };
}
else
{
return
(
undef
,
undef
,
undef
);
}
}
sub
robot_version {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_robot_version;
if
(
defined
$major
) {
if
(
defined
$minor
) {
return
"$major$minor"
;
}
else
{
return
$major
;
}
}
else
{
return
undef
;
}
}
sub
robot_major {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_robot_version;
return
$major
;
}
sub
robot_minor {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_robot_version;
return
$minor
;
}
sub
robot_beta {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_robot_version;
return
$beta
;
}
sub
os {
my
(
$self
) =
@_
;
return
undef
unless
defined
$self
->{user_agent};
$self
->_init_os
unless
$self
->{os_tests};
return
$self
->{os};
}
sub
os_string {
my
(
$self
) =
@_
;
return
undef
unless
defined
$self
->{user_agent};
$self
->_init_os
unless
$self
->{os_tests};
return
$self
->{os_string};
}
sub
_os_version {
my
(
$self
) =
@_
;
$self
->_init_os_version
if
!
exists
(
$self
->{os_version} );
if
(
$self
->{os_version} ) {
return
@{
$self
->{os_version} };
}
else
{
return
(
undef
,
undef
,
undef
);
}
}
sub
os_version {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_os_version;
return
defined
$major
?
"$major$minor"
:
undef
;
}
sub
os_major {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_os_version;
return
$major
;
}
sub
os_minor {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_os_version;
return
$minor
;
}
sub
os_beta {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_os_version;
return
$beta
;
}
sub
_realplayer_version {
my
(
$self
) =
@_
;
$self
->_init_version
unless
$self
->{version_tests};
return
$self
->{realplayer_version} || 0;
}
sub
realplayer_browser {
my
(
$self
) =
@_
;
return
defined
(
$self
->{browser} ) &&
$self
->{browser} eq
'realplayer'
;
}
sub
gecko_version {
my
(
$self
) =
@_
;
if
(
$self
->gecko ) {
return
$self
->{engine_version};
}
else
{
return
undef
;
}
}
sub
version {
my
(
$self
) =
@_
;
$self
->_init_version()
unless
$self
->{version_tests};
return
defined
$self
->{major} ?
"$self->{major}$self->{minor}"
:
undef
;
}
sub
major {
my
(
$self
) =
@_
;
$self
->_init_version()
unless
$self
->{version_tests};
my
(
$version
) =
$self
->{major};
return
$version
;
}
sub
minor {
my
(
$self
) =
@_
;
$self
->_init_version()
unless
$self
->{version_tests};
my
(
$version
) =
$self
->{minor};
return
$version
;
}
sub
public_version {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
$minor
||=
q{}
;
return
defined
$major
?
"$major$minor"
:
undef
;
}
sub
public_major {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
return
$major
;
}
sub
public_minor {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
return
$minor
;
}
sub
public_beta {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_public;
return
$beta
;
}
sub
browser_version {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
$minor
||=
q{}
;
return
defined
$major
?
"$major$minor"
:
undef
;
}
sub
browser_major {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
return
$major
;
}
sub
browser_minor {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
) =
$self
->_public;
return
$minor
;
}
sub
browser_beta {
my
(
$self
) =
@_
;
my
(
$major
,
$minor
,
$beta
) =
$self
->_public;
return
$beta
;
}
sub
_public {
my
(
$self
) =
@_
;
if
(
$self
->safari ) {
my
$ua
=
lc
$self
->{user_agent};
if
(
$ua
=~ m{
version/
( \d+ )
( \. \d+ )?
}x
) {
return
( $1, $2,
undef
);
}
if
(
$ua
=~ m{ safari/ ( \d+ (?: \.\d+ )* ) }x ) {
my
$build
= $1;
my
$version
=
$safari_build_to_version
{
$build
};
unless
(
$version
) {
for
my
$maybe_build
(
sort
{
$self
->_cmp_versions(
$b
,
$a
) }
keys
%safari_build_to_version
) {
$version
=
$safari_build_to_version
{
$maybe_build
},
last
if
$self
->_cmp_versions(
$build
,
$maybe_build
) >= 0;
}
return
(
'1'
,
'.2'
,
undef
)
if
$ua
=~ m{safari/12x};
}
return
(
undef
,
undef
,
undef
)
unless
defined
$version
;
my
(
$major
,
$minor
) =
split
/\./,
$version
;
my
$beta
;
$minor
=~ s/(\D.*)// and
$beta
= $1;
$minor
= (
'.'
.
$minor
);
return
(
$major
,
$minor
, (
$beta
? 1 :
undef
) );
}
}
$self
->_init_version()
unless
$self
->{version_tests};
return
(
$self
->{major},
$self
->{minor},
$self
->{beta} );
}
sub
_cmp_versions {
my
(
$self
,
$a
,
$b
) =
@_
;
my
@a
=
split
/\./,
$a
;
my
@b
=
split
/\./,
$b
;
while
(
@b
) {
return
-1
if
@a
== 0 ||
$a
[0] <
$b
[0];
return
1
if
@b
== 0 ||
$b
[0] <
$a
[0];
shift
@a
;
shift
@b
;
}
return
@a
<=>
@b
;
}
sub
engine {
my
(
$self
) =
@_
;
return
!
$self
->engine_string ?
undef
:
$self
->engine_string eq
'MSIE'
?
'ie'
:
lc
(
$self
->engine_string );
}
sub
engine_string {
my
(
$self
) =
@_
;
if
(
$self
->gecko ) {
return
'Gecko'
;
}
if
(
$self
->trident ) {
return
'Trident'
;
}
if
(
$self
->ie ) {
return
'MSIE'
;
}
if
(
$self
->edgelegacy ) {
return
'EdgeHTML'
;
}
if
(
$self
->webkit ) {
return
'WebKit'
;
}
if
(
$self
->presto ) {
return
'Presto'
;
}
if
(
$self
->netfront ) {
return
'NetFront'
;
}
if
(
$self
->khtml ) {
return
'KHTML'
;
}
return
undef
;
}
sub
engine_version {
my
(
$self
) =
@_
;
return
$self
->{engine_version}
&&
$self
->{engine_version} =~ m{^(\d+(\.\d+)?)} ? $1 :
undef
;
}
sub
engine_major {
my
(
$self
) =
@_
;
return
$self
->{engine_version}
&&
$self
->{engine_version} =~ m{^(\d+)} ? $1 :
undef
;
}
sub
engine_minor {
my
(
$self
) =
@_
;
return
$self
->{engine_version}
&&
$self
->{engine_version} =~ m{^\d+(\.\d+)} ? $1 :
undef
;
}
sub
engine_beta {
my
(
$self
) =
@_
;
return
$self
->{engine_version}
&&
$self
->{engine_version} =~ m{^\d+\.\d+([\.\d\+]*)} ? $1 :
undef
;
}
sub
beta {
my
(
$self
) =
@_
;
$self
->_init_version
unless
$self
->{version_tests};
my
(
$version
) =
$self
->{beta};
return
$version
;
}
sub
language {
my
(
$self
) =
@_
;
my
$parsed
=
$self
->_language_country();
return
$parsed
->{
'language'
};
}
sub
country {
my
(
$self
) =
@_
;
my
$parsed
=
$self
->_language_country();
return
$parsed
->{
'country'
};
}
sub
device {
my
(
$self
) =
@_
;
$self
->_init_device
if
!
exists
(
$self
->{device} );
return
$self
->{device};
}
sub
device_string {
my
(
$self
) =
@_
;
$self
->_init_device
if
!
exists
(
$self
->{device_string} );
return
$self
->{device_string};
}
sub
device_name {
my
(
$self
) =
@_
;
return
$self
->device_string;
}
sub
_language_country {
my
(
$self
) =
@_
;
if
(
$self
->safari ) {
if
(
$self
->major == 1
&&
$self
->{user_agent} =~ m/\s ( [a-z]{2} ) \)/xms ) {
return
{
language
=>
uc
$1 };
}
if
(
$self
->{user_agent} =~ m/\s ([a-z]{2})-([A-Za-z]{2})/xms ) {
return
{
language
=>
uc
$1,
country
=>
uc
$2 };
}
}
if
(
$self
->aol
&&
$self
->{user_agent} =~ m/;([A-Z]{2})_([A-Z]{2})\)/ ) {
return
{
language
=> $1,
country
=> $2 };
}
if
(
$self
->meta_app
&&
$self
->{user_agent}
=~ m{ ;FBLC/ ([a-z]{2}) (?: [_-] ([A-Z]{2}) )? }x ) {
return
{
language
=>
uc
$1, $2 ? (
country
=> $2 ) : () };
}
if
(
$self
->instagram
&&
$self
->{user_agent}
=~ m{ (?: [(] | ;[ ] ) ([a-z]{2}) [_-] ([A-Z]{2}) [;)] }x ) {
return
{
language
=>
uc
$1, $2 ? (
country
=> $2 ) : () };
}
if
(
$self
->{user_agent} =~ m/\b([a-z]{2})-([A-Za-z]{2})\b/xms ) {
return
{
language
=>
uc
$1,
country
=>
uc
$2 };
}
if
(
$self
->{user_agent} =~ m/\[([a-z]{2})\]/xms ) {
return
{
language
=>
uc
$1 };
}
if
(
$self
->{user_agent} =~ m/\(([^)]+)\)/xms ) {
my
@parts
=
split
( /;/, $1 );
foreach
my
$part
(
@parts
) {
if
(
$part
=~ /^\s*([a-z]{2})\s*$/
&& !(
$self
->webview && $1 eq
'wv'
) ) {
return
{
language
=>
uc
$1 };
}
}
}
return
{
language
=>
undef
,
country
=>
undef
};
}
sub
browser_properties {
my
(
$self
) =
@_
;
my
@browser_properties
;
my
(
$test
,
$value
);
while
( (
$test
,
$value
) =
each
%{
$self
->{tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
while
( (
$test
,
$value
) =
each
%{
$self
->{browser_tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
$self
->_init_device
unless
$self
->{device_tests};
$self
->_init_os
unless
$self
->{os_tests};
$self
->_init_robots
unless
$self
->{robot_tests};
$self
->_init_version
unless
$self
->{version_tests};
while
( (
$test
,
$value
) =
each
%{
$self
->{device_tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
while
( (
$test
,
$value
) =
each
%{
$self
->{os_tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
while
( (
$test
,
$value
) =
each
%{
$self
->{robot_tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
while
( (
$test
,
$value
) =
each
%{
$self
->{version_tests} } ) {
push
@browser_properties
,
$test
if
$value
;
}
push
@browser_properties
,
'device'
if
(
$self
->device() );
@browser_properties
=
sort
@browser_properties
;
return
@browser_properties
;
}
sub
lib {
my
$self
=
shift
;
$self
->_init_robots()
unless
$self
->{robot_tests};
return
$self
->{robot_tests}->{lib};
}
sub
all_robot_ids {
my
$self
=
shift
;
return
keys
%ROBOT_NAMES
;
}
sub
u2f {
my
$self
=
shift
;
return
1
if
$self
->chrome
&&
$self
->browser_major
&&
$self
->browser_major >= 41;
return
1
if
$self
->opera
&&
$self
->browser_major
&& (
$self
->browser_major == 40
||
$self
->browser_major >= 42 );
return
undef
;
}
sub
_all_tests {
return
@ALL_TESTS
;
}
sub
_robot_names {
return
%ROBOT_NAMES
;
}
sub
_robot_tests {
return
@ROBOT_TESTS
;
}
sub
_robot_ids {
return
%ROBOT_IDS
;
}
1;