ronin-web-user_agents 0.1.0.beta1
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 +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +5 -0
- data/Gemfile +26 -0
- data/README.md +177 -0
- data/Rakefile +34 -0
- data/corpus/.gitkeep +0 -0
- data/data/android/devices.txt +1393 -0
- data/data/chrome/versions.txt +394 -0
- data/data/firefox/langs.txt +125 -0
- data/data/firefox/versions.txt +584 -0
- data/gemspec.yml +21 -0
- data/lib/ronin/web/user_agents/chrome.rb +301 -0
- data/lib/ronin/web/user_agents/data_dir.rb +30 -0
- data/lib/ronin/web/user_agents/firefox.rb +360 -0
- data/lib/ronin/web/user_agents/google_bot.rb +140 -0
- data/lib/ronin/web/user_agents/os/android.rb +79 -0
- data/lib/ronin/web/user_agents/os/linux.rb +52 -0
- data/lib/ronin/web/user_agents/os/mac_os.rb +116 -0
- data/lib/ronin/web/user_agents/os/windows.rb +53 -0
- data/lib/ronin/web/user_agents/version.rb +28 -0
- data/lib/ronin/web/user_agents.rb +142 -0
- data/ronin-web-user_agents.gemspec +61 -0
- data/scripts/index_user_agents +281 -0
- data/spec/chrome_spec.rb +511 -0
- data/spec/firefox_spec.rb +414 -0
- data/spec/google_bot_spec.rb +231 -0
- data/spec/os/android_spec.rb +55 -0
- data/spec/os/linux_spec.rb +48 -0
- data/spec/os/mac_os_spec.rb +73 -0
- data/spec/os/windows_spec.rb +52 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/user_agents_spec.rb +49 -0
- metadata +110 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-user_agents - Yet another User-Agent string generator library.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-user_agents is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-user_agents is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-user_agents. If not, see <https://www.gnu.org/licenses/>
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/web/user_agents/os/windows'
|
22
|
+
require 'ronin/web/user_agents/os/mac_os'
|
23
|
+
require 'ronin/web/user_agents/os/linux'
|
24
|
+
require 'ronin/web/user_agents/os/android'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Web
|
28
|
+
module UserAgents
|
29
|
+
#
|
30
|
+
# Represents every possible Chrome `User-Agent` string.
|
31
|
+
#
|
32
|
+
module Chrome
|
33
|
+
|
34
|
+
#
|
35
|
+
# Builds a new Chrome `User-Agent` string.
|
36
|
+
#
|
37
|
+
# @param [String] chrome_version
|
38
|
+
# The `Chrome/...` version.
|
39
|
+
#
|
40
|
+
# @param [:windows, :macos, :linux, :android] os
|
41
|
+
# The Operating System.
|
42
|
+
#
|
43
|
+
# @param [String, nil] os_version
|
44
|
+
# The Operating System version. Is required if `os:` is `:windows`,
|
45
|
+
# `:macos`, or `:android`.
|
46
|
+
#
|
47
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
48
|
+
# The optional Linux Distro. Only supported if `os:` is `:linux`.
|
49
|
+
#
|
50
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm] arch
|
51
|
+
# The hardware architecture. Can be omitted if `os:` is `:android`.
|
52
|
+
#
|
53
|
+
# @param [String, nil] android_device
|
54
|
+
# The Android device. Only supported if `os:` is `:android`.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
# The new `User-Agent` string.
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
#
|
61
|
+
def self.build(chrome_version: ,
|
62
|
+
os: ,
|
63
|
+
os_version: nil,
|
64
|
+
linux_distro: nil,
|
65
|
+
arch: nil,
|
66
|
+
android_device: nil)
|
67
|
+
case os
|
68
|
+
when :windows
|
69
|
+
unless os_version
|
70
|
+
raise(ArgumentError,"os: :windows also requires an os_version: value")
|
71
|
+
end
|
72
|
+
|
73
|
+
build_windows(
|
74
|
+
chrome_version: chrome_version,
|
75
|
+
windows_version: os_version,
|
76
|
+
arch: arch
|
77
|
+
)
|
78
|
+
when :macos
|
79
|
+
unless os_version
|
80
|
+
raise(ArgumentError,"os: :macos also requires an os_version: value")
|
81
|
+
end
|
82
|
+
|
83
|
+
build_macos(
|
84
|
+
chrome_version: chrome_version,
|
85
|
+
macos_version: os_version,
|
86
|
+
arch: arch || :intel
|
87
|
+
)
|
88
|
+
when :linux
|
89
|
+
unless arch
|
90
|
+
raise(ArgumentError,"os: :linux also requires an arch: value")
|
91
|
+
end
|
92
|
+
|
93
|
+
build_linux(
|
94
|
+
chrome_version: chrome_version,
|
95
|
+
linux_distro: linux_distro,
|
96
|
+
arch: arch
|
97
|
+
)
|
98
|
+
when :android
|
99
|
+
unless os_version
|
100
|
+
raise(ArgumentError,"os: :android also requires an os_version: value")
|
101
|
+
end
|
102
|
+
|
103
|
+
build_android(
|
104
|
+
chrome_version: chrome_version,
|
105
|
+
android_version: os_version,
|
106
|
+
arch: arch,
|
107
|
+
android_device: android_device
|
108
|
+
)
|
109
|
+
else
|
110
|
+
raise(ArgumentError,"unsupported os: value (#{os.inspect})")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Known Chrome versions
|
115
|
+
KNOWN_VERSIONS = File.readlines(
|
116
|
+
File.join(DATA_DIR,'chrome','versions.txt'), chomp: true
|
117
|
+
)
|
118
|
+
|
119
|
+
# Supported Operating Systems.
|
120
|
+
SUPPORTED_OSES = [
|
121
|
+
:windows,
|
122
|
+
:macos,
|
123
|
+
:linux,
|
124
|
+
:android
|
125
|
+
]
|
126
|
+
|
127
|
+
# Known OS versions grouped by OS.
|
128
|
+
KNOWN_OS_VERSIONS = {
|
129
|
+
windows: OS::Windows::VERSIONS.keys,
|
130
|
+
macos: OS::MacOS::VERSIONS,
|
131
|
+
linux: [],
|
132
|
+
android: OS::Android::VERSIONS
|
133
|
+
}
|
134
|
+
|
135
|
+
# Supported architectures grouped by OS.
|
136
|
+
SUPPORTED_OS_ARCHES = {
|
137
|
+
windows: OS::Windows::ARCHES.keys,
|
138
|
+
macos: OS::MacOS::ARCHES.keys,
|
139
|
+
linux: OS::Linux::ARCHES.keys,
|
140
|
+
android: OS::Android::ARCHES.keys
|
141
|
+
}
|
142
|
+
|
143
|
+
# Supported Linux Distros.
|
144
|
+
SUPPORTED_LINUX_DISTROS = OS::Linux::DISTROS.keys
|
145
|
+
|
146
|
+
#
|
147
|
+
# Generates a random Chrome `User-Agent` string.
|
148
|
+
#
|
149
|
+
# @param [String] chrome_version
|
150
|
+
# The `Chrome/...` version.
|
151
|
+
#
|
152
|
+
# @param [:windows, :macos, :linux, :android] os
|
153
|
+
# The Operating System.
|
154
|
+
#
|
155
|
+
# @param [String, nil] os_version
|
156
|
+
# The Operating System version. Is required if `os:` is `:windows`,
|
157
|
+
# `:macos`, or `:android`.
|
158
|
+
#
|
159
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
160
|
+
# The optional Linux Distro. Only supported if `os:` is `:linux`.
|
161
|
+
#
|
162
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm] arch
|
163
|
+
# The hardware architecture. Can be omitted if `os:` is `:android`.
|
164
|
+
#
|
165
|
+
# @param [String, nil] android_device
|
166
|
+
# The Android device. Only supported if `os:` is `:android`.
|
167
|
+
#
|
168
|
+
# @return [String]
|
169
|
+
# The random `User-Agent` string.
|
170
|
+
#
|
171
|
+
# @api public
|
172
|
+
#
|
173
|
+
def self.random(chrome_version: KNOWN_VERSIONS.sample,
|
174
|
+
os: SUPPORTED_OSES.sample,
|
175
|
+
os_version: KNOWN_OS_VERSIONS[os].sample,
|
176
|
+
linux_distro: SUPPORTED_LINUX_DISTROS.sample,
|
177
|
+
arch: SUPPORTED_OS_ARCHES[os].sample,
|
178
|
+
android_device: OS::Android::DEVICES.sample)
|
179
|
+
build(
|
180
|
+
chrome_version: chrome_version,
|
181
|
+
os: os,
|
182
|
+
os_version: os_version,
|
183
|
+
linux_distro: linux_distro,
|
184
|
+
arch: arch,
|
185
|
+
android_device: android_device
|
186
|
+
)
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
#
|
192
|
+
# Builds a Chrome `User-Agent` string for Windows.
|
193
|
+
#
|
194
|
+
# @param [String] chrome_version
|
195
|
+
# The `Chrome/...` version.
|
196
|
+
#
|
197
|
+
# @param [String, nil] windows_version
|
198
|
+
# The Windows version.
|
199
|
+
#
|
200
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm] arch
|
201
|
+
# The hardware architecture.
|
202
|
+
#
|
203
|
+
# @return [String]
|
204
|
+
# The Chrome `User-Agent` string for Windows.
|
205
|
+
#
|
206
|
+
def self.build_windows(chrome_version: , windows_version: , arch: nil)
|
207
|
+
windows_version = OS::Windows::VERSIONS.fetch(windows_version,windows_version)
|
208
|
+
windows_arch = OS::Windows::ARCHES.fetch(arch) do
|
209
|
+
raise(ArgumentError,"unknown arch: value (#{arch.inspect})")
|
210
|
+
end
|
211
|
+
|
212
|
+
extensions = "Windows NT #{windows_version}"
|
213
|
+
extensions << "; #{windows_arch}" if windows_arch
|
214
|
+
|
215
|
+
return "Mozilla/5.0 (#{extensions}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Safari/537.36"
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# Builds a Chrome `User-Agent` string for macOS.
|
220
|
+
#
|
221
|
+
# @param [String] chrome_version
|
222
|
+
# The `Chrome/...` version.
|
223
|
+
#
|
224
|
+
# @param [String, nil] macos_version
|
225
|
+
# The macOS version.
|
226
|
+
#
|
227
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm] arch
|
228
|
+
# The hardware architecture.
|
229
|
+
#
|
230
|
+
# @return [String]
|
231
|
+
# The Chrome `User-Agent` string for macOS.
|
232
|
+
#
|
233
|
+
def self.build_macos(chrome_version: , macos_version: , arch: :intel)
|
234
|
+
macos_version = OS::MacOS::VERSIONS_UNDERSCORED[macos_version]
|
235
|
+
macos_arch = OS::MacOS::ARCHES.fetch(arch) do
|
236
|
+
raise(ArgumentError,"unknown arch: value (#{arch.inspect})")
|
237
|
+
end
|
238
|
+
|
239
|
+
return "Mozilla/5.0 (Macintosh; #{macos_arch} Mac OS X #{macos_version}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Safari/537.36"
|
240
|
+
end
|
241
|
+
|
242
|
+
#
|
243
|
+
# Builds a Chrome `User-Agent` string for Linux.
|
244
|
+
#
|
245
|
+
# @param [String] chrome_version
|
246
|
+
# The `Chrome/...` version.
|
247
|
+
#
|
248
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64] arch
|
249
|
+
# The hardware architecture.
|
250
|
+
#
|
251
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
252
|
+
# The optional Linux Distro.
|
253
|
+
#
|
254
|
+
# @return [String]
|
255
|
+
# The Chrome `User-Agent` string for Linux.
|
256
|
+
#
|
257
|
+
def self.build_linux(chrome_version: , arch: , linux_distro: nil)
|
258
|
+
linux_distro = OS::Linux::DISTROS.fetch(linux_distro,linux_distro)
|
259
|
+
linux_arch = OS::Linux::ARCHES.fetch(arch) do
|
260
|
+
raise(ArgumentError,"unknown arch: value (#{arch.inspect})")
|
261
|
+
end
|
262
|
+
|
263
|
+
extensions = String.new("X11")
|
264
|
+
extensions << "; #{linux_distro}" if linux_distro
|
265
|
+
extensions << "; Linux #{linux_arch}"
|
266
|
+
|
267
|
+
return "Mozilla/5.0 (#{extensions}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Safari/537.36"
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# Builds a Chrome `User-Agent` string for Android.
|
272
|
+
#
|
273
|
+
# @param [String] chrome_version
|
274
|
+
# The `Chrome/...` version.
|
275
|
+
#
|
276
|
+
# @param [String, nil] android_version
|
277
|
+
# The Android version.
|
278
|
+
#
|
279
|
+
# @param [:arm, :arm64, nil] arch
|
280
|
+
# The optional hardware architecture.
|
281
|
+
#
|
282
|
+
# @param [String, nil] android_device
|
283
|
+
# The optional Android device.
|
284
|
+
#
|
285
|
+
# @return [String]
|
286
|
+
# The Chrome `User-Agent` string for Android.
|
287
|
+
#
|
288
|
+
def self.build_android(chrome_version: , android_version: , arch: nil, android_device: nil)
|
289
|
+
arch = OS::Android::ARCHES.fetch(arch)
|
290
|
+
|
291
|
+
extensions = String.new("Linux")
|
292
|
+
extensions << "; #{arch}" if arch
|
293
|
+
extensions << "; Android #{android_version}"
|
294
|
+
extensions << "; #{android_device}" if android_device
|
295
|
+
|
296
|
+
return "Mozilla/5.0 (#{extensions}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Mobile Safari/537.36"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-user_agents - Yet another User-Agent string generator library.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-user_agents is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-user_agents is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-user_agents. If not, see <https://www.gnu.org/licenses/>
|
19
|
+
#
|
20
|
+
|
21
|
+
module Ronin
|
22
|
+
module Web
|
23
|
+
module UserAgents
|
24
|
+
# Path to the `data/` directory.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
DATA_DIR = File.expand_path('../../../../data',__dir__)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,360 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-user_agents - Yet another User-Agent string generator library.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-user_agents is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-user_agents is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-user_agents. If not, see <https://www.gnu.org/licenses/>
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/web/user_agents/os/windows'
|
22
|
+
require 'ronin/web/user_agents/os/mac_os'
|
23
|
+
require 'ronin/web/user_agents/os/linux'
|
24
|
+
require 'ronin/web/user_agents/os/android'
|
25
|
+
require 'ronin/web/user_agents/data_dir'
|
26
|
+
|
27
|
+
module Ronin
|
28
|
+
module Web
|
29
|
+
module UserAgents
|
30
|
+
#
|
31
|
+
# Represents all possible Firefox `User-Agent` strings.
|
32
|
+
#
|
33
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
|
34
|
+
#
|
35
|
+
module Firefox
|
36
|
+
|
37
|
+
# The default `Gecko/...` version.
|
38
|
+
#
|
39
|
+
# @note: On desktop, the `Gecko/...` version is hardcoded to `20100101`
|
40
|
+
DESKTOP_GECKO_VERSION = '20100101'
|
41
|
+
|
42
|
+
# Encryption Strengths.
|
43
|
+
#
|
44
|
+
# @see https://developers.whatismybrowser.com/useragents/notes/what-does-u-mean-in-a-user-agent
|
45
|
+
ENCRYPTION = {
|
46
|
+
usa: 'U',
|
47
|
+
international: 'I',
|
48
|
+
none: 'N',
|
49
|
+
no: 'N',
|
50
|
+
|
51
|
+
nil => nil
|
52
|
+
}
|
53
|
+
|
54
|
+
# Common device types.
|
55
|
+
DEVICE_TYPES = {
|
56
|
+
mobile: 'Mobile',
|
57
|
+
tablet: 'Tablet',
|
58
|
+
|
59
|
+
nil => nil
|
60
|
+
}
|
61
|
+
|
62
|
+
#
|
63
|
+
# Builds a new Firefox `User-Agent` string.
|
64
|
+
#
|
65
|
+
# @param [String] firefox_version
|
66
|
+
# The `rv:...` and `Firefox/...` version.
|
67
|
+
#
|
68
|
+
# @param [String, nil] lang
|
69
|
+
# The optional language identifier to add (ex: `en-GB`).
|
70
|
+
#
|
71
|
+
# @param [:usa, :international, :none, :no, nil] encryption
|
72
|
+
# The supported encryption strength.
|
73
|
+
#
|
74
|
+
# @param [:windows, :macos, :linux, :android] os
|
75
|
+
# The Operating System.
|
76
|
+
#
|
77
|
+
# @param [String, nil] os_version
|
78
|
+
# The Operating System version. Is required if `os:` is `:windows`,
|
79
|
+
# `:macos`, or `:android`.
|
80
|
+
#
|
81
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
82
|
+
# The optional Linux Distro. Only supported if `os:` is `:linux`.
|
83
|
+
#
|
84
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm, nil] arch
|
85
|
+
# The hardware architecture. Can be omitted if `os:` is `:android`.
|
86
|
+
#
|
87
|
+
# @param [:mobile, :tablet, nil] device_type
|
88
|
+
# The optional device type.
|
89
|
+
#
|
90
|
+
# @return [String]
|
91
|
+
# The Firefox `User-Agent` string.
|
92
|
+
#
|
93
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
#
|
97
|
+
def self.build(firefox_version: ,
|
98
|
+
lang: nil,
|
99
|
+
encryption: nil,
|
100
|
+
os: ,
|
101
|
+
os_version: nil,
|
102
|
+
linux_distro: nil,
|
103
|
+
arch: nil,
|
104
|
+
device_type: nil)
|
105
|
+
case os
|
106
|
+
when :windows
|
107
|
+
unless os_version
|
108
|
+
raise(ArgumentError,"os: :windows also requires an os_version: value")
|
109
|
+
end
|
110
|
+
|
111
|
+
build_windows(
|
112
|
+
windows_version: os_version,
|
113
|
+
arch: arch,
|
114
|
+
firefox_version: firefox_version
|
115
|
+
)
|
116
|
+
when :macos
|
117
|
+
unless os_version
|
118
|
+
raise(ArgumentError,"os: :macos also requires an os_version: value")
|
119
|
+
end
|
120
|
+
|
121
|
+
build_macos(
|
122
|
+
arch: arch || :intel,
|
123
|
+
macos_version: os_version,
|
124
|
+
firefox_version: firefox_version
|
125
|
+
)
|
126
|
+
when :linux
|
127
|
+
build_linux(
|
128
|
+
encryption: encryption,
|
129
|
+
linux_distro: linux_distro,
|
130
|
+
arch: arch,
|
131
|
+
lang: lang,
|
132
|
+
firefox_version: firefox_version
|
133
|
+
)
|
134
|
+
when :android
|
135
|
+
build_android(
|
136
|
+
device_type: device_type || :mobile,
|
137
|
+
firefox_version: firefox_version
|
138
|
+
)
|
139
|
+
else
|
140
|
+
raise(ArgumentError,"unsupported os: value (#{os.inspect})")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Known versions for the `rv:...` and `Firefox/...` values.
|
145
|
+
KNOWN_VERSIONS = File.readlines(
|
146
|
+
File.join(DATA_DIR,'firefox','versions.txt'), chomp: true
|
147
|
+
)
|
148
|
+
|
149
|
+
# Supported Operating Systems.
|
150
|
+
SUPPORTED_OSES = [
|
151
|
+
:windows,
|
152
|
+
:macos,
|
153
|
+
:linux,
|
154
|
+
:android
|
155
|
+
]
|
156
|
+
|
157
|
+
# Known OS versions grouped by OS.
|
158
|
+
KNOWN_OS_VERSIONS = {
|
159
|
+
windows: OS::Windows::VERSIONS.keys,
|
160
|
+
macos: OS::MacOS::VERSIONS,
|
161
|
+
linux: [],
|
162
|
+
android: OS::Android::VERSIONS
|
163
|
+
}
|
164
|
+
|
165
|
+
# Supported architectures grouped by OS.
|
166
|
+
SUPPORTED_OS_ARCHES = {
|
167
|
+
windows: OS::Windows::ARCHES.keys,
|
168
|
+
macos: OS::MacOS::ARCHES.keys,
|
169
|
+
linux: OS::Linux::ARCHES.keys,
|
170
|
+
android: OS::Android::ARCHES.keys
|
171
|
+
}
|
172
|
+
|
173
|
+
# Supported Linux Distros.
|
174
|
+
#
|
175
|
+
# @return [Array<Symbol, nil>]
|
176
|
+
SUPPORTED_LINUX_DISTROS = OS::Linux::DISTROS.keys
|
177
|
+
|
178
|
+
# Supported encryption strengths.
|
179
|
+
#
|
180
|
+
# @return [Array<Symbol, nil>]
|
181
|
+
SUPPORTED_ENCRYPTION = ENCRYPTION.keys
|
182
|
+
|
183
|
+
# IETF language tags (ex: `en-GB`).
|
184
|
+
#
|
185
|
+
# @return [Array<String>]
|
186
|
+
KNOWN_LANGS = File.readlines(
|
187
|
+
File.join(DATA_DIR,'firefox','langs.txt'), chomp: true
|
188
|
+
)
|
189
|
+
|
190
|
+
# Supported device types.
|
191
|
+
#
|
192
|
+
# @return [Array<Symbol, nil>]
|
193
|
+
SUPPORTED_DEVICE_TYPES = DEVICE_TYPES.keys
|
194
|
+
|
195
|
+
#
|
196
|
+
# Generates a random Firefox `User-Agent` string.
|
197
|
+
#
|
198
|
+
# @param [String] firefox_version
|
199
|
+
# The `rv:...` and `Firefox/...` version.
|
200
|
+
#
|
201
|
+
# @param [:usa, :international, :none, :no, nil] encryption
|
202
|
+
# The supported encryption strength.
|
203
|
+
#
|
204
|
+
# @param [String, nil] lang
|
205
|
+
# The optional language identifier to add (ex: `en-GB`).
|
206
|
+
#
|
207
|
+
# @param [:windows, :macos, :linux, :android] os
|
208
|
+
# The Operating System.
|
209
|
+
#
|
210
|
+
# @param [String, nil] os_version
|
211
|
+
# The Operating System version. Is required if `os:` is `:windows`,
|
212
|
+
# `:macos`, or `:android`.
|
213
|
+
#
|
214
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
215
|
+
# The optional Linux Distro. Only supported if `os:` is `:linux`.
|
216
|
+
#
|
217
|
+
# @param [:x86_64, :x86, :i686, :aarch64, :arm64, :arm, nil] arch
|
218
|
+
# The hardware architecture. Can be omitted if `os:` is `:android`.
|
219
|
+
#
|
220
|
+
# @param [:mobile, :tablet, nil] device_type
|
221
|
+
# The optional device type.
|
222
|
+
#
|
223
|
+
# @return [String]
|
224
|
+
# The random `User-Agent` string.
|
225
|
+
#
|
226
|
+
# @api public
|
227
|
+
#
|
228
|
+
def self.random(firefox_version: KNOWN_VERSIONS.sample,
|
229
|
+
encryption: SUPPORTED_ENCRYPTION.sample,
|
230
|
+
lang: KNOWN_LANGS.sample,
|
231
|
+
os: SUPPORTED_OSES.sample,
|
232
|
+
os_version: KNOWN_OS_VERSIONS[os].sample,
|
233
|
+
linux_distro: SUPPORTED_LINUX_DISTROS.sample,
|
234
|
+
arch: SUPPORTED_OS_ARCHES[os].sample,
|
235
|
+
device_type: DEVICE_TYPES.keys.sample)
|
236
|
+
build(
|
237
|
+
firefox_version: firefox_version,
|
238
|
+
os: os,
|
239
|
+
os_version: os_version,
|
240
|
+
device_type: device_type,
|
241
|
+
linux_distro: linux_distro,
|
242
|
+
arch: arch,
|
243
|
+
lang: lang
|
244
|
+
)
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
|
249
|
+
#
|
250
|
+
# Builds a Firefox `User-Agent` string for Windows.
|
251
|
+
#
|
252
|
+
# @param [String, nil] windows_version
|
253
|
+
# The Windows version.
|
254
|
+
#
|
255
|
+
# @param [:arm, :arm64, nil] arch
|
256
|
+
# The optional hardware architecture.
|
257
|
+
#
|
258
|
+
# @param [String] firefox_version
|
259
|
+
# The `Firefox/...` version.
|
260
|
+
#
|
261
|
+
# @return [String]
|
262
|
+
# A Firefox `User-Agent` string For Windows.
|
263
|
+
#
|
264
|
+
def self.build_windows(windows_version: , arch: , firefox_version: )
|
265
|
+
windows_version = OS::Windows::VERSIONS.fetch(windows_version,windows_version)
|
266
|
+
windows_arch = OS::Windows::ARCHES.fetch(arch)
|
267
|
+
|
268
|
+
extensions = "Windows NT #{windows_version}"
|
269
|
+
extensions << "; #{windows_arch}" if windows_arch
|
270
|
+
extensions << "; rv:#{firefox_version}"
|
271
|
+
|
272
|
+
return "Mozilla/5.0 (#{extensions}) Gecko/#{DESKTOP_GECKO_VERSION} Firefox/#{firefox_version}"
|
273
|
+
end
|
274
|
+
|
275
|
+
#
|
276
|
+
# Builds a Firefox `User-Agent` string for macOS.
|
277
|
+
#
|
278
|
+
# @param [:intel] arch
|
279
|
+
# The optional hardware architecture.
|
280
|
+
#
|
281
|
+
# @param [String, nil] macos_version
|
282
|
+
# The macOS version.
|
283
|
+
#
|
284
|
+
# @param [String] firefox_version
|
285
|
+
# The `Firefox/...` version.
|
286
|
+
#
|
287
|
+
# @return [String]
|
288
|
+
# A Firefox `User-Agent` string For macOS.
|
289
|
+
#
|
290
|
+
def self.build_macos(arch: :intel, macos_version: , firefox_version: )
|
291
|
+
macos_arch = OS::MacOS::ARCHES.fetch(arch)
|
292
|
+
|
293
|
+
extensions = "Macintosh; #{macos_arch} Mac OS X #{macos_version}"
|
294
|
+
extensions << "; rv:#{firefox_version}"
|
295
|
+
|
296
|
+
return "Mozilla/5.0 (#{extensions}) Gecko/#{DESKTOP_GECKO_VERSION} Firefox/#{firefox_version}"
|
297
|
+
end
|
298
|
+
|
299
|
+
#
|
300
|
+
# Builds a Firefox `User-Agent` string for Linux.
|
301
|
+
#
|
302
|
+
# @param [:usa, :international, :none, :no, nil] encryption
|
303
|
+
# The optional encryption strength to set.
|
304
|
+
#
|
305
|
+
# @param [:ubuntu, :fedora, :arch, String, nil] linux_distro
|
306
|
+
# The Linux Distro name.
|
307
|
+
#
|
308
|
+
# @param [:arm, :arm64, nil] arch
|
309
|
+
# The optional hardware architecture.
|
310
|
+
#
|
311
|
+
# @param [String, nil] lang
|
312
|
+
# The optional language identifier to add (ex: `en-GB`).
|
313
|
+
#
|
314
|
+
# @param [String] firefox_version
|
315
|
+
# The `Firefox/...` version.
|
316
|
+
#
|
317
|
+
# @return [String]
|
318
|
+
# A Firefox `User-Agent` string For Linux.
|
319
|
+
#
|
320
|
+
def self.build_linux(encryption: nil, linux_distro: nil, arch: nil, lang: nil, firefox_version: )
|
321
|
+
encryption_flag = ENCRYPTION.fetch(encryption)
|
322
|
+
linux_arch = OS::Linux::ARCHES[arch]
|
323
|
+
linux_distro = OS::Linux::DISTROS.fetch(linux_distro,linux_distro)
|
324
|
+
|
325
|
+
extensions = String.new("X11")
|
326
|
+
extensions << "; #{encryption_flag}" if encryption_flag
|
327
|
+
extensions << "; #{linux_distro}" if linux_distro
|
328
|
+
extensions << "; Linux"
|
329
|
+
extensions << " #{linux_arch}" if linux_arch
|
330
|
+
extensions << "; #{lang}" if lang
|
331
|
+
extensions << "; rv:#{firefox_version}"
|
332
|
+
|
333
|
+
return "Mozilla/5.0 (#{extensions}) Gecko/#{DESKTOP_GECKO_VERSION} Firefox/#{firefox_version}"
|
334
|
+
end
|
335
|
+
|
336
|
+
#
|
337
|
+
# Builds a Firefox `User-Agent` string for Android.
|
338
|
+
#
|
339
|
+
# @param [:mobile, :tablet] device_type
|
340
|
+
# The optional Android device.
|
341
|
+
#
|
342
|
+
# @param [String] firefox_version
|
343
|
+
# The `Firefox/...` version.
|
344
|
+
#
|
345
|
+
# @return [String]
|
346
|
+
# A Firefox `User-Agent` string For Android.
|
347
|
+
#
|
348
|
+
def self.build_android(device_type: :mobile, firefox_version: )
|
349
|
+
device_type = DEVICE_TYPES.fetch(device_type)
|
350
|
+
|
351
|
+
extensions = "Android; #{device_type}"
|
352
|
+
extensions << "; rv:#{firefox_version}"
|
353
|
+
|
354
|
+
return "Mozilla/5.0 (#{extensions}) Gecko/#{firefox_version} Firefox/#{firefox_version}"
|
355
|
+
end
|
356
|
+
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|