browser-6.2.0/0000755000004100000410000000000014731746717013253 5ustar www-datawww-databrowser-6.2.0/languages.yml0000644000004100000410000000466314731746717015755 0ustar www-datawww-data"af": "Afrikaans" "sq": "Albanian" "eu": "Basque" "bg": "Bulgarian" "be": "Byelorussian" "ca": "Catalan" "zh": "Chinese" "zh-CN": "Chinese/China" "zh-TW": "Chinese/Taiwan" "zh-HK": "Chinese/Hong Kong" "zh-SG": "Chinese/singapore" "hr": "Croatian" "cs": "Czech" "da": "Danish" "nl": "Dutch" "nl-NL": "Dutch/Netherlands" "nl-BE": "Dutch/Belgium" "en": "English" "en-GB": "English/United Kingdom" "en-US": "English/United States" "en-AU": "English/Australian" "en-CA": "English/Canada" "en-NZ": "English/New Zealand" "en-IE": "English/Ireland" "en-ZA": "English/South Africa" "en-JM": "English/Jamaica" "en-BZ": "English/Belize" "en-TT": "English/Trinidad" "et": "Estonian" "fo": "Faeroese" "fa": "Farsi" "fi": "Finnish" "fr": "French" "fr-BE": "French/Belgium" "fr-FR": "French/France" "fr-CH": "French/Switzerland" "fr-CA": "French/Canada" "fr-LU": "French/Luxembourg" "gl": "Galician" "de": "German" "de-AT": "German/Austria" "de-DE": "German/Germany" "de-CH": "German/Switzerland" "de-LU": "German/Luxembourg" "de-LI": "German/Liechtenstein" "el": "Greek" "he": "Hebrew" "he-IL": "Hebrew/Israel" "hi": "Hindi" "hu": "Hungarian" "ie-EE": "Internet Explorer/Easter Egg" "is": "Icelandic" "id": "Indonesian" "in": "Indonesian" "ga": "Irish" "it": "Italian" "it-CH": "Italian/ Switzerland" "ja": "Japanese" "km": "Khmer" "km-KH": "Khmer/Cambodia" "ko": "Korean" "lv": "Latvian" "lt": "Lithuanian" "mk": "Macedonian" "ms": "Malaysian" "mt": "Maltese" "no": "Norwegian" "pl": "Polish" "pt": "Portuguese" "pt-BR": "Portuguese/Brazil" "rm": "Rhaeto-Romanic" "ro": "Romanian" "ro-MO": "Romanian/Moldavia" "ru": "Russian" "ru-MO": "Russian /Moldavia" "gd": "Scots Gaelic" "sr": "Serbian" "sk": "Slovack" "sl": "Slovenian" "sb": "Sorbian" "es": "Spanish" "es-DO": "Spanish" "es-AR": "Spanish/Argentina" "es-CO": "Spanish/Colombia" "es-MX": "Spanish/Mexico" "es-ES": "Spanish/Spain" "es-GT": "Spanish/Guatemala" "es-CR": "Spanish/Costa Rica" "es-PA": "Spanish/Panama" "es-VE": "Spanish/Venezuela" "es-PE": "Spanish/Peru" "es-EC": "Spanish/Ecuador" "es-CL": "Spanish/Chile" "es-UY": "Spanish/Uruguay" "es-PY": "Spanish/Paraguay" "es-BO": "Spanish/Bolivia" "es-SV": "Spanish/El salvador" "es-HN": "Spanish/Honduras" "es-NI": "Spanish/Nicaragua" "es-PR": "Spanish/Puerto Rico" "sx": "Sutu" "sv": "Swedish" "sv-SE": "Swedish/Sweden" "sv-FI": "Swedish/Finland" "ts": "Thai" "tn": "Tswana" "tr": "Turkish" "uk": "Ukrainian" "ur": "Urdu" "vi": "Vietnamese" "xh": "Xshosa" "ji": "Yiddish" "zu": "Zulu" browser-6.2.0/samsung.yml0000644000004100000410000000636214731746717015462 0ustar www-datawww-data# Source: https://en.wikipedia.org/wiki/Samsung_Galaxy SM-G900H: Galaxy S5 Exynos SM-A320FL: Galaxy A3 SM-G780F: Galaxy S20 Fan Edition SM-G781B: Galaxy S20 Fan Edition SM-F196B: Galaxy Z Fold2 5G SM-G928A: Galaxy S6 Edge+ SM-G928AZ: Galaxy S6 Edge+ SM-G928D: Galaxy S6 Edge+ SM-G928F: Galaxy S6 Edge+ SM-G928FD: Galaxy S6 Edge+ SM-G928I: Galaxy S6 Edge+ SM-G928K: Galaxy S6 Edge+ SM-G928L: Galaxy S6 Edge+ SM-G928P: Galaxy S6 Edge+ SM-G928PZ: Galaxy S6 Edge+ SM-G928R4: Galaxy S6 Edge+ SM-G928R7: Galaxy S6 Edge+ SM-G928S: Galaxy S6 Edge+ SM-G928T: Galaxy S6 Edge+ SM-G928T1: Galaxy S6 Edge+ SM-G928TR: Galaxy S6 Edge+ SM-G928V: Galaxy S6 Edge+ SM-G9280: Galaxy S6 Edge+ SM-G9288: Galaxy S6 Edge+ SM-G9289: Galaxy S6 Edge+ SM-A8000: Galaxy A8 SM-A800F: Galaxy A8 SM-A800I: Galaxy A8 SM-A800S: Galaxy A8 SM-A800Y: Galaxy A8 SM-N9200: Galaxy Note 5 SM-N920C: Galaxy Note 5 SM-N920T: Galaxy Note 5 SM-N920A: Galaxy Note 5 SM-N920I: Galaxy Note 5 SM-N9208: Galaxy Note 5 SM-G903FP: Galaxy S5 Neo SM-G903WP: Galaxy S5 Neo SM-G925A: Galaxy S6 Edge SM-G925AZ: Galaxy S6 Edge SM-G925F: Galaxy S6 Edge SM-G925I: Galaxy S6 Edge SM-G925K: Galaxy S6 Edge SM-G925L: Galaxy S6 Edge SM-G925P: Galaxy S6 Edge SM-G925PZ: Galaxy S6 Edge SM-G925R4: Galaxy S6 Edge SM-G925R7: Galaxy S6 Edge SM-G925S: Galaxy S6 Edge SM-G925T: Galaxy S6 Edge SM-G925T1: Galaxy S6 Edge SM-G925TR: Galaxy S6 Edge SM-G925V: Galaxy S6 Edge SM-G9250: Galaxy S6 Edge SM-G9258: Galaxy S6 Edge SM-G9259: Galaxy S6 Edge SM-G920A: Galaxy S6 SM-G920AZ: Galaxy S6 SM-G920D: Galaxy S6 SM-G920F: Galaxy S6 SM-G920FD: Galaxy S6 SM-G920I: Galaxy S6 SM-G920K: Galaxy S6 SM-G920L: Galaxy S6 SM-G920P: Galaxy S6 SM-G920PZ: Galaxy S6 SM-G920R4: Galaxy S6 SM-G920R7: Galaxy S6 SM-G920S: Galaxy S6 SM-G920T: Galaxy S6 SM-G920T1: Galaxy S6 SM-G920TR: Galaxy S6 SM-G920V: Galaxy S6 SM-G9200: Galaxy S6 SM-G9208: Galaxy S6 SM-G9209: Galaxy S6 SM-A700F: Galaxy A7 SM-A700FD: Galaxy A7 SM-A700FQ: Galaxy A7 SM-A700H: Galaxy A7 SM-A700K: Galaxy A7 SM-A700L: Galaxy A7 SM-A700M: Galaxy A7 SM-A700S: Galaxy A7 SM-A700X: Galaxy A7 SM-A700YD: Galaxy A7 SM-A700YZ: Galaxy A7 SM-A7000: Galaxy A7 SM-A7009: Galaxy A7 SM-A7009W: Galaxy A7 SM-G530BT: Galaxy Grand Prime SM-G530F: Galaxy Grand Prime SM-G530FQ: Galaxy Grand Prime SM-G530FZ: Galaxy Grand Prime SM-G530H: Galaxy Grand Prime SM-G530M: Galaxy Grand Prime SM-G530MU: Galaxy Grand Prime SM-G530P: Galaxy Grand Prime SM-G530R4: Galaxy Grand Prime SM-G530R7: Galaxy Grand Prime SM-G530T: Galaxy Grand Prime SM-G530W: Galaxy Grand Prime SM-G530Y: Galaxy Grand Prime SM-G5306W: Galaxy Grand Prime SM-G5308W: Galaxy Grand Prime SM-G5309W: Galaxy Grand Prime SM-J7109: Galaxy J7 SM-J710F: Galaxy J7 SM-J710FN: Galaxy J7 SM-J710H: Galaxy J7 SM-J710MN: Galaxy J7 SM-J710FQ: Galaxy J7 SM-J710K: Galaxy J7 SM-J710K: Galaxy J7 SM-J710GN: Galaxy J7 SM-J5109: Galaxy J5 SM-J510F: Galaxy J5 SM-J510FN: Galaxy J5 SM-J510H: Galaxy J5 SM-J510G: Galaxy J5 SM-J510MN: Galaxy J5 SM-J510Y: Galaxy J5 SM-J5108: Galaxy J5 SM-J510K: Galaxy J5 SM-J510L: Galaxy J5 SM-J510S: Galaxy J5 SM-J510UN: Galaxy J5 SM-G570F: Galaxy J2 Prime SM-G570M: Galaxy J2 Prime SM-G532F: Galaxy J2 Prime SM-G532M: Galaxy J2 Prime SM-G532G: Galaxy J2 Prime SM-G610F: Galaxy J7 Prime SM-G610M: Galaxy J7 Prime SM-G975F: Galaxy S10+ SM-G960F: Galaxy S9 SM-F700F: Galaxy Z Flip browser-6.2.0/.gitignore0000644000004100000410000000005114731746717015237 0ustar www-datawww-datapkg coverage doc log *.lock bin/ .bundle browser-6.2.0/bot_exceptions.yml0000644000004100000410000000011314731746717017016 0ustar www-datawww-data--- - ruby build - pinterest/android - pinterest/ios - yandexsearchbrowser browser-6.2.0/.github/0000755000004100000410000000000014731746717014613 5ustar www-datawww-databrowser-6.2.0/.github/workflows/0000755000004100000410000000000014731746717016650 5ustar www-datawww-databrowser-6.2.0/.github/workflows/ruby-tests.yml0000644000004100000410000000246314731746717021521 0ustar www-datawww-data--- name: ruby-tests on: pull_request_target: push: branches: - main workflow_dispatch: inputs: {} jobs: build: name: Tests with Ruby ${{ matrix.ruby }} and ${{ matrix.gemfile }} runs-on: "ubuntu-latest" if: | github.actor == 'dependabot[bot]' && github.event_name == 'pull_request_target' || github.actor != 'dependabot[bot]' strategy: fail-fast: false matrix: ruby: ["3.2", "3.3"] gemfile: - Gemfile - gemfiles/7_1.gemfile - gemfiles/7_0.gemfile steps: - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2 with: path: vendor/bundle key: > ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles(matrix.gemfile) }} - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - name: Install gem dependencies env: BUNDLE_GEMFILE: ${{ matrix.gemfile }} run: | gem install bundler bundle config path vendor/bundle bundle update --jobs 4 --retry 3 - name: Run Tests env: PGHOST: localhost PGUSER: postgres BUNDLE_GEMFILE: ${{ matrix.gemfile }} run: | bundle exec rake browser-6.2.0/.github/ISSUE_TEMPLATE.md0000644000004100000410000000074614731746717017327 0ustar www-datawww-data## Description [Add feature/bug description here] ## How to reproduce [Add steps on how to reproduce this issue] ## What do you expect [Describe what do you expect to happen] ## What happened instead [Describe the actual results] ## Software: - Rails version: [Add rails version here] - Browser gem version: [Add browser gem version here] ## Full backtrace ```text [Paste full backtrace here] ``` ## Report [Visit and paste the URL here] browser-6.2.0/.github/FUNDING.yml0000644000004100000410000000016214731746717016427 0ustar www-datawww-data# These are supported funding model platforms --- github: [fnando] custom: ["https://paypal.me/nandovieira/🍕"] browser-6.2.0/lib/0000755000004100000410000000000014731746717014021 5ustar www-datawww-databrowser-6.2.0/lib/browser/0000755000004100000410000000000014731746717015504 5ustar www-datawww-databrowser-6.2.0/lib/browser/qq.rb0000644000004100000410000000066314731746717016457 0ustar www-datawww-data# frozen_string_literal: true module Browser class QQ < Base def id :qq end def name "QQ Browser" end def full_version ua[%r{(?:Mobile MQQBrowser)/([\d.]+)}i, 1] || ua[%r{(?:QQBrowserLite)/([\d.]+)}i, 1] || ua[%r{(?:QQBrowser)/([\d.]+)}i, 1] || ua[%r{(?:QQ)/([\d.]+)}i, 1] || "0.0" end def match? ua.match?(%r{QQ/|QQBrowser}i) end end end browser-6.2.0/lib/browser/otter.rb0000644000004100000410000000041314731746717017164 0ustar www-datawww-data# frozen_string_literal: true module Browser class Otter < Base def id :otter end def name "Otter" end def full_version ua[%r{Otter/([\d.]+)}, 1] || "0.0" end def match? ua.include?("Otter") end end end browser-6.2.0/lib/browser/unknown.rb0000644000004100000410000000103314731746717017525 0ustar www-datawww-data# frozen_string_literal: true module Browser class Unknown < Base NAMES = { "QuickTime" => "QuickTime", "CoreMedia" => "Apple CoreMedia" }.freeze def id :unknown_browser end def name infer_name || "Unknown Browser" end def full_version ua[%r{(?:QuickTime)/([\d.]+)}, 1] || ua[/CoreMedia v([\d.]+)/, 1] || "0.0" end def match? true end private def infer_name (NAMES.find {|key, _| ua.include?(key) } || []).last end end end browser-6.2.0/lib/browser/platform.rb0000644000004100000410000001005514731746717017656 0ustar www-datawww-data# frozen_string_literal: true require_relative "platform/base" require_relative "platform/ios" require_relative "platform/linux" require_relative "platform/windows" require_relative "platform/mac" require_relative "platform/windows_phone" require_relative "platform/windows_mobile" require_relative "platform/firefox_os" require_relative "platform/blackberry" require_relative "platform/android" require_relative "platform/unknown" require_relative "platform/chrome_os" require_relative "platform/adobe_air" require_relative "platform/kai_os" module Browser class Platform include DetectVersion attr_reader :ua # Hold the list of platform matchers. # Order is important. def self.matchers @matchers ||= [ AdobeAir, ChromeOS, WindowsMobile, WindowsPhone, Android, BlackBerry, IOS, Mac, KaiOS, FirefoxOS, Windows, Linux, Unknown ] end def initialize(ua) @ua = ua end def subject @subject ||= self.class.matchers .map {|matcher| matcher.new(ua, self) } .find(&:match?) end def adobe_air?(expected_version = nil) id == :adobe_air && detect_version?(version, expected_version) end def chrome_os?(expected_version = nil) id == :chrome_os && detect_version?(version, expected_version) end def android?(expected_version = nil) id == :android && detect_version?(version, expected_version) end def unknown? id == :unknown_platform end def linux? id == :linux end def mac?(expected_version = nil) id == :mac && detect_version?(version, expected_version) end def windows?(expected_version = nil) id == :windows && detect_version?(version, expected_version) end def firefox_os? id == :firefox_os end def kai_os? id == :kai_os end def ios?(expected_version = nil) id == :ios && detect_version?(version, expected_version) end def blackberry?(expected_version = nil) id == :blackberry && detect_version?(version, expected_version) end def windows_phone?(expected_version = nil) id == :windows_phone && detect_version?(version, expected_version) end def windows_mobile?(expected_version = nil) id == :windows_mobile && detect_version?(version, expected_version) end def id subject.id end def version subject.version end def name subject.name end def to_s id.to_s end def ==(other) id == other end # Detect if running on iOS app webview. def ios_app? ios? && !ua.include?("Safari") end # Detect if is iOS webview. def ios_webview? ios_app? end # Detect if in an Android app webview (Lollipop and newer) # https://developer.chrome.com/multidevice/user-agent#webview_user_agent def android_app? android? && ua.match?(/\bwv\b/) end alias android_webview? android_app? # http://msdn.microsoft.com/fr-FR/library/ms537503.aspx#PltToken def windows_xp? windows? && ua.match?(/Windows NT 5\.[12]/) end def windows_vista? windows? && ua.include?("Windows NT 6.0") end def windows7? windows? && ua.include?("Windows NT 6.1") end def windows8? windows? && ua.match?(/Windows NT 6\.[2-3]/) end def windows8_1? windows? && ua.include?("Windows NT 6.3") end def windows10? windows? && ua.include?("Windows NT 10") end def windows_rt? windows8? && ua.include?("ARM") end # Detect if current platform is Windows in 64-bit architecture. def windows_x64? windows? && ua.match?(/(Win64|x64|Windows NT 5\.2)/) end def windows_wow64? windows? && ua.match?(/WOW64/i) end def windows_x64_inclusive? windows_x64? || windows_wow64? end def windows_touchscreen_desktop? windows? && ua.include?("Touch") end private :subject private :ua end end browser-6.2.0/lib/browser/aliases.rb0000644000004100000410000000205514731746717017454 0ustar www-datawww-data# frozen_string_literal: true require_relative "../browser" require "forwardable" module Browser module Aliases PLATFORM_ALIASES = %w[ adobe_air? android? blackberry? chrome_os? firefox_os? ios? ios_app? ios_webview? linux? mac? windows10? windows7? windows8? windows8_1? windows? windows_mobile? windows_phone? windows_rt? windows_touchscreen_desktop? windows_vista? windows_wow64? windows_x64? windows_x64_inclusive? windows_xp? ].freeze DEVICE_ALIASES = %w[ blackberry_playbook? console? ipad? iphone? ipod_touch? kindle? kindle_fire? mobile? nintendo? nintendo_switch? nintendo_wii? nintendo_wiiu? playbook? playstation3? playstation4? playstation? playstation_vita? ps3? ps4? psp? psp_vita? silk? surface? tablet? tv? vita? wii? wiiu? xbox? xbox_360? xbox_one? ].freeze def self.included(target) target.class_eval do extend Forwardable def_delegators :platform, *PLATFORM_ALIASES def_delegators :device, *DEVICE_ALIASES end end end end browser-6.2.0/lib/browser/platform/0000755000004100000410000000000014731746717017330 5ustar www-datawww-databrowser-6.2.0/lib/browser/platform/windows_mobile.rb0000644000004100000410000000047114731746717022700 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class WindowsMobile < Base def version "0" end def name "Windows Mobile" end def id :windows_mobile end def match? ua.include?("Windows CE") end end end end browser-6.2.0/lib/browser/platform/unknown.rb0000644000004100000410000000043114731746717021352 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Unknown < Base def version "0" end def name "Unknown" end def id :unknown_platform end def match? true end end end end browser-6.2.0/lib/browser/platform/mac.rb0000644000004100000410000000057614731746717020425 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Mac < Base def version (ua[/Mac OS X\s*([0-9_.]+)?/, 1] || "0").tr("_", ".") end def name return "macOS" if platform.mac?(">= 10.12") "Mac OS X" end def id :mac end def match? ua.include?("Mac") end end end end browser-6.2.0/lib/browser/platform/kai_os.rb0000644000004100000410000000046114731746717021123 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class KaiOS < Base def version ua[%r{KAIOS/([\d.]+)}, 1] end def name "KaiOS" end def id :kai_os end def match? ua.include?("KAIOS") end end end end browser-6.2.0/lib/browser/platform/windows_phone.rb0000644000004100000410000000052514731746717022542 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class WindowsPhone < Base def version ua[/Windows Phone ([\d.]+)/, 1] end def name "Windows Phone" end def id :windows_phone end def match? ua.include?("Windows Phone") end end end end browser-6.2.0/lib/browser/platform/base.rb0000644000004100000410000000041514731746717020567 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Base attr_reader :ua, :platform def initialize(ua, platform = nil) @ua = ua @platform = platform end def match? false end end end end browser-6.2.0/lib/browser/platform/windows.rb0000644000004100000410000000050714731746717021351 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Windows < Base def version ua[/Windows NT\s*([0-9_.]+)?/, 1] || "0" end def name "Windows" end def id :windows end def match? ua.include?("Windows") end end end end browser-6.2.0/lib/browser/platform/linux.rb0000644000004100000410000000044214731746717021014 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Linux < Base def version "0" end def name "Generic Linux" end def id :linux end def match? ua.include?("Linux") end end end end browser-6.2.0/lib/browser/platform/adobe_air.rb0000644000004100000410000000050114731746717021556 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class AdobeAir < Base def match? ua.include?("AdobeAIR") end def version ua[%r{AdobeAIR/([\d.]+)}, 1] end def name "Adobe AIR" end def id :adobe_air end end end end browser-6.2.0/lib/browser/platform/chrome_os.rb0000644000004100000410000000050314731746717021631 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class ChromeOS < Base def match? ua.include?("CrOS") end def name "Chrome OS" end def id :chrome_os end def version ua[/CrOS(?: x86_64)? ([\d.]+)/, 1] end end end end browser-6.2.0/lib/browser/platform/ios.rb0000644000004100000410000000142714731746717020453 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class IOS < Base MATCHER = /(iPhone|iPad|iPod|CriOS)/.freeze VERSION_MATCHER = /OS (?\d+)_(?\d+)_?(?\d+)?/.freeze def version matches = VERSION_MATCHER.match(ua) return "0" unless matches versions = [matches[:major]] if matches[:patch] versions.push(matches[:minor], matches[:patch]) else versions.push(matches[:minor]) unless matches[:minor] == "0" end versions.join(".") end def name "iOS (#{device})" end def id :ios end def match? ua.match?(MATCHER) end def device ua[MATCHER, 1] end end end end browser-6.2.0/lib/browser/platform/firefox_os.rb0000644000004100000410000000053414731746717022022 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class FirefoxOS < Base def version "0" end def name "Firefox OS" end def id :firefox_os end def match? ua !~ /(Android|Linux|BlackBerry|Windows|Mac)/ && ua.include?("Firefox") end end end end browser-6.2.0/lib/browser/platform/blackberry.rb0000644000004100000410000000054014731746717021774 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class BlackBerry < Base def match? ua.match?(/BB10|BlackBerry/) end def name "BlackBerry" end def id :blackberry end def version ua[%r{(?:Version|BlackBerry[\da-z]+)/([\d.]+)}, 1] end end end end browser-6.2.0/lib/browser/platform/android.rb0000644000004100000410000000052114731746717021273 0ustar www-datawww-data# frozen_string_literal: true module Browser class Platform class Android < Base def match? ua.include?("Android") && !ua.include?("KAIOS") end def name "Android" end def id :android end def version ua[/Android ([\d.]+)/, 1] end end end end browser-6.2.0/lib/browser/bot/0000755000004100000410000000000014731746717016270 5ustar www-datawww-databrowser-6.2.0/lib/browser/bot/keyword_matcher.rb0000644000004100000410000000031714731746717022005 0ustar www-datawww-data# frozen_string_literal: true module Browser class Bot class KeywordMatcher def self.call(ua, _browser) ua.match?(/crawl|fetch|search|monitoring|spider|bot/) end end end end browser-6.2.0/lib/browser/bot/known_bots_matcher.rb0000644000004100000410000000031714731746717022504 0ustar www-datawww-data# frozen_string_literal: true module Browser class Bot class KnownBotsMatcher def self.call(ua, _browser) Browser::Bot.bots.any? {|key, _| ua.include?(key) } end end end end browser-6.2.0/lib/browser/bot/empty_user_agent_matcher.rb0000644000004100000410000000025114731746717023670 0ustar www-datawww-data# frozen_string_literal: true module Browser class Bot class EmptyUserAgentMatcher def self.call(ua, _browser) ua == "" end end end end browser-6.2.0/lib/browser/huawei_browser.rb0000644000004100000410000000047114731746717021060 0ustar www-datawww-data# frozen_string_literal: true module Browser class HuaweiBrowser < Base def id :huawei_browser end def name "Huawei Browser" end def full_version ua[%r{(?:HuaweiBrowser)/([\d.]+)}i, 1] || "0.0" end def match? ua.match?(/HuaweiBrowser/i) end end end browser-6.2.0/lib/browser/phantom_js.rb0000644000004100000410000000044014731746717020171 0ustar www-datawww-data# frozen_string_literal: true module Browser class PhantomJS < Base def id :phantom_js end def name "PhantomJS" end def full_version ua[%r{PhantomJS/([\d.]+)}, 1] || "0.0" end def match? ua.include?("PhantomJS") end end end browser-6.2.0/lib/browser/middleware/0000755000004100000410000000000014731746717017621 5ustar www-datawww-databrowser-6.2.0/lib/browser/middleware/context.rb0000644000004100000410000000064214731746717021634 0ustar www-datawww-data# frozen_string_literal: true module Browser class Middleware class Context attr_reader :browser, :request def initialize(request) @request = request @browser = Browser.new( request.user_agent, accept_language: request.env["HTTP_ACCEPT_LANGUAGE"] ) end def redirect_to(path) throw :redirected, path.to_s end end end end browser-6.2.0/lib/browser/middleware/context/0000755000004100000410000000000014731746717021305 5ustar www-datawww-databrowser-6.2.0/lib/browser/middleware/context/url_methods.rb0000644000004100000410000000050414731746717024156 0ustar www-datawww-data# frozen_string_literal: true module Browser class Middleware class Context module UrlMethods def default_url_options Rails.configuration.browser.default_url_options || Rails.configuration.action_mailer.default_url_options || {} end end end end end browser-6.2.0/lib/browser/middleware/context/additions.rb0000644000004100000410000000050114731746717023604 0ustar www-datawww-data# frozen_string_literal: true require_relative "url_methods" module Browser class Middleware class Context module Additions extend ActiveSupport::Concern included do include Rails.application.routes.url_helpers include UrlMethods end end end end end browser-6.2.0/lib/browser/device.rb0000644000004100000410000001356114731746717017276 0ustar www-datawww-data# frozen_string_literal: true require_relative "device/base" require_relative "device/android" require_relative "device/unknown" require_relative "device/ipad" require_relative "device/ipod_touch" require_relative "device/iphone" require_relative "device/playstation3" require_relative "device/playstation4" require_relative "device/psp" require_relative "device/psvita" require_relative "device/kindle" require_relative "device/kindle_fire" require_relative "device/wii" require_relative "device/wiiu" require_relative "device/blackberry_playbook" require_relative "device/surface" require_relative "device/switch" require_relative "device/tv" require_relative "device/xbox_one" require_relative "device/xbox_360" require_relative "device/samsung" module Browser class Device attr_reader :ua # Hold the list of device matchers. # Order is important. def self.matchers @matchers ||= [ Samsung, XboxOne, Xbox360, Surface, TV, BlackBerryPlaybook, WiiU, Wii, Switch, KindleFire, Kindle, PlayStation4, PlayStation3, PSVita, PSP, Ipad, Iphone, IpodTouch, Android, Unknown ] end def initialize(ua) @ua = ua end def subject @subject ||= self.class.matchers .map {|matcher| matcher.new(ua) } .find(&:match?) end def id subject.id end def name subject.name end # Detect if browser is tablet (currently iPad, Android, Surface or # Playbook). def tablet? ipad? || (platform.android? && !detect_mobile?) || surface? || playbook? end # Detect if browser is mobile. def mobile? detect_mobile? && !tablet? end def ipad? id == :ipad end def unknown? id == :unknown_device end def ipod_touch? id == :ipod_touch end alias ipod? ipod_touch? def iphone? id == :iphone end def ps3? id == :ps3 end alias playstation3? ps3? def ps4? id == :ps4 end alias playstation4? ps4? def psp? id == :psp end def playstation_vita? id == :psvita end alias vita? playstation_vita? alias psp_vita? playstation_vita? def kindle? id == :kindle || kindle_fire? end def kindle_fire? id == :kindle_fire end def nintendo_wii? id == :wii end alias wii? nintendo_wii? def nintendo_wiiu? id == :wiiu end alias wiiu? nintendo_wiiu? def nintendo_switch? id == :switch end alias switch? nintendo_switch? def blackberry_playbook? id == :playbook end alias playbook? blackberry_playbook? def surface? id == :surface end def tv? id == :tv end # Detect if browser is Silk. def silk? ua.include?("Silk") end # Detect if browser is running under Xbox. def xbox? ua.include?("Xbox") end # Detect if browser is running under Xbox 360. def xbox_360? id == :xbox_360 end # Detect if browser is running under Xbox One. def xbox_one? id == :xbox_one end # Detect if browser is running under PlayStation. def playstation? ps3? || ps4? end # Detect if browser is Nintendo. def nintendo? wii? || wiiu? || switch? end # Detect if browser is console (currently Xbox, PlayStation, or Nintendo). def console? xbox? || playstation? || nintendo? end # Detect if device is a Samsung. def samsung? id == :samsung end # Regex taken from http://detectmobilebrowsers.com # rubocop:disable Layout/LineLength private def detect_mobile? psp? || /zunewp7|crios/i.match?(ua) || %r{(android|bb\d+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino}i.match(ua) || %r{1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-}i.match?(ua[0..3]) end # rubocop:enable Layout/LineLength private def platform @platform ||= Platform.new(ua) end private :subject private :ua end end browser-6.2.0/lib/browser/nokia.rb0000644000004100000410000000045314731746717017134 0ustar www-datawww-data# frozen_string_literal: true module Browser class Nokia < Base def id :nokia end def name "Nokia S40 Ovi Browser" end def full_version ua[%r{S40OviBrowser/([\d.]+)}, 1] || "0.0" end def match? ua.include?("S40OviBrowser") end end end browser-6.2.0/lib/browser/micro_messenger.rb0000644000004100000410000000047514731746717021220 0ustar www-datawww-data# frozen_string_literal: true module Browser class MicroMessenger < Base def id :micro_messenger end def name "MicroMessenger" end def full_version ua[%r{(?:MicroMessenger)/([\d.]+)}i, 1] || "0.0" end def match? ua.match?(/MicroMessenger/i) end end end browser-6.2.0/lib/browser/accept_language.rb0000644000004100000410000000241114731746717021131 0ustar www-datawww-data# frozen_string_literal: true module Browser class AcceptLanguage def self.languages @languages ||= YAML.load_file(Browser.root.join("languages.yml")) end def self.parse(accept_language) return [] unless accept_language accept_language .split(",") .map {|string| string.squeeze(" ").strip } .map {|part| new(part) } .reject {|al| al.quality.zero? } .sort_by.with_index {|al, idx| [-al.quality, idx] } end attr_reader :part def initialize(part) @part = part end def full @full ||= [code, region].compact.join("-") end def name self.class.languages[full] || self.class.languages[code] end def code @code ||= begin code = part[/\A([^-;]+)/, 1] code&.downcase end end def region @region ||= begin region = part[/\A(?:.*?)-([^;-]+)/, 1] region&.upcase end end def quality @quality ||= begin Float(quality_value || 1.0) rescue ArgumentError 0.1 end end private def quality_value qvalue = part[/;q=([\d.]+)/, 1] qvalue = "0.0" if /\A0\.0?\z/.match?(qvalue) qvalue = qvalue.squeeze(".") if qvalue qvalue end end end browser-6.2.0/lib/browser/facebook.rb0000644000004100000410000000051014731746717017576 0ustar www-datawww-data# frozen_string_literal: true module Browser class Facebook < Base def id :facebook end def name "Facebook" end def full_version ua[%r{FBAV/([\d.]+)}, 1] || ua[%r{AppleWebKit/([\d.]+)}, 0] || "0.0" end def match? ua.match?(/FBAV|FBAN/) end end end browser-6.2.0/lib/browser/sougou_browser.rb0000644000004100000410000000075114731746717021120 0ustar www-datawww-data# frozen_string_literal: true module Browser class SougouBrowser < Base def id :sougou_browser end def name "Sougou Browser" end # We can't get the real version on desktop device from the ua string def full_version ua[%r{(?:SogouMobileBrowser)/([\d.]+)}, 1] || "0.0" end # SogouMobileBrowser for mobile device # SE for desktop device def match? ua.match?(/SogouMobileBrowser/i) || ua.match?(/\bSE\b/) end end end browser-6.2.0/lib/browser/epiphany.rb0000644000004100000410000000043214731746717017645 0ustar www-datawww-data# frozen_string_literal: true module Browser class Epiphany < Base def id :epiphany end def name "Epiphany" end def full_version ua[%r{Epiphany/([\d.]+)}, 1] || "0.0" end def match? ua.include?("Epiphany") end end end browser-6.2.0/lib/browser/weibo.rb0000644000004100000410000000042414731746717017136 0ustar www-datawww-data# frozen_string_literal: true module Browser class Weibo < Base def id :weibo end def name "Weibo" end def full_version ua[/(?:__weibo__)([\d.]+)/i, 1] || "0.0" end def match? ua.match?(/__weibo__/i) end end end browser-6.2.0/lib/browser/base.rb0000644000004100000410000001735314731746717016754 0ustar www-datawww-data# frozen_string_literal: true module Browser class Base include DetectVersion attr_reader :ua def initialize(ua, accept_language: nil) validate_size(:user_agent, ua.to_s) @ua = ua @accept_language_raw = accept_language.to_s end # Return a meta info about this browser. def meta Meta.get(self) end # Return an array with all preferred languages that this browser accepts. def accept_language @accept_language ||= begin validate_size(:accept_language, @accept_language_raw) AcceptLanguage.parse(@accept_language_raw) end end alias to_a meta # Return meta representation as string. def to_s meta.to_a.join(" ") end def version full_version.split(".").first end # Return the platform. def platform @platform ||= Platform.new(ua) end # Return the bot info. def bot @bot ||= Bot.new(ua) end # Detect if current user agent is from a bot. def bot? bot.bot? end # Return the device info. def device @device ||= Device.new(ua) end # Detect if browser is Microsoft Internet Explorer. def ie?(expected_version = nil) instance_of?(InternetExplorer) && detect_version?(full_version, expected_version) end # Detect if browser is Microsoft Edge. def edge?(expected_version = nil) instance_of?(Edge) && detect_version?(full_version, expected_version) end def compatibility_view? false end def msie_full_version "0.0" end def msie_version "0" end # Detect if browser is Instagram. def instagram?(expected_version = nil) instance_of?(Instagram) && detect_version?(full_version, expected_version) end # Detect if browser is Snapchat. def snapchat?(expected_version = nil) instance_of?(Snapchat) && detect_version?(full_version, expected_version) end # Detect if browser if Facebook. def facebook?(expected_version = nil) instance_of?(Facebook) && detect_version?(full_version, expected_version) end # Detect if browser is Otter. def otter?(expected_version = nil) instance_of?(Otter) && detect_version?(full_version, expected_version) end # Detect if browser is WebKit-based. def webkit?(expected_version = nil) ua.match?(/AppleWebKit/i) && (!edge? || chromium_based?) && detect_version?(webkit_full_version, expected_version) end # Detect if browser is QuickTime def quicktime?(expected_version = nil) ua.match?(/QuickTime/i) && detect_version?(full_version, expected_version) end # Detect if browser is Apple CoreMedia. def core_media?(expected_version = nil) ua.include?("CoreMedia") && detect_version?(full_version, expected_version) end # Detect if browser is PhantomJS def phantom_js?(expected_version = nil) instance_of?(PhantomJS) && detect_version?(full_version, expected_version) end # Detect if browser is Safari. def safari?(expected_version = nil) instance_of?(Safari) && detect_version?(full_version, expected_version) end def safari_webapp_mode? (device.ipad? || device.iphone?) && ua.include?("AppleWebKit") end # Detect if browser is Firefox. def firefox?(expected_version = nil) instance_of?(Firefox) && detect_version?(full_version, expected_version) end # Detect if browser is Chrome. def chrome?(expected_version = nil) instance_of?(Chrome) && detect_version?(full_version, expected_version) end # Detect if browser is Opera. def opera?(expected_version = nil) instance_of?(Opera) && detect_version?(full_version, expected_version) end # Detect if browser is Sputnik. def sputnik?(expected_version = nil) instance_of?(Sputnik) && detect_version?(full_version, expected_version) end # Detect if browser is Yandex. def yandex?(expected_version = nil) instance_of?(Yandex) && detect_version?(full_version, expected_version) end alias yandex_browser? yandex? # Detect if browser is UCBrowser. def uc_browser?(expected_version = nil) instance_of?(UCBrowser) && detect_version?(full_version, expected_version) end # Detect if browser is Nokia S40 Ovi Browser. def nokia?(expected_version = nil) instance_of?(Nokia) && detect_version?(full_version, expected_version) end # Detect if browser is MicroMessenger. def micro_messenger?(expected_version = nil) instance_of?(MicroMessenger) && detect_version?(full_version, expected_version) end alias wechat? micro_messenger? def weibo?(expected_version = nil) instance_of?(Weibo) && detect_version?(full_version, expected_version) end def alipay?(expected_version = nil) instance_of?(Alipay) && detect_version?(full_version, expected_version) end # Detect if browser is Opera Mini. def opera_mini?(expected_version = nil) ua.include?("Opera Mini") && detect_version?(full_version, expected_version) end # Detect if browser is DuckDuckGo. def duck_duck_go?(expected_version = nil) ua.include?("DuckDuckGo") && detect_version?(full_version, expected_version) end # Detect if browser is Samsung. def samsung_browser?(expected_version = nil) ua.include?("SamsungBrowser") && detect_version?(full_version, expected_version) end # Detect if browser is Huawei. def huawei_browser?(expected_version = nil) instance_of?(HuaweiBrowser) && detect_version?(full_version, expected_version) end # Detect if browser is Xiaomi Miui. def miui_browser?(expected_version = nil) instance_of?(MiuiBrowser) && detect_version?(full_version, expected_version) end # Detect if browser is Maxthon. def maxthon?(expected_version = nil) instance_of?(Maxthon) && detect_version?(full_version, expected_version) end # Detect if browser is QQ. def qq?(expected_version = nil) instance_of?(QQ) && detect_version?(full_version, expected_version) end # Detect if browser is Sougou. def sougou_browser?(expected_version = nil) instance_of?(SougouBrowser) && detect_version?(full_version, expected_version) end # Detect if browser is Google Search App def google_search_app?(expected_version = nil) ua.include?("GSA") && detect_version?(full_version, expected_version) end # Detect if browser is Chromium-based. def chromium_based? false end def webkit_full_version ua[%r{AppleWebKit/([\d.]+)}, 1] || "0.0" end def known? !unknown? end def unknown? id == :unknown_browser end # Detect if browser is a proxy browser. def proxy? nokia? || uc_browser? || opera_mini? end # Detect if the browser is Electron. def electron?(expected_version = nil) instance_of?(Electron) && detect_version?(full_version, expected_version) end # Detect if the browser is Epiphany. def epiphany?(expected_version = nil) instance_of?(Epiphany) && detect_version?(full_version, expected_version) end private def validate_size(subject, input) actual_bytesize = input.bytesize size_limit = Browser.public_send(:"#{subject}_size_limit") return if actual_bytesize < size_limit raise Error, "#{subject} cannot be larger than #{size_limit} bytes; " \ "actual size is #{actual_bytesize} bytes" end end end browser-6.2.0/lib/browser/bot.rb0000644000004100000410000000300514731746717016613 0ustar www-datawww-data# frozen_string_literal: true module Browser class Bot GENERIC_NAME = "Generic Bot" def self.matchers @matchers ||= default_matchers end def self.default_matchers [ EmptyUserAgentMatcher, KnownBotsMatcher, KeywordMatcher ] end def self.load_yaml(path) YAML.load_file(Browser.root.join(path)) end def self.bots @bots ||= load_yaml("bots.yml") end def self.bot_exceptions @bot_exceptions ||= load_yaml("bot_exceptions.yml") end def self.search_engines @search_engines ||= load_yaml("search_engines.yml") end def self.why?(ua) ua = ua.downcase.strip browser = Browser.new(ua) matchers.find {|matcher| matcher.call(ua, browser) } end attr_reader :ua, :browser def initialize(ua) @ua = ua.downcase.strip @browser = Browser.new(@ua) end def bot? !bot_exception? && detect_bot? end def why? self.class.matchers.find {|matcher| matcher.call(ua, self) } end def search_engine? self.class.search_engines.any? {|key, _| ua.include?(key) } end def name return unless bot? self.class.bots.find {|key, _| ua.include?(key) }&.last || GENERIC_NAME end private def bot_exception? self.class.bot_exceptions.any? {|key| ua.include?(key) } end private def detect_bot? self.class.matchers.any? {|matcher| matcher.call(ua, browser) } end private :ua private :browser end end browser-6.2.0/lib/browser/duck_duck_go.rb0000644000004100000410000000045414731746717020455 0ustar www-datawww-data# frozen_string_literal: true module Browser class DuckDuckGo < Base def id :duckduckgo end def name "DuckDuckGo" end def full_version ua[%r{DuckDuckGo/([\d.]+)}, 1] || "0.0" end def match? ua.include?("DuckDuckGo") end end end browser-6.2.0/lib/browser/alipay.rb0000644000004100000410000000044014731746717017306 0ustar www-datawww-data# frozen_string_literal: true module Browser class Alipay < Base def id :alipay end def name "Alipay" end def full_version ua[%r{(?:AlipayClient)/([\d.]+)}i, 1] || "0.0" end def match? ua.match?(/AlipayClient/i) end end end browser-6.2.0/lib/browser/action_controller.rb0000644000004100000410000000063314731746717021553 0ustar www-datawww-data# frozen_string_literal: true require "action_controller/railtie" module Browser module ActionController extend ActiveSupport::Concern included do helper_method(:browser) if respond_to?(:helper_method) end private def browser @browser ||= Browser.new( request.headers["User-Agent"], accept_language: request.headers["Accept-Language"] ) end end end browser-6.2.0/lib/browser/device/0000755000004100000410000000000014731746717016743 5ustar www-datawww-databrowser-6.2.0/lib/browser/device/playstation4.rb0000644000004100000410000000040314731746717021720 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class PlayStation4 < Base def id :ps4 end def name "PlayStation 4" end def match? ua.match?(/PLAYSTATION 4/i) end end end end browser-6.2.0/lib/browser/device/tv.rb0000644000004100000410000000040314731746717017716 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class TV < Base def id :tv end def name "TV" end def match? ua.match?(/(\btv|Android.*?ADT-1|Nexus Player)/i) end end end end browser-6.2.0/lib/browser/device/psvita.rb0000644000004100000410000000040514731746717020575 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class PSVita < Base def id :psvita end def name "PlayStation Vita" end def match? ua.match?("Playstation Vita") end end end end browser-6.2.0/lib/browser/device/unknown.rb0000644000004100000410000000035414731746717020771 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Unknown < Base def id :unknown_device end def name "Unknown" end def match? true end end end end browser-6.2.0/lib/browser/device/xbox_one.rb0000644000004100000410000000037114731746717021112 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class XboxOne < Base def id :xbox_one end def name "Xbox One" end def match? ua.match?(/Xbox One/i) end end end end browser-6.2.0/lib/browser/device/switch.rb0000644000004100000410000000040414731746717020567 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Switch < Base def id :switch end def name "Nintendo Switch" end def match? ua.match?(/Nintendo Switch/i) end end end end browser-6.2.0/lib/browser/device/xbox_360.rb0000644000004100000410000000036514731746717020644 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Xbox360 < Base def id :xbox_360 end def name "Xbox 360" end def match? ua.match?(/Xbox/i) end end end end browser-6.2.0/lib/browser/device/base.rb0000644000004100000410000000025114731746717020200 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Base attr_reader :ua def initialize(ua) @ua = ua end end end end browser-6.2.0/lib/browser/device/surface.rb0000644000004100000410000000054414731746717020723 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Surface < Base def id :surface end def name "Microsoft Surface" end def match? platform.windows_rt? && ua.include?("Touch") end private def platform @platform ||= Platform.new(ua) end end end end browser-6.2.0/lib/browser/device/wii.rb0000644000004100000410000000037014731746717020060 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Wii < Base def id :wii end def name "Nintendo Wii" end def match? ua.match?(/Nintendo Wii/i) end end end end browser-6.2.0/lib/browser/device/psp.rb0000644000004100000410000000041114731746717020066 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class PSP < Base def id :psp end def name "PlayStation Portable" end def match? ua.include?("PlayStation Portable") end end end end browser-6.2.0/lib/browser/device/kindle.rb0000644000004100000410000000036314731746717020540 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Kindle < Base def id :kindle end def name "Kindle" end def match? ua.include?("Kindle") end end end end browser-6.2.0/lib/browser/device/samsung.rb0000644000004100000410000000107714731746717020752 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Samsung < Base REGEX = /\(Linux.*?; Android.*?; (SAMSUNG )?(SM-[A-Z0-9]+).*?\)/i.freeze def self.names @names ||= YAML.load_file(Browser.root.join("samsung.yml").to_s) end def id :samsung end def name "Samsung #{self.class.names[code] || code}" end def code matches && matches[2] end def matches @matches ||= ua.match(REGEX) end def match? !!matches end end end end browser-6.2.0/lib/browser/device/playstation3.rb0000644000004100000410000000040314731746717021717 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class PlayStation3 < Base def id :ps3 end def name "PlayStation 3" end def match? ua.match?(/PLAYSTATION 3/i) end end end end browser-6.2.0/lib/browser/device/wiiu.rb0000644000004100000410000000037414731746717020251 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class WiiU < Base def id :wiiu end def name "Nintendo WiiU" end def match? ua.match?(/Nintendo WiiU/i) end end end end browser-6.2.0/lib/browser/device/iphone.rb0000644000004100000410000000036314731746717020554 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Iphone < Base def id :iphone end def name "iPhone" end def match? ua.include?("iPhone") end end end end browser-6.2.0/lib/browser/device/kindle_fire.rb0000644000004100000410000000041114731746717021537 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class KindleFire < Base def id :kindle_fire end def name "Kindle Fire" end def match? ua.match?(/Kindle Fire|KFTT/) end end end end browser-6.2.0/lib/browser/device/blackberry_playbook.rb0000644000004100000410000000043314731746717023310 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class BlackBerryPlaybook < Base def id :playbook end def name "BlackBerry Playbook" end def match? ua.match?(/PlayBook.*?RIM Tablet/) end end end end browser-6.2.0/lib/browser/device/ipad.rb0000644000004100000410000000035314731746717020206 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Ipad < Base def id :ipad end def name "iPad" end def match? ua.include?("iPad") end end end end browser-6.2.0/lib/browser/device/ipod_touch.rb0000644000004100000410000000037414731746717021431 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class IpodTouch < Base def id :ipod_touch end def name "iPod Touch" end def match? ua.include?("iPod") end end end end browser-6.2.0/lib/browser/device/android.rb0000644000004100000410000000050214731746717020705 0ustar www-datawww-data# frozen_string_literal: true module Browser class Device class Android < Base def id :unknown end def name ua[/\(Linux.*?; Android.*?; ([-_a-z0-9 ]+) Build[^)]+\)/i, 1] || "Unknown" end def match? ua.include?("Android") end end end end browser-6.2.0/lib/browser/yandex.rb0000644000004100000410000000042614731746717017323 0ustar www-datawww-data# frozen_string_literal: true module Browser class Yandex < Base def id :yandex end def name "Yandex" end def full_version ua[%r{YaBrowser/([\d.]+)}, 1] || "0.0" end def match? ua.include?("YaBrowser") end end end browser-6.2.0/lib/browser/miui_browser.rb0000644000004100000410000000045314731746717020541 0ustar www-datawww-data# frozen_string_literal: true module Browser class MiuiBrowser < Base def id :miui_browser end def name "Miui Browser" end def full_version ua[%r{MiuiBrowser/([\d.]+)}, 1] || "0.0" end def match? ua.include?("MiuiBrowser") end end end browser-6.2.0/lib/browser/detect_version.rb0000644000004100000410000000116214731746717021046 0ustar www-datawww-data# frozen_string_literal: true module Browser module DetectVersion private def detect_version?(actual_version, expected_version) return true unless expected_version return false if expected_version && !actual_version expected_version = parse_version(expected_version) actual_version = parse_version(actual_version) Gem::Requirement.create(expected_version) .satisfied_by?(Gem::Version.create(actual_version)) rescue ArgumentError false end private def parse_version(version) version.is_a?(Numeric) ? version.to_s : version end end end browser-6.2.0/lib/browser/testing.rb0000644000004100000410000000122114731746717017502 0ustar www-datawww-data# frozen_string_literal: true module Browser def self.user_agents @user_agents ||= browser_user_agents .merge(bot_user_agents) .merge(search_engine_user_agents) end def self.browser_user_agents @browser_user_agents ||= YAML.load_file(Browser.root.join("test/ua.yml")) end def self.bot_user_agents @bot_user_agents ||= YAML.load_file(Browser.root.join("test/ua_bots.yml")) end def self.search_engine_user_agents @search_engine_user_agents ||= YAML.load_file( Browser.root.join("test/ua_search_engines.yml") ) end def self.[](key) user_agents.fetch(key) end end browser-6.2.0/lib/browser/firefox.rb0000644000004100000410000000044314731746717017474 0ustar www-datawww-data# frozen_string_literal: true module Browser class Firefox < Base def id :firefox end def name "Firefox" end def full_version ua[%r{(?:Firefox|FxiOS)/([\d.]+)}, 1] || "0.0" end def match? ua.match?(/Firefox|FxiOS/) end end end browser-6.2.0/lib/browser/meta.rb0000644000004100000410000000062014731746717016755 0ustar www-datawww-data# frozen_string_literal: true require_relative "meta/base" require_relative "meta/generic_browser" require_relative "meta/id" require_relative "meta/ie" require_relative "meta/ios" require_relative "meta/mobile" require_relative "meta/platform" require_relative "meta/proxy" require_relative "meta/safari" require_relative "meta/webkit" require_relative "meta/tablet" require_relative "meta/device" browser-6.2.0/lib/browser/chrome.rb0000644000004100000410000000150714731746717017311 0ustar www-datawww-data# frozen_string_literal: true module Browser class Chrome < Base def id :chrome end def name "Chrome" end def full_version # Each regex on its own line to enforce precedence. ua[%r{Chrome/([\d.]+)}, 1] || ua[%r{CriOS/([\d.]+)}, 1] || ua[%r{Safari/([\d.]+)}, 1] || ua[%r{AppleWebKit/([\d.]+)}, 1] || "0.0" end def chromium_based? true end def match? ua.match?(/Chrome|CriOS/) && !ua.match?(/PhantomJS|FxiOS|ArchiveBot/) && !opera? && !edge? && !duck_duck_go? && !yandex? && !sputnik? && !samsung_browser? && !huawei_browser? && !miui_browser? && !maxthon? && !qq? && !sougou_browser? && !google_search_app? end end end browser-6.2.0/lib/browser/snapchat.rb0000644000004100000410000000043714731746717017636 0ustar www-datawww-data# frozen_string_literal: true module Browser class Snapchat < Base def id :snapchat end def name "Snapchat" end def full_version ua[%r{Snapchat( ?|/)([\d.]+)}, 2] || "0.0" end def match? ua.include?("Snapchat") end end end browser-6.2.0/lib/browser/rails.rb0000644000004100000410000000124114731746717017141 0ustar www-datawww-data# frozen_string_literal: true require "rails/railtie" require_relative "action_controller" require_relative "middleware/context/additions" module Browser class Railtie < Rails::Railtie config.browser = ActiveSupport::OrderedOptions.new initializer "browser" do ActiveSupport.on_load(:action_controller) do ::ActionController::Base.include(Browser::ActionController) ::ActionController::Metal.include(Browser::ActionController) if defined?(::ActionController::Metal) # rubocop:disable Layout/LineLength Browser::Middleware::Context.include( Browser::Middleware::Context::Additions ) end end end end browser-6.2.0/lib/browser/instagram.rb0000644000004100000410000000044214731746717020016 0ustar www-datawww-data# frozen_string_literal: true module Browser class Instagram < Base def id :instagram end def name "Instagram" end def full_version ua[%r{Instagram[ /]([\d.]+)}, 1] || "0.0" end def match? ua.include?("Instagram") end end end browser-6.2.0/lib/browser/version.rb0000644000004100000410000000010614731746717017513 0ustar www-datawww-data# frozen_string_literal: true module Browser VERSION = "6.2.0" end browser-6.2.0/lib/browser/sputnik.rb0000644000004100000410000000044314731746717017527 0ustar www-datawww-data# frozen_string_literal: true module Browser class Sputnik < Base def id :sputnik end def name "Sputnik" end def full_version ua[%r{SputnikBrowser/([\d.]+)}, 1] || "0.0" end def match? ua.include?("SputnikBrowser") end end end browser-6.2.0/lib/browser/maxthon.rb0000644000004100000410000000043114731746717017505 0ustar www-datawww-data# frozen_string_literal: true module Browser class Maxthon < Base def id :maxthon end def name "Maxthon" end def full_version ua[%r{(?:Maxthon)/([\d.]+)}i, 1] || "0.0" end def match? ua.match?(/Maxthon/i) end end end browser-6.2.0/lib/browser/uc_browser.rb0000644000004100000410000000044014731746717020201 0ustar www-datawww-data# frozen_string_literal: true module Browser class UCBrowser < Base def id :uc_browser end def name "UCBrowser" end def full_version ua[%r{UCBrowser/([\d.]+)}, 1] || "0.0" end def match? ua.include?("UCBrowser") end end end browser-6.2.0/lib/browser/middleware.rb0000644000004100000410000000302214731746717020143 0ustar www-datawww-data# frozen_string_literal: true require "uri" require_relative "middleware/context" module Browser class Middleware # Detect the most common assets. ASSETS_REGEX = /\.(css|png|jpe?g|gif|js|svg|ico|flv|mov|m4v|ogg|swf)\z/i.freeze # Detect the ACCEPT header. IE8 send */*. ACCEPT_REGEX = %r{(text/html|\*/\*)}.freeze def initialize(app, &block) raise ArgumentError, "Browser::Middleware requires a block" unless block @app = app @block = block end def call(env) request = Rack::Request.new(env) # Only apply verification on HTML requests. # This ensures that images, CSS and JavaScript # will be rendered. return run_app(env) unless process?(request) path = catch(:redirected) do Context.new(request).instance_eval(&@block) end # No path, no match. return run_app(env) unless path resolve_redirection(env, request.path, path) end def resolve_redirection(env, current_path, path) uri = URI.parse(path) if uri.path == current_path run_app(env) else redirect(path) end end def redirect(path) [302, {"Content-Type" => "text/html", "Location" => path}, []] end def run_app(env) @app.call(env) end def process?(request) html?(request) && !assets?(request) end def html?(request) request.env["HTTP_ACCEPT"].to_s.match(ACCEPT_REGEX) end def assets?(request) request.path.match(ASSETS_REGEX) end end end browser-6.2.0/lib/browser/meta/0000755000004100000410000000000014731746717016432 5ustar www-datawww-databrowser-6.2.0/lib/browser/meta/ie.rb0000644000004100000410000000055414731746717017360 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class IE < Base def version @version ||= browser.version.to_i end def meta return unless browser.ie? meta = [] meta << "oldie lt-ie8 lt-ie9" if version < 8 meta << "lt-ie9" if version == 8 meta.join(" ") end end end end browser-6.2.0/lib/browser/meta/platform.rb0000644000004100000410000000023514731746717020603 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Platform < Base def meta browser.platform.id end end end end browser-6.2.0/lib/browser/meta/device.rb0000644000004100000410000000023114731746717020212 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Device < Base def meta browser.device.id end end end end browser-6.2.0/lib/browser/meta/base.rb0000644000004100000410000000127214731746717017673 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta def self.rules @rules ||= [ Device, GenericBrowser, Id, IE, IOS, Mobile, Platform, Proxy, Safari, Tablet, Webkit ] end def self.get(browser) rules.each_with_object(Set.new) do |rule, meta| meta.merge(rule.new(browser).to_a) end.to_a end class Base # Set the browser instance. attr_reader :browser def initialize(browser) @browser = browser end def meta nil end def to_a meta.to_s.squeeze(" ").split end end end end browser-6.2.0/lib/browser/meta/tablet.rb0000644000004100000410000000025214731746717020231 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Tablet < Base def meta "tablet" if browser.device.tablet? end end end end browser-6.2.0/lib/browser/meta/ios.rb0000644000004100000410000000024314731746717017550 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class IOS < Base def meta "ios" if browser.platform.ios? end end end end browser-6.2.0/lib/browser/meta/mobile.rb0000644000004100000410000000025214731746717020225 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Mobile < Base def meta "mobile" if browser.device.mobile? end end end end browser-6.2.0/lib/browser/meta/id.rb0000644000004100000410000000021614731746717017352 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Id < Base def meta browser.id end end end end browser-6.2.0/lib/browser/meta/proxy.rb0000644000004100000410000000024014731746717020134 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Proxy < Base def meta "proxy" if browser.proxy? end end end end browser-6.2.0/lib/browser/meta/safari.rb0000644000004100000410000000027414731746717020227 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Safari < Base def meta "safari safari#{browser.version}" if browser.safari? end end end end browser-6.2.0/lib/browser/meta/generic_browser.rb0000644000004100000410000000043614731746717022141 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class GenericBrowser < Base def meta "#{browser.id} #{browser.id}#{browser.version}" if generic? end private def generic? !browser.safari? && !browser.chrome? end end end end browser-6.2.0/lib/browser/meta/webkit.rb0000644000004100000410000000024314731746717020243 0ustar www-datawww-data# frozen_string_literal: true module Browser module Meta class Webkit < Base def meta "webkit" if browser.webkit? end end end end browser-6.2.0/lib/browser/samsung_browser.rb0000644000004100000410000000047414731746717021256 0ustar www-datawww-data# frozen_string_literal: true module Browser class SamsungBrowser < Chrome def id :samsung_browser end def name "Samsung Browser" end def full_version ua[%r{SamsungBrowser/([\d.]+)}, 1] || super end def match? ua.include?("SamsungBrowser") end end end browser-6.2.0/lib/browser/electron.rb0000644000004100000410000000044214731746717017644 0ustar www-datawww-data# frozen_string_literal: true module Browser class Electron < Base def id :electron end def name "Electron" end def full_version ua[%r{Electron/([\d.]+)}, 1] || "0.0" end def match? ua.include?("Electron") end end end browser-6.2.0/lib/browser/browser.rb0000644000004100000410000000472514731746717017524 0ustar www-datawww-data# frozen_string_literal: true require "set" require "yaml" require "pathname" require_relative "version" require_relative "detect_version" require_relative "accept_language" require_relative "base" require_relative "safari" require_relative "chrome" require_relative "internet_explorer" require_relative "firefox" require_relative "edge" require_relative "opera" require_relative "blackberry" require_relative "unknown" require_relative "phantom_js" require_relative "uc_browser" require_relative "nokia" require_relative "micro_messenger" require_relative "weibo" require_relative "qq" require_relative "alipay" require_relative "electron" require_relative "facebook" require_relative "otter" require_relative "instagram" require_relative "yandex" require_relative "sputnik" require_relative "snapchat" require_relative "duck_duck_go" require_relative "samsung_browser" require_relative "huawei_browser" require_relative "miui_browser" require_relative "maxthon" require_relative "sougou_browser" require_relative "google_search_app" require_relative "epiphany" require_relative "bot" require_relative "bot/empty_user_agent_matcher" require_relative "bot/keyword_matcher" require_relative "bot/known_bots_matcher" require_relative "middleware" require_relative "platform" require_relative "device" require_relative "meta" module Browser EMPTY_STRING = "" Error = Class.new(StandardError) def self.root @root ||= Pathname.new(File.expand_path("../..", __dir__)) end class << self attr_accessor :user_agent_size_limit, :accept_language_size_limit end self.user_agent_size_limit = 2048 self.accept_language_size_limit = 2048 # Hold the list of browser matchers. # Order is important. def self.matchers @matchers ||= [ Nokia, UCBrowser, PhantomJS, BlackBerry, Opera, Edge, InternetExplorer, Firefox, Otter, Epiphany, Facebook, Instagram, Snapchat, Weibo, MicroMessenger, # must be placed before QQ QQ, Alipay, Electron, Yandex, Sputnik, DuckDuckGo, SamsungBrowser, HuaweiBrowser, MiuiBrowser, Maxthon, SougouBrowser, GoogleSearchApp, # Must be last Chrome, Safari, Unknown ] end def self.new(user_agent, **kwargs) matchers.each do |matcher_class| matcher = matcher_class.new(user_agent || EMPTY_STRING, **kwargs) return matcher if matcher.match? end end end browser-6.2.0/lib/browser/safari.rb0000644000004100000410000000136214731746717017300 0ustar www-datawww-data# frozen_string_literal: true module Browser class Safari < Base def id :safari end def name "Safari" end def full_version ua[%r{Version/([\d.]+)}, 1] || ua[%r{Safari/([\d.]+)}, 1] || ua[%r{AppleWebKit/([\d.]+)}, 1] || "0.0" end def match? ua.include?("Safari") && !platform.linux? && !ua.match?(/PhantomJS|FxiOS/) && !edge? && !chrome? && !opera? && !samsung_browser? && !huawei_browser? && !miui_browser? && !duck_duck_go? && !yandex? && !sputnik? && !maxthon? && !qq? && !alipay? && !sougou_browser? && !google_search_app? end end end browser-6.2.0/lib/browser/google_search_app.rb0000644000004100000410000000045514731746717021476 0ustar www-datawww-data# frozen_string_literal: true module Browser class GoogleSearchApp < Chrome def id :google_search_app end def name "Google Search App" end def full_version ua[%r{GSA/([\d.]+\d)}, 1] || super end def match? ua.include?("GSA") end end end browser-6.2.0/lib/browser/internet_explorer.rb0000644000004100000410000000240114731746717021576 0ustar www-datawww-data# frozen_string_literal: true module Browser class InternetExplorer < Base # https://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx#TriToken TRIDENT_MAPPING = { "4.0" => "8", "5.0" => "9", "6.0" => "10", "7.0" => "11", "8.0" => "12" }.freeze def id :ie end def name "Internet Explorer" end def full_version "#{ie_version}.0" end def msie_full_version (ua.match(%r{MSIE ([\d.]+)|Trident/.*?; rv:([\d.]+)}) && (Regexp.last_match(1) || Regexp.last_match(2))) || "0.0" end def msie_version msie_full_version.split(".").first end def match? msie? || modern_ie? end # Detect if IE is running in compatibility mode. def compatibility_view? trident_version && msie_version.to_i < (trident_version.to_i + 4) end private def ie_version TRIDENT_MAPPING[trident_version] || msie_version end # Return the trident version. private def trident_version ua.match(%r{Trident/([0-9.]+)}) && Regexp.last_match(1) end private def msie? ua.include?("MSIE") && !ua.include?("Opera") end private def modern_ie? ua.match?(%r{Trident/.*?; rv:(.*?)}) end end end browser-6.2.0/lib/browser/blackberry.rb0000644000004100000410000000053614731746717020155 0ustar www-datawww-data# frozen_string_literal: true module Browser class BlackBerry < Base def id :blackberry end def name "BlackBerry" end def full_version ua[%r{BlackBerry[\da-z]+/([\d.]+)}, 1] || ua[%r{Version/([\d.]+)}, 1] || "0.0" end def match? ua.match?(/BlackBerry|BB10/) end end end browser-6.2.0/lib/browser/opera.rb0000644000004100000410000000045714731746717017145 0ustar www-datawww-data# frozen_string_literal: true module Browser class Opera < Base def id :opera end def name "Opera" end def full_version ua[%r{OPR/([\d.]+)}, 1] || ua[%r{Version/([\d.]+)}, 1] || "0.0" end def match? ua.match?(%r{(Opera|OPR/)}) end end end browser-6.2.0/lib/browser/edge.rb0000644000004100000410000000063514731746717016741 0ustar www-datawww-data# frozen_string_literal: true module Browser class Edge < InternetExplorer def id :edge end def name "Microsoft Edge" end def full_version ua[%r{(?:Edge|Edg|EdgiOS|EdgA)/([\d.]+)}, 1] || super end def match? ua.match?(%r{((?:Edge|Edg|EdgiOS|EdgA)/[\d.]+|Trident/8)}) end def chromium_based? match? && ua.match?(/\bEdg\b/) end end end browser-6.2.0/lib/browser.rb0000644000004100000410000000016614731746717016034 0ustar www-datawww-data# frozen_string_literal: true require_relative "browser/browser" require_relative "browser/rails" if defined?(Rails) browser-6.2.0/test/0000755000004100000410000000000014731746717014232 5ustar www-datawww-databrowser-6.2.0/test/ua_bots.yml0000644000004100000410000002044014731746717016411 0ustar www-datawww-data--- ADLXBOT: "Mozilla/5.0 (compatible; adidxbot/2.0; +http://www.bing.com/bingbot.htm)" ADS_TXT_CRAWLER: "AdsTxtCrawler/1.0" AMAZONBOT: Amazonbot ANDERSPINK: "Mozilla/5.0 (compatible; AndersPinkBot/1.0; +http://anderspink.com/bot.html)" ANTHROPIC_AI: anthropic-ai APIS_GOOGLE: "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)" APPLE_BOT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1)" APPLEBOT: Applebot APPSIGNALBOT: "AppSignalBot/1.0 (+https://appsignal.com)" ARCHIVEBOT: "ArchiveTeam ArchiveBot/20190617.01 (wpull 2.0.3) and not Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" ASK: "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)" AWS_ELB: ELB-HealthChecker/1.0 BAIDU: "Baiduspider+(+http://www.baidu.com/search/spider.htm)" BARKROWLER: "Barkrowler/0.7 (+http://www.exensa.com/crawl)" BINGBOT: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" BINGPREVIEW: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b" BUBING: "BUbiNG (+http://law.di.unimi.it/BUbiNG.html)" BUZZBOT: "Buzzbot/1.0 (Buzzbot; http://www.buzzstream.com; buzzbot@buzzstream.com)" BYTESPIDER: Bytespider CCBOT: CCBot CHATGPT_USER: ChatGPT-User CHECKLY: "Checkly/1.0 (https://www.checklyhq.com)" CHROME_LIGHTHOUSE: "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3694.0 Mobile Safari/537.36 Chrome-Lighthouse" CIPACRAWLER: "CipaCrawler/3.0 (info@domaincrawler.com; http://www.domaincrawler.com/www.example.com)" CLAUDE_WEB: Claude-Web CLAUDEBOT: ClaudeBot CLOUDFLARE: "Mozilla/5.0 (compatible; CloudFlare-AlwaysOnline/1.0; +http://www.cloudflare.com/always-online) AppleWebKit/534.34" COHERE-AI: cohere-ai COMMONCRAWL: "CCBot/2.0 (http://commoncrawl.org/faq/)" COMODO_SSL_CHECKER: "COMODO SSL Checker" COPYPANTS: "Mozilla/5.0 (compatible; BotPants/1.0; Linux; +info@copypants.com) KHTML/3.5.5 (like Gecko)" DATAFEEDWATCH: "Datafeedwatch/2.1.x" DATANYZE: "Mozilla/5.0 (X11; Datanyze; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" DAUMOA: "Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server;) Daumoa 4.0" DIFFBOT: Diffbot DOMAINAREANIMATOR: "Domain Re-Animator Bot (http://domainreanimator.com) - support@domainreanimator.com" DOT_BOT: "Mozilla/5.0 (compatible; DotBot/1.1; http://www.opensiteexplorer.org/dotbot, help@moz.com)" DUCKDUCKGO: "DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)" EZPUBLISH: "eZ Publish Link Validator" FACEBOOK_BOT: "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" FACEBOOKBOT: FacebookBot FYREBOT: "Fyrebot/1.0" GARLIK: "GarlikCrawler/1.2 (http://garlik.com/, crawler@garlik.com)" GERMCRAWLER: "GermCrawler" GO_1.1_PACKAGE_HTTP: "Go 1.1 package http" GO_HTTP_CLIENT: "Go-http-client" GOOGLE-EXTENDED: Google-Extended GOOGLE_BOT: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" GOOGLE_IMAGE_PROXY: "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)" GOOGLE_PAGE_SPEED_INSIGHTS: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko; Google Page Speed Insights) Chrome/22.0.1229 Safari/537.4" GOOGLE_SHOPPING: "google-xrawler" GOOGLE_SITE_VERIFICATION: Mozilla/5.0 (compatible; Google-Site-Verification/1.0) GOOGLE_STACKDRIVER_UPTIME_CHECKS: "GoogleStackdriverMonitoring-UptimeChecks" GOOGLE_STRUCTURED_DATA_TESTING_TOOL2: "Mozilla/5.0 (compatible; Google-Structured-Data-Testing-Tool +http://developers.google.com/structured-data/testing-tool/)" GOOGLE_STRUCTURED_DATA_TESTING_TOOL: "Mozilla/5.0 (compatible; X11; Linux x86_64; Google-StructuredDataTestingTool; +http://www.google.com/webmasters/tools/richsnippets)" GPTBOT: GPTBot GRAPESHOT: "Mozilla/5.0 (compatible; GrapeshotCrawler/2.0; +http://www.grapeshot.co.uk/crawler.php)" HTTRACK: "Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)" IMPLISENSEBOT: "ImplisenseBot 1.0" JAUNT: "Jaunt/1.5" JOBSEEKER: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) JobBot/5.0 (compatible; +http://www.jobseeker.com.au/bot.html) Safari/538.1" JOOBLE: "Mozilla/5.0 (compatible; Jooblebot/2.0; Windows NT 6.1; WOW64; +http://jooble.org/jooble-bot) Mobile" KNOWLEDGE_AI: "The Knowledge AI" LINKDEXBOT: "Mozilla/5.0 (compatible; linkdexbot/2.0; +http://www.linkdex.com/bots/)" LINKEDIN: "LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)" LOAD_TIME_BOT: "Mozilla/5.0 (compatible; LoadTimeBot/0.9; +http://www.loadtime.net/bot.html)" LTX71: "ltx71 - (http://ltx71.com/)" MAIL_RU: "Mozilla/5.0 (compatible; Linux x86_64; Mail.RU_Bot/2.0; +http://go.mail.ru/help/robots)" MAPPYDATA: "Mozilla/5.0 (compatible; Mappy/1.0; +http://mappydata.net/bot/)" MASTODONBOT: "http.rb/3.0.0 (Mastodon/2.2.0; +https://mstdn.io/)" MAUIBOT: "MauiBot (crawler.feedback+wc@gmail.com)" MEGAINDEX_RU: "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)" MSNBOT: "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" MSNBOT_MEDIA: "msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)" NETCRAFT2: Netcraft SSL Server Survey - contact info@netcraft.com NETCRAFT: Mozilla/5.0 (compatible; NetcraftSurveyAgent/1.0; +info@netcraft.com) NEWRELICPINGER: NewRelicPinger/1.0 (12345) OMGILI: omgili PAESSLER: Mozilla/5.0 (compatible; PRTG Network Monitor (www.paessler.com); Windows) PERPLEXITYBOT: PerplexityBot PR-CY_RU: Mozilla/5.0 (compatible; PR-CY.RU; + https://a.pr-cy.ru) PRIVACYAWAREBOT: "Mozilla/5.0 (compatible; PrivacyAwareBot/1.1; +http://www.privacyaware.org)" PROXIMIC: "Mozilla/5.0 (compatible; proximic; +http://www.proximic.com/info/spider.php)" PUINCRAWLER: "Pu_iN Crawler (+http://semanticjuice.com/)" QUERYSEEKER: "QuerySeekerSpider ( http://queryseeker.com/bot.html )" QUICKCRAWLER: "Quick-Crawler (+https://www.scrapinghub.com/)" SCOUT_URL_MONITOR: ScoutURLMonitor/6.2.2 SCRAPY: "Scrapy/0.18.4 (+http://scrapy.org)" SEMANTICBOT: "Mozilla/5.0 (compatible; Semanticbot/1.0; +http://sempi.tech/bot.html)" SEO_AUDIT: "Mozilla/5.0 (compatible; seo-audit-check-bot/1.0)" SEOBILITYBOT: "SeobilityBot (SEO Tool; https://www.seobility.net/sites/bot.html)" SEODIVER: "Mozilla/5.0 (compatible; SEOdiver/1.0; +http://www.seodiver.com/bot)" SEOKICKS: "Mozilla/5.0 (compatible; SEOkicks-Robot; +http://www.seokicks.de/robot.html)" SISTRIX: "Mozilla/5.0 (compatible; SISTRIX Crawler; http://crawler.sistrix.net/)" SITECHECK: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.0) SiteCheck-sitecrawl by Siteimprove.com" SKYPE: "Mozilla/5.0 (Windows NT 6.1; WOW64) SkypeUriPreview Preview/0.5" SOCIALRANKIO: SocialRankIOBot; http://socialrank.io/about SQUIDER: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36 Squider/0.01" SWIFTYPE: "Swiftbot" TANGIBLEEBOT: "TangibleeBot" TEERAID: "Mozilla/5.0 (compatible; TeeRaidBot; +https://teeraid.com/bot/)" TINEYE: "TinEye-bot/0.51 (see http://www.tineye.com/crawler.html)" TRAACKR: "Traackr.com" TRENDSMAP: "Mozilla/5.0 (compatible; TrendsmapResolver/0.1)" UPDOWN_MONITOR: "updown.io daemon 2.2" WATCHSUMO: "Mozilla/5.0 (compatible) WatchSumo/1.0.0 (http://www.watchsumo.com)" WEBCEO: "Mozilla/5.0 (compatible; online-webceo-bot/1.0; +http://online.webceo.com)" WHATSAPP: "WhatsApp/2.17.38 Mozilla/5.0 (Linux; U; Android 6.1; en-us; DV Build/Donut) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36" WIKIDO: "WikiDo/1.1 (http://wikido.com; crawler@wikido.com)" WOORANK: "Mozilla/5.0 (compatible; woorankreview/2.0; +https://www.woorank.com/)" WORIOBOT: "Mozilla/5.0 (compatible; woriobot +http://worio.com)" YAHOO_AD_MONITORING: "Mozilla/5.0 (compatible; Yahoo Ad monitoring; https://help.yahoo.com/kb/yahoo-ad-monitoring-SLN24857.html)" YAHOO_SLURP: "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)" YANDEX_DIRECT: "Mozilla/5.0 (compatible; YandexDirect/3.0; +http://yandex.com/bots)" YANDEX_METRIKA: "Mozilla/5.0 (compatible; YandexMetrika/3.0; +http://yandex.com/bots)" YANGA: "Yanga WorldSearch Bot v1.1/beta (http://www.yanga.co.uk/)" YOUBOT: YouBot ZABBIX: "Zabbix" ZOOMBOT: "ZoomBot (Linkbot 1.0 http://suite.seozoom.it/bot.html)" ZOOMINFOBOT: "ZoominfoBot (zoominfobot at zoominfo dot com)" browser-6.2.0/test/ua.yml0000644000004100000410000006222214731746717015366 0ustar www-datawww-data--- ADOBE_AIR: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/13.0" ALIPAY_ANDROID: "Mozilla/5.0 (Linux; U; Android 4.2.1; zh-cn; HUAWEI G610-T00 Build/HuaweiG610-T00) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 AlipayDefined(nt:WIFI,ws:360|640|1.5) AliApp(AP/9.0.1.073001) AlipayClient/9.0.1.073001 GCanvas/1.4.2.15" ALIPAY_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 AliApp(AP/2.3.4) AlipayClient/2.3.4" ANDROID: "Android SDK 1.5r3: Mozilla/5.0 (Linux; U; Android 1.5; de-; sdk Build/CUPCAKE) AppleWebkit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1" ANDROID_CUPCAKE: Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile G1 Build/CRC1) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 ANDROID_DONUT: Mozilla/5.0 (Linux; U; Android 1.6; ar-us; SonyEricssonX10i Build/R2BA026) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 ANDROID_ECLAIR_21: Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 ANDROID_FROYO: Mozilla/5.0 (Linux; U; Android 2.2; en-sa; HTC_DesireHD_A9191 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 ANDROID_GINGERBREAD: Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; Sensation_4G Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/5.0 Safari/533.16 ANDROID_HONEYCOMB_30: Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13 ANDROID_ICECREAM: Mozilla/5.0 (Linux; U; Android 4.0.1; en-us; sdk Build/ICS_MR0) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 ANDROID_JELLYBEAN_41: Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Nexus S Build/JRO03E) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 ANDROID_JELLYBEAN_42: Mozilla/5.0 (Linux; U; Android 4.2; en-us; Nexus 10 Build/JVP15I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 ANDROID_JELLYBEAN_43: Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JWR66D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.111 Safari/537.36 ANDROID_KITKAT: Mozilla/5.0 (Linux; Android 4.4; Nexus 7 Build/KOT24) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Safari/537.36 ANDROID_LOLLIPOP_50: Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Mobile Safari/537.36 ANDROID_LOLLIPOP_51: Mozilla/5.0 (Linux; Android 5.1; Nexus 5 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.0.0 Mobile Safari/537.36; DailymotionEmbedSDK 1.0 ANDROID_NEXUS_PLAYER: Mozilla/5.0 (Linux; Android 5.0; Nexus Player Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.0 ANDROID_OREO: Mozilla/5.0 (Linux; Android 8.0.0; Pixel Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.03112.107 Mobile Safari/537.36 ANDROID_Q: Mozilla/5.0 (Linux; Android 10; Pixel 2 Build/QQ1A.191205.008; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 ANDROID_TV: Mozilla/5.0 (Linux; Android 5.0; ADT-1 Build/LRW87K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36 ANDROID_WEBVIEW: Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile Safari/537.36 ANDROID_WITH_SAFARI: "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SCH-I535 Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30" BLACKBERRY10: "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.1675 Mobile Safari/537.10+" BLACKBERRY4: "BlackBerry8100/4.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103" BLACKBERRY5: "BlackBerry9000/5.0.0.93 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/179" BLACKBERRY6: "Mozilla/5.0 (BlackBerry; U; BlackBerry AAAA; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/6.0.0.141 Mobile Safari/534.11+" BLACKBERRY7: "Mozilla/5.0 (BlackBerry; U; BlackBerry AAAA; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.1 Mobile Safari/534.11+" BLACKBERRY: "BlackBerry7100i/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103" CHROME: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4" CHROME_OS: "Mozilla/5.0 (X11; CrOS x86_64 3701.81.0) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.57 Safari/537.31." CHROME_REQUEST_DESKTOP_SITE: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/130 Version/11.1.1 Safari/605.1.15" COREMEDIA: "Apple Mac OS X v10.6.4 CoreMedia v1.0.0.10F569" CUSTOM_APP: "Our App 0.0.1 (Linux; Android 4.0.3; HTC Ruby Build/IML74K; en_CA)" DUCKDUCKGO_BROWSER_ANDROID: Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.96 Mobile Safari/537.36 DuckDuckGo/5" DUCKDUCKGO_BROWSER_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 DuckDuckGo/7" ELECTRON: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Electron/1.4.12 Safari/537.36" EPIPHANY: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15 Ubuntu/16.04 (3.18.11-0ubuntu1) Epiphany/3.18.11" FACEBOOK: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 [FBAN/FBIOS;FBAV/135.0.0.45.90;FBBV/66877072;FBDV/iPhone9,3;FBMD/iPhone;FBSN/iOS;FBSV/10.3.3;FBSS/2;FBCR/AT&T;FBID/phone;FBLC/en_US;FBOP/5;FBRV/0] FACEBOOK_ANDROID: "Mozilla/5.0 (Linux; Android 9; ONEPLUS A6003 Build/PKQ1.180716.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/73.0.3683.90 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/214.0.0.43.83;]" FACEBOOK_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 [FBAN/FBIOS;FBDV/iPhone11,2;FBMD/iPhone;FBSN/iOS;FBSV/12.1.4;FBSS/3;FBCR/KPN NL;FBID/phone;FBLC/en_GB;FBOP/5]" FIREFOX: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8" FIREFOX_ANDROID: "Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0" FIREFOX_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) FxiOS/1.2 Mobile/13C75 Safari/601.1.46" FIREFOX_MODERN: "Mozilla/5.0 (X11; Ubuntu; Linux armv7l; rv:17.0) Gecko/20100101 Firefox/17.0" FIREFOX_OS: "Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0" FIREFOX_TABLET: "Mozilla/5.0 (Android; Tablet; rv:14.0) Gecko/14.0 Firefox/14.0" GOOGLE_SEARCH_APP_ANDROID: "Mozilla/5.0 (Linux; Android 10; SM-G960U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.117 Mobile Safari/537.36 GSA/11.6.8.21.arm64" GOOGLE_SEARCH_APP_IPAD: "Mozilla/5.0 (iPad; CPU OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/102.0.304944559 Mobile/15E148 Safari/605.1" GOOGLE_SEARCH_APP_IPHONE: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/105.0.307913796 Mobile/17D50 Safari/604.1" HUAWEI_BROWSER: "Mozilla/5.0 (Linux; Android 10; HMA-AL00; HMSCore 5.0.0.304; GMSCore 19.6.29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 HuaweiBrowser/10.1.2.300 Mobile Safari/537.36" IE10: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0; EIE10;ENUSMSN)" IE10_COMPAT: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; EIE10;ENUSMSN)" IE10_X64_WINX64: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)" IE11: "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko" IE11_COMPAT: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729)" IE11_TOUCH_SCREEN: "Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; rv:11.0) like Gecko" IE6: "Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)" IE7: "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)" IE8: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)" IE8_COMPAT: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SLCC1; Media Center PC 5.0; .NET CLR 3.5.21022)" IE9: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" IE9_CHROME_FRAME: "Mozilla/5.0 (Windows NT 6.1; WOW64; chromeframe/26.0.1410.43) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31" IE9_COMPAT: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)" IE_WITHOUT_TRIDENT: Mozilla/4.0 (compatible; MSIE8.0; Windows NT 6.0) .NET CLR 2.0.50727) INSTAGRAM: "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E216 Instagram 41.0.0.14.90 (iPhone9,3; iOS 11_3; pl_PL; pl-PL; scale=2.00; gamut=wide; 750x1334)" INSTAGRAM_OTHER: "Instagram/182257141 CFNetwork/1107.1 Darwin/19.0.0" IOS12: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1" IOS3: "Mozilla/5.0 (iPad; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10" IOS4: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7" IOS5: "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3" IOS6: "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25" IOS7: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53" IOS8: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4" IOS8_1_2: 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4' IOS8_3: 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4' IOS9: "Mozilla/5.0 (iPad; CPU OS 9_0 like Mac OS X) AppleWebKit/601.1.17 (KHTML, like Gecko) Version/8.0 Mobile/13A175 Safari/600.1.4" IOS_WEBVIEW: Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H141 IPAD: "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10" IPHONE: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/1A542a Safari/419.3" IPOD: "Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3" JIOPHONE_2: "Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5" KINDLE: "Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600×800; rotate)" KINDLE_FIRE: "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" KINDLE_FIRE_HD: "Mozilla/5.0 (Linux; U; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Safari/535.19 Silk-Accelerated=true" KINDLE_FIRE_HD_MOBILE: "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true" KINDLE_SILK_DESKTOP: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36 KINDLE_SILK_MOBILE: Mozilla/5.0 (Linux; U; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Mobile Safari/537.36 KINDLE_SILK_MOBILE_1ST_GEN: Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 Silk-Accelerated=true KINDLE_SILK_TABLET: Mozilla/5.0 (Linux; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36 KINDLE_SILK_TABLET_1ST_GEN: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true LUMIA800: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; XBLWP7; ZuneWP7" MAC_OS: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15" MAC_OSX: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9" MAXTHON: "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36 Maxthon/5.3.8.2000" MICRO_MESSENGER_ANDROID: "Mozilla/5.0 (Linux; Android 7.1.2; Redmi 4X Build/N2G47H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36 MMWEBID/9286 MicroMessenger/7.0.13.1640(0x27000D37) Process/tools NetType/WIFI Language/zh_CN ABI/arm64 WeChat/arm64" MICRO_MESSENGER_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.10(0x17000a21) NetType/4G Language/zh_CN" MIDP: MIDP-2.0 MIUI_BROWSER: "Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; Redmi 4X Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.141 Mobile Safari/537.36 XiaoMi/MiuiBrowser/12.3.3-g" MOBILE_CHROME: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3" MS_EDGE: "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0" MS_EDGE_ANDROID: "Mozilla/5.0 (Linux; Android 7.1.2; Redmi 4X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.0 Mobile Safari/537.36 EdgA/44.11.2.4122" MS_EDGE_CHROME: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.29 Safari/537.36 Edg/79.0.309.18" MS_EDGE_COMPAT: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/8.0; .NET4.0C; .NET4.0E; Tablet PC 2.0; Microsoft Outlook 15.0.4433; ms-office; MSOffice 15)" MS_EDGE_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 EdgiOS/44.5.0.10 Mobile/15E148 Safari/604.1" MS_EDGE_MOBILE: "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0" NEXUS7: "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JWR66Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36" NEXUS_TABLET: "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19" NINTENDO_SWITCH: "Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/601.6 (KHTML, like Gecko) NF/4.0.0.7.9 NintendoBrowser/5.1.0.15785" NINTENDO_WII: "Opera/9.00 (Nintendo Wii; U; ; 1309-9; en)" NINTENDO_WIIU: "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/534.52 (KHTML, like Gecko) NX/2.1.0.8.23 NintendoBrowser/1.1.0.7579.EU" NOKIA: "Mozilla/5.0 (Series40; NokiaX3-02/le6.32; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.0.2.62.10" NOKIA_8110: "Mozilla/5.0 (Mobile; Nokia_8110_4G; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5" NOOK: "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; NOOK BNTV250A Build/GINGERBREAD 1.4.3) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1" OPERA: "Opera/9.80 (Macintosh; Intel Mac OS X 10.7.4; U; en) Presto/2.10.229 Version/11.64" OPERA_ANDROID: "Mozill/5.0 (Linux; Android 4.4.2; A1-810 Build/KOT49H) Apple/WebKit/537.36 (KHTML, like Gecko) Chrome/48.0.25 64.99 Safari/537.36 OPR/35.0.2070.100283" OPERA_MINI: "Opera/9.80 (Android; Opera Mini/7.029952/28.2359;u; fr) Presto/2.8.119 Version/11.10" OPERA_MOBI: "Opera/9.8 (Android 2.3.5; Linux; Opera Mobi/ADR-1205181138; U; en) Presto/2.10.254 Version/12.00" OPERA_NEXT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.37 Safari/537.36 OPR/15.0.1147.44 (Edition Next)" OTTER: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) Otter/0.9.91 PHANTOM_JS: "Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.0 Safari/534.34" PLAYBOOK: "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+" PLAYSTATION3: "Mozilla/5.0 (PLAYSTATION 3; 3.55)" PLAYSTATION4: "Mozilla/5.0 (PlayStation 4 1.020) AppleWebKit/536.26 (KHTML, like Gecko)" PSP: "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)" PSP_VITA: "Mozilla/5.0 (Playstation Vita 1.61) AppleWebKit/531.22.8 (KHTML, like Gecko) Silk/3.2" QQ_BROWSER_ANDROID: "Mozilla/5.0 (Linux; Android 5.1.1; SM-N9108V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.2 TBS/036222 Safari/537.36 V1_AND_SQ_6.2.0_320_YYB_D QQ/6.2.0.2655 NetType/WIFI WebP/0.3.0 Pixel/1440" QQ_BROWSER_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13E238 QQ/6.3.3.432 V1_IPH_SQ_6.3.3_1_APP_A Pixel/640 Core/UIWebView NetType/WIFI Mem/47" QQ_BROWSER_MAC: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36 QQBrowser/4.2.4753.400" QQ_BROWSER_MAC_LITE: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14 QQBrowserLite/1.0.4" QUICKTIME: "QuickTime/7.6.8 (qtver=7.6.8;os=Windows NT 5.1Service Pack 3)" SAFARI3: "Mozilla/5.0 (Windows; U; Windows NT 6.0; en) AppleWebKit/522.15.5 (KHTML, like Gecko) Version/3.0.3 Safari/522.15.5" SAFARI4: "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr-ch) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9" SAFARI5: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; fr-ch) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" SAFARI6: "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25" SAFARI7: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71" SAFARI8: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_90) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25" SAFARI9: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9" SAFARI: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8" SAFARI_IPAD_WEBAPP_MODE: "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405" SAFARI_IPHONE_WEBAPP_MODE: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g" SAMSUNG: "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; SAMSUNG-SGH-I497 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30" SAMSUNG_BROWSER: "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-N960U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.1 Chrome/75.0.3770.143 Mobile Safari/537.36" SAMSUNG_CHROME: "Mozilla/5.0 (Linux; Android 4.4.2; en-gb; SAMSUNG GT-I9195/I9195XXUCNEA Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36" SAMSUNG_SM-F700F: "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-F700F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.1 Chrome/75.0.3770.143 Mobile Safari/537.36" SAMSUNG_SM-FAKE: "Mozilla/5.0 (Linux; Android 8.0.0; SM-0000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36" SAMSUNG_SM-G960F: "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36" SAMSUNG_SM-G975F: "Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36" SMART_TV: "Mozilla/5.0 (SmartHub; SMART-TV; U; Linux/SmartTV) AppleWebKit/531.2+ (KHTML, like Gecko) WebBrowser/1.0 SmartTV Safari/531.2+" SNAPCHAT: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Snapchat/10.69.5.72 (iPhone10,3; iOS 13.2.2; gzip) SNAPCHAT_EMPTY_STRING_VERSION: "Mozilla/5.0 (Linux; Android 9; SM-N960U Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.96 Mobile Safari/537.36Snapchat10.70.0.0 (SM-N960U; Android 9#N960USQS3CSJ2#28; gzip)" SNAPCHAT_SPACE_VERSION: "Mozilla/5.0 (Linux; Android 9; SM-N960U Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.96 Mobile Safari/537.36Snapchat 10.70.0.0 (SM-N960U; Android 9#N960USQS3CSJ2#28; gzip)" SOUGOU_BROWSER: "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0" SOUGOU_BROWSER_MOBILE: "Mozilla/5.0 (Linux; Android 7.1.2; Redmi 4X Build/N2G47H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.106 Mobile Safari/537.36 AWP/2.0 SogouMSE,SogouMobileBrowser/5.28.12" SPUTNIK: "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 SputnikBrowser/4.1.2801.0 Safari/537.36" SURFACE: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)" SYMBIAN: "Nokia5250/10.0.011 (SymbianOS/9.4; U; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Safari/525 3gpp-gba" TABLOID: "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13" UC_BROWSER: "Mozilla/5.0 (Linux; U; Android 4.4.2; en-US; GT-I9500 Build/KOT49H) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.9.4.484 U3/0.8.0 Mobile Safari/533.1" WEIBO_ANDROID: "Mozilla/5.0 (Linux; Android 5.0.2; vivo X5M Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36 Weibo (vivo-vivo X5M__weibo__5.7.1__android__android5.0.2)" WEIBO_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H143 Weibo (iPhone7,2__weibo__5.7.1__iphone__os8.4)" WINDOWS10: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; Trident/6.0)" WINDOWS7: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205" WINDOWS81: "Mozilla/5.0 (IE 11.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko" WINDOWS8: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)" WINDOWS_2000: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 5.0; Trident/6.0)" WINDOWS_2000_SP1: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 5.01; Trident/6.0)" WINDOWS_MOBILE: "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12)" WINDOWS_PHONE8: "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)" WINDOWS_PHONE: "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; DELL; Venue Pro)" WINDOWS_PHONE_81: "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 929) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537" WINDOWS_VISTA: "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" WINDOWS_WOW64: "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko" WINDOWS_XP: "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; FDM; .NET CLR 1.1.4322)" WINDOWS_XP_64: "Mozilla/4.0 (Compatible; MSIE 8.0; Windows NT 5.2; Trident/6.0)" XBOX360: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox), or Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; Xbox)" XBOXONE: "Mozilla/5.0 (Compatible; MSIE 10.0; Windows NT 6.2; Trident /6.0; Xbox; Xbox One)" XOOM: "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13" YANDEX_BROWSER_DESKTOP: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 YaBrowser/19.6.0.1583 Yowser/2.5 Safari/537.36" YANDEX_BROWSER_IOS: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 YaBrowser/19.6.1.157.10 Mobile/15E148 Safari/605.1" browser-6.2.0/test/browser_test.rb0000644000004100000410000001161614731746717017306 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class BrowserTest < Minitest::Test test "sets user agent while instantianting object" do browser = Browser.new("Safari") assert_equal "Safari", browser.ua end test "does not fail with nil user agent" do browser = Browser.new(nil) refute browser.known? end %w[ BlackBerry Chrome Edge Firefox MSIE Opera PhantomJS S40OviBrowser Safari UCBrowser ].each do |ua| test "does not fail when have no version info (#{ua})" do browser = Browser.new(ua) assert_equal "0", browser.version assert_equal "0.0", browser.full_version end end test "detects android" do browser = Browser.new(Browser["ANDROID"]) assert_equal "Safari", browser.name assert browser.platform.android? assert browser.safari? assert browser.webkit? assert_equal "3.1.2", browser.full_version assert_equal "3", browser.version end test "detects android tablet" do browser = Browser.new(Browser["TABLOID"]) assert_equal "Safari", browser.name assert browser.platform.android? assert browser.safari? assert browser.webkit? assert_equal "4.0", browser.full_version assert_equal "4", browser.version end test "detects surface tablet" do browser = Browser.new(Browser["SURFACE"]) assert_equal "Internet Explorer", browser.name assert browser.device.surface? assert browser.ie? assert_equal "10.0", browser.full_version assert_equal "10", browser.version end test "detects quicktime" do browser = Browser.new(Browser["QUICKTIME"]) assert_equal "QuickTime", browser.name assert browser.quicktime? assert_equal "7.6.8", browser.full_version assert_equal "7", browser.version assert browser.quicktime?(%w[>=7 <8]) end test "detects core media" do browser = Browser.new(Browser["COREMEDIA"]) assert_equal "Apple CoreMedia", browser.name assert browser.core_media? assert_equal "1.0.0.10", browser.full_version assert_equal "1", browser.version assert browser.core_media?(%w[>=1 <2]) end test "detects phantom.js" do browser = Browser.new(Browser["PHANTOM_JS"]) assert_equal "PhantomJS", browser.name assert_equal :phantom_js, browser.id assert browser.phantom_js? assert_equal "1.9.0", browser.full_version assert_equal "1", browser.version assert browser.phantom_js?(%w[>=1 <2]) end test "returns a zero version" do browser = Browser.new("Bot") assert_equal "0.0", browser.full_version assert_equal "0", browser.version end test "ignores malformed strings when comparing versions" do browser = Browser.new("Chrome/65.0.3325.99.FreeBrowser.3.0.5") refute browser.chrome?(">=65") end test "detects unknown browser" do browser = Browser.new("Unknown") assert browser.unknown? refute browser.known? assert_equal :unknown_browser, browser.id assert_equal "Unknown Browser", browser.name end test "returns empty language set for missing accept language" do browser = Browser.new("") assert_empty browser.accept_language end test "sets accept language while instantiating object" do browser = Browser.new("", accept_language: "pt-br") assert_kind_of Array, browser.accept_language assert_equal ["pt-BR"], browser.accept_language.map(&:full) end test "returns all known languages" do accept_language = "en-us,en;q=0.8,pt-br;q=0.5,pt;q=0.3" browser = Browser.new("", accept_language: accept_language) languages = browser.accept_language.map(&:full) assert_equal %w[en-US en pt-BR pt], languages end test "removes duplicate items" do browser = Browser.new(Browser["SAFARI"]) assert_equal ["safari"], (browser.meta.select {|item| item == "safari" }) end test "detects meta aliased as to_a" do browser = Browser.new(Browser["SAFARI"]) assert_equal browser.meta, browser.to_a end test "knows a supported browser" do browser = Browser.new("Chrome") assert browser.known? end test "does not know an unsupported browser" do browser = Browser.new("Fancy new browser") refute browser.known? end test "rejects user agent larger than 2048 bytes" do message = "user_agent cannot be larger than 2048 bytes; actual size is " \ "2049 bytes" error = begin Browser.new("a" * 2049) nil rescue Browser::Error => error error end refute_nil error assert_equal message, error.message end test "rejects accept language larger than 2048 bytes" do message = "accept_language cannot be larger than 2048 bytes; actual size " \ "is 2049 bytes" error = begin Browser.new("Chrome", accept_language: "a" * 2049).accept_language nil rescue Browser::Error => error error end refute_nil error assert_equal message, error.message end end browser-6.2.0/test/test_helper.rb0000644000004100000410000000136614731746717017103 0ustar www-datawww-data# frozen_string_literal: true require "simplecov" SimpleCov.start do add_filter %r{/test/} end ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" require "minitest/autorun" require "minitest/utils" require "browser" require "browser/testing" require "yaml" module Minitest class Test setup do Browser::Bot.instance_variable_set(:@detect_empty_ua, false) end def assert_deprecated(message, file, line, &block) message = "#{message} (called from #{file}:#{line})" _out, err = capture_io(&block) assert_includes err, message end end end # Override Browser::Base#warn, so we don't output deprecation messages. module Browser class Base def warn(*) end end end browser-6.2.0/test/sample_app.rb0000644000004100000410000000261614731746717016705 0ustar www-datawww-data# frozen_string_literal: true require "rails" require "browser" class PagesController < ActionController::Base def home render html: "#{browser.name}:#{browser.accept_language.first.full}" end end class BotsController < ActionController::API def index render json: { isBot: browser.bot?, acceptLanguages: browser.accept_language.map(&:full) } end end class SampleApp < Rails::Application config.secret_token = "99f19f08db7a37bdcb9d6701f54dca" config.secret_key_base = "99f19f08db7a37bdcb9d6701f54dca" config.eager_load = true config.active_support.deprecation = :log # Introduced by Rails 6. config.hosts << "example.org" if config.respond_to?(:hosts) routes.append do default_headers = {"Content-Type" => "text/html"} root to: ->(_env) { [200, default_headers, ["ROOT"]] } get "upgrade", to: lambda {|env| browser = Rack::Request.new(env).params["browser"] [200, default_headers, ["UPGRADE: #{browser}"]] }, as: "upgrade" get "/asset", to: proc { [200, {"Content-Type" => "image/png"}, []] } get "/home", to: "pages#home" get "/api/pages", to: "bots#index" end config.middleware.use Browser::Middleware do redirect_to upgrade_path(browser: "ie6") if browser.ie?(6) redirect_to upgrade_path(browser: "ie7") if browser.ie?(7) redirect_to "/invalid" if browser.ie?(8) end end SampleApp.initialize! browser-6.2.0/test/ua_search_engines.yml0000644000004100000410000000077514731746717020430 0ustar www-datawww-data--- ASK: "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)" BAIDU: "Baiduspider+(+http://www.baidu.com/search/spider.htm)" BINGBOT: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" DUCKDUCKGO: "DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)" GOOGLE_BOT: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" YAHOO_SLURP: "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)" browser-6.2.0/test/middleware_test.rb0000644000004100000410000000245014731746717017734 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" require "browser/rails" require "sample_app" class MiddlewareTest < Minitest::Test include Rack::Test::Methods def app Rails.application end test "redirects with 302" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 6", "HTTP_ACCEPT" => "text/html" assert_equal 302, last_response.status end test "redirects ie6 to upgrade path" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 6", "HTTP_ACCEPT" => "text/html" follow_redirect! assert_equal "UPGRADE: ie6", last_response.body end test "redirects ie7 to upgrade path" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 7", "HTTP_ACCEPT" => "text/html" follow_redirect! assert_equal "UPGRADE: ie7", last_response.body end test "redirects ie8 and returns 404" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 8", "HTTP_ACCEPT" => "text/html" follow_redirect! assert_equal 404, last_response.status end test "redirects ie8 with wildcard http accept" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 8", "HTTP_ACCEPT" => "*/*" follow_redirect! assert_equal 404, last_response.status end test "ignores non-html requests" do get "/", {}, "HTTP_USER_AGENT" => "MSIE 6", "HTTP_ACCEPT" => "image/png" assert_equal 200, last_response.status end end browser-6.2.0/test/rails_test.rb0000644000004100000410000000162014731746717016727 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" require "browser/rails" require "sample_app" class RailsTest < Minitest::Test include Rack::Test::Methods def app Rails.application end test "renders page" do get "/home", {}, "HTTP_USER_AGENT" => Browser["CHROME"], "HTTP_ACCEPT" => "text/html", "HTTP_ACCEPT_LANGUAGE" => "en-US;q=0.8" assert_equal 200, last_response.status assert_equal "Chrome:en-US", last_response.body end test "renders json" do get "/api/pages", {}, "HTTP_USER_AGENT" => Browser["COMMONCRAWL"], "HTTP_ACCEPT" => "application/json", "HTTP_ACCEPT_LANGUAGE" => "en-US;q=0.8" assert_equal 200, last_response.status assert JSON.parse(last_response.body)["isBot"] assert_equal "en-US", JSON.parse(last_response.body)["acceptLanguages"][0] end end browser-6.2.0/test/unit/0000755000004100000410000000000014731746717015211 5ustar www-datawww-databrowser-6.2.0/test/unit/accept_language_test.rb0000644000004100000410000001341114731746717021677 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class AcceptLanguageTest < Minitest::Test def assert_language(item, expect = {}) assert_equal expect[:code], item.code, "failed code comparison" if expect[:region] assert_equal expect[:region], item.region, "failed region comparison" else assert_nil item.region, "region should be nil; got #{item.region.inspect} instead" end assert_equal expect[:quality], item.quality, "failed quality comparison" end test "returns full language" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "en-GB", language.full end test "returns language name" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "English/United Kingdom", language.name language = Browser::AcceptLanguage.new("en") assert_equal "English", language.name end test "returns nil for unknown languages" do language = Browser::AcceptLanguage.new("unknown") assert_nil language.name end test "returns code" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "en", language.code end test "returns formatted code" do %w[EN-GB En-GB eN-GB].each do |locale| language = Browser::AcceptLanguage.new(locale) assert_equal "en", language.code end end test "returns region" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "GB", language.region end test "returns formatted region" do %w[en-gb en-Gb en-gB].each do |locale| language = Browser::AcceptLanguage.new(locale) assert_equal "GB", language.region end end test "returns nil for language without region" do language = Browser::AcceptLanguage.new("en") assert_nil language.region end test "parses language with quality" do language = Browser::AcceptLanguage.new("en-GB;q=0.8") assert_language language, code: "en", region: "GB", quality: 0.8 end test "parses language without quality" do language = Browser::AcceptLanguage.new("en-GB") assert_language language, code: "en", region: "GB", quality: 1.0 end test "parses language without region" do language = Browser::AcceptLanguage.new("en") assert_language language, code: "en", region: nil, quality: 1.0 end test "ignores multi-part region" do language = Browser::AcceptLanguage.new("az-AZ-Cyrl") assert_language language, code: "az", region: "AZ", quality: 1.0 end test "parses multi-language set" do result = Browser::AcceptLanguage.parse("fr-CA,fr;q=0.8") assert_equal 2, result.count assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 end test "parses wildcard" do result = Browser::AcceptLanguage.parse("fr-CA,*;q=0.8") assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "*", region: nil, quality: 0.8 end test "parses complex set" do accept_language = "fr-CA,fr;q=0.8,en-US;q=0.6,en;q=0.4,*;q=0.1" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 assert_language result[2], code: "en", region: "US", quality: 0.6 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "*", region: nil, quality: 0.1 end test "handles random white spaces" do accept_language = "fr-CA, fr;q=0.8, en-US;q=0.6,en;q=0.4, *;q=0.1" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 assert_language result[2], code: "en", region: "US", quality: 0.6 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "*", region: nil, quality: 0.1 end test "sorts based on quality" do accept_language = "fr-CA,fr;q=0.2,en-US;q=0.6,en;q=0.4,*;q=0.5" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "en", region: "US", quality: 0.6 assert_language result[2], code: "*", region: nil, quality: 0.5 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "fr", region: nil, quality: 0.2 end test "sorts the same quality in a descending priority" do accept_language = "fr-CA,fr;q=0.2,en-US;q=0.2,en" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "en", region: nil, quality: 1.0 assert_language result[2], code: "fr", region: nil, quality: 0.2 assert_language result[3], code: "en", region: "US", quality: 0.2 end test "rejects quality values equals to zero (#241)" do result = Browser::AcceptLanguage.parse("de-DE,ru;q=0.9,de;q=0.8,en;q=0.") assert_equal 3, result.size assert_language result[0], code: "de", region: "DE", quality: 1.0 assert_language result[1], code: "ru", region: nil, quality: 0.9 assert_language result[2], code: "de", region: nil, quality: 0.8 end test "handles invalid quality values that look like a number" do accept_language = "fr-CH, fr;q=0.9, en;q=0.8, de;q=0..7, *;q=0.5" result = Browser::AcceptLanguage.parse(accept_language) assert_equal 5, result.size assert_language result[3], code: "de", region: nil, quality: 0.7 end test "sets default quality value for invalid strings" do result = Browser::AcceptLanguage.parse(";q=0.0.0.0") assert_equal 0.1, result[0].quality # rubocop:disable Minitest/AssertInDelta end end browser-6.2.0/test/unit/nokia_test.rb0000644000004100000410000000057214731746717017702 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class NokiaTest < Minitest::Test test "detects Nokia S40" do browser = Browser.new(Browser["NOKIA"]) assert browser.nokia? assert_equal "Nokia S40 Ovi Browser", browser.name end test "detects version by range" do browser = Browser.new(Browser["NOKIA"]) assert browser.nokia?(%w[>=2 <3]) end end browser-6.2.0/test/unit/aliases_test.rb0000644000004100000410000000162614731746717020223 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" require "browser/aliases" class AliasesTest < Minitest::Test class BrowserMock include Browser::Aliases def platform @platform ||= Object.new end def device @device ||= Object.new end end Browser::Aliases::PLATFORM_ALIASES.each do |method_name| test "adds #{method_name.inspect} as a platform alias" do browser = BrowserMock.new browser.platform.define_singleton_method(method_name) do :called end assert_equal :called, browser.public_send(method_name) end end Browser::Aliases::DEVICE_ALIASES.each do |method_name| test "adds #{method_name.inspect} as a device alias" do browser = BrowserMock.new browser.device.define_singleton_method(method_name) do :called end assert_equal :called, browser.public_send(method_name) end end end browser-6.2.0/test/unit/kindle_test.rb0000644000004100000410000000200214731746717020035 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class KindleTest < Minitest::Test test "detects kindle monochrome" do browser = Browser.new(Browser["KINDLE"]) assert browser.webkit? end test "detects kindle fire" do browser = Browser.new(Browser["KINDLE_FIRE"]) assert browser.webkit? browser = Browser.new(Browser["KINDLE_SILK_TABLET"]) assert browser.webkit? browser = Browser.new(Browser["KINDLE_SILK_DESKTOP"]) assert browser.webkit? browser = Browser.new(Browser["KINDLE_SILK_MOBILE"]) assert browser.webkit? browser = Browser.new(Browser["KINDLE_SILK_TABLET_1ST_GEN"]) assert browser.webkit? browser = Browser.new(Browser["KINDLE_SILK_MOBILE_1ST_GEN"]) assert browser.webkit? end test "detects kindle fire hd" do browser = Browser.new(Browser["KINDLE_FIRE_HD"]) assert browser.webkit? end test "detects kindle fire hd mobile" do browser = Browser.new(Browser["KINDLE_FIRE_HD_MOBILE"]) assert browser.webkit? end end browser-6.2.0/test/unit/android_test.rb0000644000004100000410000000617614731746717020227 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class AndroidTest < Minitest::Test test "detects android cupcake (1.5)" do browser = Browser.new(Browser["ANDROID_CUPCAKE"]) assert browser.platform.android? assert browser.platform.android?(1.5) end test "detects android donut (1.6)" do browser = Browser.new(Browser["ANDROID_DONUT"]) assert browser.platform.android? assert browser.platform.android?(1.6) end test "detects android eclair (2.1)" do browser = Browser.new(Browser["ANDROID_ECLAIR_21"]) assert browser.platform.android? assert browser.platform.android?(2.1) end test "detects android froyo (2.2)" do browser = Browser.new(Browser["ANDROID_FROYO"]) assert browser.platform.android? assert browser.platform.android?(2.2) end test "detects android gingerbread (2.3)" do browser = Browser.new(Browser["ANDROID_GINGERBREAD"]) assert browser.platform.android? assert browser.platform.android?("~> 2.3.0") end test "detects android honeycomb (3.0)" do browser = Browser.new(Browser["ANDROID_HONEYCOMB_30"]) assert browser.platform.android? assert browser.platform.android?("~> 3.0") end test "detects android ice cream sandwich (4.0)" do browser = Browser.new(Browser["ANDROID_ICECREAM"]) assert browser.platform.android? assert browser.platform.android?("~> 4.0") end test "detects android jellybean (4.1)" do browser = Browser.new(Browser["ANDROID_JELLYBEAN_41"]) assert browser.platform.android? assert browser.platform.android?("~> 4.1") end test "detects android jellybean (4.2)" do browser = Browser.new(Browser["ANDROID_JELLYBEAN_42"]) assert browser.platform.android? assert browser.platform.android?(4.2) end test "detects android jellybean (4.3)" do browser = Browser.new(Browser["ANDROID_JELLYBEAN_43"]) assert browser.platform.android? assert browser.platform.android?(4.3) end test "detects android kitkat (4.4)" do browser = Browser.new(Browser["ANDROID_KITKAT"]) assert browser.platform.android? assert browser.platform.android?(4.4) end test "detects android lollipop (5.0)" do browser = Browser.new(Browser["ANDROID_LOLLIPOP_50"]) assert browser.platform.android? assert browser.platform.android?(5.0) end test "detects android lollipop (5.1)" do browser = Browser.new(Browser["ANDROID_LOLLIPOP_51"]) assert browser.platform.android? assert browser.platform.android?(5.1) end test "detects android oreo (8.0)" do browser = Browser.new(Browser["ANDROID_OREO"]) assert browser.platform.android? assert browser.platform.android?(8.0) end test "detects android tv" do browser = Browser.new(Browser["ANDROID_TV"]) assert browser.platform.android? assert browser.device.tv? end test "detects nexus player" do browser = Browser.new(Browser["ANDROID_NEXUS_PLAYER"]) assert browser.platform.android? end test "detects firefox for android without android version" do browser = Browser.new(Browser["FIREFOX_ANDROID"]) assert browser.platform.android? refute browser.platform.android?(5) end end browser-6.2.0/test/unit/proxy_test.rb0000644000004100000410000000052214731746717017755 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class ProxyTest < Minitest::Test %w[ NOKIA OPERA_MINI UC_BROWSER ].each do |name| ua = Browser[name] test "detects #{name} as proxy" do browser = Browser.new(ua) assert browser.proxy? assert_includes browser.meta, "proxy" end end end browser-6.2.0/test/unit/kai_os_test.rb0000644000004100000410000000165314731746717020047 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class KaiOSTest < Minitest::Test test "detects KaiOS" do browser = Browser.new(Browser["NOKIA_8110"]) assert browser.firefox? assert_equal "48", browser.version assert_equal "48.0", browser.full_version assert_equal "Firefox", browser.name assert browser.platform.kai_os? assert_equal "KaiOS", browser.platform.name assert_equal "2.5", browser.platform.version refute browser.platform.android? end test "detects KaiOS with Android string in user-agent " do browser = Browser.new(Browser["JIOPHONE_2"]) assert browser.firefox? assert_equal "48", browser.version assert_equal "48.0", browser.full_version assert_equal "Firefox", browser.name assert browser.platform.kai_os? assert_equal "KaiOS", browser.platform.name assert_equal "2.5", browser.platform.version refute browser.platform.android? end end browser-6.2.0/test/unit/snapchat_test.rb0000644000004100000410000000221314731746717020374 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class SnapchatTest < Minitest::Test test "detects snapchat" do browser = Browser.new(Browser["SNAPCHAT"]) assert_equal "Snapchat", browser.name assert browser.snapchat? assert_equal :snapchat, browser.id assert_equal "10.69.5.72", browser.full_version assert_equal "10", browser.version end test "detects snapchat for badly formatted user agent" do browser = Browser.new(Browser["SNAPCHAT_EMPTY_STRING_VERSION"]) assert_equal "Snapchat", browser.name assert browser.snapchat? assert_equal :snapchat, browser.id assert_equal "10.70.0.0", browser.full_version assert_equal "10", browser.version end test "detects alternate snapchat user agent" do browser = Browser.new(Browser["SNAPCHAT_SPACE_VERSION"]) assert_equal "Snapchat", browser.name assert browser.snapchat? assert_equal :snapchat, browser.id assert_equal "10.70.0.0", browser.full_version assert_equal "10", browser.version end test "detects version by range" do browser = Browser.new(Browser["SNAPCHAT"]) assert browser.snapchat?(%w[>=10]) end end browser-6.2.0/test/unit/opera_test.rb0000644000004100000410000000246314731746717017710 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class OperaTest < Minitest::Test test "detects opera" do browser = Browser.new(Browser["OPERA"]) assert_equal "Opera", browser.name assert browser.opera? assert_equal "11.64", browser.full_version assert_equal "11", browser.version end test "detects opera next" do browser = Browser.new(Browser["OPERA_NEXT"]) assert_equal "Opera", browser.name assert_equal :opera, browser.id assert browser.opera? assert browser.webkit? refute browser.chrome? refute browser.safari? assert_equal "15.0.1147.44", browser.full_version assert_equal "15", browser.version end test "detects opera mini" do browser = Browser.new(Browser["OPERA_MINI"]) assert browser.opera_mini? end test "detects opera mini version by range" do browser = Browser.new(Browser["OPERA_MINI"]) assert browser.opera_mini?(%w[>=11 <12]) end test "detects opera mobi" do browser = Browser.new(Browser["OPERA_MOBI"]) assert browser.opera? end test "detects opera running in Android" do browser = Browser.new(Browser["OPERA_ANDROID"]) assert browser.platform.android? end test "detects version by range" do browser = Browser.new(Browser["OPERA"]) assert browser.opera?(%w[>=11 <12]) end end browser-6.2.0/test/unit/adobe_air_test.rb0000644000004100000410000000067014731746717020505 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class AdobeAirTest < Minitest::Test test "detects adobe air" do browser = Browser.new(Browser["ADOBE_AIR"]) assert browser.webkit? assert_equal "0", browser.version assert_equal "0.0", browser.full_version assert_equal "Unknown Browser", browser.name assert_equal "Adobe AIR", browser.platform.name assert_equal "13.0", browser.platform.version end end browser-6.2.0/test/unit/miui_browser_test.rb0000644000004100000410000000125614731746717021307 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class MiuiBrowserTest < Minitest::Test test "detects Miui Browser" do browser = Browser.new(Browser["MIUI_BROWSER"]) assert browser.miui_browser? refute browser.safari? refute browser.chrome? assert_equal "Miui Browser", browser.name assert_equal :miui_browser, browser.id end test "detects correct version" do browser = Browser.new(Browser["MIUI_BROWSER"]) assert_equal "12.3.3", browser.full_version assert_equal "12", browser.version end test "detects version by range" do browser = Browser.new(Browser["MIUI_BROWSER"]) assert browser.miui_browser?(%w[>=12 <13]) end end browser-6.2.0/test/unit/instagram_test.rb0000644000004100000410000000151114731746717020560 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class InstagramTest < Minitest::Test test "detects instagram" do browser = Browser.new(Browser["INSTAGRAM"]) assert_equal "Instagram", browser.name assert browser.instagram? assert_equal :instagram, browser.id assert_equal "41.0.0.14.90", browser.full_version assert_equal "41", browser.version end test "detects alternate instagram user agent" do browser = Browser.new(Browser["INSTAGRAM_OTHER"]) assert_equal "Instagram", browser.name assert browser.instagram? assert_equal :instagram, browser.id assert_equal "182257141", browser.full_version assert_equal "182257141", browser.version end test "detects version by range" do browser = Browser.new(Browser["INSTAGRAM"]) assert browser.instagram?(%w[>=41]) end end browser-6.2.0/test/unit/weibo_test.rb0000644000004100000410000000127014731746717017702 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class WeiboTest < Minitest::Test test "detects weibo iOS" do browser = Browser.new(Browser["WEIBO_IOS"]) assert_equal :weibo, browser.id assert browser.weibo? assert_equal "Weibo", browser.name assert_equal "5.7.1", browser.full_version end test "detects weibo Android" do browser = Browser.new(Browser["WEIBO_ANDROID"]) assert_equal :weibo, browser.id assert browser.weibo? assert_equal "Weibo", browser.name assert_equal "5.7.1", browser.full_version end test "detects version by range" do browser = Browser.new(Browser["WEIBO_IOS"]) assert browser.weibo?(%w[>=5 <6]) end end browser-6.2.0/test/unit/epiphany_test.rb0000644000004100000410000000104614731746717020413 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class EpiphanyBrowserTest < Minitest::Test test "detects epiphany browser" do browser = Browser.new(Browser["EPIPHANY"]) assert browser.epiphany? refute browser.safari? assert_equal "Epiphany", browser.name assert_equal :epiphany, browser.id assert_equal "3.18.11", browser.full_version assert_equal "3", browser.version end test "detects version by range" do browser = Browser.new(Browser["EPIPHANY"]) assert browser.epiphany?(%w[=3.18.11]) end end browser-6.2.0/test/unit/facebook_test.rb0000644000004100000410000000217414731746717020352 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class FacebookTest < Minitest::Test test "detects facebook" do browser = Browser.new(Browser["FACEBOOK"]) assert_equal "Facebook", browser.name assert browser.facebook? assert_equal :facebook, browser.id assert_equal "135.0.0.45.90", browser.full_version assert_equal "135", browser.version end test "detects new facebook on iOS" do browser = Browser.new(Browser["FACEBOOK_IOS"]) assert_equal "Facebook", browser.name assert browser.facebook? assert_equal :facebook, browser.id assert_equal "AppleWebKit/605.1.15", browser.full_version assert_equal "AppleWebKit/605", browser.version end test "detects new facebook on Android" do browser = Browser.new(Browser["FACEBOOK_ANDROID"]) assert_equal "Facebook", browser.name assert browser.facebook? assert_equal :facebook, browser.id assert_equal "214.0.0.43.83", browser.full_version assert_equal "214", browser.version end test "detects version by range" do browser = Browser.new(Browser["FACEBOOK"]) assert browser.facebook?(%w[>=135]) end end browser-6.2.0/test/unit/meta_test.rb0000644000004100000410000000253714731746717017532 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class MetaTest < Minitest::Test class CustomRule < Browser::Meta::Base def meta "custom" if browser.ua.include?("Custom") end end test "extends rules" do Browser::Meta.rules.unshift(CustomRule) browser = Browser.new("Custom") assert_includes browser.meta, "custom" browser = Browser.new("Safari") refute_includes browser.meta, "custom" Browser::Meta.rules.shift browser = Browser.new("Custom") refute_includes browser.meta, "custom" end test "sets meta" do browser = Browser.new(Browser["CHROME"]) assert_kind_of Array, browser.meta end test "returns string representation" do browser = Browser.new(Browser["CHROME"]) meta = browser.to_s assert_includes meta, "chrome" assert_includes meta, "webkit" assert_includes meta, "mac" end test "returns string representation for mobile" do browser = Browser.new(Browser["BLACKBERRY"]) meta = browser.to_s assert_includes meta, "blackberry" assert_includes meta, "mobile" end test "returns string representation for unknown platform/device/browser" do browser = Browser.new("Unknown") meta = browser.to_s assert_includes meta, "unknown_platform" assert_includes meta, "unknown_device" assert_includes meta, "unknown_browser" end end browser-6.2.0/test/unit/yandex_test.rb0000644000004100000410000000205114731746717020063 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class YandexTest < Minitest::Test test "detects Yandex on iOS device" do browser = Browser.new(Browser["YANDEX_BROWSER_IOS"]) assert browser.yandex? assert browser.yandex_browser? refute browser.safari? refute browser.chrome? assert browser.webkit? assert_equal "Yandex", browser.name assert_equal :yandex, browser.id end test "detects Yandex on non-iOS devices" do browser = Browser.new(Browser["YANDEX_BROWSER_DESKTOP"]) assert browser.yandex? assert browser.yandex_browser? refute browser.safari? refute browser.chrome? assert_equal "Yandex", browser.name assert_equal :yandex, browser.id end test "detects correct version" do browser = Browser.new(Browser["YANDEX_BROWSER_DESKTOP"]) assert_equal "19.6.0.1583", browser.full_version assert_equal "19", browser.version end test "detects version by range" do browser = Browser.new(Browser["YANDEX_BROWSER_DESKTOP"]) assert browser.yandex?(%w[>=18 <20]) end end browser-6.2.0/test/unit/uc_browser_test.rb0000644000004100000410000000061014731746717020744 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class UcBrowserTest < Minitest::Test test "detects UC Browser" do browser = Browser.new(Browser["UC_BROWSER"]) assert browser.uc_browser? assert_equal "UCBrowser", browser.name end test "detects version by range" do browser = Browser.new(Browser["UC_BROWSER"]) assert browser.uc_browser?(%w[>=9 <10]) end end browser-6.2.0/test/unit/google_search_app_test.rb0000644000004100000410000000327514731746717022245 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class GoogleSearchAppTest < Minitest::Test test "detects Google Search App (Android)" do browser = Browser.new(Browser["GOOGLE_SEARCH_APP_ANDROID"]) assert browser.webkit? assert browser.google_search_app? assert browser.platform.android? assert_equal :google_search_app, browser.id assert_equal "11", browser.version assert_equal "11.6.8.21", browser.full_version assert_equal "Google Search App", browser.name refute browser.chrome? refute browser.safari? end test "detects Google Search App (iPad)" do browser = Browser.new(Browser["GOOGLE_SEARCH_APP_IPAD"]) assert browser.webkit? assert browser.google_search_app? assert browser.device.ipad? assert browser.platform.ios? assert_equal :google_search_app, browser.id assert_equal "102", browser.version assert_equal "102.0.304944559", browser.full_version assert_equal "Google Search App", browser.name refute browser.chrome? refute browser.safari? end test "detects Google Search App (iPhone)" do browser = Browser.new(Browser["GOOGLE_SEARCH_APP_IPHONE"]) assert browser.webkit? assert browser.google_search_app? assert browser.device.iphone? assert browser.platform.ios? assert_equal :google_search_app, browser.id assert_equal "105", browser.version assert_equal "105.0.307913796", browser.full_version assert_equal "Google Search App", browser.name refute browser.chrome? refute browser.safari? end test "detects version by range (iPad)" do browser = Browser.new(Browser["GOOGLE_SEARCH_APP_IPAD"]) assert browser.google_search_app?(%w[>=102 <103]) end end browser-6.2.0/test/unit/maxthon_test.rb0000644000004100000410000000120314731746717020247 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class MaxthonTest < Minitest::Test test "detects Maxthon" do browser = Browser.new(Browser["MAXTHON"]) assert browser.maxthon? refute browser.safari? refute browser.chrome? assert_equal "Maxthon", browser.name assert_equal :maxthon, browser.id end test "detects correct version" do browser = Browser.new(Browser["MAXTHON"]) assert_equal "5.3.8.2000", browser.full_version assert_equal "5", browser.version end test "detects version by range" do browser = Browser.new(Browser["MAXTHON"]) assert browser.maxthon?(%w[>=5 <6]) end end browser-6.2.0/test/unit/edge_test.rb0000644000004100000410000000646114731746717017510 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class EdgeTest < ActionController::TestCase test "detects Microsoft Edge" do browser = Browser.new(Browser["MS_EDGE"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "12.0", browser.full_version assert_equal "12", browser.version assert browser.platform.windows10? assert browser.edge? refute browser.webkit? refute browser.chrome? refute browser.safari? refute browser.device.mobile? refute browser.chromium_based? end test "detects Microsoft Edge in compatibility view" do browser = Browser.new(Browser["MS_EDGE_COMPAT"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "12.0", browser.full_version assert_equal "12", browser.version assert_equal "7.0", browser.msie_full_version assert_equal "7", browser.msie_version assert browser.edge? assert browser.compatibility_view? refute browser.webkit? refute browser.chrome? refute browser.safari? refute browser.device.mobile? refute browser.chromium_based? end test "detects Microsoft Edge Mobile" do browser = Browser.new(Browser["MS_EDGE_MOBILE"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "12.0", browser.full_version assert_equal "12", browser.version refute browser.platform.windows10? assert browser.platform.windows_phone? assert browser.edge? refute browser.webkit? refute browser.chrome? refute browser.safari? refute browser.chromium_based? end test "detects Microsoft Edge based on Chrome" do browser = Browser.new(Browser["MS_EDGE_CHROME"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "79.0.309.18", browser.full_version assert_equal "79", browser.version assert browser.platform.mac? assert browser.chromium_based? refute browser.platform.windows? assert browser.edge? assert browser.webkit? refute browser.chrome? refute browser.safari? end test "detects Microsoft Edge Mobile on iOS" do browser = Browser.new(Browser["MS_EDGE_IOS"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "44.5.0.10", browser.full_version assert_equal "44", browser.version refute browser.platform.windows10? refute browser.platform.windows_phone? assert browser.platform.ios? assert browser.edge? refute browser.webkit? refute browser.chrome? refute browser.safari? refute browser.chromium_based? end test "detects Microsoft Edge Mobile on Android" do browser = Browser.new(Browser["MS_EDGE_ANDROID"]) assert_equal :edge, browser.id assert_equal "Microsoft Edge", browser.name assert_equal "44.11.2.4122", browser.full_version assert_equal "44", browser.version refute browser.platform.windows10? refute browser.platform.windows_phone? assert browser.platform.android? assert browser.edge? refute browser.webkit? refute browser.chrome? refute browser.safari? refute browser.chromium_based? end test "detects version by range" do browser = Browser.new(Browser["MS_EDGE_IOS"]) assert browser.edge?(%w[>=43 <45]) end end browser-6.2.0/test/unit/samsung_browser_test.rb0000644000004100000410000000120214731746717022010 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class SamsungBrowserTest < Minitest::Test test "detects samsung browser" do browser = Browser.new(Browser["SAMSUNG_BROWSER"]) assert browser.webkit? assert browser.samsung_browser? assert_equal "11", browser.version assert_equal :samsung_browser, browser.id assert_equal "11.1", browser.full_version assert_equal "Samsung Browser", browser.name refute browser.chrome? refute browser.safari? end test "detects version by range" do browser = Browser.new(Browser["SAMSUNG_BROWSER"]) assert browser.samsung_browser?(%w[>=11 <12]) end end browser-6.2.0/test/unit/alipay_test.rb0000644000004100000410000000147214731746717020060 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class AlipayTest < Minitest::Test test "detects alipay iOS" do browser = Browser.new(Browser["ALIPAY_IOS"]) assert_equal :alipay, browser.id assert browser.alipay? assert_equal "Alipay", browser.name assert_equal "2.3.4", browser.full_version refute browser.chrome? refute browser.safari? end test "detects alipay Android" do browser = Browser.new(Browser["ALIPAY_ANDROID"]) assert_equal :alipay, browser.id assert browser.alipay? assert_equal "Alipay", browser.name assert_equal "9.0.1.073001", browser.full_version refute browser.chrome? refute browser.safari? end test "detects version by range" do browser = Browser.new(Browser["ALIPAY_IOS"]) assert browser.alipay?(%w[>=2 <3]) end end browser-6.2.0/test/unit/duck_duck_go_test.rb0000644000004100000410000000207314731746717021220 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class DuckDuckGoTest < Minitest::Test test "detects DuckDuckGo on iOS device" do browser = Browser.new(Browser["DUCKDUCKGO_BROWSER_IOS"]) assert browser.duck_duck_go? refute browser.safari? refute browser.chrome? assert browser.webkit? refute browser.bot? assert_equal "DuckDuckGo", browser.name assert_equal :duckduckgo, browser.id end test "detects DuckDuckGo on Android device" do browser = Browser.new(Browser["DUCKDUCKGO_BROWSER_ANDROID"]) assert browser.duck_duck_go? refute browser.safari? refute browser.chrome? refute browser.bot? assert_equal "DuckDuckGo", browser.name assert_equal :duckduckgo, browser.id end test "detects correct version" do browser = Browser.new(Browser["DUCKDUCKGO_BROWSER_IOS"]) assert_equal "7", browser.full_version assert_equal "7", browser.version end test "detects version by range" do browser = Browser.new(Browser["DUCKDUCKGO_BROWSER_IOS"]) assert browser.duck_duck_go?(%w[>=7 <8]) end end browser-6.2.0/test/unit/sputnik_test.rb0000644000004100000410000000105314731746717020271 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class SputnikTest < Minitest::Test test "detects sputnik" do browser = Browser.new(Browser["SPUTNIK"]) assert_equal "Sputnik", browser.name assert_equal :sputnik, browser.id assert browser.sputnik? refute browser.chrome? refute browser.safari? assert_equal "4.1.2801.0", browser.full_version assert_equal "4", browser.version end test "detects version by range" do browser = Browser.new(Browser["SPUTNIK"]) assert browser.sputnik?(%w[>=4 <5]) end end browser-6.2.0/test/unit/console_test.rb0000644000004100000410000000053214731746717020237 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class ConsoleTest < Minitest::Test test "detects psp" do browser = Browser.new(Browser["PSP"]) assert_equal "Unknown Browser", browser.name end test "detects psp vita" do browser = Browser.new(Browser["PSP_VITA"]) assert_equal "Unknown Browser", browser.name end end browser-6.2.0/test/unit/huawei_browser_test.rb0000644000004100000410000000130414731746717021620 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class HuaweiBrowserTest < Minitest::Test test "detects Huawei Browser" do browser = Browser.new(Browser["HUAWEI_BROWSER"]) assert browser.huawei_browser? refute browser.safari? refute browser.chrome? assert_equal "Huawei Browser", browser.name assert_equal :huawei_browser, browser.id end test "detects correct version" do browser = Browser.new(Browser["HUAWEI_BROWSER"]) assert_equal "10.1.2.300", browser.full_version assert_equal "10", browser.version end test "detects version by range" do browser = Browser.new(Browser["HUAWEI_BROWSER"]) assert browser.huawei_browser?(%w[>=10 <11]) end end browser-6.2.0/test/unit/chrome_test.rb0000644000004100000410000000413314731746717020053 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class ChromeTest < Minitest::Test test "detects chrome" do browser = Browser.new(Browser["CHROME"]) assert_equal "Chrome", browser.name assert browser.chrome? refute browser.safari? assert browser.webkit? assert_equal "5.0.375.99", browser.full_version assert_equal "5", browser.version assert browser.chromium_based? end test "detects mobile chrome" do browser = Browser.new(Browser["MOBILE_CHROME"]) assert_equal "Chrome", browser.name assert browser.chrome? refute browser.safari? assert browser.webkit? assert_equal "19.0.1084.60", browser.full_version assert_equal "19", browser.version end test "detects chrome in desktop mode" do browser = Browser.new(Browser["CHROME_REQUEST_DESKTOP_SITE"]) assert browser.chromium_based? assert browser.chrome? end test "detects samsung chrome" do browser = Browser.new(Browser["SAMSUNG_CHROME"]) assert_equal "Chrome", browser.name assert browser.chrome? assert browser.platform.android? refute browser.safari? assert browser.webkit? assert_equal "28.0.1500.94", browser.full_version assert_equal "28", browser.version end test "detects chrome os" do browser = Browser.new(Browser["CHROME_OS"]) assert browser.platform.chrome_os? end test "detects chrome frame" do browser = Browser.new(Browser["IE9_CHROME_FRAME"]) assert browser.chrome? refute browser.safari? assert browser.webkit? assert_equal "26.0.1410.43", browser.full_version assert_equal "26", browser.version end test "detects chrome not opera when android build number contains 'OPR'" do browser = Browser.new(Browser["ANDROID_OREO"]) assert browser.chrome? end test "detects chrome on android 10" do browser = Browser.new(Browser["ANDROID_Q"]) assert browser.chrome? assert_equal "Chrome", browser.name assert_equal "78", browser.version end test "detects version by range" do browser = Browser.new(Browser["CHROME"]) assert browser.chrome?(%w[>=5 <6]) end end browser-6.2.0/test/unit/bots_test.rb0000644000004100000410000000635014731746717017550 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class BotsTest < Minitest::Test Browser.bot_user_agents.each do |key, ua| test "detects #{key} as bot" do browser = Browser.new(ua) assert browser.bot? end end test "does not detect as bot" do browser = Browser.new(Browser["CHROME"]) refute browser.bot? end test "returns bot name" do browser = Browser.new(Browser["GOOGLE_BOT"]) assert_equal "Google Bot", browser.bot.name browser = Browser.new(Browser["FACEBOOK_BOT"]) assert_equal "Facebook Bot", browser.bot.name end test "returns nil for non-bots" do browser = Browser.new(Browser["CHROME"]) assert_nil browser.bot.name end Browser.search_engine_user_agents.each do |key, ua| test "detects #{key} as search engine" do browser = Browser.new(ua) assert browser.bot.search_engine? end end test "detects Daumoa" do browser = Browser.new(Browser["DAUMOA"]) assert_equal :ie, browser.id assert_equal "Internet Explorer", browser.name assert_equal "0.0", browser.msie_full_version assert_equal "0", browser.msie_version assert_equal "0.0", browser.full_version assert_equal "0", browser.version assert browser.ie? assert browser.bot? refute browser.platform.windows10? refute browser.platform.windows_phone? refute browser.edge? refute browser.device.mobile? refute browser.webkit? refute browser.chrome? refute browser.safari? end test "handles custom android user agent (#144)" do browser = Browser.new(Browser["CUSTOM_APP"]) assert browser.platform.android? refute browser.bot? end test "extends list in runtime" do browser = Browser.new("Faraday/0.9.2") refute browser.bot? Browser::Bot.bots["faraday"] = "Faraday" assert browser.bot? Browser::Bot.bots.delete("faraday") end test "detects recognized bots using common libs" do browser = Browser.new(Browser.bot_user_agents["LINKEDIN"]) assert browser.bot? assert_equal "LinkedIn", browser.bot.name end test "tells why user agent is considered a bot" do matcher = Browser::Bot.why?(Browser.bot_user_agents["LINKEDIN"]) assert_equal Browser::Bot::KnownBotsMatcher, matcher end test "adds custom bot matcher" do Browser::Bot.matchers << ->(ua, _) { ua.include?("some-script") } browser = Browser.new("some-script") assert browser.bot? assert_equal "Generic Bot", browser.bot.name end %w[ content-fetcher content-crawler some-search-engine monitoring-service content-spider some-bot ].each do |ua| test "detects user agents based on keywords (#{ua})" do browser = Browser.new(ua) assert browser.bot? assert_equal Browser::Bot::KeywordMatcher, browser.bot.why? end end test "extends lists" do Browser::Bot.bots["another-bot"] = "Another bot" Browser::Bot.bot_exceptions.push("exclude-this-bot") Browser::Bot.search_engines["new-search-engine"] = "New search engine" assert_equal "Another bot", Browser::Bot.bots["another-bot"] assert_includes Browser::Bot.bot_exceptions, "exclude-this-bot" assert_equal "New search engine", Browser::Bot.search_engines["new-search-engine"] end end browser-6.2.0/test/unit/ios_app_test.rb0000644000004100000410000000055614731746717020235 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class IosAppTest < Minitest::Test let(:browser) { Browser.new(Browser["IOS_WEBVIEW"]) } test "detects as ios" do assert browser.platform.ios? end test "does not detect as safari" do refute browser.safari? end test "detects as webview" do assert browser.platform.ios_webview? end end browser-6.2.0/test/unit/sougou_browser_test.rb0000644000004100000410000000242414731746717021663 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class SougouBrowserTest < Minitest::Test test "detects Sougou Browser on desktop device" do browser = Browser.new(Browser["SOUGOU_BROWSER"]) assert browser.sougou_browser? refute browser.safari? refute browser.chrome? assert_equal "Sougou Browser", browser.name assert_equal :sougou_browser, browser.id end test "detects correct version on desktop device" do browser = Browser.new(Browser["SOUGOU_BROWSER"]) assert_equal "0.0", browser.full_version assert_equal "0", browser.version end test "detects Sougou Browser on mobile device" do browser = Browser.new(Browser["SOUGOU_BROWSER_MOBILE"]) assert browser.sougou_browser? assert browser.device.mobile? refute browser.safari? refute browser.chrome? assert_equal "Sougou Browser", browser.name assert_equal :sougou_browser, browser.id end test "detects correct version on mobile device" do browser = Browser.new(Browser["SOUGOU_BROWSER_MOBILE"]) assert_equal "5.28.12", browser.full_version assert_equal "5", browser.version end test "detects version by range on mobile device" do browser = Browser.new(Browser["SOUGOU_BROWSER_MOBILE"]) assert browser.sougou_browser?(%w[>=5 <6]) end end browser-6.2.0/test/unit/platform_test.rb0000644000004100000410000001506414731746717020427 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class PlatformTest < Minitest::Test class CustomPlatform < Browser::Platform::Base def match? ua.include?("Custom") end def id :custom end end test "extends matchers" do Browser::Platform.matchers.unshift(CustomPlatform) platform = Browser::Platform.new("Custom") assert_equal :custom, platform.id Browser::Platform.matchers.shift platform = Browser::Platform.new("Custom") assert_equal :unknown_platform, platform.id end test "implements to_s" do platform = Browser::Platform.new(Browser["IOS9"]) assert_equal "ios", platform.to_s end test "implements ==" do platform = Browser::Platform.new(Browser["IOS9"]) assert_operator platform, :==, :ios # rubocop:disable Minitest/AssertEqual refute_equal platform, :android end test "detects unknown platforms" do platform = Browser::Platform.new("Unknown") assert_equal "Unknown", platform.name assert_equal :unknown_platform, platform.id assert_equal "0", platform.version assert platform.unknown? end test "detects ios (iPhone)" do platform = Browser::Platform.new(Browser["IOS4"]) assert_equal "iOS (iPhone)", platform.name assert_equal :ios, platform.id assert platform.ios? assert_equal "4", platform.version end test "detects ios (iPad)" do platform = Browser::Platform.new(Browser["IOS9"]) assert_equal "iOS (iPad)", platform.name assert_equal :ios, platform.id assert platform.ios? assert_equal "9", platform.version end test "detects specific minor iOS (iPhone)" do platform = Browser::Platform.new(Browser["IOS8_3"]) assert_equal "iOS (iPhone)", platform.name assert_equal :ios, platform.id assert platform.ios? assert platform.ios?(8.3) assert_equal "8.3", platform.version end test "detects specific patch iOS (iPhone)" do platform = Browser::Platform.new(Browser["IOS8_1_2"]) assert_equal "iOS (iPhone)", platform.name assert_equal :ios, platform.id assert platform.ios? assert platform.ios?("8.1.2") assert platform.ios?("<8.2") assert_equal "8.1.2", platform.version end test "detects ios (iPod Touch)" do platform = Browser::Platform.new(Browser["IPOD"]) assert_equal "iOS (iPod)", platform.name assert_equal :ios, platform.id assert platform.ios? assert_equal "0", platform.version end test "detects linux" do platform = Browser::Platform.new(Browser["FIREFOX"]) assert_equal "Generic Linux", platform.name assert_equal :linux, platform.id assert platform.linux? assert_equal "0", platform.version end test "detects mac" do platform = Browser::Platform.new(Browser["SAFARI"]) assert_equal "Mac OS X", platform.name assert_equal :mac, platform.id assert platform.mac? assert_equal "10.6.4", platform.version assert platform.mac?(["=10.6.4"]) end test "returns stub version for Mac user agent without version" do platform = Browser::Platform.new("Macintosh") assert_equal "0", platform.version end test "detects mac names" do assert_equal "Mac OS X", Browser::Platform.new(Browser["MAC_OSX"]).name assert_equal "macOS", Browser::Platform.new(Browser["MAC_OS"]).name end test "detects firefox os" do platform = Browser::Platform.new(Browser["FIREFOX_OS"]) assert_equal "Firefox OS", platform.name assert_equal :firefox_os, platform.id assert platform.firefox_os? assert_equal "0", platform.version end test "detects windows phone" do platform = Browser::Platform.new(Browser["MS_EDGE_MOBILE"]) assert_equal "Windows Phone", platform.name assert_equal :windows_phone, platform.id assert platform.windows_phone? assert_equal "10.0", platform.version end test "detects windows mobile" do platform = Browser::Platform.new(Browser["WINDOWS_MOBILE"]) assert_equal "Windows Mobile", platform.name assert_equal :windows_mobile, platform.id assert platform.windows_mobile? assert_equal "0", platform.version end test "detects blackberry 10" do platform = Browser::Platform.new(Browser["BLACKBERRY10"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "10.0.9.1675", platform.version end test "detects blackberry 4" do platform = Browser::Platform.new(Browser["BLACKBERRY4"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "4.2.1", platform.version end test "detects blackberry 4 (other)" do platform = Browser::Platform.new(Browser["BLACKBERRY"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "4.1.0", platform.version end test "detects blackberry 5" do platform = Browser::Platform.new(Browser["BLACKBERRY5"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "5.0.0.93", platform.version end test "detects blackberry 6" do platform = Browser::Platform.new(Browser["BLACKBERRY6"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "6.0.0.141", platform.version end test "detects blackberry 7" do platform = Browser::Platform.new(Browser["BLACKBERRY7"]) assert_equal "BlackBerry", platform.name assert_equal :blackberry, platform.id assert platform.blackberry? assert_equal "7.0.0.1", platform.version end test "detects android" do platform = Browser::Platform.new(Browser["ANDROID_CUPCAKE"]) assert_equal "Android", platform.name assert_equal :android, platform.id assert platform.android? assert_equal "1.5", platform.version end test "detects chrome os" do platform = Browser::Platform.new(Browser["CHROME_OS"]) assert_equal "Chrome OS", platform.name assert_equal :chrome_os, platform.id assert platform.chrome_os? assert platform.chrome_os?(%w[>=3701 <3702]) assert_equal "3701.81.0", platform.version end test "detects adobe air" do platform = Browser::Platform.new(Browser["ADOBE_AIR"]) assert platform.adobe_air? assert platform.adobe_air?(%w[>=13 <14]) end test "implements default match?" do matcher_class = Class.new(Browser::Platform::Base) Browser::Platform.matchers.unshift(matcher_class) platform = Browser::Platform.new("") assert platform.unknown? end end browser-6.2.0/test/unit/otter_test.rb0000644000004100000410000000076114731746717017736 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class OtterBrowserTest < Minitest::Test test "detects Otter Browser" do browser = Browser.new(Browser["OTTER"]) assert browser.otter? assert_equal "Otter", browser.name assert_equal :otter, browser.id assert_equal "0.9.91", browser.full_version assert_equal "0", browser.version end test "detects version by range" do browser = Browser.new(Browser["OTTER"]) assert browser.otter?(%w[=0.9.91]) end end browser-6.2.0/test/unit/micro_messenger_test.rb0000644000004100000410000000204714731746717021761 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class MicroMessengerTest < Minitest::Test test "detects micro messenger 7.0.10 on iOS" do browser = Browser.new(Browser["MICRO_MESSENGER_IOS"]) assert browser.micro_messenger? assert browser.wechat? assert_equal "7.0.10", browser.full_version assert_equal "MicroMessenger", browser.name assert_equal :micro_messenger, browser.id end test "detects version by range on iOS" do browser = Browser.new(Browser["MICRO_MESSENGER_IOS"]) assert browser.wechat?(%w[>=7 <8]) end test "detects micro messenger 7.0.13.1640 on Android" do browser = Browser.new(Browser["MICRO_MESSENGER_ANDROID"]) assert browser.micro_messenger? assert browser.wechat? assert_equal "7.0.13.1640", browser.full_version assert_equal "MicroMessenger", browser.name assert_equal :micro_messenger, browser.id end test "detects version by range on Android" do browser = Browser.new(Browser["MICRO_MESSENGER_ANDROID"]) assert browser.wechat?(%w[>=7 <8]) end end browser-6.2.0/test/unit/electron_test.rb0000644000004100000410000000051714731746717020413 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class ElectronTest < Minitest::Test test "detects electron" do browser = Browser.new(Browser["ELECTRON"]) assert_equal "Electron", browser.name assert browser.electron? assert_equal :electron, browser.id assert_equal "1.4.12", browser.full_version end end browser-6.2.0/test/unit/internet_explorer_test.rb0000644000004100000410000002071514731746717022352 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class IeTest < Minitest::Test test "detects ie6" do browser = Browser.new(Browser["IE6"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(6) assert_equal "6.0", browser.full_version assert_equal "6", browser.version end test "detects ie7" do browser = Browser.new(Browser["IE7"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(7) assert_equal "7.0", browser.full_version assert_equal "7", browser.version end test "detects ie8" do browser = Browser.new(Browser["IE8"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(8) refute browser.compatibility_view? assert_equal "8.0", browser.full_version assert_equal "8", browser.version end test "detects ie8 in compatibility view" do browser = Browser.new(Browser["IE8_COMPAT"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(8) assert browser.compatibility_view? assert_equal "8.0", browser.full_version assert_equal "8", browser.version assert_equal "7.0", browser.msie_full_version assert_equal "7", browser.msie_version end test "detects ie9" do browser = Browser.new(Browser["IE9"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(9) refute browser.compatibility_view? assert_equal "9.0", browser.full_version assert_equal "9", browser.version end test "detects ie9 in compatibility view" do browser = Browser.new(Browser["IE9_COMPAT"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(9) assert browser.compatibility_view? assert_equal "9.0", browser.full_version assert_equal "9", browser.version assert_equal "7.0", browser.msie_full_version assert_equal "7", browser.msie_version end test "detects ie10" do browser = Browser.new(Browser["IE10"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(10) refute browser.compatibility_view? assert_equal "10.0", browser.full_version assert_equal "10", browser.version end test "detects ie10 in compatibility view" do browser = Browser.new(Browser["IE10_COMPAT"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(10) assert browser.compatibility_view? assert_equal "10.0", browser.full_version assert_equal "10", browser.version assert_equal "7.0", browser.msie_full_version assert_equal "7", browser.msie_version end test "detects ie11" do browser = Browser.new(Browser["IE11"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(11) refute browser.compatibility_view? assert_equal "11.0", browser.full_version assert_equal "11", browser.version end test "detects ie11 in compatibility view" do browser = Browser.new(Browser["IE11_COMPAT"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(11) assert browser.compatibility_view? assert_equal "11.0", browser.full_version assert_equal "11", browser.version assert_equal "7.0", browser.msie_full_version assert_equal "7", browser.msie_version end test "detects Lumia 800" do browser = Browser.new(Browser["LUMIA800"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(9) assert_equal "9.0", browser.full_version assert_equal "9", browser.version end test "detects ie11 touch desktop pc" do browser = Browser.new(Browser["IE11_TOUCH_SCREEN"]) assert_equal "Internet Explorer", browser.name assert browser.ie? assert browser.ie?(11) refute browser.compatibility_view? refute browser.platform.windows_rt? assert browser.platform.windows_touchscreen_desktop? assert browser.platform.windows8? assert_equal "11.0", browser.full_version assert_equal "11", browser.version end test "detects IE without Trident" do browser = Browser.new(Browser["IE_WITHOUT_TRIDENT"]) assert_equal :ie, browser.id assert_equal "Internet Explorer", browser.name assert_equal "0.0", browser.msie_full_version assert_equal "0", browser.msie_version assert_equal "0.0", browser.full_version assert_equal "0", browser.version refute browser.platform.windows10? refute browser.platform.windows_phone? refute browser.edge? refute browser.device.mobile? refute browser.webkit? refute browser.chrome? refute browser.safari? end test "detects windows phone" do browser = Browser.new(Browser["WINDOWS_PHONE"]) assert browser.ie? assert_equal "7", browser.version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows phone 8" do browser = Browser.new(Browser["WINDOWS_PHONE8"]) assert browser.ie? assert_equal "10", browser.version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows phone 8.1" do browser = Browser.new(Browser["WINDOWS_PHONE_81"]) assert browser.ie? assert_equal "Internet Explorer", browser.name assert_equal :ie, browser.id assert_equal "11", browser.version assert_equal "11.0", browser.full_version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows mobile (windows phone 8)" do browser = Browser.new(Browser["WINDOWS_PHONE8"]) assert browser.ie? assert_equal "10", browser.version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows x64" do browser = Browser.new(Browser["IE10_X64_WINX64"]) assert browser.platform.windows_x64? refute browser.platform.windows_wow64? assert browser.platform.windows_x64_inclusive? end test "detects windows wow64" do browser = Browser.new(Browser["WINDOWS_WOW64"]) refute browser.platform.windows_x64? assert browser.platform.windows_wow64? assert browser.platform.windows_x64_inclusive? end test "detects windows platform" do browser = Browser.new("Windows") assert_equal :windows, browser.platform.id assert browser.platform.windows? end test "detects windows_xp" do browser = Browser.new(Browser["WINDOWS_XP"]) assert browser.platform.windows? assert browser.platform.windows_xp? end test "detects windows_vista" do browser = Browser.new(Browser["WINDOWS_VISTA"]) assert browser.platform.windows? assert browser.platform.windows_vista? end test "detects windows7" do browser = Browser.new(Browser["WINDOWS7"]) assert browser.platform.windows? assert browser.platform.windows7? end test "detects windows8" do browser = Browser.new(Browser["WINDOWS8"]) assert browser.platform.windows? assert browser.platform.windows8? refute browser.platform.windows8_1? end test "detects windows8.1" do browser = Browser.new(Browser["WINDOWS81"]) assert browser.platform.windows? assert browser.platform.windows8? assert browser.platform.windows8_1? end test "returns string representation for ie6" do browser = Browser.new(Browser["IE6"]) meta = browser.meta assert_includes meta, "ie" assert_includes meta, "ie6" assert_includes meta, "oldie" assert_includes meta, "lt-ie8" assert_includes meta, "lt-ie9" assert_includes meta, "windows" end test "returns string representation for ie7" do browser = Browser.new(Browser["IE7"]) meta = browser.meta assert_includes meta, "ie" assert_includes meta, "ie7" assert_includes meta, "oldie" assert_includes meta, "lt-ie8" assert_includes meta, "lt-ie9" assert_includes meta, "windows" end test "returns string representation for ie8" do browser = Browser.new(Browser["IE8"]) meta = browser.meta assert_includes meta, "ie" assert_includes meta, "ie8" assert_includes meta, "lt-ie9" assert_includes meta, "windows" end test "does not detect as two different versions" do browser = Browser.new(Browser["IE8"]) assert browser.ie?(8) refute browser.ie?(7) end test "handles more complex versioning check" do browser = Browser.new(Browser["IE8"]) assert browser.ie?(["> 7", "< 9"]) end end browser-6.2.0/test/unit/windows_phone_test.rb0000644000004100000410000000170414731746717021462 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class WindowPhoneTest < Minitest::Test test "detects windows phone" do browser = Browser.new(Browser["WINDOWS_PHONE"]) assert browser.ie? assert_equal "7", browser.version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows phone 8" do browser = Browser.new(Browser["WINDOWS_PHONE8"]) assert browser.ie? assert_equal "10", browser.version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end test "detects windows phone 8.1" do browser = Browser.new(Browser["WINDOWS_PHONE_81"]) assert browser.ie? assert_equal "Internet Explorer", browser.name assert_equal :ie, browser.id assert_equal "11", browser.version assert_equal "11.0", browser.full_version assert browser.platform.windows_phone? refute browser.platform.windows_mobile? end end browser-6.2.0/test/unit/windows_test.rb0000644000004100000410000000616414731746717020276 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class WindowsTest < Minitest::Test test "detects windows x64" do browser = Browser.new(Browser["IE10_X64_WINX64"]) assert browser.platform.windows_x64? refute browser.platform.windows_wow64? assert browser.platform.windows_x64_inclusive? assert_equal "6.2", browser.platform.version end test "detects windows wow64" do browser = Browser.new(Browser["WINDOWS_WOW64"]) refute browser.platform.windows_x64? assert browser.platform.windows_wow64? assert browser.platform.windows_x64_inclusive? assert_equal "6.3", browser.platform.version end test "detects windows_2000" do browser = Browser.new(Browser["WINDOWS_2000"]) assert browser.platform.windows? assert_equal "5.0", browser.platform.version assert browser.platform.windows?(["=5.0"]) end test "detects windows_2000_sp1" do browser = Browser.new(Browser["WINDOWS_2000_SP1"]) assert browser.platform.windows? assert_equal "5.01", browser.platform.version assert browser.platform.windows?(["=5.01"]) end test "detects windows_xp" do browser = Browser.new(Browser["WINDOWS_XP"]) assert browser.platform.windows? assert browser.platform.windows_xp? assert_equal "5.1", browser.platform.version assert browser.platform.windows?(["=5.1"]) end test "detects windows_xp (64-bit)" do browser = Browser.new(Browser["WINDOWS_XP_64"]) assert browser.platform.windows? assert browser.platform.windows_xp? assert browser.platform.windows_x64? assert_equal "5.2", browser.platform.version assert browser.platform.windows?(["=5.2"]) end test "detects windows_vista" do browser = Browser.new(Browser["WINDOWS_VISTA"]) assert browser.platform.windows? assert browser.platform.windows_vista? assert_equal "6.0", browser.platform.version assert browser.platform.windows?(["=6.0"]) end test "detects windows7" do browser = Browser.new(Browser["WINDOWS7"]) assert browser.platform.windows? assert browser.platform.windows7? assert_equal "6.1", browser.platform.version assert browser.platform.windows?(["=6.1"]) end test "detects windows8" do browser = Browser.new(Browser["WINDOWS8"]) assert browser.platform.windows? assert browser.platform.windows8? refute browser.platform.windows8_1? assert_equal "6.2", browser.platform.version assert browser.platform.windows?(["=6.2"]) end test "detects windows8.1" do browser = Browser.new(Browser["WINDOWS81"]) assert browser.platform.windows? assert browser.platform.windows8? assert browser.platform.windows8_1? assert_equal "6.3", browser.platform.version assert browser.platform.windows?(["=6.3"]) end test "detects windows10" do browser = Browser.new(Browser["WINDOWS10"]) assert browser.platform.windows? assert browser.platform.windows10? assert_equal "10.0", browser.platform.version assert browser.platform.windows?(["=10.0"]) end test "returns name" do browser = Browser.new(Browser["WINDOWS8"]) assert_equal "Windows", browser.platform.name end end browser-6.2.0/test/unit/android_app_test.rb0000644000004100000410000000155214731746717021060 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class AndroidAppTest < Minitest::Test let(:browser) { Browser.new(Browser["ANDROID_WEBVIEW"]) } test "detects as android" do assert browser.platform.android? end test "detects as webview" do assert browser.platform.android_webview? end test "does not detect non-webviews as webview" do %w[ ANDROID_CUPCAKE ANDROID_DONUT ANDROID_ECLAIR_21 ANDROID_FROYO ANDROID_GINGERBREAD ANDROID_HONEYCOMB_30 ANDROID_ICECREAM ANDROID_JELLYBEAN_41 ANDROID_JELLYBEAN_42 ANDROID_JELLYBEAN_43 ANDROID_KITKAT ANDROID_LOLLIPOP_50 ANDROID_LOLLIPOP_51 ANDROID_TV ANDROID_NEXUS_PLAYER FIREFOX_ANDROID ].each do |android_type| refute Browser.new(Browser[android_type]).platform.android_webview? end end end browser-6.2.0/test/unit/firefox_test.rb0000644000004100000410000000251414731746717020241 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class FirefoxTest < Minitest::Test test "detects firefox" do browser = Browser.new(Browser["FIREFOX"]) assert_equal "Firefox", browser.name assert browser.firefox? assert_equal "3.8", browser.full_version assert_equal "3", browser.version end test "detects firefox for iOS" do browser = Browser.new(Browser["FIREFOX_IOS"]) assert_equal "Firefox", browser.name assert browser.firefox? assert browser.platform.ios? assert_equal "1.2", browser.full_version assert_equal "1", browser.version end test "detects modern firefox" do browser = Browser.new(Browser["FIREFOX_MODERN"]) assert_equal :firefox, browser.id assert_equal "Firefox", browser.name assert browser.firefox? assert_equal "17.0", browser.full_version assert_equal "17", browser.version end test "detects firefox android tablet" do browser = Browser.new(Browser["FIREFOX_TABLET"]) assert_equal :firefox, browser.id assert_equal "Firefox", browser.name assert browser.firefox? assert browser.platform.android? assert_equal "14.0", browser.full_version assert_equal "14", browser.version end test "detects version by range" do browser = Browser.new(Browser["FIREFOX"]) assert browser.firefox?(%w[>=3 <4]) end end browser-6.2.0/test/unit/ios_test.rb0000644000004100000410000000746514731746717017403 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class IosTest < Minitest::Test test "detects iphone" do browser = Browser.new(Browser["IPHONE"]) assert_equal "Safari", browser.name assert browser.safari? assert browser.webkit? assert browser.platform.ios? refute browser.platform.mac? assert_equal "3.0", browser.full_version assert_equal "3", browser.version end test "detects safari" do browser = Browser.new(Browser["SAFARI"]) assert_equal "Safari", browser.name assert browser.safari? assert browser.webkit? assert_equal "5.0.1", browser.full_version assert_equal "5", browser.version end test "detects chrome in desktop mode" do browser = Browser.new(Browser["CHROME_REQUEST_DESKTOP_SITE"]) assert browser.platform.ios? assert browser.device.mobile? end test "detects safari in webapp mode" do browser = Browser.new(Browser["SAFARI_IPAD_WEBAPP_MODE"]) refute browser.safari? assert browser.platform.ios_webview? browser = Browser.new(Browser["SAFARI_IPHONE_WEBAPP_MODE"]) refute browser.safari? assert browser.platform.ios_webview? end test "detects ipod" do browser = Browser.new(Browser["IPOD"]) assert_equal "Safari", browser.name assert browser.safari? assert browser.webkit? assert browser.platform.ios? refute browser.device.tablet? refute browser.platform.mac? assert_equal "3.0", browser.full_version assert_equal "3", browser.version end test "detects ipad" do browser = Browser.new(Browser["IPAD"]) assert_equal "Safari", browser.name assert browser.safari? assert browser.webkit? assert browser.platform.ios? refute browser.platform.mac? assert_equal "4.0.4", browser.full_version assert_equal "4", browser.version end test "detects ios4" do browser = Browser.new(Browser["IOS4"]) assert browser.platform.ios? assert browser.platform.ios?(4) refute browser.platform.mac? end test "detects ios5" do browser = Browser.new(Browser["IOS5"]) assert browser.platform.ios? assert browser.platform.ios?(5) refute browser.platform.mac? end test "detects ios6" do browser = Browser.new(Browser["IOS6"]) assert browser.platform.ios? assert browser.platform.ios?(6) refute browser.platform.mac? end test "detects ios7" do browser = Browser.new(Browser["IOS7"]) assert browser.platform.ios? assert browser.platform.ios?(7) refute browser.platform.mac? end test "detects ios8" do browser = Browser.new(Browser["IOS8"]) assert browser.platform.ios? assert browser.platform.ios?(8) refute browser.platform.mac? end test "detects ios9" do browser = Browser.new(Browser["IOS9"]) assert browser.platform.ios? assert browser.platform.ios?(9) refute browser.platform.mac? end test "detects ios12" do browser = Browser.new(Browser["IOS12"]) assert browser.platform.ios? assert browser.platform.ios?(12) refute browser.platform.mac? end test "does not detect as two different versions" do browser = Browser.new(Browser["IOS8"]) assert browser.platform.ios?(8) refute browser.platform.ios?(7) end test "returns string representation for iphone" do browser = Browser.new(Browser["IPHONE"]) meta = browser.to_s assert_includes meta, "webkit" assert_includes meta, "ios" assert_includes meta, "safari" assert_includes meta, "safari3" assert_includes meta, "mobile" refute_includes meta, "tablet" end test "returns string representation for ipad" do browser = Browser.new(Browser["IPAD"]) meta = browser.to_s assert_includes meta, "webkit" assert_includes meta, "ios" assert_includes meta, "safari" assert_includes meta, "tablet" refute_includes meta, "mobile" end end browser-6.2.0/test/unit/safari_test.rb0000644000004100000410000000475614731746717020056 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class SafariTest < Minitest::Test test "detects safari 3" do browser = Browser.new(Browser["SAFARI3"]) assert browser.safari? assert browser.safari?("~>3.0") assert_equal "3", browser.version assert_equal "3.0.3", browser.full_version end test "detects safari 4" do browser = Browser.new(Browser["SAFARI4"]) assert browser.safari? assert browser.safari?("~>4.0") assert_equal "4", browser.version assert_equal "4.0.3", browser.full_version end test "detects safari 5" do browser = Browser.new(Browser["SAFARI5"]) assert browser.safari? assert browser.safari?("~>5.0") assert_equal "5", browser.version assert_equal "5.0.3", browser.full_version end test "detects safari 6" do browser = Browser.new(Browser["SAFARI6"]) assert browser.safari? assert browser.safari?("~>6.0") assert_equal "6", browser.version assert_equal "6.0", browser.full_version end test "detects safari 7" do browser = Browser.new(Browser["SAFARI7"]) assert browser.safari? assert browser.safari?("~>7.0") assert_equal "7", browser.version assert_equal "7.0", browser.full_version end test "detects safari 8" do browser = Browser.new(Browser["SAFARI8"]) assert browser.safari? assert browser.safari?("~>8.0") assert_equal "8", browser.version assert_equal "8.0", browser.full_version end test "detects safari 9" do browser = Browser.new(Browser["SAFARI9"]) assert browser.safari? assert browser.safari?("~>9.0") assert_equal "9", browser.version assert_equal "9.0.2", browser.full_version end test "detects web app mode" do browser = Browser.new(Browser["SAFARI_IPHONE_WEBAPP_MODE"]) assert browser.safari_webapp_mode? end test "rejects regular safari as web app mode" do browser = Browser.new(Browser["SAFARI9"]) refute browser.safari_webapp_mode? end test "returns webkit version" do browser = Browser.new(Browser["SAFARI9"]) assert_equal "601.3.9", browser.webkit_full_version end test "detects webkit version by range" do browser = Browser.new(Browser["SAFARI9"]) assert browser.webkit?(%w[>=601 <602]) end test "detects safari version by range" do browser = Browser.new(Browser["SAFARI9"]) assert browser.safari?(%w[>=9.0 <10]) end test "does not detect as chromium" do browser = Browser.new(Browser["SAFARI9"]) refute browser.chromium_based? end end browser-6.2.0/test/unit/generic_test.rb0000644000004100000410000000100114731746717020201 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class GenericTest < Minitest::Test test "returns default msie version" do browser = Browser.new("") assert_equal "0.0", browser.msie_full_version assert_equal "0", browser.msie_version end test "returns default compatibility view" do browser = Browser.new("") refute browser.compatibility_view? end test "returns default safari web app mode" do browser = Browser.new("") refute browser.safari_webapp_mode? end end browser-6.2.0/test/unit/blackberry_test.rb0000644000004100000410000000434114731746717020717 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class BlackberryTest < Minitest::Test test "detects blackberry" do browser = Browser.new(Browser["BLACKBERRY"]) assert_equal "BlackBerry", browser.name refute browser.device.tablet? assert browser.device.mobile? assert_equal "4.1.0", browser.full_version assert_equal "4", browser.version end test "detects blackberry4" do browser = Browser.new(Browser["BLACKBERRY4"]) assert_equal "BlackBerry", browser.name assert_equal "4.2.1", browser.full_version assert_equal "4", browser.version end test "detects blackberry5" do browser = Browser.new(Browser["BLACKBERRY5"]) assert_equal "BlackBerry", browser.name refute browser.device.tablet? assert browser.device.mobile? assert_equal "5.0.0.93", browser.full_version assert_equal "5", browser.version end test "detects blackberry6" do browser = Browser.new(Browser["BLACKBERRY6"]) assert_equal "BlackBerry", browser.name refute browser.device.tablet? assert browser.device.mobile? assert_equal "6.0.0.141", browser.full_version assert_equal "6", browser.version end test "detects blackberry7" do browser = Browser.new(Browser["BLACKBERRY7"]) assert_equal "BlackBerry", browser.name refute browser.device.tablet? assert browser.device.mobile? assert_equal "7.0.0.1", browser.full_version assert_equal "7", browser.version end test "detects blackberry10" do browser = Browser.new(Browser["BLACKBERRY10"]) assert_equal "BlackBerry", browser.name refute browser.device.tablet? assert browser.device.mobile? assert_equal "10.0.9.1675", browser.full_version assert_equal "10", browser.version end test "detects blackberry playbook tablet" do browser = Browser.new(Browser["PLAYBOOK"]) refute browser.platform.android? assert browser.device.tablet? refute browser.device.mobile? assert_equal "7.2.1.0", browser.full_version assert_equal "7", browser.version end test "does not detect as two different versions" do browser = Browser.new(Browser["BLACKBERRY10"]) assert browser.platform.blackberry?("~> 10.0") refute browser.platform.blackberry?("~> 7.0") end end browser-6.2.0/test/unit/qq_test.rb0000644000004100000410000000231614731746717017220 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class QQTest < Minitest::Test test "detects QQ browser for iOS" do browser = Browser.new(Browser["QQ_BROWSER_IOS"]) assert_equal "6.3.3.432", browser.full_version assert_equal "QQ Browser", browser.name assert_equal :qq, browser.id refute browser.chrome? refute browser.safari? end test "detects QQ browser for Android" do browser = Browser.new(Browser["QQ_BROWSER_ANDROID"]) assert_equal "6.2", browser.full_version assert_equal "QQ Browser", browser.name assert_equal :qq, browser.id refute browser.chrome? refute browser.safari? end test "detects QQ browser for Mac" do browser = Browser.new(Browser["QQ_BROWSER_MAC"]) assert_equal "4.2.4753.400", browser.full_version assert_equal "QQ Browser", browser.name assert_equal :qq, browser.id refute browser.chrome? refute browser.safari? end test "detects QQ browser lite for Mac" do browser = Browser.new(Browser["QQ_BROWSER_MAC_LITE"]) assert_equal "1.0.4", browser.full_version assert_equal "QQ Browser", browser.name assert_equal :qq, browser.id refute browser.chrome? refute browser.safari? end end browser-6.2.0/test/unit/device_test.rb0000644000004100000410000001612514731746717020041 0ustar www-datawww-data# frozen_string_literal: true require "test_helper" class DeviceTest < Minitest::Test class CustomDevice < Browser::Device::Base def match? ua.include?("Custom") end def id :custom end end test "extends matchers" do Browser::Device.matchers.unshift(CustomDevice) device = Browser::Device.new("Custom") assert_equal :custom, device.id Browser::Device.matchers.shift device = Browser::Device.new("Custom") assert_equal :unknown_device, device.id end test "detects generic device" do device = Browser::Device.new("") assert device.unknown? assert_equal :unknown_device, device.id end test "detects ipad" do device = Browser::Device.new(Browser["IOS9"]) assert device.ipad? assert_equal :ipad, device.id assert_equal "iPad", device.name end test "detects old ipad" do device = Browser::Device.new(Browser["IOS3"]) assert device.ipad? assert_equal :ipad, device.id assert_equal "iPad", device.name end test "detects ipod" do device = Browser::Device.new(Browser["IPOD"]) assert device.ipod_touch? assert device.ipod? assert_equal :ipod_touch, device.id assert_equal "iPod Touch", device.name end test "detects iphone" do device = Browser::Device.new(Browser["IOS8"]) assert device.iphone? assert_equal :iphone, device.id assert_equal "iPhone", device.name end test "detects ps3" do device = Browser::Device.new(Browser["PLAYSTATION3"]) assert device.ps3? assert device.playstation3? assert device.playstation? assert_equal :ps3, device.id assert_equal "PlayStation 3", device.name end test "detects ps4" do device = Browser::Device.new(Browser["PLAYSTATION4"]) assert device.ps4? assert device.playstation4? assert device.playstation? assert_equal :ps4, device.id assert_equal "PlayStation 4", device.name end test "detects xbox 360" do device = Browser::Device.new(Browser["XBOX360"]) assert device.console? assert device.xbox? assert device.xbox_360? refute device.xbox_one? assert_equal :xbox_360, device.id assert_equal "Xbox 360", device.name end test "detects xbox one" do device = Browser::Device.new(Browser["XBOXONE"]) assert device.console? assert device.xbox? assert device.xbox_one? refute device.xbox_360? assert_equal :xbox_one, device.id assert_equal "Xbox One", device.name end test "detects psp" do device = Browser::Device.new(Browser["PSP"]) assert device.psp? assert_equal :psp, device.id assert_equal "PlayStation Portable", device.name end test "detects psvita" do device = Browser::Device.new(Browser["PSP_VITA"]) assert device.playstation_vita? assert device.vita? assert_equal :psvita, device.id assert_equal "PlayStation Vita", device.name end test "detects kindle" do device = Browser::Device.new(Browser["KINDLE"]) assert device.kindle? assert_equal :kindle, device.id assert_equal "Kindle", device.name refute device.silk? end %w[ KINDLE_FIRE KINDLE_FIRE_HD KINDLE_FIRE_HD_MOBILE ].each do |key| test "detects #{key} as kindle fire" do device = Browser::Device.new(Browser[key]) assert device.kindle? assert device.kindle_fire? assert_equal :kindle_fire, device.id assert_equal "Kindle Fire", device.name end end test "detects wii" do device = Browser::Device.new(Browser["NINTENDO_WII"]) assert device.nintendo_wii? assert device.console? assert device.nintendo? assert device.wii? assert_equal :wii, device.id assert_equal "Nintendo Wii", device.name end test "detects wiiu" do device = Browser::Device.new(Browser["NINTENDO_WIIU"]) assert device.nintendo_wiiu? assert device.wiiu? assert device.console? assert device.nintendo? assert_equal :wiiu, device.id assert_equal "Nintendo WiiU", device.name end test "detects switch" do device = Browser::Device.new(Browser["NINTENDO_SWITCH"]) assert device.nintendo_switch? assert device.switch? assert device.console? assert device.nintendo? assert_equal :switch, device.id assert_equal "Nintendo Switch", device.name end test "detects blackberry playbook" do device = Browser::Device.new(Browser["PLAYBOOK"]) assert device.playbook? assert device.blackberry_playbook? assert_equal :playbook, device.id assert_equal "BlackBerry Playbook", device.name end test "detects surface" do device = Browser::Device.new(Browser["SURFACE"]) assert device.surface? assert_equal :surface, device.id assert_equal "Microsoft Surface", device.name end test "detects tv" do device = Browser::Device.new(Browser["SMART_TV"]) assert device.tv? assert_equal :tv, device.id assert_equal "TV", device.name end test "detects unknown device" do device = Browser::Device.new("") assert device.unknown? assert_equal "Unknown", device.name end %w[ ANDROID SYMBIAN MIDP IPHONE IPOD WINDOWS_MOBILE WINDOWS_PHONE WINDOWS_PHONE8 WINDOWS_PHONE_81 OPERA_MINI LUMIA800 MS_EDGE_MOBILE UC_BROWSER NOKIA OPERA_MOBI KINDLE_FIRE_HD_MOBILE ].each do |key| test "detects #{key} as mobile" do device = Browser::Device.new(Browser[key]) assert device.mobile? refute device.tablet? end end %w[ PLAYBOOK IPAD NEXUS_TABLET SURFACE XOOM NOOK SAMSUNG FIREFOX_TABLET NEXUS7 ].each do |key| test "detects #{key} as tablet" do device = Browser::Device.new(Browser[key]) assert device.tablet? refute device.mobile? end end { "ANDROID_CUPCAKE" => "T-Mobile G1", "ANDROID_DONUT" => "SonyEricssonX10i", "ANDROID_ECLAIR_21" => "Nexus One", "ANDROID_FROYO" => "HTC_DesireHD_A9191", "ANDROID_GINGERBREAD" => "Sensation_4G", "ANDROID_HONEYCOMB_30" => "Xoom", "ANDROID_ICECREAM" => "sdk", "ANDROID_JELLYBEAN_41" => "Nexus S", "ANDROID_JELLYBEAN_42" => "Nexus 10", "ANDROID_JELLYBEAN_43" => "Nexus 7", "CUSTOM_APP" => "HTC Ruby", "NOOK" => "NOOK BNTV250A" }.each do |key, name| test "detects device name of #{key} as #{name}" do device = Browser::Device.new(Browser[key]) assert_equal name, device.name end end test "detects samsung devices" do device = Browser::Device.new(Browser["SAMSUNG_SM-G975F"]) assert device.samsung? assert_equal :samsung, device.id assert_equal "Samsung Galaxy S10+", device.name end test "detects generic samsung devices" do device = Browser::Device.new(Browser["SAMSUNG_SM-FAKE"]) assert device.samsung? assert_equal :samsung, device.id assert_equal "Samsung SM-0000", device.name end { "SAMSUNG_SM-G975F" => "Samsung Galaxy S10+", "SAMSUNG_SM-G960F" => "Samsung Galaxy S9", "SAMSUNG_SM-F700F" => "Samsung Galaxy Z Flip" }.each do |key, name| test "detects device name of #{key} as #{name}" do device = Browser::Device.new(Browser[key]) assert_equal name, device.name end end end browser-6.2.0/search_engines.yml0000644000004100000410000000024714731746717016756 0ustar www-datawww-data--- ask jeeves: "Ask Jeeves" baidu: "Chinese search engine" bingbot: "Microsoft bing bot" duckduckbot: "Duck Duck Go" googlebot: "Google spider" slurp: "Yahoo spider" browser-6.2.0/gemfiles/0000755000004100000410000000000014731746717015046 5ustar www-datawww-databrowser-6.2.0/gemfiles/7_1.gemfile0000644000004100000410000000015114731746717016763 0ustar www-datawww-data# frozen_string_literal: true source "https://rubygems.org" gemspec path: ".." gem "rails", "~> 7.1.0" browser-6.2.0/gemfiles/7_0.gemfile0000644000004100000410000000015114731746717016762 0ustar www-datawww-data# frozen_string_literal: true source "https://rubygems.org" gemspec path: ".." gem "rails", "~> 7.0.0" browser-6.2.0/Rakefile0000644000004100000410000000142114731746717014716 0ustar www-datawww-data# frozen_string_literal: true require "bundler" require "bundler/setup" Bundler::GemHelper.install_tasks require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "lib" t.libs << "test" t.test_files = FileList["test/**/*_test.rb"] t.verbose = true t.warning = false end require "rubocop/rake_task" desc "Run rubocop" task :rubocop do RuboCop::RakeTask.new do |t| t.options += %w[ --display-style-guide --display-cop-names --extra-details --auto-correct ] end end desc "Run specs against all gemfiles" task "test:all" do %w[ Gemfile gemfiles/rails4.gemfile ].each do |gemfile| puts "=> Running with Gemfile: #{gemfile}" system "BUNDLE_GEMFILE=#{gemfile} rake test" end end task default: %i[test rubocop] browser-6.2.0/bots.yml0000644000004100000410000002116614731746717014753 0ustar www-datawww-data--- 200pleasebot: 200PleaseBot 360spider: 360Spider abot: CrawlDaddy, abot addthis: AddThis adldxbot: Microsoft Bing Ads admantx: ADmantX Platform Semantic Analyzer adsbot-google: Google Adwords adstxtcrawler: AdsTxtCrawler advbot: AdvBot ahrefsbot: Ahrefs backlinks research tool alexa: Alexa Crawler anderspink: AndersPinkBot apache-httpclient: Java http library apachebench: ApacheBench (ab) apis-google: APIs-Google appengine-google: Google App Engine applebot: Apple Bot appsignal: AppSignal Bot archive.org_bot: Internet Archive (archive.org) archiveteam archivebot: ArchiveTeam ArchiveBot ask jeeves: Ask Jeeves asynchttpclient: Java http and WebSocket client library awe.sm: Awe.sm URL expander baidu: Baidu barkrowler: Barkrowler bdcbot: Big Data Corp bingbot: Microsoft Bing bingpreview: Microsoft Bing preview bitlybot: bit.ly bot blekkobot: Blekkobot blexbot: BLEXBot (webmeup) bot@linkfluence.net: Linkfluence bot bubing: BUbiNG bufferbot: BufferBot buibui-checkbot: buibui butterfly: Topsy Labs buzzbot: Buzzbot buzztalk: buzztalk catchbot: CatchBot (catchbot.com) check_http: Nagios monitor checkly: Checkly chrome-lighthouse: Chrome-Lighthouse cipacrawler: CipaCrawler cliqzbot: Cliqzbot cloudflare: CloudFlare-AlwaysOnline cmradar/0.1: CMRadar/0.1 coldfusion: ColdFusion http library commoncrawl: CCBot comodo ssl checker: COMODO SSL Checker comodo-webinspector-crawler: Comodo copypants: BotPants crowsnest: Crowsnest curabot: cura.yt curl: curl unix CLI http client dap/nethttp: DAP/NetHTTP datafeedwatch: DataFeedWatch datagnionbot: datagnion.com/bot.html datanyze: Datanyze daumoa: Korean portal and search engine indexing bot developers.google.com/+/web/snippet/: Google Plus diffbot: Diffbot digitalpersona fingerprint software: HP Fingerprint scanner domain re-animator bot: Domain Re-Animator Bot domainsbot: DomainsBot domaintunocrawler: DomainTuno dotbot: Dot Bot duckduckbot: Duck Duck Go elb-healthchecker: AWS ELB HealthChecker embedly: Embedly eoaagent: EOAAgent everyonesocialbot: EveryoneSocial evrinid: Evri bot exabot: Exalead's bot exaleadcloudview: ExaleadCloudView ez publish: eZ Publish Link Validator facebookexternalhit: Facebook Bot facebot: Facebook Bot feedburner: RSS bot feedfetcher-google: Google Feedfetcher findxbot: Findxbot flipboardproxy: FlipboardProxy friendfeedbot: FriendFeed fyrebot: Fyrebot garlik: GarlikCrawler genieo: Genieo Web filter bot germcrawler: GermCrawler getprismatic.com: getprismatic.com gigabot: Gigabot spider gimme60bot: Gimme60 (gimme60.com) gimmeusabot: Gimme60 (gimme60.com) go http package: Go http library go-http-client: Go http client google page speed insights: Google Page Speed Insights google web preview: Google Instant Previews crawler google-site-verification: Google Site Verification google-structured-data-testing-tool: Google Structured Data Testing Tool google-structureddatatestingtool: Google Structured Data Testing Tool google-xrawler: Google Shopping googlebot: Google Bot googleimageproxy: Google Image Proxy googlestackdrivermonitoring-uptimechecks: Google Stackdriver Monitoring - Uptime Checks grapeshotcrawler: GrapeshotCrawler gravitybot: Gravity Bot hatena::bookmark: Hatena::Bookmark heritrix: heritrix https://developers.google.com/+/web/snippet: Google+ Snippet Fetcher httrack: HTTrack hubspot: HubSpot ia_archiver: Internet Archive (WayBackMachine) icoreservice: iCoreService idmarch: idmarch.org/bot.html implisensebot: ImplisenseBot inagist: URL resolver insieve: Insieve Bot insitesbot: Insitesbot instapaper: Instapaper istellabot: IstellaBot jaunt: Jaunt - Java Web Scraping & JSON Querying jetslide: Jetslide jobseeker: jobseeker.com.au/bot.html jooble: Jooble js-kit: URL resolver kemvibot: Kemvi kimengi: Kimengi Bot knows.is: knows.is kojitsubot: Kojitsubot komodiabot: KomodiaBot kraken: kraken laconica: Laconica lijit crawler: Lijit linkdexbot: Linkdex Bot linkedinbot: LinkedIn linkscrawler: LinksCrawler linode: Linode Longview lipperhey: Lipperhey livelapbot: Livelapbot loadtimebot: Load Time Bot longurl: URL expander service ltx71: ltx71.com lumibot: Lumibot magpie-crawler: magpie-crawler mail.ru_bot: Mail.ru Bot mappydata: Mappy mastodon: Mastodon URL expander mauibot: MauiBot meanpathbot: meanpath mediapartners-google: Google Adsense bot megaindex.ru: MegaIndex memorybot: mignify.com/bot.html metauri: MetaURI mfe_expand: Mcafee spider mir web crawler: MIR web crawler mj12bot: Majestic-12 spider mojeekbot: Mojeek UK search crawler ms search 6.0 robot: MS Search 6.0 Robot msnbot-media: Microsoft media bot msnbot: Microsoft bot nerdybot: NerdyBot netcraft: Netcraft netstate: netEstate NE Crawler netvibes: Personalized dashboard bot netzcheckbot: netzcheck newrelicmonitor: NewRelic monitor newrelicpinger: NewRelicPinger newsme: newsme niki-bot: niki-bot ning: NING - Yet Another Twitter Swarmer nutch: Apache search spider openhosebot: OpenHoseBot orangebot: OrangeBot paessler: paessler.com - PRTG Network Monitor pagesinventory: pagesinventory.com panopta: Monitoring service paperlibot: PaperLi peerindex: peerindex percolatecrawler: PercolateCrawler perfectmarketkwtbot: PerfectMarket phantomjs: PhantomJS pingdom: Pingdom monitoring pinterest: Pinterest plukkie: botje.com/plukkie.htm pr-cy.ru: PR-CY.RU privacyawarebot: PrivacyAwareBot proximic: Proximic Spider psbot-page: Picsearch pu_in: Pu_iN Crawler publiclibraryarchive.org: publiclibraryarchive.org pycurl: Python http library python-httplib2: Python-httplib2 python-requests: Python http library python-urllib: Python http library queryseeker: QuerySeekerSpider quick-crawler: Quick-Crawler quicklook: QuickLook re-animator: Domain Re-Animator Bot readability: Readability rebelmouse: RebelMouse redditbot: Reddit Bot relateiq: RelateIQ riddler: Riddler Bot rogerbot: SeoMoz spider rssmicro: RSS/Atom Feed Robot (rssmicro.com) scouturlmonitor: ScoutURLMonitor scrapy: Scrapy screaming frog seo spider: Screaming Frog SEO Spider searchmetricsbot: SearchmetricsBot semanticbot: Semanticbot semrushbot: SEO analysis bot seo-audit: seo-audit-check-bot seobilitybot: SeobilityBot seodiver: SEOdiver seokicks: SEOKicks seznambot: SeznamBot shopwiki: ShopWiki shortlinktranslate: Link shortener showyoubot: Showyou iOS app spider siege: Joe Dog Siege sistrix: SISTRIX sitecheck: SiteCheck sitecrawl siteuptime: Site monitoring services skypeuripreview: SkypeUriPreview slack-imgproxy: Slack Image Proxy slack-linkexpanding: Slack Link Expanding slack: Slack Link Expanding slackbot: Slackbot slurp: Yahoo spider smtbot: SimilarTech snapchat: Snapchat socialrank: SocialRankIOBot sogou: Chinese search engine spbot: OpenLinkProfiler spinn3r: Spinn3r aggregator sputnikbot: SputnikBot squider: Squider statuscake: StatusCake swiftbot: Swiftype Bot tangibleebot: TangibleeBot teeraid: TeeRaidBot test certificate info: C http library? the knowledge ai: Knowledge AI Bot tineye: TinEye Bot traackr: Traackr Bot trendictionbot: Trendiction Search trendsmap: Trendsmap Resolver turnitinbot: TurnitinBot tweetedtimes: The Tweeted Times tweetmemebot: TweetMeMe Crawler twikle: Social web search bot twitjobsearch: TwitJobSearch twitmunin: Twitmunin twitterbot: Twitter URL expander twurly: Twurly typhoeus: Typhoeus umbot: uberMetrics unwindfetch: Gnip updown: Updown.io monitor uptimerobot: Uptime Robot vagabondo: Vagabondo vb project: Visual Basic vigil: Vigil vkshare: VKontake Sharer voilabot: VoilaBot vrcrawler: Venture Radar wasalive-bot: Wasalive Bots watchsumo: WatchSumo wbsearchbot: Ware Bay Best Buys webceo: online-webceo-bot webscout: Webscout wesee: WeSEE wget: wget unix CLI http client whatsapp: WhatsApp wikido: WikiDo woorank: WooRank wordpress: WordPress spider woriobot: woriobot wormly: WormlyBot wotbox: Wotbox xenu link sleuth: Xenu Link Sleuth xing-contenttabreceiver: Xing bot xovibot: XoviBot yacybot: YaCy yahoo-ad-monitoring: Yahoo Ad monitoring yandex: Yandex yanga: Yanga WorldSearch Bot yeti: Naver Corp yourls: YOURLS zabbix: Zabbix zelist.ro: feed parser zibb: ZIBB spider zitebot: Zite zoombot: ZoomBot zoominfobot: ZoominfoBot zyborg: Zyborg # AI Crawlers # https://darkvisitors.com amazonbot: Amazon anthropic-ai: Anthropic-AI applebot: Apple bytespider: TikTok ccbot: Common Crawl chatgpt-user: ChatGPT claude-web: Anthropic-AI cohere-ai: Cohere diffbot: Diffbot facebookbot: Facebook google-extended: Google googleother: Google gptbot: ChatGPT omgili: Webz.io perplexitybot: Perplexity webz.io: Webz.io youbot: You.com # Generic lib user agents go here. httpie: HTTPie eventmachine httpclient: Ruby http library go 1.1 package http: Go 1.1 package http htmlparser: HTMLParser http_request2: HTTP_Request2 httpclient: HTTPClient jakarta commons: Jakarta Commons HttpClient java: Generic Java http library libwww-perl: Perl client-server library lwp-trivial: Another Perl library ruby: Ruby browser-6.2.0/LICENSE.md0000644000004100000410000000207114731746717014657 0ustar www-datawww-data# The MIT License (MIT) Copyright (c) 2010 Nando Vieira Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. browser-6.2.0/Gemfile0000644000004100000410000000010414731746717014541 0ustar www-datawww-data# frozen_string_literal: true source "http://rubygems.org" gemspec browser-6.2.0/.prettierignore0000644000004100000410000000000614731746717016312 0ustar www-datawww-data*.yml browser-6.2.0/config.ru0000644000004100000410000000006214731746717015066 0ustar www-datawww-datarequire "./test/sample_app" run Rails.application browser-6.2.0/README.md0000644000004100000410000003067614731746717014546 0ustar www-datawww-data# Browser [![Tests](https://github.com/fnando/browser/workflows/ruby-tests/badge.svg)](https://github.com/fnando/browser) [![Gem](https://img.shields.io/gem/v/browser.svg)](https://rubygems.org/gems/browser) [![Gem](https://img.shields.io/gem/dt/browser.svg)](https://rubygems.org/gems/browser) Do some browser detection with Ruby. Includes ActionController integration. ## Installation ```bash gem install browser ``` ## Usage ```ruby require "browser" browser = Browser.new("Some User Agent", accept_language: "en-us") # General info browser.bot? browser.chrome? browser.chromium_based? browser.core_media? browser.duck_duck_go? browser.edge? # Newest MS browser browser.electron? # Electron Framework browser.firefox? browser.full_version browser.ie? browser.ie?(6) # detect specific IE version browser.ie?([">8", "<10"]) # detect specific IE (IE9). browser.known? # has the browser been successfully detected? browser.unknown? # the browser wasn't detected. browser.meta # an array with several attributes browser.name # readable browser name browser.nokia? browser.opera? browser.opera_mini? browser.phantom_js? browser.quicktime? browser.safari? browser.safari_webapp_mode? browser.samsung_browser? browser.to_s # the meta info joined by space browser.uc_browser? browser.version # major version number browser.webkit? browser.webkit_full_version browser.yandex? browser.wechat? browser.qq? browser.weibo? browser.sputnik? browser.sougou_browser? browser.epiphany? # Get bot info browser.bot.name browser.bot.search_engine? browser.bot? browser.bot.why? # shows which matcher detected this user agent as a bot. Browser::Bot.why?(ua) # Get device info browser.device browser.device.id browser.device.name browser.device.unknown? browser.device.blackberry_playbook? browser.device.console? browser.device.ipad? browser.device.iphone? browser.device.ipod_touch? browser.device.kindle? browser.device.kindle_fire? browser.device.mobile? browser.device.nintendo? browser.device.playstation? browser.device.ps3? browser.device.ps4? browser.device.psp? browser.device.silk? browser.device.surface? browser.device.tablet? browser.device.tv? browser.device.vita? browser.device.wii? browser.device.wiiu? browser.device.samsung? browser.device.switch? browser.device.xbox? browser.device.xbox_360? browser.device.xbox_one? # Get platform info browser.platform browser.platform.id browser.platform.name browser.platform.version # e.g. 9 (for iOS9) browser.platform.adobe_air? browser.platform.android? browser.platform.android?(4.2) # detect Android Jelly Bean 4.2 browser.platform.android_app? # detect webview in an Android app browser.platform.android_webview? # alias for android_app? browser.platform.blackberry? browser.platform.blackberry?(10) # detect specific BlackBerry version browser.platform.chrome_os? browser.platform.firefox_os? browser.platform.ios? # detect iOS browser.platform.ios?(9) # detect specific iOS version browser.platform.ios_app? # detect webview in an iOS app browser.platform.ios_webview? # alias for ios_app? browser.platform.linux? browser.platform.mac? browser.platform.unknown? browser.platform.windows10? browser.platform.windows7? browser.platform.windows8? browser.platform.windows8_1? browser.platform.windows? browser.platform.windows_mobile? browser.platform.windows_phone? browser.platform.windows_rt? browser.platform.windows_touchscreen_desktop? browser.platform.windows_vista? browser.platform.windows_wow64? browser.platform.windows_x64? browser.platform.windows_x64_inclusive? browser.platform.windows_xp? browser.platform.kai_os? ``` ### Aliases To add aliases like `mobile?` and `tablet?` to the base object (e.g `browser.mobile?`), require the `browser/aliases` file and extend the Browser::Base object like the following: ```ruby require "browser/aliases" Browser::Base.include(Browser::Aliases) browser = Browser.new("Some user agent") browser.mobile? #=> false ``` ### What's being detected? - For a list of platform detections, check [lib/browser/platform.rb](https://github.com/fnando/browser/blob/master/lib/browser/platform.rb) - For a list of device detections, check [lib/browser/device.rb](https://github.com/fnando/browser/blob/master/lib/browser/device.rb) - For a list of bot detections, check [bots.yml](https://github.com/fnando/browser/blob/master/bots.yml) ### Detecting modern browsers To detect whether a browser can be considered as modern or not, create a method that abstracts your versioning constraints. The following example will consider any of the following browsers as a modern: ```ruby # Expects an Browser instance, # like in `Browser.new(user_agent, accept_language: language)`. def modern_browser?(browser) [ browser.chrome?(">= 65"), browser.safari?(">= 10"), browser.firefox?(">= 52"), browser.ie?(">= 11") && !browser.compatibility_view?, browser.edge?(">= 15"), browser.opera?(">= 50"), browser.facebook? && browser.safari_webapp_mode? && browser.webkit_full_version.to_i >= 602 ].any? end ``` ### Rails integration Just add it to the Gemfile. ```ruby gem "browser" ``` This adds a helper method called `browser`, that inspects your current user agent. ```erb <% if browser.ie?(6) %>

You're running an older IE version. Please update it!

<% end %> ``` If you want to use Browser on your Rails app but don't want to taint your controller, use the following line on your Gemfile: ```ruby gem "browser", require: "browser/browser" ``` ### Accept Language Parses the accept-language header from an HTTP request and produces an array of language objects sorted by quality. ```ruby browser = Browser.new("Some User Agent", accept_language: "en-us") browser.accept_language.class #=> Array language = browser.accept_language.first language.code #=> "en" language.region #=> "US" language.full #=> "en-US" language.quality #=> 1.0 language.name #=> "English/United States" ``` Result is always sorted in quality order from highest to lowest. As per the HTTP spec: - omitting the quality value implies 1.0. - quality value equal to zero means that is not accepted by the client. ### Internet Explorer Internet Explorer has a compatibility view mode that allows newer versions (IE8+) to run as an older version. Browser will always return the navigator version, ignoring the compatibility view version, when defined. If you need to get the engine's version, you have to use `Browser#msie_version` and `Browser#msie_full_version`. So, let's say an user activates compatibility view in a IE11 browser. This is what you'll get: ```ruby browser.version #=> 11 browser.full_version #=> 11.0 browser.msie_version #=> 7 browser.msie_full_version #=> 7.0 browser.compatibility_view? #=> true ``` This behavior changed in `v1.0.0`; previously there wasn't a way of getting the real browser version. ### Safari iOS webviews and web apps aren't detected as Safari anymore, so be aware of that if that's your case. You can use a combination of platform and webkit detection to do whatever you want. ```ruby # iPad's Safari running as web app mode. browser = Browser.new("Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405") browser.safari? #=> false browser.webkit? #=> true browser.platform.ios? #=> true ``` ### Bots The bot detection is quite aggressive. Anything that matches at least one of the following requirements will be considered a bot. - Empty user agent string - User agent that matches `/crawl|fetch|search|monitoring|spider|bot/` - Any known bot listed under [bots.yml](https://github.com/fnando/browser/blob/master/bots.yml) To add custom matchers, you can add a callable object to `Browser::Bot.matchers`. The following example matches everything that has a `externalhit` substring on it. The bot name will always be `General Bot`. ```ruby Browser::Bot.matchers << ->(ua, _browser) { ua.match?(/externalhit/i) } ``` To clear all matchers, including the ones that are bundled, use `Browser::Bot.matchers.clear`. You can re-add built-in matchers by doing the following: ```ruby Browser::Bot.matchers += Browser::Bot.default_matchers ``` To restore v2's bot detection, remove the following matchers: ```ruby Browser::Bot.matchers.delete(Browser::Bot::KeywordMatcher) Browser::Bot.matchers.delete(Browser::Bot::EmptyUserAgentMatcher) ``` To extend the bot list, you can manipulate the methods below: ```ruby Browser::Bot.bots.merge!(new_bots_hash) Browser::Bot.bot_exceptions += new_exceptions Browser::Bot.search_engines.merge!(new_search_engines_hash) ``` ### Middleware You can use the `Browser::Middleware` to redirect user agents. ```ruby use Browser::Middleware do redirect_to "/upgrade" if browser.ie? end ``` If you're using Rails, you can use the route helper methods. Just add something like the following to a initializer file (`config/initializers/browser.rb`). ```ruby Rails.configuration.middleware.use Browser::Middleware do redirect_to upgrade_path if browser.ie? end ``` If you need access to the `Rack::Request` object (e.g. to exclude a path), you can do so with `request`. ```ruby Rails.configuration.middleware.use Browser::Middleware do redirect_to upgrade_path if browser.ie? && request.env["PATH_INFO"] != "/exclude_me" end ``` ### Restrictions - User agent has a size limit of 2048 bytes. This can be customized through `Browser.user_agent_size_limit=(size)`. - Accept-Language has a size limit of 2048 bytes. This can be customized through `Browser.accept_language_size_limit=(size)`. If size is not respected, then `Browser::Error` is raised. ```ruby Browser.user_agent_size_limit = 4096 Browser.accept_language_size_limit = 4096 ``` ## Development ### Versioning This library follows http://semver.org. ### Writing code Once you've made your great commits (include tests, please): 1. [Fork](http://help.github.com/forking/) browser 2. Create a topic branch - `git checkout -b my_branch` 3. Push to your branch - `git push origin my_branch` 4. Create a pull request 5. That's it! Please respect the indentation rules and code style. And use 2 spaces, not tabs. And don't touch the version thing. ## Configuring environment To configure your environment, you must have Ruby and bundler installed. Then run `bundle install` to install all dependencies. To run tests, execute `./bin/rake`. ### Adding new features Before using your time to code a new feature, open a ticket asking if it makes sense and if it's on this project's scope. Don't forget to add a new entry to `CHANGELOG.md`. #### Adding a new bot 1. Add the user agent to `test/ua_bots.yml`. 2. Add the readable name to `bots.yml`. The key must be something that matches the user agent, in lowercased text. 3. Run tests. Don't forget to add a new entry to `CHANGELOG.md`. #### Adding a new search engine 1. Add the user agent to `test/ua_search_engines.yml`. 2. Add the same user agent to `test/ua_bots.yml`. 3. Add the readable name to `search_engines.yml`. The key must be something that matches the user agent, in lowercased text. 4. Run tests. Don't forget to add a new entry to `CHANGELOG.md`. #### Wrong browser/platform/device detection If you know how to fix it, follow the "Writing code" above. Open an issue otherwise; make sure you fill in the issue template with all the required information. ## Maintainer - Nando Vieira - https://nandovieira.com ## Contributors - https://github.com/fnando/browser/contributors ## License (The MIT License) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. browser-6.2.0/.rubocop.yml0000644000004100000410000000051114731746717015522 0ustar www-datawww-data--- inherit_gem: rubocop-fnando: .rubocop.yml AllCops: TargetRubyVersion: 2.5 NewCops: enable Exclude: - bin/**/* - gemfiles/**/* - vendor/**/* - Gemfile - Rakefile - "*.gemspec" - config.ru Naming/VariableNumber: Enabled: false Minitest/EmptyLineBeforeAssertionMethods: Enabled: false browser-6.2.0/CHANGELOG.md0000644000004100000410000002027114731746717015066 0ustar www-datawww-data# Changelog ## 6.2.0 - Add `Browser::Base#epiphany?`. - Don't ever match linux-based browsers as Safari. ## 6.1.0 - Add more bots (mostly related to AI crawlers) - Add AppSignal bot - Add Checkly bot - Detect Chrome when requesting desktop site. ## 6.0.0 - Add `Browser::Base#chromium_based?`. - Change how browser detection works to avoid re-instantiating classes. - Bump up minimum required ruby version to 3.2.0. ## 5.3.1 - Remove Stripe webhooks from bot list. ## 5.3.0 - Bump up minimum required ruby version to 2.5.0. We're now relying on `String#match?`, which was introduced by ruby-2.4, but given that ruby's stable version is >= 2.5, seems reasonable. ## 5.2.0 - Add KaiOS detection. - Replace `String#=~` with `String#match?` and other optimizations. ## 5.1.0 - Add Samsung device detection. - Delay parsing `Accept-Language` until `Browser::Base#accept_language` is called for the first time. - Bump up default size limit for `Accept-Language` and `User-Agent` to 2048 bytes. ## 5.0.0 - Rename `Browser::Platform#other?` to `Browser::Platform#unknown?`. - Unknown platforms now return `:unknown_platform` as the id. - Unknown devices now return `:unknown_device` as the id. - Unknown browsers now return `:unknown_browser` as the id. - All the changes above affect how `browser.meta` is composed. - Add method `Browser::Base#unknown?`. - Fix issue with `Browser::Base#safari?` matching full version. - Add Maxthon detection. - Add Google Search App detection. - Add Huawei Browser detection. - Fix Duck Duck Go browser that was being recognized as a bot. - Add Miui Browser detection. - Add `Browser::Base#qq?`. - Fix QQ detection. - Fix Alipay detection. - Add Sougou Browser detection. - User agent has a size limit of 512 bytes. This can be customized through `Browser.user_agent_size_limit`. - Accept-Language has a size limit of 256 bytes. This can be customized through `Browser.accept_language_size_limit`. ## 4.2.0 - Fix Chrome Lighthouse detection. - Add Skype to bot list. ## 4.1.0 - Add Samsung browser. - Add Google Image Proxy to the bot list. - Add The Knowledge AI bot to the bot list. - Add Go HttpClient to the bot list. - Fix Microsoft Edge detection on Android and iOS. - Fix MicroMessenger detection on Android ## 4.0.0 - Add Chrome Lighthouse to bot list. - Add SeobilityBot to the bot list. - Detect Mac-based platforms differently, depending on the version; "Mac OS X" will be returned for versions prior to 10.12, and "macOS" for newer versions. - Remove `Browser.modern_rules` and `Browser::Base#modern?`. - Add DuckDuckGo browser. # 3.0.3 - Deprecate `Browser.modern_rules` and `Browser::Base#modern?`. Theses methods will be removed on the next major released, or by June 1st 2020. ## 3.0.2 - Remove .bundle directory from package. ## 3.0.1 - Fix issue with MS Edge detection as a modern browser. ## 3.0.0 - Add ArchiveTeam's ArchiveBot to the bot list. - Fix QQ Browser detection. - Update modern rules. - You can now define new bot matchers by adding a callable object to `Browser::Bot.matchers`. - Fix `browser.yandex?` and `browser.sputnik?`. - [BREAKING CHANGE] Removed methods to enable the bot's empty user agent detection (`Browser::Bot.detect_empty_ua!` and `Browser::Bot.detect_empty_ua?`). - [BREAKING CHANGE] Bot detection is now more aggressive by default. It matches empty user agents, anything that matches `crawl|fetch|search|monitoring|spider|bot`, and anything listed under https://github.com/fnando/browser/blob/master/bots.yml. - Add Jaunt to the bot list. ## 2.7.1 - Handle Snapchat user agents that have a space or an empty string instead of a slash before the version. - Fix iOS 10+ version detection. - Add fallback versions for instagram and snapchat to avoid NoMethodErrors on unexpected user agents. ## 2.7.0 - Add more Slack bots. - Handle instagram user agents that have a slash instead of a space. - Add `Browser::Bot.why?(ua)` to help debugging why a user agent is considered bot. - Promote Snapchat to a browser (it was detected as a bot previously). - Detect Edge based on Chrome correctly. - Improve Yandex detection. - Add Sputnik (https://browser.sputnik.ru) - Detect Android devices. - Add ScoutURLMonitor to the bot list. ## 2.6.1 - Also include controller extensions to `ActionController::Base`. ## 2.6.0 - Add GarlikCrawler, ImplisenseBot and WikiDo bots. - Add Mastodon URL expander bot. - Add eZ Publish Link Validator, GermCrawler, Pu_iN Crawler, ZoomBot, and ZoominfoBot bots. - Add Datanyze bot. - Add support for Instagram in-app browser. - Add Updown.io monitor bot. - Add Snapshat detection. - Add Instagram detection. - Add Nintendo Switch detection. - Add WooRank bot. - Add Trendsmap bot. - Add Go 1.1 package http bot. - Add MauiBot. - Add SiteCheck-sitecrawl bot. - Add PR-CY.RU bot. - Add AdsTxtCrawler bot. - Add HTTrack bot. - Add Google Shopping bot. - Add DataFeedWatch bot. - Add Zabbix bot. - Add TangibleeBot. - Add Jooble bot. - Add Fyre bot. - Drop Rails 4 official support. - Fix accept-language sorting (If HTTP-header has value `en,fr`—without qualities—the first language should be `en` instead of `fr`). - Ignore malformed strings when comparing versions. - Fix Facebook detection on newer apps. - Change precedence for bot detection when common libs are used. - Add Yandex's search browser to the exception list. ## v2.5.3 - Add Google Site Verification to the bot list. - Handle invalid quality values that look like numbers. - Add Barkrowler bot. - Add AlwaysOnline bot: CloudFlare. - Add News aggregator crawler: AndersPink, BuzzBot. - Add Domain crawler: CipaCrawler. - Add Job bot: JobSeeker's. - Add Apparel crawler: TeeRaid. - Add Search engine crawler: SemanticBot, Mappy. - Add Copyright crawler: Copypants' BotPants. - Add SEO bots: SEOdiver, SeoAudit, WebCeo. - Add Woriobot from Zite. - Add BUbiNG bot. - Add Paessler bot. ## v2.5.2 - Add COMODO SSL Checker bot. - Add Swiftype bot. - Add WhatsApp detection. ## v2.5.1 - Add Android Oreo detection. ## v2.5.0 - Add support for QQ Browser Mac & Mac Lite. - Add support for Electron Framework. - Add support for Facebook in-app browser. - Add support for Otter Browser. - Add Android webview detection. ## v2.4.0 - Add Google Drive API, Proximic Spider, NewRelic pinger and SocialRank bots. - Add Pinboard in-app browser to the bot exception list. - All browser detection methods can now compare versions. - All platform detection methods can now compare versions (except `#linux?` and `#firefox_os?`). - Add `browser/aliases`, so you can have methods on the base object (e.g. `browser.mobile?`). See README for instructions. - Remove official support for Rails 3 and Ruby 2.1. ## v2.3.0 - Add AWS ELB bot. - Add CommonCrawl and Yahoo Ad Monitoring bots. - Add Google Stackdriver Uptime Check bot. - Add Microsoft Bing bots (adldxbot, bingpreview, and msnbot-media). - Add Stripe and Netcraft bots. - Add support for loading browser without extending Rails' helpers. - Add Watchsumo bot. - Match Alipay. ## v2.2.0 - `Browser::Platform#windows?` can now compare versions. - `Browser::Platform#mac?` can now compare versions. - Detect QQ Browser. - Fix issue with Mac user agents that didn't include the version. ## v2.1.0 - Add PrivacyAwareBot, ltx71, Squider and Traackr to bots. - Match Google Structured Data alternative bot. - Match MicroMessenger (WeChat). - Match Weibo. - Detect Windows & Mac OS versions. ## v2.0.3 - Fix issue with version detection when no actual version is provided (i.e. the user agent doesn't have any version information). ## v2.0.2 - Fix issue when user agent is set to `nil`. - Fix issue with user agent without version information. ## v2.0.1 - Fix Rails integration. ## v2.0.0 - `Browser#platform` now returns instance of `Browser::Platform`, instead of a `String`. It contains information about the platform (software). - `Browser#device` was added. It returns information about the device (hardware). - `Browser#accept_language` now returns a list of `Browser::AcceptLanguage` objects. - `Browser#bot` now returns a `Browser::Bot` instance. - Safari running as web app mode is not recognized as Safari anymore. - ruby-2.3+ will always activate frozen strings. - [List of all commits since last release](https://github.com/fnando/browser/compare/v1.1.0...v2.0.0). browser-6.2.0/browser.gemspec0000644000004100000410000000257514731746717016314 0ustar www-datawww-data# frozen_string_literal: true require "./lib/browser/version" Gem::Specification.new do |s| s.name = "browser" s.version = Browser::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Nando Vieira"] s.email = ["me@fnando.com"] s.homepage = "https://github.com/fnando/browser" s.summary = "Do some browser detection with Ruby." s.description = s.summary s.license = "MIT" s.required_ruby_version = ">= 3.2.0" s.metadata["rubygems_mfa_required"] = "true" s.metadata["changelog_uri"] = "https://github.com/fnando/browser/blob/main/CHANGELOG.md" s.metadata["funding_uri"] = "https://github.com/sponsors/fnando" s.files = `git ls-files`.split("\n") s.executables = `git ls-files -- exe/*` .split("\n") .map {|f| File.basename(f) } s.require_paths = ["lib"] s.add_development_dependency "bundler" s.add_development_dependency "minitest" s.add_development_dependency "minitest-autotest" s.add_development_dependency "minitest-utils" s.add_development_dependency "rack-test" s.add_development_dependency "rails" s.add_development_dependency "rake" s.add_development_dependency "rubocop" s.add_development_dependency "rubocop-fnando" s.add_development_dependency "simplecov" end