wordlist 0.1.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +28 -0
  3. data/.gitignore +6 -3
  4. data/ChangeLog.md +55 -1
  5. data/Gemfile +15 -0
  6. data/LICENSE.txt +1 -3
  7. data/README.md +301 -60
  8. data/Rakefile +7 -32
  9. data/benchmarks.rb +115 -0
  10. data/bin/wordlist +4 -7
  11. data/data/stop_words/ar.txt +104 -0
  12. data/data/stop_words/bg.txt +259 -0
  13. data/data/stop_words/bn.txt +363 -0
  14. data/data/stop_words/ca.txt +126 -0
  15. data/data/stop_words/cs.txt +138 -0
  16. data/data/stop_words/da.txt +101 -0
  17. data/data/stop_words/de.txt +129 -0
  18. data/data/stop_words/el.txt +79 -0
  19. data/data/stop_words/en.txt +175 -0
  20. data/data/stop_words/es.txt +178 -0
  21. data/data/stop_words/eu.txt +98 -0
  22. data/data/stop_words/fa.txt +332 -0
  23. data/data/stop_words/fi.txt +747 -0
  24. data/data/stop_words/fr.txt +116 -0
  25. data/data/stop_words/ga.txt +109 -0
  26. data/data/stop_words/gl.txt +160 -0
  27. data/data/stop_words/he.txt +499 -0
  28. data/data/stop_words/hi.txt +97 -0
  29. data/data/stop_words/hr.txt +179 -0
  30. data/data/stop_words/hu.txt +35 -0
  31. data/data/stop_words/hy.txt +45 -0
  32. data/data/stop_words/id.txt +357 -0
  33. data/data/stop_words/it.txt +134 -0
  34. data/data/stop_words/ja.txt +44 -0
  35. data/data/stop_words/ko.txt +677 -0
  36. data/data/stop_words/ku.txt +63 -0
  37. data/data/stop_words/lt.txt +507 -0
  38. data/data/stop_words/lv.txt +163 -0
  39. data/data/stop_words/mr.txt +99 -0
  40. data/data/stop_words/nl.txt +48 -0
  41. data/data/stop_words/no.txt +172 -0
  42. data/data/stop_words/pl.txt +138 -0
  43. data/data/stop_words/pt.txt +147 -0
  44. data/data/stop_words/ro.txt +281 -0
  45. data/data/stop_words/ru.txt +421 -0
  46. data/data/stop_words/sk.txt +173 -0
  47. data/data/stop_words/sv.txt +386 -0
  48. data/data/stop_words/th.txt +115 -0
  49. data/data/stop_words/tr.txt +114 -0
  50. data/data/stop_words/uk.txt +28 -0
  51. data/data/stop_words/ur.txt +513 -0
  52. data/data/stop_words/zh.txt +125 -0
  53. data/gemspec.yml +13 -12
  54. data/lib/wordlist/abstract_wordlist.rb +25 -0
  55. data/lib/wordlist/builder.rb +172 -138
  56. data/lib/wordlist/cli.rb +459 -0
  57. data/lib/wordlist/compression/reader.rb +72 -0
  58. data/lib/wordlist/compression/writer.rb +80 -0
  59. data/lib/wordlist/exceptions.rb +31 -0
  60. data/lib/wordlist/file.rb +177 -0
  61. data/lib/wordlist/format.rb +39 -0
  62. data/lib/wordlist/lexer/lang.rb +34 -0
  63. data/lib/wordlist/lexer/stop_words.rb +69 -0
  64. data/lib/wordlist/lexer.rb +221 -0
  65. data/lib/wordlist/list_methods.rb +462 -0
  66. data/lib/wordlist/modifiers/capitalize.rb +46 -0
  67. data/lib/wordlist/modifiers/downcase.rb +46 -0
  68. data/lib/wordlist/modifiers/gsub.rb +52 -0
  69. data/lib/wordlist/modifiers/modifier.rb +44 -0
  70. data/lib/wordlist/modifiers/mutate.rb +134 -0
  71. data/lib/wordlist/modifiers/mutate_case.rb +26 -0
  72. data/lib/wordlist/modifiers/sub.rb +98 -0
  73. data/lib/wordlist/modifiers/tr.rb +72 -0
  74. data/lib/wordlist/modifiers/upcase.rb +46 -0
  75. data/lib/wordlist/modifiers.rb +9 -0
  76. data/lib/wordlist/operators/binary_operator.rb +39 -0
  77. data/lib/wordlist/operators/concat.rb +48 -0
  78. data/lib/wordlist/operators/intersect.rb +56 -0
  79. data/lib/wordlist/operators/operator.rb +29 -0
  80. data/lib/wordlist/operators/power.rb +73 -0
  81. data/lib/wordlist/operators/product.rb +51 -0
  82. data/lib/wordlist/operators/subtract.rb +55 -0
  83. data/lib/wordlist/operators/unary_operator.rb +30 -0
  84. data/lib/wordlist/operators/union.rb +62 -0
  85. data/lib/wordlist/operators/unique.rb +53 -0
  86. data/lib/wordlist/operators.rb +8 -0
  87. data/lib/wordlist/unique_filter.rb +41 -61
  88. data/lib/wordlist/version.rb +4 -2
  89. data/lib/wordlist/words.rb +72 -0
  90. data/lib/wordlist.rb +104 -2
  91. data/spec/abstract_list_spec.rb +18 -0
  92. data/spec/builder_spec.rb +220 -76
  93. data/spec/cli_spec.rb +802 -0
  94. data/spec/compression/reader_spec.rb +137 -0
  95. data/spec/compression/writer_spec.rb +194 -0
  96. data/spec/file_spec.rb +269 -0
  97. data/spec/fixtures/wordlist.txt +15 -0
  98. data/spec/fixtures/wordlist.txt.bz2 +0 -0
  99. data/spec/fixtures/wordlist.txt.gz +0 -0
  100. data/spec/fixtures/wordlist.txt.xz +0 -0
  101. data/spec/fixtures/wordlist_with_ambiguous_format +3 -0
  102. data/spec/fixtures/wordlist_with_comments.txt +19 -0
  103. data/spec/fixtures/wordlist_with_empty_lines.txt +19 -0
  104. data/spec/format_spec.rb +50 -0
  105. data/spec/helpers/text.rb +3 -3
  106. data/spec/helpers/wordlist.rb +2 -2
  107. data/spec/lexer/lang_spec.rb +70 -0
  108. data/spec/lexer/stop_words_spec.rb +77 -0
  109. data/spec/lexer_spec.rb +718 -0
  110. data/spec/list_methods_spec.rb +181 -0
  111. data/spec/modifiers/capitalize_spec.rb +27 -0
  112. data/spec/modifiers/downcase_spec.rb +27 -0
  113. data/spec/modifiers/gsub_spec.rb +59 -0
  114. data/spec/modifiers/modifier_spec.rb +20 -0
  115. data/spec/modifiers/mutate_case_spec.rb +46 -0
  116. data/spec/modifiers/mutate_spec.rb +39 -0
  117. data/spec/modifiers/sub_spec.rb +98 -0
  118. data/spec/modifiers/tr_spec.rb +46 -0
  119. data/spec/modifiers/upcase_spec.rb +27 -0
  120. data/spec/operators/binary_operator_spec.rb +19 -0
  121. data/spec/operators/concat_spec.rb +26 -0
  122. data/spec/operators/intersect_spec.rb +37 -0
  123. data/spec/operators/operator_spec.rb +16 -0
  124. data/spec/operators/power_spec.rb +57 -0
  125. data/spec/operators/product_spec.rb +39 -0
  126. data/spec/operators/subtract_spec.rb +37 -0
  127. data/spec/operators/unary_operator_spec.rb +14 -0
  128. data/spec/operators/union_spec.rb +37 -0
  129. data/spec/operators/unique_spec.rb +25 -0
  130. data/spec/spec_helper.rb +2 -1
  131. data/spec/unique_filter_spec.rb +108 -18
  132. data/spec/wordlist_spec.rb +55 -3
  133. data/spec/words_spec.rb +41 -0
  134. data/wordlist.gemspec +1 -0
  135. metadata +164 -126
  136. data/lib/wordlist/builders/website.rb +0 -216
  137. data/lib/wordlist/builders.rb +0 -1
  138. data/lib/wordlist/flat_file.rb +0 -47
  139. data/lib/wordlist/list.rb +0 -162
  140. data/lib/wordlist/mutator.rb +0 -113
  141. data/lib/wordlist/parsers.rb +0 -74
  142. data/lib/wordlist/runners/list.rb +0 -116
  143. data/lib/wordlist/runners/runner.rb +0 -67
  144. data/lib/wordlist/runners.rb +0 -2
  145. data/scripts/benchmark +0 -59
  146. data/scripts/text/comedy_of_errors.txt +0 -4011
  147. data/spec/classes/parser_class.rb +0 -7
  148. data/spec/classes/test_list.rb +0 -9
  149. data/spec/flat_file_spec.rb +0 -25
  150. data/spec/list_spec.rb +0 -58
  151. data/spec/mutator_spec.rb +0 -43
  152. data/spec/parsers_spec.rb +0 -118
@@ -0,0 +1,125 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ 使
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+ 沿
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
data/gemspec.yml CHANGED
@@ -1,22 +1,23 @@
1
1
  name: wordlist
2
- summary: A Ruby library for generating and working with word-lists.
2
+ summary:
3
+ Ruby library and CLI for reading, combining, mutating, and building wordlists
3
4
  description:
4
- A Ruby library for generating and working with word-lists. Wordlist
5
- allows one to efficiently generate unique word-lists from arbitrary text
6
- or other sources, such as website content. Wordlist can also quickly
7
- enumerate through words within an existing word-list, applying multiple
8
- mutation rules to each word in the list.
5
+ Wordlist is a Ruby library and CLI for reading, combining, mutating, and
6
+ building wordlists, efficiently.
9
7
 
10
8
  license: MIT
11
9
  authors: Postmodern
12
10
  email: postmodern.mod3@gmail.com
13
- homepage: https://github.com/sophsec/wordlist
11
+ homepage: https://github.com/postmodern/wordlist.rb
14
12
  has_yard: true
15
13
 
16
- dependencies:
17
- spidr: ~> 0.2
14
+ metadata:
15
+ documentation_uri: https://rubydoc.info/gems/wordlist
16
+ source_code_uri: https://github.com/postmodern/wordlist.rb
17
+ bug_tracker_uri: https://github.com/postmodern/wordlist.rb/issues
18
+ changelog_uri: https://github.com/postmodern/wordlist.rb/blob/master/ChangeLog.md
19
+
20
+ required_ruby_version: ">= 2.0.0"
18
21
 
19
22
  development_dependencies:
20
- rubygems-tasks: ~> 0.1
21
- rspec: ~> 2.4
22
- yard: ~> 0.8
23
+ bundler: ~> 2.0
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ require 'wordlist/list_methods'
3
+
4
+ module Wordlist
5
+ #
6
+ # The base class for all wordlist classes.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class AbstractWordlist
11
+
12
+ include Enumerable
13
+ include ListMethods
14
+
15
+ #
16
+ # Place holder method.
17
+ #
18
+ # @abstract
19
+ #
20
+ def each(&block)
21
+ raise(NotImplementedError,"#{self.class}#each was not implemented")
22
+ end
23
+
24
+ end
25
+ end
@@ -1,58 +1,102 @@
1
+ # frozen_string_literal: true
2
+ require 'wordlist/format'
3
+ require 'wordlist/lexer'
1
4
  require 'wordlist/unique_filter'
2
- require 'wordlist/parsers'
5
+ require 'wordlist/file'
6
+ require 'wordlist/compression/writer'
3
7
 
4
8
  module Wordlist
9
+ #
10
+ # Parses text and builds a wordlist file.
11
+ #
12
+ # @api public
13
+ #
14
+ # @since 1.0.0
15
+ #
5
16
  class Builder
6
17
 
7
- include Parsers
8
-
9
- # Path of the word-list
18
+ # Path of the wordlist
19
+ #
20
+ # @return [String]
10
21
  attr_reader :path
11
22
 
12
- # Minimum number of words
13
- attr_reader :min_words
14
-
15
- # Maximum number of words
16
- attr_reader :max_words
17
-
18
- # File for the word-list
19
- attr_reader :file
23
+ # The format of the wordlist file.
24
+ #
25
+ # @return [:txt, :gzip, :bzip2, :xz]
26
+ attr_reader :format
20
27
 
21
- # The unique word filter
22
- attr_reader :filter
28
+ # The word lexer.
29
+ #
30
+ # @return [Lexer]
31
+ attr_reader :lexer
23
32
 
24
- # The queue of words awaiting processing
25
- attr_reader :word_queue
33
+ # The unique filter.
34
+ #
35
+ # @return [UniqueFilter]
36
+ attr_reader :unique_filter
26
37
 
27
38
  #
28
39
  # Creates a new word-list Builder object.
29
40
  #
30
41
  # @param [String] path
31
- # The path of the word-list file.
42
+ # The path of the wordlist file.
32
43
  #
33
- # @param [Hash] options
34
- # Additional options.
44
+ # @param [:txt, :gz, :bzip2, :xz, nil] format
45
+ # The format of the wordlist. If not given the format will be inferred
46
+ # from the file extension.
35
47
  #
36
- # @option options [Integer] :min_words (1)
37
- # The minimum number of words each line of the word-list must contain.
48
+ # @param [Boolean] append
49
+ # Indicates whether new words will be appended to the wordlist or
50
+ # overwrite the wordlist.
38
51
  #
39
- # @option options [Integer] :max_words
40
- # The maximum number of words each line of the word-list may contain.
41
- # Defaults to the value of `:min_words`, if not given.
52
+ # @param [Hash{Symbol => Object}] kwargs
53
+ # Additional keyword arguments for {Lexer#initialize}.
42
54
  #
43
- def initialize(path,options={})
44
- super()
45
-
46
- @path = File.expand_path(path)
47
-
48
- @min_words = options.fetch(:min_words,1)
49
- @max_words = options.fetch(:max_words,@min_words)
55
+ # @option kwargs [Symbol] :lang
56
+ # The language to use. Defaults to {Lexer::Lang.default}.
57
+ #
58
+ # @option kwargs [Array<String>] :stop_words
59
+ # The explicit stop-words to ignore. If not given, default stop words
60
+ # will be loaded based on `lang` or {Lexer::Lang.default}.
61
+ #
62
+ # @option kwargs [Array<String, Regexp>] :ignore_words
63
+ # Optional list of words to ignore. Can contain Strings or Regexps.
64
+ #
65
+ # @option kwargs [Boolean] :digits (true)
66
+ # Controls whether parsed words may contain digits or not.
67
+ #
68
+ # @option kwargs [Array<String>] :special_chars (Lexer::SPCIAL_CHARS)
69
+ # The additional special characters allowed within words.
70
+ #
71
+ # @option kwargs [Boolean] :numbers (false)
72
+ # Controls whether whole numbers will be parsed as words.
73
+ #
74
+ # @option kwargs [Boolean] :acronyms (true)
75
+ # Controls whether acronyms will be parsed as words.
76
+ #
77
+ # @option kwargs [Boolean] :normalize_case (false)
78
+ # Controls whether to convert all words to lowercase.
79
+ #
80
+ # @option kwargs [Boolean] :normalize_apostrophes (false)
81
+ # Controls whether apostrophes will be removed from the end of words.
82
+ #
83
+ # @option kwargs [Boolean] :normalize_acronyms (false)
84
+ # Controls whether acronyms will have `.` characters removed.
85
+ #
86
+ # @raise [ArgumentError]
87
+ # The format could not be inferred from the file extension, or the
88
+ # `ignore_words` keyword contained a value other than a String or Regexp.
89
+ #
90
+ def initialize(path, format: Format.infer(path), append: false, **kwargs)
91
+ @path = ::File.expand_path(path)
92
+ @format = format
93
+ @append = append
50
94
 
51
- @file = nil
52
- @filter = UniqueFilter.new
53
- @word_queue = []
95
+ @lexer = Lexer.new(**kwargs)
96
+ @unique_filter = UniqueFilter.new
54
97
 
55
- yield self if block_given?
98
+ load! if append? && ::File.file?(@path)
99
+ open!
56
100
  end
57
101
 
58
102
  #
@@ -60,151 +104,94 @@ module Wordlist
60
104
  # word-list file, passes the builder object to the given block
61
105
  # then finally closes the word-list file.
62
106
  #
63
- # @param [Array] arguments
64
- # Additional arguments to pass to {#initialize}.
107
+ # @param [String] path
108
+ # The path of the wordlist file.
65
109
  #
66
110
  # @yield [builder]
67
111
  # If a block is given, it will be passed the new builder.
68
112
  #
69
- # @yieldparam [Builder] builder
70
- # The newly created builer object.
113
+ # @yieldparam [self] builder
114
+ # The newly created builder object.
71
115
  #
72
116
  # @return [Builder]
73
117
  # The newly created builder object.
74
118
  #
75
119
  # @example
76
- # Builder.build('some/path') do |builder|
77
- # builder.parse(readline)
120
+ # Builder.open('path/to/file.txt') do |builder|
121
+ # builder.parse(text)
78
122
  # end
79
123
  #
80
- def self.build(*arguments,&block)
81
- self.new(*arguments) do |builder|
82
- builder.open!
83
- builder.build!(&block)
84
- builder.close!
85
- end
86
- end
124
+ def self.open(path,**kwargs)
125
+ builder = new(path,**kwargs)
87
126
 
88
- #
89
- # Opens the word-list file for writing. If the file already exists, the
90
- # previous words will be used to filter future duplicate words.
91
- #
92
- # @return [File]
93
- # The open word-list file.
94
- #
95
- def open!
96
- if File.file?(@path)
97
- File.open(@path) do |file|
98
- file.each_line do |line|
99
- @filter.saw!(line.chomp)
100
- end
127
+ if block_given?
128
+ begin
129
+ yield builder
130
+ ensure
131
+ builder.close
101
132
  end
102
133
  end
103
134
 
104
- @file = File.new(@path,File::RDWR | File::CREAT | File::APPEND)
135
+ return builder
105
136
  end
106
137
 
107
138
  #
108
- # Default to be called when the word-list is to be built.
139
+ # Determines if the builder will append new words to the existing wordlist
140
+ # or overwrite it.
109
141
  #
110
- # @yield [builder]
111
- # If a block is given, it will be passed the new builder object.
142
+ # @return [Boolean]
112
143
  #
113
- def build!
114
- yield self if block_given?
144
+ def append?
145
+ @append
115
146
  end
116
147
 
117
148
  #
118
- # Enqueues a given word for processing.
149
+ # Writes a comment line to the wordlist file.
119
150
  #
120
- # @param [String] word
121
- # The word to enqueue.
122
- #
123
- # @return [String]
124
- # The enqueued word.
151
+ # @param [String] message
152
+ # The comment message to write.
125
153
  #
126
- def enqueue(word)
127
- # enqueue the word
128
- if @max_words == 1
129
- @word_queue[0] = word.to_s
130
- else
131
- @word_queue << word.to_s
132
-
133
- # make sure the queue does not overflow
134
- if @word_queue.length > @max_words
135
- @word_queue.shift
136
- end
137
- end
138
-
139
- return word
154
+ def comment(message)
155
+ write("# #{message}")
140
156
  end
141
157
 
142
158
  #
143
- # Enumerates over the combinations of previously seen words.
144
- #
145
- # @yield [combination]
146
- # The given block will be passed the combinations of previously
147
- # seen words.
148
- #
149
- # @yieldparam [String] combination
150
- # A combination of one or more space-separated words.
151
- #
152
- def word_combinations
153
- if @max_words == 1
154
- yield @word_queue[0]
155
- else
156
- current_words = @word_queue.length
157
-
158
- # we must have atleast the minimum amount of words
159
- if current_words >= @min_words
160
- upper_bound = (current_words - @min_words)
161
-
162
- # combine the words
163
- upper_bound.downto(0) do |i|
164
- yield @word_queue[i..-1].join(' ')
165
- end
166
- end
167
- end
168
- end
169
-
170
- #
171
- # Appends the given word to the word-list file, only if it has not
172
- # been previously seen.
159
+ # Appends the given word to the wordlist file, only if it has not
160
+ # been previously added.
173
161
  #
174
162
  # @param [String] word
175
163
  # The word to append.
176
164
  #
177
- # @return [Builder]
165
+ # @return [self]
178
166
  # The builder object.
179
167
  #
180
- def <<(word)
181
- enqueue(word)
182
-
183
- if @file
184
- word_combinations do |words|
185
- @filter.pass(words) do |unique|
186
- @file.puts unique
187
- end
188
- end
168
+ def add(word)
169
+ if @unique_filter.add?(word)
170
+ write(word)
189
171
  end
190
172
 
191
173
  return self
192
174
  end
193
175
 
176
+ alias << add
177
+ alias push add
178
+
194
179
  #
195
180
  # Add the given words to the word-list.
196
181
  #
197
182
  # @param [Array<String>] words
198
183
  # The words to add to the list.
199
184
  #
200
- # @return [Builder]
185
+ # @return [self]
201
186
  # The builder object.
202
187
  #
203
- def +(words)
204
- words.each { |word| self << word }
188
+ def append(words)
189
+ words.each { |word| add(word) }
205
190
  return self
206
191
  end
207
192
 
193
+ alias concat append
194
+
208
195
  #
209
196
  # Parses the given text, adding each unique word to the word-list file.
210
197
  #
@@ -212,7 +199,9 @@ module Wordlist
212
199
  # The text to parse.
213
200
  #
214
201
  def parse(text)
215
- super(text).each { |word| self << word }
202
+ @lexer.parse(text) do |word|
203
+ add(word)
204
+ end
216
205
  end
217
206
 
218
207
  #
@@ -223,7 +212,7 @@ module Wordlist
223
212
  # The path of the file to parse.
224
213
  #
225
214
  def parse_file(path)
226
- File.open(path) do |file|
215
+ ::File.open(path) do |file|
227
216
  file.each_line do |line|
228
217
  parse(line)
229
218
  end
@@ -233,13 +222,58 @@ module Wordlist
233
222
  #
234
223
  # Closes the word-list file.
235
224
  #
236
- def close!
237
- if @file
238
- @file.close
239
- @file = nil
225
+ def close
226
+ unless @io.closed?
227
+ @io.close
228
+ @unique_filter.clear
229
+ end
230
+ end
240
231
 
241
- @filter.clear
242
- @word_queue.clear
232
+ #
233
+ # Indicates whether the wordlist builder has been closed.
234
+ #
235
+ # @return [Boolean]
236
+ #
237
+ def closed?
238
+ @io.closed?
239
+ end
240
+
241
+ private
242
+
243
+ #
244
+ # Prepopulates the builder with the existing wordlist's content.
245
+ #
246
+ def load!
247
+ Wordlist::File.read(@path) do |word|
248
+ @unique_filter << word
249
+ end
250
+ end
251
+
252
+ #
253
+ # Writes a line to the wordlist file.
254
+ #
255
+ # @param [String] line
256
+ # The line to write.
257
+ #
258
+ # @abstract
259
+ #
260
+ def write(line)
261
+ @io.puts(line)
262
+ @io.flush
263
+ end
264
+
265
+ #
266
+ # Opens the wordlist file.
267
+ #
268
+ def open!
269
+ if @format == :txt
270
+ mode = if append? then 'a'
271
+ else 'w'
272
+ end
273
+
274
+ @io = ::File.open(@path,mode)
275
+ else
276
+ @io = Compression::Writer.open(@path, format: @format, append: append?)
243
277
  end
244
278
  end
245
279