lib/wpxf/net/user_agent.rb
# frozen_string_literal: true
module Wpxf
module Net
# Provides functionality for generating user agent strings.
module UserAgent
include Wpxf::Versioning::BrowserVersions
include Wpxf::Versioning::OSVersions
# A random browser and OS combination.
# @return [Hash] a hash containing a :browser and :os
def random_browser_and_os
frequencies = clients_by_frequency
target_frequency = rand(1..100)
sum = 0
frequencies.each do |browser_frequency, combinations|
sum += browser_frequency.to_i
next if target_frequency > sum
# This browser encompasses our target frequency, so reset the
# frequency sum and generate a new target frequency for the
# operating system selection.
target_frequency = rand(1..100)
sum = 0
# Once we find an OS that covers the target frequency, return
# the browser/OS combination.
combinations.each do |os_frequency, combo|
sum += os_frequency.to_i
if target_frequency <= sum
return {
browser: combo['browser'].to_sym,
os: combo['os'].to_sym
}
end
end
end
# This point should never be reached, as the frequencies should
# always total 100 and thus we should always retrieve a combo.
raise 'Browser and OS frequencies exceeded 100'
end
# @return [Hash] a hash of browser and OS combinations grouped by
# frequencies drawn from real-world statistics.
def clients_by_frequency
json = Wpxf::DataFile.new('json', 'browser_usage_by_frequency.json').content
JSON.parse(json)
end
# A random date between two dates in a specific format.
# @param min the minimum date to return.
# @param max the maximum date to return.
# @param format the format string to use when formatting the date.
# @return [String] a formatted random date.
def random_time_string(min, max = Time.now.to_s, format = '%Y%m%d')
rand(Time.parse(min)..Time.parse(max)).strftime(format)
end
# A random CPU type.
# @param os the operating system that the CPU would be used with.
# @return [String] a random CPU type.
def random_processor_string(os)
return ['i686', 'x86_64'].sample if os == :linux
return ['Intel', 'PPC', 'U; Intel', 'U; PPC'].sample if os == :osx
end
# @return [String] a random Firefox version string.
def random_firefox_version_string
[
"Gecko/#{random_time_string('2011-01-01')} "\
"Firefox/#{rand(5..7)}.0",
"Gecko/#{random_time_string('2011-01-01')} "\
"Firefox/#{rand(5..7)}.0.1",
"Gecko/#{random_time_string('2010-01-01')} "\
"Firefox/3.6.#{rand(1..20)}",
"Gecko/#{random_time_string('2010-01-01')} "\
'Firefox/3.8'
].sample
end
# A random Firefox platform string.
# @param os the operating system that Firefox would be running on.
# @return [String] a random Firefox platform string.
def random_firefox_platform_string(os)
version = random_firefox_version_string
cpu = random_processor_string(os)
if os == :linux
return "(X11; Linux #{cpu}; rv:#{rand(5..7)}.0) #{version}"
end
if os == :osx
return "(Macintosh; #{cpu} Mac OS X #{random_osx_version} "\
"rv:#{rand(2..6)}.0) #{version}"
end
if os == :windows
return "(Windows NT #{random_nt_version}; en-US; rv:1.9."\
"#{rand(0..2)}.20) #{version}"
end
end
# A random Safari platform string.
# @param os the operating system that Safari would be running on.
# @return [String] a random Safari platform string.
def random_safari_platform_string(os)
build = random_safari_build_number
cpu = random_processor_string(os)
version = random_safari_version
if os == :osx
return "(Macintosh; U; #{cpu} Mac OS X #{random_osx_version} rv:"\
"#{rand(2..6)}.0; en-US) AppleWebKit/#{build} "\
"(KHTML, like Gecko) Version/#{version} Safari/#{build}"
else
return "(Windows; U; Windows NT #{random_nt_version}) AppleWebKit/"\
"#{build} (KHTML, like Gecko) Version/#{version} "\
"Safari/#{build}"
end
end
# A random Internet Explorer platform string.
# @return [String] a random Internet Explorer platform string.
def random_iexplorer_platform_string
"(compatible; MSIE #{random_ie_version}; Windows NT "\
"#{random_nt_version}; Trident/#{random_trident_version})"
end
# A random Opera platform string.
# @param os the operating system that Opera would be running on.
# @return [String] a random Opera platform string.
def random_opera_platform_string(os)
cpu = random_processor_string(os)
presto = random_presto_version
version = random_presto_version2
if os == :linux
return "(X11; Linux #{cpu}; U; en-US) Presto/#{presto} "\
"Version/#{version}"
else
return "(Windows NT #{random_nt_version}; U; en-US) "\
"Presto/#{presto} Version/#{version}"
end
end
# A random Chrome platform string.
# @param os the operating system that Chrome would be running on.
# @return [String] a random Chrome platform string.
def random_chrome_platform_string(os)
cpu = random_processor_string(os)
build = random_chrome_build_number
version = random_chrome_version
if os == :linux
return "(X11; Linux #{cpu}) AppleWebKit/#{build} (KHTML, like Gecko)"\
" Chrome/#{version} Safari/#{build}"
end
if os == :osx
return "(Macintosh; U; #{cpu} Mac OS X #{random_osx_version}) "\
"AppleWebKit/#{build} (KHTML, like Gecko) Chrome/"\
"#{version} Safari/#{build}"
end
if os == :windows
return "(Windows NT #{random_nt_version}) AppleWebKit/#{build} "\
"(KHTML, like Gecko) Chrome/#{version} Safari/#{build}"
end
end
# @return [String] a random browser user agent.
def random_user_agent
platform = random_browser_and_os
os = platform[:os]
if platform[:browser] == :firefox
return "Mozilla/5.0 #{random_firefox_platform_string(os)}"
elsif platform[:browser] == :safari
return "Mozilla/5.0 #{random_safari_platform_string(os)}"
elsif platform[:browser] == :iexplorer
return "Mozilla/5.0 #{random_iexplorer_platform_string}"
elsif platform[:browser] == :opera
return "Opera/#{random_opera_version} "\
"#{random_opera_platform_string(os)}"
else
return "Mozilla/5.0 #{random_chrome_platform_string(os)}"
end
end
end
end
end