wordlist 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -3
- data/ChangeLog.md +10 -0
- data/README.md +56 -3
- data/gemspec.yml +2 -2
- data/lib/wordlist/builder.rb +2 -2
- data/lib/wordlist/cli.rb +5 -3
- data/lib/wordlist/compression/reader.rb +12 -15
- data/lib/wordlist/compression/writer.rb +30 -19
- data/lib/wordlist/exceptions.rb +6 -0
- data/lib/wordlist/file.rb +2 -2
- data/lib/wordlist/format.rb +4 -2
- data/lib/wordlist/version.rb +1 -1
- data/lib/wordlist.rb +1 -1
- data/spec/builder_spec.rb +32 -0
- data/spec/compression/reader_spec.rb +23 -1
- data/spec/compression/writer_spec.rb +124 -4
- data/spec/file_spec.rb +80 -0
- data/spec/fixtures/wordlist.txt.7z +0 -0
- data/spec/fixtures/wordlist.txt.zip +0 -0
- data/spec/format_spec.rb +12 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84d2d2f168e655e19497f02a9cf7841e553315ec52e64ea46e9a9f01e943db9d
|
4
|
+
data.tar.gz: 709fedece526b979a744579a1868e6612b24da8ea0e85a2c9a496e2a219f58a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd6bf3d64ddef5eae7bd03e03b53676b03b06165233b0bc8812c81cce5ad04f208e969f1d5a69f6330641d4997a3bdfaa43d00103721b9704fdf4f0d98331261
|
7
|
+
data.tar.gz: 44c4075fdd792d75586be3d6b82ab93da2e2bb6ad07c7139479996bb46751aa483937097a53da1a968996ca3e5bb4341fc05767bb999f3c23ed4f7e46081bd7d
|
data/.github/workflows/ruby.yml
CHANGED
@@ -12,8 +12,6 @@ jobs:
|
|
12
12
|
- ubuntu-latest
|
13
13
|
- macos-latest
|
14
14
|
ruby:
|
15
|
-
- 2.6
|
16
|
-
- 2.7
|
17
15
|
- 3.0
|
18
16
|
- 3.1
|
19
17
|
- 3.2
|
@@ -26,7 +24,13 @@ jobs:
|
|
26
24
|
uses: ruby/setup-ruby@v1
|
27
25
|
with:
|
28
26
|
ruby-version: ${{ matrix.ruby }}
|
29
|
-
-
|
27
|
+
- if: matrix.os == 'ubuntu-latest'
|
28
|
+
name: Install external dependencies
|
29
|
+
run: sudo apt-get install -y xz-utils unzip p7zip
|
30
|
+
- if: matrix.os == 'macos-latest'
|
31
|
+
name: Install external dependencies
|
32
|
+
run: brew install xz unzip p7zip
|
33
|
+
- name: Install Ruby dependencies
|
30
34
|
run: bundle install --jobs 4 --retry 3
|
31
35
|
- name: Run tests
|
32
36
|
run: bundle exec rake test
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
### 1.1.0 / 2023-09-12
|
2
|
+
|
3
|
+
* Added support for reading zip (`.zip`) and 7zip (`.7z`) compressed wordlist
|
4
|
+
files.
|
5
|
+
* Added support for building zip or 7zip compressed wordlist files.
|
6
|
+
|
7
|
+
#### CLI
|
8
|
+
|
9
|
+
* `-f,--format` now accepts `zip` and `7zip` format values.
|
10
|
+
|
1
11
|
### 1.0.3 / 2023-08-04
|
2
12
|
|
3
13
|
* Fix reading of compressed wordlists on macOS.
|
data/README.md
CHANGED
@@ -15,10 +15,10 @@ building wordlists, efficiently.
|
|
15
15
|
|
16
16
|
## Features
|
17
17
|
|
18
|
-
* Supports reading `.txt` wordlists, and `.
|
18
|
+
* Supports reading `.txt` wordlists, and `.gz`, `.bz2`, `.xz`, `.zip`, and `.7z`
|
19
19
|
compressed wordlists.
|
20
20
|
* Supports building wordlists from arbitrary text. Also supports `.gz`, `.bz2,`
|
21
|
-
and `.
|
21
|
+
`.xz`, `.zip`, and `.7z` compression.
|
22
22
|
* Provides an advanced lexer for parsing text into words.
|
23
23
|
* Can parse/skip digits, special characters, whole numbers, acronyms.
|
24
24
|
* Can normalize case, apostrophes, and acronyms.
|
@@ -223,7 +223,7 @@ builder.parse_file(path)
|
|
223
223
|
|
224
224
|
## Requirements
|
225
225
|
|
226
|
-
* [ruby] >=
|
226
|
+
* [ruby] >= 3.0.0
|
227
227
|
|
228
228
|
[ruby]: https://www.ruby-lang.org/
|
229
229
|
|
@@ -247,6 +247,59 @@ gem 'wordlist', '~> 1.0'
|
|
247
247
|
|
248
248
|
### Synopsis
|
249
249
|
|
250
|
+
```
|
251
|
+
usage: wordlist { [options] WORDLIST ... | --build WORDLIST [FILE ...] }
|
252
|
+
|
253
|
+
Wordlist Reading Options:
|
254
|
+
-f {txt|gzip|bz2|xz|zip|7zip}, Sets the desired wordlist format
|
255
|
+
--format
|
256
|
+
--exec COMMAND Runs the command with each word from the wordlist.
|
257
|
+
The string "{}" will be replaced with each word.
|
258
|
+
|
259
|
+
Wordlist Operations:
|
260
|
+
-U, --union WORDLIST Unions the wordlist with the other WORDLIST
|
261
|
+
-I, --intersect WORDLIST Intersects the wordlist with the other WORDLIST
|
262
|
+
-S, --subtract WORDLIST Subtracts the words from the WORDLIST
|
263
|
+
-p, --product WORDLIST Combines every word with the other words from WORDLIST
|
264
|
+
-P, --power NUM Combines every word with the other words from WORDLIST
|
265
|
+
-u, --unique Filters out duplicate words
|
266
|
+
|
267
|
+
Wordlist Modifiers:
|
268
|
+
-C, --capitalize Capitalize each word
|
269
|
+
--uppercase, --upcase Converts each word to UPPERCASE
|
270
|
+
--lowercase, --downcase Converts each word to lowercase
|
271
|
+
-t, --tr CHARS:REPLACE Translates the characters of each word
|
272
|
+
-s, --sub PATTERN:SUB Replaces PATTERN with SUB in each word
|
273
|
+
-g, --gsub PATTERN:SUB Replaces all PATTERNs with SUB in each word
|
274
|
+
-m, --mutate PATTERN:SUB Performs every possible substitution on each word
|
275
|
+
-M, --mutate-case Switches the case of each letter in each word
|
276
|
+
|
277
|
+
Wordlist Building Options:
|
278
|
+
-b, --build WORDLIST Builds a wordlist
|
279
|
+
-a, --[no-]append Appends to the new wordlist instead of overwriting it
|
280
|
+
-L, --lang LANG The language to expect
|
281
|
+
--stop-words WORDS... Ignores the stop words
|
282
|
+
--ignore-words WORDS... Ignore the words
|
283
|
+
--[no-]digits Allow digits in the middle of words
|
284
|
+
--special-chars CHARS Allows the given special characters inside of words
|
285
|
+
--[no-]numbers Parses whole numbers in addition to words
|
286
|
+
--[no-]acronyms Parses acronyms in addition to words
|
287
|
+
--[no-]normalize-case Converts all words to lowercase
|
288
|
+
--[no-]normalize-apostrophes Removes "'s" from words
|
289
|
+
--[no-]normalize-acronyms Removes the dots from acronyms
|
290
|
+
|
291
|
+
General Options:
|
292
|
+
-V, --version Print the version
|
293
|
+
-h, --help Print the help output
|
294
|
+
|
295
|
+
Examples:
|
296
|
+
wordlist rockyou.txt.gz
|
297
|
+
wordlist passwords_short.txt passwords_long.txt
|
298
|
+
wordlist sport_teams.txt -p beers.txt -p digits.txt
|
299
|
+
cat *.txt | wordlist --build custom.txt
|
300
|
+
|
301
|
+
```
|
302
|
+
|
250
303
|
Reading a wordlist:
|
251
304
|
|
252
305
|
```shell
|
data/gemspec.yml
CHANGED
@@ -8,7 +8,7 @@ description:
|
|
8
8
|
license: MIT
|
9
9
|
authors: Postmodern
|
10
10
|
email: postmodern.mod3@gmail.com
|
11
|
-
homepage: https://github.com/postmodern/wordlist.rb
|
11
|
+
homepage: https://github.com/postmodern/wordlist.rb#readme
|
12
12
|
has_yard: true
|
13
13
|
|
14
14
|
metadata:
|
@@ -17,7 +17,7 @@ metadata:
|
|
17
17
|
bug_tracker_uri: https://github.com/postmodern/wordlist.rb/issues
|
18
18
|
changelog_uri: https://github.com/postmodern/wordlist.rb/blob/master/ChangeLog.md
|
19
19
|
|
20
|
-
required_ruby_version: ">=
|
20
|
+
required_ruby_version: ">= 3.0.0"
|
21
21
|
|
22
22
|
development_dependencies:
|
23
23
|
bundler: ~> 2.0
|
data/lib/wordlist/builder.rb
CHANGED
@@ -22,7 +22,7 @@ module Wordlist
|
|
22
22
|
|
23
23
|
# The format of the wordlist file.
|
24
24
|
#
|
25
|
-
# @return [:txt, :gzip, :bzip2, :xz]
|
25
|
+
# @return [:txt, :gzip, :bzip2, :xz, :zip, :7zip]
|
26
26
|
attr_reader :format
|
27
27
|
|
28
28
|
# The word lexer.
|
@@ -41,7 +41,7 @@ module Wordlist
|
|
41
41
|
# @param [String] path
|
42
42
|
# The path of the wordlist file.
|
43
43
|
#
|
44
|
-
# @param [:txt, :gz, :bzip2, :xz, nil] format
|
44
|
+
# @param [:txt, :gz, :bzip2, :xz, :zip, :7zip, nil] format
|
45
45
|
# The format of the wordlist. If not given the format will be inferred
|
46
46
|
# from the file extension.
|
47
47
|
#
|
data/lib/wordlist/cli.rb
CHANGED
@@ -26,7 +26,9 @@ module Wordlist
|
|
26
26
|
'txt' => :txt,
|
27
27
|
'gzip' => :gzip,
|
28
28
|
'bzip2'=> :bzip2,
|
29
|
-
'xz' => :xz
|
29
|
+
'xz' => :xz,
|
30
|
+
'zip' => :zip,
|
31
|
+
'7zip' => :"7zip"
|
30
32
|
}
|
31
33
|
|
32
34
|
# The command's option parser.
|
@@ -74,7 +76,7 @@ module Wordlist
|
|
74
76
|
#
|
75
77
|
# @param [:read, :build] mode
|
76
78
|
#
|
77
|
-
# @param [:txt, :gzip, :bzip2, :xz, nil] format
|
79
|
+
# @param [:txt, :gzip, :bzip2, :xz, :zip, :7zip, nil] format
|
78
80
|
#
|
79
81
|
# @param [String, nil] command
|
80
82
|
#
|
@@ -277,7 +279,7 @@ module Wordlist
|
|
277
279
|
opts.separator ""
|
278
280
|
opts.separator "Wordlist Reading Options:"
|
279
281
|
|
280
|
-
opts.on('-f','--format {txt|gzip|bz2|xz}', FORMATS, 'Saves the output to FILE') do |format|
|
282
|
+
opts.on('-f','--format {txt|gzip|bz2|xz|zip|7zip}', FORMATS, 'Saves the output to FILE') do |format|
|
281
283
|
@format = format
|
282
284
|
end
|
283
285
|
|
@@ -10,34 +10,31 @@ module Wordlist
|
|
10
10
|
# @since 1.0.0
|
11
11
|
#
|
12
12
|
module Reader
|
13
|
-
# Mapping of compression formats to the commands to read them.
|
14
|
-
COMMANDS = {
|
15
|
-
gzip: 'zcat',
|
16
|
-
bzip2: 'bzcat',
|
17
|
-
xz: 'xzcat'
|
18
|
-
}
|
19
|
-
|
20
13
|
#
|
21
14
|
# Returns the command to read the compressed wordlist.
|
22
15
|
#
|
23
16
|
# @param [String] path
|
24
17
|
# The path to the file.
|
25
18
|
#
|
26
|
-
# @param [:gzip, :bzip2, :xz] format
|
19
|
+
# @param [:gzip, :bzip2, :xz, :zip, :7zip] format
|
27
20
|
# The compression format of the file.
|
28
21
|
#
|
29
22
|
# @return [String]
|
30
23
|
# The shellescaped command string.
|
31
24
|
#
|
32
25
|
# @raise [UnknownFormat]
|
33
|
-
# The given format was not `:gzip`, `:bzip2`,
|
26
|
+
# The given format was not `:gzip`, `:bzip2`, `:xz`, `:zip`, `:7zip`.
|
34
27
|
#
|
35
28
|
def self.command(path, format: )
|
36
|
-
|
37
|
-
|
29
|
+
case format
|
30
|
+
when :gzip then "zcat < #{Shellwords.shellescape(path)}"
|
31
|
+
when :bzip2 then "bzcat < #{Shellwords.shellescape(path)}"
|
32
|
+
when :xz then "xzcat < #{Shellwords.shellescape(path)}"
|
33
|
+
when :zip then "unzip -p #{Shellwords.shellescape(path)}"
|
34
|
+
when :"7zip" then "7za e -so #{Shellwords.shellescape(path)}"
|
35
|
+
else
|
36
|
+
raise(UnknownFormat,"unsupported input format: #{format.inspect}")
|
38
37
|
end
|
39
|
-
|
40
|
-
"#{command} < #{Shellwords.shellescape(path)}"
|
41
38
|
end
|
42
39
|
|
43
40
|
#
|
@@ -53,10 +50,10 @@ module Wordlist
|
|
53
50
|
# The uncompressed IO stream.
|
54
51
|
#
|
55
52
|
# @raise [ArgumentError]
|
56
|
-
# The given format was not `:gzip`, `:bzip2`, or `:
|
53
|
+
# The given format was not `:gzip`, `:bzip2`, `:xz`, `:zip`, or `:7zip`.
|
57
54
|
#
|
58
55
|
# @raise [CommandNotFound]
|
59
|
-
# The `zcat,` `bzcat`, or `
|
56
|
+
# The `zcat,` `bzcat`, `xzcat`, or `unzip` command could not be found.
|
60
57
|
#
|
61
58
|
def self.open(path,**kwargs,&block)
|
62
59
|
command = self.command(path,**kwargs)
|
@@ -10,20 +10,13 @@ module Wordlist
|
|
10
10
|
# @since 1.0.0
|
11
11
|
#
|
12
12
|
module Writer
|
13
|
-
# Mapping of compression formats to the commands to write to them.
|
14
|
-
COMMANDS = {
|
15
|
-
gzip: 'gzip',
|
16
|
-
bzip2: 'bzip2',
|
17
|
-
xz: 'xz'
|
18
|
-
}
|
19
|
-
|
20
13
|
#
|
21
14
|
# Returns the command to write to the compressed wordlist.
|
22
15
|
#
|
23
16
|
# @param [String] path
|
24
17
|
# The path to the file.
|
25
18
|
#
|
26
|
-
# @param [:gzip, :bzip2, :xz] format
|
19
|
+
# @param [:gzip, :bzip2, :xz, :zip] format
|
27
20
|
# The compression format of the file.
|
28
21
|
#
|
29
22
|
# @param [Boolean] append
|
@@ -33,19 +26,36 @@ module Wordlist
|
|
33
26
|
# @return [String]
|
34
27
|
# The shellescaped command string.
|
35
28
|
#
|
36
|
-
# @raise [UnknownFormat]
|
37
|
-
#
|
29
|
+
# @raise [UnknownFormat, AppendNotSupported]
|
30
|
+
# * {UnknownFormat} - the given format was not `:gzip`, `:bzip2`, `:xz`,
|
31
|
+
# or `:zip`.
|
32
|
+
# * {AppendNotSupported} - the `zip` archive format does not support
|
33
|
+
# appending to existing files within existing archives.
|
38
34
|
#
|
39
35
|
def self.command(path, format: , append: false)
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
case format
|
37
|
+
when :gzip, :bzip2, :xz
|
38
|
+
command = format.to_s
|
39
|
+
redirect = if append then '>>'
|
40
|
+
else '>'
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
"#{command} #{redirect} #{Shellwords.shellescape(path)}"
|
44
|
+
when :zip
|
45
|
+
if append
|
46
|
+
raise(AppendNotSupported,"zip format does not support appending to files within pre-existing archives: #{path.inspect}")
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
+
"zip -q #{Shellwords.shellescape(path)} -"
|
50
|
+
when :"7zip"
|
51
|
+
if append
|
52
|
+
raise(AppendNotSupported,"7zip format does not support appending to files within pre-existing archives: #{path.inspect}")
|
53
|
+
end
|
54
|
+
|
55
|
+
"7za a -si #{Shellwords.shellescape(path)} >/dev/null"
|
56
|
+
else
|
57
|
+
raise(UnknownFormat,"unsupported output format: #{format.inspect}")
|
58
|
+
end
|
49
59
|
end
|
50
60
|
|
51
61
|
#
|
@@ -61,10 +71,11 @@ module Wordlist
|
|
61
71
|
# The uncompressed IO stream.
|
62
72
|
#
|
63
73
|
# @raise [ArgumentError]
|
64
|
-
# The given format was not `:gzip`, `:bzip2`,
|
74
|
+
# The given format was not `:gzip`, `:bzip2`, `:xz`, `:zip`.
|
65
75
|
#
|
66
76
|
# @raise [CommandNotFound]
|
67
|
-
# The `gzip`, `bzip2,` or `
|
77
|
+
# The `gzip`, `bzip2,` `xz`, or `zip` command was not found on the
|
78
|
+
# system.
|
68
79
|
#
|
69
80
|
def self.open(path,**kwargs)
|
70
81
|
command = self.command(path,**kwargs)
|
data/lib/wordlist/exceptions.rb
CHANGED
data/lib/wordlist/file.rb
CHANGED
@@ -24,7 +24,7 @@ module Wordlist
|
|
24
24
|
|
25
25
|
# The format of the wordlist file.
|
26
26
|
#
|
27
|
-
# @return [:txt, :gzip, :bzip2, :xz]
|
27
|
+
# @return [:txt, :gzip, :bzip2, :xz, :zip, :7zip]
|
28
28
|
attr_reader :format
|
29
29
|
|
30
30
|
#
|
@@ -33,7 +33,7 @@ module Wordlist
|
|
33
33
|
# @param [String] path
|
34
34
|
# The path to the `.txt` file wordlist read from.
|
35
35
|
#
|
36
|
-
# @param [:txt, :gz, :bzip2, :xz, nil] format
|
36
|
+
# @param [:txt, :gz, :bzip2, :xz, :zip, :7zip, nil] format
|
37
37
|
# The format of the wordlist. If not given the format will be inferred
|
38
38
|
# from the file extension.
|
39
39
|
#
|
data/lib/wordlist/format.rb
CHANGED
@@ -13,7 +13,9 @@ module Wordlist
|
|
13
13
|
'.txt' => :txt,
|
14
14
|
'.gz' => :gzip,
|
15
15
|
'.bz2' => :bzip2,
|
16
|
-
'.xz' => :xz
|
16
|
+
'.xz' => :xz,
|
17
|
+
'.zip' => :zip,
|
18
|
+
'.7z' => :"7zip"
|
17
19
|
}
|
18
20
|
|
19
21
|
# Valid formats.
|
@@ -25,7 +27,7 @@ module Wordlist
|
|
25
27
|
# @param [String] path
|
26
28
|
# The path to the file.
|
27
29
|
#
|
28
|
-
# @return [:txt, :gzip, :bzip2, :xz]
|
30
|
+
# @return [:txt, :gzip, :bzip2, :xz, :zip, :7zip]
|
29
31
|
#
|
30
32
|
# @raise [UnknownFormat]
|
31
33
|
# The format could not be inferred from the file path.
|
data/lib/wordlist/version.rb
CHANGED
data/lib/wordlist.rb
CHANGED
@@ -31,7 +31,7 @@ module Wordlist
|
|
31
31
|
# @param [Hash{Symbol => Object}] kwargs
|
32
32
|
# Additional keyword arguments for {Wordlist::File#initialize}.
|
33
33
|
#
|
34
|
-
# @option kwargs [:txt, :bzip, :bzip2, :xz] :format
|
34
|
+
# @option kwargs [:txt, :bzip, :bzip2, :xz, :zip, :7zip] :format
|
35
35
|
# Specifies the format of the wordlist. If no format is given, the format
|
36
36
|
# will be inferred from the path's file extension.
|
37
37
|
#
|
data/spec/builder_spec.rb
CHANGED
@@ -46,6 +46,22 @@ describe Wordlist::Builder do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
context "when the path ends in '.zip'" do
|
50
|
+
let(:path) { ::File.join(fixtures_dir,'new_wordlist.zip') }
|
51
|
+
|
52
|
+
it "must default #format to :zip" do
|
53
|
+
expect(subject.format).to eq(:zip)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when the path ends in '.7z'" do
|
58
|
+
let(:path) { ::File.join(fixtures_dir,'new_wordlist.7z') }
|
59
|
+
|
60
|
+
it "must default #format to :7zip" do
|
61
|
+
expect(subject.format).to eq(:"7zip")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
49
65
|
context "when format: :txt is given" do
|
50
66
|
subject { described_class.new(path, format: :txt) }
|
51
67
|
|
@@ -78,6 +94,22 @@ describe Wordlist::Builder do
|
|
78
94
|
end
|
79
95
|
end
|
80
96
|
|
97
|
+
context "when format: :zip is given" do
|
98
|
+
subject { described_class.new(path, format: :zip) }
|
99
|
+
|
100
|
+
it "must set #format to :zip" do
|
101
|
+
expect(subject.format).to eq(:zip)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when format: :7zip is given" do
|
106
|
+
subject { described_class.new(path, format: :"7zip") }
|
107
|
+
|
108
|
+
it "must set #format to :7zip" do
|
109
|
+
expect(subject.format).to eq(:"7zip")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
81
113
|
it "must default #append? to false" do
|
82
114
|
expect(subject.append?).to be(false)
|
83
115
|
end
|
@@ -53,13 +53,35 @@ describe Wordlist::Compression::Reader do
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
context "when given format: :zip" do
|
57
|
+
let(:file_name) { 'file_name' }
|
58
|
+
let(:path) { "path/to/#{file_name}.zip" }
|
59
|
+
|
60
|
+
subject { described_class.command(path, format: :zip) }
|
61
|
+
|
62
|
+
it "must return 'unzip -p path/to/file_name.zip'" do
|
63
|
+
expect(subject).to eq("unzip -p #{path}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when given format: :7zip" do
|
68
|
+
let(:file_name) { 'file_name' }
|
69
|
+
let(:path) { "path/to/#{file_name}.7z" }
|
70
|
+
|
71
|
+
subject { described_class.command(path, format: :"7zip") }
|
72
|
+
|
73
|
+
it "must return 'unzip -p path/to/file_name.zip'" do
|
74
|
+
expect(subject).to eq("7za e -so #{path}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
56
78
|
context "when given an unknown format: value" do
|
57
79
|
let(:format) { :foo }
|
58
80
|
|
59
81
|
it do
|
60
82
|
expect {
|
61
83
|
subject.command(path, format: format)
|
62
|
-
}.to raise_error(Wordlist::UnknownFormat,"unsupported format: #{format.inspect}")
|
84
|
+
}.to raise_error(Wordlist::UnknownFormat,"unsupported input format: #{format.inspect}")
|
63
85
|
end
|
64
86
|
end
|
65
87
|
end
|
@@ -79,13 +79,61 @@ describe Wordlist::Compression::Writer do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
context "when given format: :zip" do
|
83
|
+
subject { described_class.command(path, format: :zip) }
|
84
|
+
|
85
|
+
it "must return 'zip -q path/to/file -'" do
|
86
|
+
expect(subject).to eq("zip -q #{path} -")
|
87
|
+
end
|
88
|
+
|
89
|
+
context "and given append: true" do
|
90
|
+
it do
|
91
|
+
expect {
|
92
|
+
described_class.command(path, format: :zip, append: true)
|
93
|
+
}.to raise_error(Wordlist::AppendNotSupported,"zip format does not support appending to files within pre-existing archives: #{path.inspect}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "and the file contains special characters" do
|
98
|
+
let(:path) { 'path/to/the file' }
|
99
|
+
|
100
|
+
it "must shellescape them" do
|
101
|
+
expect(subject).to eq("zip -q #{Shellwords.shellescape(path)} -")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when given format: :7zip" do
|
107
|
+
subject { described_class.command(path, format: :"7zip") }
|
108
|
+
|
109
|
+
it "must return '7za a -si path/to/file'" do
|
110
|
+
expect(subject).to eq("7za a -si #{path} >/dev/null")
|
111
|
+
end
|
112
|
+
|
113
|
+
context "and given append: true" do
|
114
|
+
it do
|
115
|
+
expect {
|
116
|
+
described_class.command(path, format: :"7zip", append: true)
|
117
|
+
}.to raise_error(Wordlist::AppendNotSupported,"7zip format does not support appending to files within pre-existing archives: #{path.inspect}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "and the file contains special characters" do
|
122
|
+
let(:path) { 'path/to/the file' }
|
123
|
+
|
124
|
+
it "must shellescape them" do
|
125
|
+
expect(subject).to eq("7za a -si #{Shellwords.shellescape(path)} >/dev/null")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
82
130
|
context "when given an unknown format: value" do
|
83
131
|
let(:format) { :foo }
|
84
132
|
|
85
133
|
it do
|
86
134
|
expect {
|
87
135
|
subject.command(path, format: format)
|
88
|
-
}.to raise_error(Wordlist::UnknownFormat,"unsupported format: #{format.inspect}")
|
136
|
+
}.to raise_error(Wordlist::UnknownFormat,"unsupported output format: #{format.inspect}")
|
89
137
|
end
|
90
138
|
end
|
91
139
|
end
|
@@ -107,6 +155,7 @@ describe Wordlist::Compression::Writer do
|
|
107
155
|
context "when written to" do
|
108
156
|
before do
|
109
157
|
subject.puts words
|
158
|
+
subject.flush
|
110
159
|
subject.close
|
111
160
|
end
|
112
161
|
|
@@ -118,7 +167,10 @@ describe Wordlist::Compression::Writer do
|
|
118
167
|
end
|
119
168
|
end
|
120
169
|
|
121
|
-
after
|
170
|
+
after do
|
171
|
+
subject.close
|
172
|
+
::FileUtils.rm_f(path)
|
173
|
+
end
|
122
174
|
end
|
123
175
|
|
124
176
|
context "when given format: :bzip2" do
|
@@ -133,6 +185,7 @@ describe Wordlist::Compression::Writer do
|
|
133
185
|
context "when written to" do
|
134
186
|
before do
|
135
187
|
subject.puts words
|
188
|
+
subject.flush
|
136
189
|
subject.close
|
137
190
|
end
|
138
191
|
|
@@ -144,7 +197,10 @@ describe Wordlist::Compression::Writer do
|
|
144
197
|
end
|
145
198
|
end
|
146
199
|
|
147
|
-
after
|
200
|
+
after do
|
201
|
+
subject.close
|
202
|
+
::FileUtils.rm_f(path)
|
203
|
+
end
|
148
204
|
end
|
149
205
|
|
150
206
|
context "when given format: :xz" do
|
@@ -159,6 +215,7 @@ describe Wordlist::Compression::Writer do
|
|
159
215
|
context "when written to" do
|
160
216
|
before do
|
161
217
|
subject.puts words
|
218
|
+
subject.flush
|
162
219
|
subject.close
|
163
220
|
end
|
164
221
|
|
@@ -170,7 +227,70 @@ describe Wordlist::Compression::Writer do
|
|
170
227
|
end
|
171
228
|
end
|
172
229
|
|
173
|
-
after
|
230
|
+
after do
|
231
|
+
subject.close
|
232
|
+
::FileUtils.rm_f(path)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "when given format: :zip" do
|
237
|
+
let(:path) { ::File.join(fixtures_dir,'new_wordlist.txt.zip') }
|
238
|
+
|
239
|
+
subject { described_class.open(path, format: :zip) }
|
240
|
+
|
241
|
+
it "must return an IO object" do
|
242
|
+
expect(subject).to be_kind_of(IO)
|
243
|
+
end
|
244
|
+
|
245
|
+
context "when written to" do
|
246
|
+
before do
|
247
|
+
subject.puts words
|
248
|
+
subject.flush
|
249
|
+
subject.close
|
250
|
+
end
|
251
|
+
|
252
|
+
let(:written_contents) { `unzip -p #{Shellwords.shellescape(path)}` }
|
253
|
+
let(:written_words) { written_contents.lines.map(&:chomp) }
|
254
|
+
|
255
|
+
it "must writing xz compressed data to the file" do
|
256
|
+
expect(written_words).to eq(words)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
after do
|
261
|
+
subject.close
|
262
|
+
::FileUtils.rm_f(path)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "when given format: :7zip" do
|
267
|
+
let(:path) { ::File.join(fixtures_dir,'new_wordlist.txt.7z') }
|
268
|
+
|
269
|
+
subject { described_class.open(path, format: :"7zip") }
|
270
|
+
|
271
|
+
it "must return an IO object" do
|
272
|
+
expect(subject).to be_kind_of(IO)
|
273
|
+
end
|
274
|
+
|
275
|
+
context "when written to" do
|
276
|
+
before do
|
277
|
+
subject.puts words
|
278
|
+
subject.flush
|
279
|
+
subject.close
|
280
|
+
end
|
281
|
+
|
282
|
+
let(:written_contents) { `7za e -so #{Shellwords.shellescape(path)}` }
|
283
|
+
let(:written_words) { written_contents.lines.map(&:chomp) }
|
284
|
+
|
285
|
+
it "must writing xz compressed data to the file" do
|
286
|
+
expect(written_words).to eq(words)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
after do
|
291
|
+
subject.close
|
292
|
+
::FileUtils.rm_f(path)
|
293
|
+
end
|
174
294
|
end
|
175
295
|
|
176
296
|
context "when the command is not installed" do
|
data/spec/file_spec.rb
CHANGED
@@ -75,6 +75,22 @@ describe Wordlist::File do
|
|
75
75
|
expect(subject.format).to eq(:xz)
|
76
76
|
end
|
77
77
|
end
|
78
|
+
|
79
|
+
context "and the path ends in .zip" do
|
80
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.zip') }
|
81
|
+
|
82
|
+
it "must set #format to :zip" do
|
83
|
+
expect(subject.format).to eq(:zip)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "and the path ends in .7z" do
|
88
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.7z') }
|
89
|
+
|
90
|
+
it "must set #format to :7zip" do
|
91
|
+
expect(subject.format).to eq(:"7zip")
|
92
|
+
end
|
93
|
+
end
|
78
94
|
end
|
79
95
|
|
80
96
|
context "when format: is given" do
|
@@ -162,6 +178,28 @@ describe Wordlist::File do
|
|
162
178
|
}.to yield_successive_args(*expected_lines)
|
163
179
|
end
|
164
180
|
end
|
181
|
+
|
182
|
+
context "and the wordlist format is zip" do
|
183
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.zip') }
|
184
|
+
let(:expected_contents) { `unzip -p #{Shellwords.shellescape(path)}` }
|
185
|
+
|
186
|
+
it "must read the uncompressed zip data" do
|
187
|
+
expect { |b|
|
188
|
+
subject.each_line(&b)
|
189
|
+
}.to yield_successive_args(*expected_lines)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "and the wordlist format is 7zip" do
|
194
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.7z') }
|
195
|
+
let(:expected_contents) { `7za e -so #{Shellwords.shellescape(path)}` }
|
196
|
+
|
197
|
+
it "must read the uncompressed 7zip data" do
|
198
|
+
expect { |b|
|
199
|
+
subject.each_line(&b)
|
200
|
+
}.to yield_successive_args(*expected_lines)
|
201
|
+
end
|
202
|
+
end
|
165
203
|
end
|
166
204
|
|
167
205
|
context "when not given a block" do
|
@@ -199,6 +237,26 @@ describe Wordlist::File do
|
|
199
237
|
expect(subject.each_line.to_a).to eq(expected_lines)
|
200
238
|
end
|
201
239
|
end
|
240
|
+
|
241
|
+
context "and the wordlist format is zip" do
|
242
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.zip') }
|
243
|
+
let(:expected_contents) { `unzip -p #{Shellwords.shellescape(path)}` }
|
244
|
+
|
245
|
+
it "must return an Enumerator of the compressed zip data" do
|
246
|
+
expect(subject.each_line).to be_kind_of(Enumerator)
|
247
|
+
expect(subject.each_line.to_a).to eq(expected_lines)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context "and the wordlist format is 7zip" do
|
252
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.7z') }
|
253
|
+
let(:expected_contents) { `7za e -so #{Shellwords.shellescape(path)}` }
|
254
|
+
|
255
|
+
it "must return an Enumerator of the compressed 7zip data" do
|
256
|
+
expect(subject.each_line).to be_kind_of(Enumerator)
|
257
|
+
expect(subject.each_line.to_a).to eq(expected_lines)
|
258
|
+
end
|
259
|
+
end
|
202
260
|
end
|
203
261
|
end
|
204
262
|
|
@@ -242,6 +300,28 @@ describe Wordlist::File do
|
|
242
300
|
end
|
243
301
|
end
|
244
302
|
|
303
|
+
context "and the wordlist format is zip" do
|
304
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.zip') }
|
305
|
+
let(:expected_contents) { `unzip -p #{Shellwords.shellescape(path)}` }
|
306
|
+
|
307
|
+
it "must read the uncompressed zip data" do
|
308
|
+
expect { |b|
|
309
|
+
subject.each_line(&b)
|
310
|
+
}.to yield_successive_args(*expected_lines)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "and the wordlist format is 7z" do
|
315
|
+
let(:path) { ::File.join(fixtures_dir,'wordlist.txt.7z') }
|
316
|
+
let(:expected_contents) { `7za e -so #{Shellwords.shellescape(path)}` }
|
317
|
+
|
318
|
+
it "must read the uncompressed 7zip data" do
|
319
|
+
expect { |b|
|
320
|
+
subject.each_line(&b)
|
321
|
+
}.to yield_successive_args(*expected_lines)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
245
325
|
context "when the wordlist contains empty lines" do
|
246
326
|
let(:expected_words) do
|
247
327
|
super().reject { |w| w.empty? }
|
Binary file
|
Binary file
|
data/spec/format_spec.rb
CHANGED
@@ -27,6 +27,18 @@ describe Wordlist::Format do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
context "when given a path ending in '.zip'" do
|
31
|
+
it "must return :zip" do
|
32
|
+
expect(subject.infer("path/to/file.zip")).to eq(:zip)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when given a path ending in '.7z'" do
|
37
|
+
it "must return :7zip" do
|
38
|
+
expect(subject.infer("path/to/file.7z")).to eq(:"7zip")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
30
42
|
context "when given a path ending in another file extension" do
|
31
43
|
let(:path) { "path/to/file.foo" }
|
32
44
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wordlist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -135,9 +135,11 @@ files:
|
|
135
135
|
- spec/compression/writer_spec.rb
|
136
136
|
- spec/file_spec.rb
|
137
137
|
- spec/fixtures/wordlist.txt
|
138
|
+
- spec/fixtures/wordlist.txt.7z
|
138
139
|
- spec/fixtures/wordlist.txt.bz2
|
139
140
|
- spec/fixtures/wordlist.txt.gz
|
140
141
|
- spec/fixtures/wordlist.txt.xz
|
142
|
+
- spec/fixtures/wordlist.txt.zip
|
141
143
|
- spec/fixtures/wordlist_with_ambiguous_format
|
142
144
|
- spec/fixtures/wordlist_with_comments.txt
|
143
145
|
- spec/fixtures/wordlist_with_empty_lines.txt
|
@@ -175,7 +177,7 @@ files:
|
|
175
177
|
- spec/wordlist_spec.rb
|
176
178
|
- spec/words_spec.rb
|
177
179
|
- wordlist.gemspec
|
178
|
-
homepage: https://github.com/postmodern/wordlist.rb
|
180
|
+
homepage: https://github.com/postmodern/wordlist.rb#readme
|
179
181
|
licenses:
|
180
182
|
- MIT
|
181
183
|
metadata:
|
@@ -191,7 +193,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
193
|
requirements:
|
192
194
|
- - ">="
|
193
195
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
196
|
+
version: 3.0.0
|
195
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
198
|
requirements:
|
197
199
|
- - ">="
|