ronin-web-user_agents 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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