wordlist 1.0.3 → 1.1.0
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 +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
|
- - ">="
|