browser_sniffer 2.5.1 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 063bbcdba6a86e10804f3685bfd18cca2171abba2283deeb36ec52faec7a09eb
4
- data.tar.gz: 7cfac68c97ffb4b1103b1a794fdf16b87dee8028c68618fdfa89bbdbf08c7c39
3
+ metadata.gz: f1fa6f0ef701270fad08c72634ccbb5c9a01a8748eb5368ccff0d62066065c9a
4
+ data.tar.gz: 7915b883d825b1776b6833ea89cdde0be71ebed046fd06e73627cdc6b52c07ad
5
5
  SHA512:
6
- metadata.gz: 448d4bdecf7bc7fc1f71c493f72fe819ae1ec8be3c3f0edb26f04d3b8ac0a210451f1554a6c368a0392b31d4a2c0afe142454f38efc0ea1c779d2691ccbc057b
7
- data.tar.gz: c45d7149bd168e6e74bede798620ea823bba03dfe174f737b56799fa424635daa705bd8490afa4b4358d5a67d71b37bbe67d7be4773309d3931477381fd4bf4f
6
+ metadata.gz: 53940f3356cabe18354c764930c2acbfb0e09c884147d63e5556f139c41df51a0c437fa05b77bf50a10e117e6d3aec2a8f2e4450be2f762a909e2ac9f64eb8ab
7
+ data.tar.gz: 6cb0b817ae2c25c0163d7a70e6db1952878ce2a96d19981d158b0de53d45943d587584ff64e66076c1b5e5d68cfc47ad7e2c220babff87e4ffe5c0aba4f3efa1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- browser_sniffer (2.5.1)
4
+ browser_sniffer (2.5.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -222,10 +222,10 @@ class BrowserSniffer
222
222
  %r{.*Shopify POS\/[\d\.]+ \((iPod touch)\;.*Scale/([\d\.]+)}i,
223
223
  ], [[:type, :handheld], :scale], [
224
224
  # Shopify POS for Android (SmartWebView)
225
- %r{.*Shopify\sPOS.*\(.*(Android)\s[\d\.]+\;\s(.*)\sBuild/.*\)\sPOS.*[\d+\.]+}i,
225
+ %r{.*Shopify\sPOS[^\(]*\((?:[^()]*)(Android)\s[\d\.]+\;\s(?:[^;()]*\;\s)*([^;()]*)\sBuild/[^)]*\)\sPOS[^\d]*[\d+\.]+}i,
226
226
  ], [[:type, :handheld], :model], [
227
227
  # Shopify POS for Android (Native App)
228
- %r{.*\(.*(Android)\s[\d\.]+\;\s(.*)\sBuild/.*\)\sPOS.*[\d+\.]+}i,
228
+ %r{.*\((?:[^()]*)(Android)\s[\d\.]+\;\s(?:[^;()]*\;\s)*([^;()]*)\sBuild/[^)]*\)\sPOS[^\d]*[\d+\.]+}i,
229
229
  ], [[:type, :handheld], :model], [
230
230
  # New tablet patterns (must come early to avoid generic matches)
231
231
  # Xiaomi Tablets
@@ -496,7 +496,7 @@ class BrowserSniffer
496
496
  # BSD based
497
497
  /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i # FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
498
498
  ], [:name, :version],[
499
- /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i # iOS
499
+ /(ip[honead]+)(?:.*os\s*([\w]+)\slike\smac|;\sopera)/i # iOS
500
500
  ], [[:name, 'iOS'], [:version, lambda {|str| str && str.gsub(/_/, '.') }], [:type, :ios]], [
501
501
  /(mac\sos\sx)\s?([\w\s\.]+\w)*/i # Mac OS
502
502
  ], [:name, [:version, lambda {|str| str && str.gsub(/_/, '.') }], [:type, :mac]], [
@@ -1,3 +1,3 @@
1
1
  class BrowserSniffer
2
- VERSION = "2.5.1"
2
+ VERSION = "2.5.2"
3
3
  end
@@ -2,10 +2,16 @@ require "browser_sniffer/version"
2
2
  require "browser_sniffer/patterns"
3
3
 
4
4
  class BrowserSniffer
5
+ MAX_USER_AGENT_LENGTH = 512
6
+
5
7
  attr_reader :user_agent
6
8
 
7
9
  def initialize(user_agent)
8
- @user_agent = user_agent
10
+ @user_agent = if user_agent.is_a?(String)
11
+ user_agent[0, MAX_USER_AGENT_LENGTH]
12
+ else
13
+ user_agent
14
+ end
9
15
  end
10
16
 
11
17
  def ios?
@@ -1439,8 +1439,70 @@ class BrowserSnifferTest < Minitest::Test
1439
1439
  :device_vendor => 'Onyx',
1440
1440
  :device_name => 'NoteAir3C',
1441
1441
  },
1442
+ :shopify_pos_android_native => {
1443
+ :user_agent => "Mozilla/5.0 (Linux; Android 10; SM-G973U Build/QP1A.190711.020) POS 1.0",
1444
+ :form_factor => :handheld,
1445
+ :ios? => false,
1446
+ :android? => true,
1447
+ :desktop? => false,
1448
+ :os => :android,
1449
+ :os_version => "10",
1450
+ :device_name => 'SM-G973U',
1451
+ },
1452
+ :shopify_pos_android_native_with_locale => {
1453
+ :user_agent => "Mozilla/5.0 (Linux; U; Android 7.1.1; en-US; SM-T560NU Build/NMF26X) POS 2.4.10",
1454
+ :form_factor => :handheld,
1455
+ :ios? => false,
1456
+ :android? => true,
1457
+ :desktop? => false,
1458
+ :os => :android,
1459
+ :os_version => "7.1.1",
1460
+ :device_name => 'SM-T560NU',
1461
+ },
1462
+ :shopify_pos_android_smartwebview => {
1463
+ :user_agent => "Shopify POS/1.0 Mozilla/5.0 (Linux; Android 10; SM-G973U Build/QP1A.190711.020) POS 1.0",
1464
+ :form_factor => :handheld,
1465
+ :ios? => false,
1466
+ :android? => true,
1467
+ :desktop? => false,
1468
+ :os => :android,
1469
+ :os_version => "10",
1470
+ :device_name => 'SM-G973U',
1471
+ },
1472
+ :shopify_pos_android_smartwebview_with_locale => {
1473
+ :user_agent => "Shopify POS/2.4.10 Mozilla/5.0 (Linux; U; Android 7.1.1; en-US; SM-T560NU Build/NMF26X) POS 2.4.10",
1474
+ :form_factor => :handheld,
1475
+ :ios? => false,
1476
+ :android? => true,
1477
+ :desktop? => false,
1478
+ :os => :android,
1479
+ :os_version => "7.1.1",
1480
+ :device_name => 'SM-T560NU',
1481
+ },
1442
1482
  }
1443
1483
 
1484
+ def test_nil_user_agent_is_preserved
1485
+ assert_nil BrowserSniffer.new(nil).user_agent
1486
+ end
1487
+
1488
+ def test_user_agent_length_is_capped
1489
+ long_user_agent = "a" * 10_000
1490
+ sniffer = BrowserSniffer.new(long_user_agent)
1491
+ assert_equal BrowserSniffer::MAX_USER_AGENT_LENGTH, sniffer.user_agent.length
1492
+ end
1493
+
1494
+ def test_pos_android_regex_does_not_backtrack_catastrophically
1495
+ malicious_user_agent = ("(Android 1.0; a Build/" * 160) + "!"
1496
+ time = Benchmark.realtime { BrowserSniffer.new(malicious_user_agent).form_factor }
1497
+ assert time < 0.1, "Expected POS Android regex to reject crafted UA quickly, took #{time}s"
1498
+ end
1499
+
1500
+ def test_ios_os_regex_does_not_backtrack_catastrophically
1501
+ malicious_user_agent = "iphone os " + ("a" * 320) + "!"
1502
+ time = Benchmark.realtime { BrowserSniffer.new(malicious_user_agent).os }
1503
+ assert time < 0.1, "Expected iOS OS regex to reject crafted UA quickly, took #{time}s"
1504
+ end
1505
+
1444
1506
  AGENTS.each do |agent, attributes|
1445
1507
  define_method "test_sniff_#{agent}_correctly" do
1446
1508
  sniffer = BrowserSniffer.new(attributes[:user_agent])
data/test/test_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $VERBOSE = true
2
2
 
3
+ require 'benchmark'
3
4
  require 'minitest/autorun'
4
5
 
5
6
  require "#{File.dirname(__FILE__)}/../init"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browser_sniffer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify