browserino 3.0.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/.travis.yml +6 -7
- data/bin/browserino +20 -52
- data/bin/console +5 -8
- data/browserino.gemspec +2 -6
- data/lib/browserino/client.rb +216 -0
- data/lib/browserino/config.rb +90 -0
- data/lib/browserino/definitions/aliasses.rb +12 -0
- data/lib/browserino/definitions/filters.rb +67 -0
- data/lib/browserino/definitions/labels.rb +45 -0
- data/lib/browserino/definitions/matchers.rb +290 -0
- data/lib/browserino/identity.rb +55 -0
- data/lib/browserino/integrate/action_controller.rb +4 -2
- data/lib/browserino/integrate/rails.rb +2 -0
- data/lib/browserino/methods.rb +110 -0
- data/lib/browserino/options.rb +44 -0
- data/lib/browserino/version.rb +72 -1
- data/lib/browserino.rb +16 -58
- metadata +15 -61
- data/lib/browserino/agent.rb +0 -116
- data/lib/browserino/browser.rb +0 -28
- data/lib/browserino/console.rb +0 -10
- data/lib/browserino/core/alias.rb +0 -23
- data/lib/browserino/core/helpers.rb +0 -141
- data/lib/browserino/core/lies.rb +0 -14
- data/lib/browserino/core/mapping.rb +0 -78
- data/lib/browserino/core/patterns.rb +0 -142
- data/lib/browserino/core/questions.rb +0 -88
- data/lib/browserino/core/supported.rb +0 -31
- data/lib/browserino/engine.rb +0 -16
- data/lib/browserino/operating_system.rb +0 -33
- data/lib/browserino/unknown.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bdd2af440a3b1476900a3cdd36d2905660053c6
|
4
|
+
data.tar.gz: 0c7a2151e6ec79341ba5dda81eceddef2e8128ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb4d367fb7cfd3bd9cf637998de4a41549e18f20aaa0f14e007cb28883aff70b66e4beb75f757d99fe299b61a77db0c4322b90da74691e30677c524428a1c3eb
|
7
|
+
data.tar.gz: c13adf9ce004e08c5504b07367c5f362446ca06dbc6abe372872f703cca9694e8b3dd6f8fd7900970dea265a917e5d37ca9e951aef94176f241afaa4eba3f82c
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
language: ruby
|
2
|
-
cache: bundler
|
3
2
|
rvm:
|
4
|
-
- 2.3.1
|
5
|
-
- 2.3.0
|
6
|
-
- 2.2.1
|
7
|
-
- 2.1.0
|
8
3
|
- 2.0.0
|
9
|
-
|
10
|
-
|
4
|
+
- 2.1.0
|
5
|
+
- 2.2.0
|
6
|
+
- 2.3.0
|
7
|
+
- 2.4.0
|
8
|
+
before_install: gem install bundler
|
9
|
+
script: bundle exec rspec spec
|
data/bin/browserino
CHANGED
@@ -1,60 +1,28 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
2
|
require 'bundler/setup'
|
3
|
+
require 'pry'
|
4
4
|
require_relative '../lib/browserino'
|
5
5
|
|
6
|
-
|
6
|
+
props = Browserino.parse(ARGV[0].dup).properties
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
puts Browserino.parse(ARGV[1]).to_console_s
|
12
|
-
else
|
13
|
-
puts ' Usage: browserino parse [ua]'
|
14
|
-
puts ' * ua: the user agent string you want to parse'
|
15
|
-
end
|
16
|
-
when 'list', '-l'
|
17
|
-
ARGV[1] ||= 'info'
|
18
|
-
type = (ARGV[1].to_s.gsub(/[\s\-]/, '_')).to_sym
|
19
|
-
if type == :info
|
20
|
-
puts ' Usage: browserino list [subject]'
|
21
|
-
puts ' * subject: the type you want to display'
|
22
|
-
puts ' * all - list everything that is supported'
|
23
|
-
puts ' * bots - list supported bots'
|
24
|
-
puts ' * browsers - list supported browsers'
|
25
|
-
puts ' * social-media - list supported social media'
|
26
|
-
puts ' * search-engines - list supported search engines'
|
27
|
-
puts ' * consoles - list supported consoles'
|
28
|
-
puts ' * libraries - list supported libraries'
|
29
|
-
puts ' * operating-systems - list supported operating systems'
|
30
|
-
else
|
31
|
-
res = {}
|
32
|
-
res[:bots] = Browserino::Core::SUPPORTED[:bots] - aliasses if type == :all || type == :bots
|
33
|
-
res[:browsers] = Browserino::Core::SUPPORTED[:browsers] - aliasses if type == :all || type == :browsers
|
34
|
-
res[:consoles] = Browserino::Core::SUPPORTED[:consoles] - aliasses if type == :all || type == :consoles
|
35
|
-
res[:libraries] = Browserino::Core::SUPPORTED[:libraries] - aliasses if type == :all || type == :libraries
|
36
|
-
res[:social_media] = Browserino::Core::SUPPORTED[:social_media] - aliasses if type == :all || type == :social_media
|
37
|
-
res[:search_engines] = Browserino::Core::SUPPORTED[:search_engines] - aliasses if type == :all || type == :search_engines
|
38
|
-
res[:operating_systems] = Browserino::Core::SUPPORTED[:operating_systems] - aliasses if type == :all || type == :operating_systems
|
8
|
+
parsed = props.each_with_object({}) do |(prop, val), store|
|
9
|
+
store[prop] = val.to_s
|
10
|
+
end
|
39
11
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
puts out
|
45
|
-
end
|
46
|
-
when 'console', '-c'
|
47
|
-
require 'pry'
|
48
|
-
puts "Starting Browserino #{Browserino::VERSION} on Ruby #{RUBY_VERSION}"
|
49
|
-
Pry.start
|
12
|
+
max_key_len = parsed.keys.map(&:size).max
|
13
|
+
max_val_len = parsed.values.map(&:size).max
|
14
|
+
spacing = 2
|
15
|
+
spacer = ' ' * spacing
|
50
16
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
puts "\n"
|
57
|
-
puts ' * parse or -p - parse a user agent'
|
58
|
-
puts ' * list or -l - list supported entities'
|
59
|
-
puts ' * console or -c - enter a console'
|
17
|
+
out = parsed.map do |pair|
|
18
|
+
key = [spacer, pair[0], spacer].join.ljust(max_key_len + (spacing * 2))
|
19
|
+
val = [spacer, pair[1], spacer].join.ljust(max_val_len + (spacing * 2))
|
20
|
+
tmp = [key, val].join '|'
|
21
|
+
"|#{tmp}|\n"
|
60
22
|
end
|
23
|
+
|
24
|
+
row = '+' * (out.map(&:size).max - 1) + "\n"
|
25
|
+
|
26
|
+
out[0] = "#{row}#{out[0]}"
|
27
|
+
out[-1] = "#{out[-1]}#{row}"
|
28
|
+
puts out.join("#{row}")
|
data/bin/console
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'bundler/setup'
|
4
|
-
require 'browserino'
|
5
4
|
require 'pry'
|
5
|
+
require 'browserino'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
puts "> You can create a fresh object by using\n"
|
12
|
-
puts "> Browserino.parse([string] ua)\n\n"
|
13
|
-
puts "> ua - The user agent you'd actually want to parse as a string"
|
7
|
+
@client = Browserino.parse ARGV[0].dup || 'Mozilla/5.0 (Macintosh; Intel Mac\
|
8
|
+
OS X 10_11_2) AppleWebKit/601.3.9\
|
9
|
+
(KHTML, l ike Gecko) Version/9.0.\
|
10
|
+
2 Safari/601.3.9'
|
14
11
|
|
15
12
|
Pry.start
|
data/browserino.gemspec
CHANGED
@@ -8,7 +8,6 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Browserino::VERSION
|
9
9
|
spec.authors = ["Sidney Liebrand"]
|
10
10
|
spec.email = ["sidneyliebrand@gmail.com"]
|
11
|
-
|
12
11
|
spec.summary = %q{A browser identification gem with command line and Rails (>= 3.2.0) integration}
|
13
12
|
spec.homepage = "https://sidofc.github.io/projects/browserino/"
|
14
13
|
spec.license = "MIT"
|
@@ -18,12 +17,9 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.executables = ['browserino']
|
19
18
|
spec.require_paths = ["lib"]
|
20
19
|
|
21
|
-
spec.add_development_dependency "
|
22
|
-
spec.add_development_dependency "
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_development_dependency "term-ansicolor"
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
21
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
25
22
|
spec.add_development_dependency "rspec"
|
26
|
-
spec.add_development_dependency "tins"
|
27
23
|
spec.add_development_dependency "coveralls"
|
28
24
|
spec.add_development_dependency "pry"
|
29
25
|
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Browserino
|
3
|
+
class Client
|
4
|
+
attr_reader :property_names
|
5
|
+
|
6
|
+
def initialize(props = {}, like = nil)
|
7
|
+
@property_names = props.is_a?(Hash) && props.keys || []
|
8
|
+
@like = like if like
|
9
|
+
# properties are added as methods that will each be defined in a specific
|
10
|
+
# order below. First, seperate static value methods from procs,
|
11
|
+
# procs will be able to call methods in this instances' context
|
12
|
+
# therefore we need to define static methods before procs
|
13
|
+
|
14
|
+
# for each static property:
|
15
|
+
# -- define a method that returns it's property value
|
16
|
+
# -- define a question method that returns it's property value or
|
17
|
+
# checks version against supplied value if truthy
|
18
|
+
define_simple_methods! props
|
19
|
+
|
20
|
+
# for each proc property:
|
21
|
+
# -- define a method that returns it's instance evalled block value
|
22
|
+
# -- define a question method that returns it's instance evalled block
|
23
|
+
# value or checks version against supplied value if truthy
|
24
|
+
define_proc_methods! props
|
25
|
+
|
26
|
+
# for each of #name, #engine and #platform, use their results as
|
27
|
+
# methods names, this will create a method #firefox? for the output
|
28
|
+
# of a #name # => :firefox for example.
|
29
|
+
define_name_result_methods!
|
30
|
+
|
31
|
+
# finally, add labels and their aliasses into the mix
|
32
|
+
# none of these methods should override an existing method
|
33
|
+
# therefore we check it's existence using defined?
|
34
|
+
define_label_methods!
|
35
|
+
end
|
36
|
+
|
37
|
+
def properties
|
38
|
+
@properties ||= @property_names.each_with_object({}) do |prop, result|
|
39
|
+
result[prop] = send prop
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def like
|
44
|
+
@like ||= self
|
45
|
+
end
|
46
|
+
|
47
|
+
def like?(sym = nil, opts = {})
|
48
|
+
opts = sym if sym.is_a? Hash
|
49
|
+
must = []
|
50
|
+
must << like.is?(sym) if sym
|
51
|
+
must << like.version?(opts[:version]) if opts[:version]
|
52
|
+
|
53
|
+
must.any? && must.all?
|
54
|
+
end
|
55
|
+
|
56
|
+
def x64?
|
57
|
+
@x64_cache ||= architecture == :x64
|
58
|
+
end
|
59
|
+
|
60
|
+
def x32?
|
61
|
+
@x32_cache ||= architecture == :x32
|
62
|
+
end
|
63
|
+
|
64
|
+
# check the type of a Client
|
65
|
+
def type?(sym)
|
66
|
+
return type == sym if sym.is_a? Symbol
|
67
|
+
type == sym.to_sym
|
68
|
+
end
|
69
|
+
|
70
|
+
# the catch all method, anything it can ask as question will respond
|
71
|
+
# otherwise nil is returned, this is also true when supplying a version
|
72
|
+
def is?(sym, opts = {})
|
73
|
+
return send "#{sym}?", opts[:version] if opts[:version]
|
74
|
+
send "#{sym}?"
|
75
|
+
end
|
76
|
+
|
77
|
+
def ===(other)
|
78
|
+
return false unless name
|
79
|
+
|
80
|
+
case other
|
81
|
+
when Regexp then other =~ name
|
82
|
+
when String then other.to_sym == name
|
83
|
+
when Symbol, Browserino::Client then other == name
|
84
|
+
else false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def ==(other)
|
89
|
+
self === other
|
90
|
+
end
|
91
|
+
|
92
|
+
def =~(other)
|
93
|
+
self === other
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_str
|
97
|
+
to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_json(*args)
|
101
|
+
@json_cache ||= properties.map do |prop, val|
|
102
|
+
final = val.is_a?(Version) && val.full || val
|
103
|
+
[prop, final]
|
104
|
+
end.to_h.to_json(*args)
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
@str_cache ||= [:name, :engine, :platform].map do |prop|
|
109
|
+
name = send prop
|
110
|
+
ver = version if prop == :name
|
111
|
+
ver = send "#{prop}_version" if ver.nil?
|
112
|
+
|
113
|
+
[[name], [name, (ver.major if ver > '0.0.0')].compact.join.to_sym]
|
114
|
+
end.flatten.uniq.join(' ').gsub(/\s{2,}/, ' ').strip
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_hash
|
118
|
+
properties
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_h
|
122
|
+
properties
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_a
|
126
|
+
properties.to_a
|
127
|
+
end
|
128
|
+
|
129
|
+
# scary, I know, but a falsy value is all we need to return if some
|
130
|
+
# property isn't known or true as any property can be defined on the Client
|
131
|
+
def method_missing(_, *__, &___)
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
# always respond to missing, read method_missing comment
|
136
|
+
def respond_to_missing?(_, *__, &___)
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def define_simple_methods!(props)
|
143
|
+
props.reject { |val| val.respond_to? :call }.each do |name, value|
|
144
|
+
define_singleton_method(name) { value }
|
145
|
+
define_singleton_method("#{name}?") do |val = nil, **opts|
|
146
|
+
values = [value, *Browserino.config.aliasses[value]]
|
147
|
+
return values.include? val if val && !opts[:version]
|
148
|
+
if val && opts[:version]
|
149
|
+
ver_res = send(name == :name ? :version : "#{name}_version")
|
150
|
+
return (ver_res == opts[:version]) && values.include?(val)
|
151
|
+
end
|
152
|
+
return value > 0 if value.is_a? Version
|
153
|
+
value && true
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def define_proc_methods!(props)
|
159
|
+
props.select { |_, val| val.respond_to? :call }.each do |name, value|
|
160
|
+
result = instance_eval(&value)
|
161
|
+
define_singleton_method(name) { result }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def define_name_result_methods!
|
166
|
+
[:name, :engine, :platform].each do |prop|
|
167
|
+
result = send prop
|
168
|
+
ver_res = version if prop == :name
|
169
|
+
ver_res = send("#{prop}_version") if ver_res.nil?
|
170
|
+
|
171
|
+
# for each of the props:
|
172
|
+
# -- define a question method using the value of prop
|
173
|
+
# (ex: name # => firefox # => "firefox?")
|
174
|
+
# -- when supplied with a value, check it against {prop_res}_version
|
175
|
+
# -- when called without argument, return result
|
176
|
+
define_singleton_method("#{result}?") do |value = nil|
|
177
|
+
return ver_res == value if value
|
178
|
+
result && true
|
179
|
+
end
|
180
|
+
|
181
|
+
# for each of the aliasses found:
|
182
|
+
# -- define a question method using the current alias
|
183
|
+
# -- when supplied with a value, check it against {prop_res}_version
|
184
|
+
# -- when called without argument, return result
|
185
|
+
Browserino.config.aliasses[result].each do |alt|
|
186
|
+
define_singleton_method("#{alt}?") do |value = nil|
|
187
|
+
return ver_res == value if value
|
188
|
+
result && true
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def define_label_methods!
|
195
|
+
property_names.select { |name| name =~ /label/i }.each do |prop|
|
196
|
+
next unless (result = send(prop))
|
197
|
+
|
198
|
+
ver_type = prop.to_s.gsub /_?label/, ''
|
199
|
+
ver_res = version if ver_type.empty?
|
200
|
+
ver_res = send("#{ver_type}_version") unless prop == :label
|
201
|
+
|
202
|
+
define_singleton_method("#{result}?") do |value = nil|
|
203
|
+
return ver_res == value if value
|
204
|
+
result && true
|
205
|
+
end
|
206
|
+
|
207
|
+
Browserino.config.aliasses[result].each do |alt|
|
208
|
+
define_singleton_method("#{alt}?") do |value = nil|
|
209
|
+
return ver_res == value if value
|
210
|
+
result && true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Browserino
|
3
|
+
class Config < Options
|
4
|
+
def define(&block)
|
5
|
+
instance_eval(&block)
|
6
|
+
return unless identities.any? && identities.all?
|
7
|
+
|
8
|
+
identities.each do |identity|
|
9
|
+
properties << identity.properties.keys
|
10
|
+
types << identity.type
|
11
|
+
names << identity.name
|
12
|
+
end
|
13
|
+
|
14
|
+
properties.flatten!.uniq!
|
15
|
+
types.uniq!
|
16
|
+
names.uniq!
|
17
|
+
end
|
18
|
+
|
19
|
+
def label(name, **opts)
|
20
|
+
return false unless opts[:for]
|
21
|
+
opts[:name] ||= name
|
22
|
+
labels[opts[:for]] << opts
|
23
|
+
end
|
24
|
+
|
25
|
+
def filter(*props, &block)
|
26
|
+
props << :global unless props.any?
|
27
|
+
props.each { |prop| filters[prop] << block }
|
28
|
+
end
|
29
|
+
|
30
|
+
def smart_match(prop, **options)
|
31
|
+
smart_matchers[prop] = options if options[:with]
|
32
|
+
end
|
33
|
+
|
34
|
+
def match(rgxp = nil, **opts, &block)
|
35
|
+
rgxp, opts = [nil, rgxp] if rgxp.is_a? Hash
|
36
|
+
opts = @tmp_defaults.merge opts if @tmp_defaults.is_a? Hash
|
37
|
+
|
38
|
+
if rgxp && opts[:like]
|
39
|
+
identities.unshift with_alias(rgxp, opts, &block)
|
40
|
+
elsif rgxp
|
41
|
+
identities << Identity.new(rgxp, opts, &block)
|
42
|
+
else
|
43
|
+
global_identities.unshift Identity.new(&block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def alias_for(name, *names)
|
48
|
+
aliasses[name] += names
|
49
|
+
end
|
50
|
+
|
51
|
+
def before_parse(&block)
|
52
|
+
@options[:before_parse] << block if block
|
53
|
+
@options[:before_parse]
|
54
|
+
end
|
55
|
+
|
56
|
+
def preset(props, &block)
|
57
|
+
@tmp_defaults = props
|
58
|
+
instance_eval(&block)
|
59
|
+
@tmp_defaults = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def like(tmp, &block)
|
63
|
+
preset like: tmp.to_sym, &block
|
64
|
+
end
|
65
|
+
|
66
|
+
def validators(&block)
|
67
|
+
preset type: :validator, &block
|
68
|
+
end
|
69
|
+
|
70
|
+
def browsers(&block)
|
71
|
+
preset type: :browser, &block
|
72
|
+
end
|
73
|
+
|
74
|
+
def bots(&block)
|
75
|
+
preset type: :bot, &block
|
76
|
+
end
|
77
|
+
|
78
|
+
def libraries(&block)
|
79
|
+
preset type: :library, &block
|
80
|
+
end
|
81
|
+
|
82
|
+
def with_alias(pattern, **opts, &block)
|
83
|
+
id = identities.select { |id| id == opts[:like] }.first
|
84
|
+
|
85
|
+
raise "No alias found for: #{opts[:like] || 'nil'}" unless id
|
86
|
+
|
87
|
+
Identity.new pattern, id.properties.merge(opts), &block
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Browserino.config.define do
|
3
|
+
# aliasses will be defined after a Client has been initialized
|
4
|
+
# only the aliasses matching the Client will be defined
|
5
|
+
alias_for :firefox, :ff
|
6
|
+
alias_for :windows, :win
|
7
|
+
alias_for :macintosh, :mac, :osx, :macos
|
8
|
+
alias_for :blackberry, :bb
|
9
|
+
alias_for :ie, :internet_explorer
|
10
|
+
alias_for :facebook, :fb
|
11
|
+
alias_for :duckduckgo, :ddg
|
12
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Browserino.config.define do
|
3
|
+
# executes before parsing the user agent, 's' in this case is the actual
|
4
|
+
# user agent string in full glory. Do manipulations as you wish, I'm
|
5
|
+
# using it to successfully strip lies from the user agent and to sometimes
|
6
|
+
# simplify a word e.g. 'AppleWebKit' => 'webkit'
|
7
|
+
|
8
|
+
# the returned result will be used as the user agent to parse so make
|
9
|
+
# sure to return the final ua at the end
|
10
|
+
before_parse do |ua|
|
11
|
+
ua = ua.gsub(%r{applewebkit}i, 'webkit').gsub %r{(Mozilla/[\d\.]+)}i, ''
|
12
|
+
ua = ua.gsub(%r{chrome|safari}i, '').gsub('OPR', 'opera') if ua =~ %r{OPR}
|
13
|
+
ua = ua.gsub %r{9\.80}, '' if ua =~ %r{opera}i
|
14
|
+
ua = ua.gsub %r{webkit/}i, '' if ua =~ %r{presto}i
|
15
|
+
ua = ua.gsub %r{(?:ms)?ie}i, '' if ua =~ %r{rv:}i
|
16
|
+
ua = ua.gsub %r{android|linux}i, '' if ua =~ %r{tizen}i
|
17
|
+
ua = ua.gsub %r{linux}i, '' if ua =~ %r{android|s(unos|olaris)|w(eb)?os}i
|
18
|
+
ua = ua.gsub %r{x11}i, '' if ua =~ %r{bsd|s(unos|olaris)}i
|
19
|
+
ua = ua.gsub %r{windows\snt}i, '' if ua =~ %r{windows\sphone}i
|
20
|
+
ua = ua.gsub %r{rv:}i, '' if ua =~ %r{servo}i
|
21
|
+
ua = ua.gsub %r{mac\sos\sx}i, '' if ua =~ %r{ip(?:[ao]d|hone)}i
|
22
|
+
ua = ua.gsub %r{msie}i, '' if ua =~ %r{huaweisymantecspider}i
|
23
|
+
ua
|
24
|
+
end
|
25
|
+
|
26
|
+
# after an identity is found, it's values are filtered in two stages
|
27
|
+
# first, filters will parse all statically defined values (e.g.) no regexp
|
28
|
+
# or block within matchers, after that, smart matcher patterns will be
|
29
|
+
# conditionally added and parsed with the previously collected values and
|
30
|
+
# then also filtered
|
31
|
+
|
32
|
+
# this is a global filter, multiple can be defined and they will all run
|
33
|
+
# before any named filters
|
34
|
+
filter do |value|
|
35
|
+
case value
|
36
|
+
when TrueClass, FalseClass, NilClass, Proc then value
|
37
|
+
when %r{\A[\d_\.]+\z}i then value.to_s.strip.tr('_', '.')
|
38
|
+
else value.to_s.downcase.strip.gsub(%r{[\s-]+}i, '_').to_sym
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# this is a named filter, it defines the same filter for 3 properties
|
43
|
+
# multiple name filters for the same property can be created, they will be
|
44
|
+
# executed in order of addition
|
45
|
+
filter :version, :engine_version, :platform_version do |value|
|
46
|
+
Browserino::Version.new value
|
47
|
+
end
|
48
|
+
|
49
|
+
filter :platform do |value|
|
50
|
+
value = :ios if value =~ %r{ip(?:[ao]d|hone)}i
|
51
|
+
value = :webos if value =~ %r{w(?:eb)?os}i
|
52
|
+
value = :linux if value =~ %r{ubuntu|x11}i
|
53
|
+
value = :solaris if value =~ %r{s(?:unos|olaris)}i
|
54
|
+
value = :macintosh if value =~ %r{mac_os_x}i
|
55
|
+
value
|
56
|
+
end
|
57
|
+
|
58
|
+
filter :architecture do |value|
|
59
|
+
value = :x64 if value && value =~ %r{(?:x86_|amd|wow)?64|i686}i
|
60
|
+
value = :x32 if value && value != :x64
|
61
|
+
value
|
62
|
+
end
|
63
|
+
|
64
|
+
filter :mobile do |value|
|
65
|
+
!value.to_s.strip.empty?
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Browserino.config.define do
|
3
|
+
# labels will be defined before a client has been initialized
|
4
|
+
# they will not be filtered before being injected into the Client
|
5
|
+
|
6
|
+
# labels will be matched against values of #name, #engine and #platform and
|
7
|
+
# will create #label, #engine_label and #platform_label properties
|
8
|
+
# respectively. These enjoy all the features that regular defined properties
|
9
|
+
# in for instance methods enjoy, such as automatic question methods like
|
10
|
+
# client.platform_label? :mavericks
|
11
|
+
label :android, for: :android, range: '1'..'1.4.9'
|
12
|
+
label :cupcake, for: :android, range: '1.5'..'1.9.9'
|
13
|
+
label :eclair, for: :android, range: '2'..'2.1'
|
14
|
+
label :froyo, for: :android, range: '2.2'..'2.2.3'
|
15
|
+
label :gingerbread, for: :android, range: '2.2.4'..'2.3.7'
|
16
|
+
label :honeycomb, for: :android, range: '3'..'3.2.6'
|
17
|
+
label :ice_cream_sandwich, for: :android, range: '4'..'4.0.4'
|
18
|
+
label :jelly_bean, for: :android, range: '4.1'..'4.3.1'
|
19
|
+
label :kitkat, for: :android, range: '4.4'..'4.4.4'
|
20
|
+
label :lollipop, for: :android, range: '5'..'5.1.1'
|
21
|
+
label :marshmallow, for: :android, range: '6'..'6.1.1'
|
22
|
+
label :nougat, for: :android, range: '7'..'7.1.1'
|
23
|
+
|
24
|
+
label :cheetah, for: :macintosh, range: '10.0'..'10.0.9'
|
25
|
+
label :puma, for: :macintosh, range: '10.1'..'10.1.9'
|
26
|
+
label :jaguar, for: :macintosh, range: '10.2'..'10.2.9'
|
27
|
+
label :panther, for: :macintosh, range: '10.3'..'10.3.9'
|
28
|
+
label :tiger, for: :macintosh, range: '10.4'..'10.4.9'
|
29
|
+
label :leopard, for: :macintosh, range: '10.5'..'10.5.9'
|
30
|
+
label :snow_leopard, for: :macintosh, range: '10.6'..'10.6.9'
|
31
|
+
label :lion, for: :macintosh, range: '10.7'..'10.7.9'
|
32
|
+
label :mountain_lion, for: :macintosh, range: '10.8'..'10.8.9'
|
33
|
+
label :mavericks, for: :macintosh, range: '10.9'..'10.9.9'
|
34
|
+
label :yosemite, for: :macintosh, range: '10.10'..'10.10.9'
|
35
|
+
label :el_capitan, for: :macintosh, range: '10.11'..'10.11.9'
|
36
|
+
label :sierra, for: :macintosh, range: '10.12'..'10.12.9'
|
37
|
+
|
38
|
+
label :windows_dos, for: :windows, range: '3.1'..'4.0'
|
39
|
+
label :windows_2000, for: :windows, range: '5.0'..'5.0.9'
|
40
|
+
label :windows_xp, for: :windows, range: '5.1'..'5.2.9'
|
41
|
+
label :windows_vista, for: :windows, range: '6.0'..'6.0.9'
|
42
|
+
label :windows_7, for: :windows, range: '6.1'..'6.1.9'
|
43
|
+
label :windows_8, for: :windows, range: '6.2'..'6.3'
|
44
|
+
label :windows_10, for: :windows, range: '10.0'..'10.0.9'
|
45
|
+
end
|