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.
@@ -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