cabriolet 0.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 +7 -0
- data/ARCHITECTURE.md +799 -0
- data/CHANGELOG.md +44 -0
- data/LICENSE +29 -0
- data/README.adoc +1207 -0
- data/exe/cabriolet +6 -0
- data/lib/cabriolet/auto.rb +173 -0
- data/lib/cabriolet/binary/bitstream.rb +148 -0
- data/lib/cabriolet/binary/bitstream_writer.rb +180 -0
- data/lib/cabriolet/binary/chm_structures.rb +213 -0
- data/lib/cabriolet/binary/hlp_structures.rb +66 -0
- data/lib/cabriolet/binary/kwaj_structures.rb +74 -0
- data/lib/cabriolet/binary/lit_structures.rb +107 -0
- data/lib/cabriolet/binary/oab_structures.rb +112 -0
- data/lib/cabriolet/binary/structures.rb +56 -0
- data/lib/cabriolet/binary/szdd_structures.rb +60 -0
- data/lib/cabriolet/cab/compressor.rb +382 -0
- data/lib/cabriolet/cab/decompressor.rb +510 -0
- data/lib/cabriolet/cab/extractor.rb +357 -0
- data/lib/cabriolet/cab/parser.rb +264 -0
- data/lib/cabriolet/chm/compressor.rb +513 -0
- data/lib/cabriolet/chm/decompressor.rb +436 -0
- data/lib/cabriolet/chm/parser.rb +254 -0
- data/lib/cabriolet/cli.rb +776 -0
- data/lib/cabriolet/compressors/base.rb +34 -0
- data/lib/cabriolet/compressors/lzss.rb +250 -0
- data/lib/cabriolet/compressors/lzx.rb +581 -0
- data/lib/cabriolet/compressors/mszip.rb +315 -0
- data/lib/cabriolet/compressors/quantum.rb +446 -0
- data/lib/cabriolet/constants.rb +75 -0
- data/lib/cabriolet/decompressors/base.rb +39 -0
- data/lib/cabriolet/decompressors/lzss.rb +138 -0
- data/lib/cabriolet/decompressors/lzx.rb +726 -0
- data/lib/cabriolet/decompressors/mszip.rb +390 -0
- data/lib/cabriolet/decompressors/none.rb +27 -0
- data/lib/cabriolet/decompressors/quantum.rb +456 -0
- data/lib/cabriolet/errors.rb +39 -0
- data/lib/cabriolet/format_detector.rb +156 -0
- data/lib/cabriolet/hlp/compressor.rb +272 -0
- data/lib/cabriolet/hlp/decompressor.rb +198 -0
- data/lib/cabriolet/hlp/parser.rb +131 -0
- data/lib/cabriolet/huffman/decoder.rb +79 -0
- data/lib/cabriolet/huffman/encoder.rb +108 -0
- data/lib/cabriolet/huffman/tree.rb +138 -0
- data/lib/cabriolet/kwaj/compressor.rb +479 -0
- data/lib/cabriolet/kwaj/decompressor.rb +237 -0
- data/lib/cabriolet/kwaj/parser.rb +183 -0
- data/lib/cabriolet/lit/compressor.rb +255 -0
- data/lib/cabriolet/lit/decompressor.rb +250 -0
- data/lib/cabriolet/models/cabinet.rb +81 -0
- data/lib/cabriolet/models/chm_file.rb +28 -0
- data/lib/cabriolet/models/chm_header.rb +67 -0
- data/lib/cabriolet/models/chm_section.rb +38 -0
- data/lib/cabriolet/models/file.rb +119 -0
- data/lib/cabriolet/models/folder.rb +102 -0
- data/lib/cabriolet/models/folder_data.rb +21 -0
- data/lib/cabriolet/models/hlp_file.rb +45 -0
- data/lib/cabriolet/models/hlp_header.rb +37 -0
- data/lib/cabriolet/models/kwaj_header.rb +98 -0
- data/lib/cabriolet/models/lit_header.rb +55 -0
- data/lib/cabriolet/models/oab_header.rb +95 -0
- data/lib/cabriolet/models/szdd_header.rb +72 -0
- data/lib/cabriolet/modifier.rb +326 -0
- data/lib/cabriolet/oab/compressor.rb +353 -0
- data/lib/cabriolet/oab/decompressor.rb +315 -0
- data/lib/cabriolet/parallel.rb +333 -0
- data/lib/cabriolet/repairer.rb +288 -0
- data/lib/cabriolet/streaming.rb +221 -0
- data/lib/cabriolet/system/file_handle.rb +107 -0
- data/lib/cabriolet/system/io_system.rb +87 -0
- data/lib/cabriolet/system/memory_handle.rb +105 -0
- data/lib/cabriolet/szdd/compressor.rb +217 -0
- data/lib/cabriolet/szdd/decompressor.rb +184 -0
- data/lib/cabriolet/szdd/parser.rb +127 -0
- data/lib/cabriolet/validator.rb +332 -0
- data/lib/cabriolet/version.rb +5 -0
- data/lib/cabriolet.rb +104 -0
- metadata +157 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cabriolet
|
|
4
|
+
# Archive validation and integrity checking
|
|
5
|
+
class Validator
|
|
6
|
+
# Validation levels
|
|
7
|
+
LEVEL_QUICK = :quick # Basic structure validation
|
|
8
|
+
LEVEL_STANDARD = :standard # Standard validation with checksums
|
|
9
|
+
LEVEL_THOROUGH = :thorough # Full decompression validation
|
|
10
|
+
|
|
11
|
+
def initialize(path, level: LEVEL_STANDARD)
|
|
12
|
+
@path = path
|
|
13
|
+
@level = level
|
|
14
|
+
@errors = []
|
|
15
|
+
@warnings = []
|
|
16
|
+
@format = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Validate the archive
|
|
20
|
+
#
|
|
21
|
+
# @return [ValidationReport] Validation report object
|
|
22
|
+
#
|
|
23
|
+
# @example
|
|
24
|
+
# validator = Cabriolet::Validator.new('archive.cab')
|
|
25
|
+
# report = validator.validate
|
|
26
|
+
# puts "Valid: #{report.valid?}"
|
|
27
|
+
# puts "Errors: #{report.errors}"
|
|
28
|
+
def validate
|
|
29
|
+
detect_format
|
|
30
|
+
|
|
31
|
+
case @level
|
|
32
|
+
when LEVEL_QUICK
|
|
33
|
+
validate_quick
|
|
34
|
+
when LEVEL_STANDARD
|
|
35
|
+
validate_standard
|
|
36
|
+
when LEVEL_THOROUGH
|
|
37
|
+
validate_thorough
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
ValidationReport.new(
|
|
41
|
+
valid: @errors.empty?,
|
|
42
|
+
format: @format,
|
|
43
|
+
level: @level,
|
|
44
|
+
errors: @errors,
|
|
45
|
+
warnings: @warnings,
|
|
46
|
+
path: @path,
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def detect_format
|
|
53
|
+
@format = FormatDetector.detect(@path)
|
|
54
|
+
|
|
55
|
+
unless @format
|
|
56
|
+
@errors << "Unable to detect archive format"
|
|
57
|
+
return
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
@warnings << "Format detected as: #{@format}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def validate_quick
|
|
64
|
+
return unless @format
|
|
65
|
+
|
|
66
|
+
# Basic file checks
|
|
67
|
+
validate_file_exists
|
|
68
|
+
validate_file_readable
|
|
69
|
+
validate_magic_bytes
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def validate_standard
|
|
73
|
+
validate_quick
|
|
74
|
+
return unless @errors.empty?
|
|
75
|
+
|
|
76
|
+
# Structure validation
|
|
77
|
+
validate_structure
|
|
78
|
+
validate_checksums if should_validate_checksums?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def validate_thorough
|
|
82
|
+
validate_standard
|
|
83
|
+
return unless @errors.empty?
|
|
84
|
+
|
|
85
|
+
# Full decompression test
|
|
86
|
+
validate_decompression
|
|
87
|
+
validate_file_integrity
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def validate_file_exists
|
|
91
|
+
return if File.exist?(@path)
|
|
92
|
+
|
|
93
|
+
@errors << "File does not exist: #{@path}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def validate_file_readable
|
|
97
|
+
return if File.readable?(@path)
|
|
98
|
+
|
|
99
|
+
@errors << "File is not readable: #{@path}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def validate_magic_bytes
|
|
103
|
+
File.open(@path, "rb") do |f|
|
|
104
|
+
magic = f.read(4)
|
|
105
|
+
|
|
106
|
+
expected = expected_magic_bytes(@format)
|
|
107
|
+
@errors << "Invalid magic bytes for #{@format} format" unless expected.any? do |m|
|
|
108
|
+
magic.start_with?(m)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
@errors << "Error reading magic bytes: #{e.message}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def validate_structure
|
|
116
|
+
parser_class = FormatDetector.format_to_parser(@format)
|
|
117
|
+
unless parser_class
|
|
118
|
+
@errors << "No parser available for format: #{@format}"
|
|
119
|
+
return
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
archive = parser_class.new.parse(@path)
|
|
123
|
+
|
|
124
|
+
# Format-specific structure validation
|
|
125
|
+
case @format
|
|
126
|
+
when :cab
|
|
127
|
+
validate_cab_structure(archive)
|
|
128
|
+
when :chm
|
|
129
|
+
validate_chm_structure(archive)
|
|
130
|
+
end
|
|
131
|
+
rescue StandardError => e
|
|
132
|
+
@errors << "Structure validation failed: #{e.message}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def validate_cab_structure(cabinet)
|
|
136
|
+
# Validate CAB header
|
|
137
|
+
unless cabinet.respond_to?(:header)
|
|
138
|
+
@errors << "Missing CAB header"
|
|
139
|
+
return
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
header = cabinet.header
|
|
143
|
+
|
|
144
|
+
# Check version
|
|
145
|
+
unless header.version_major == 1 && header.version_minor >= 1
|
|
146
|
+
@warnings << "Unusual CAB version: #{header.version_major}.#{header.version_minor}"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Check folder count
|
|
150
|
+
@errors << "CAB has no folders" if cabinet.folders.empty?
|
|
151
|
+
|
|
152
|
+
# Check file count
|
|
153
|
+
@warnings << "CAB has no files" if cabinet.files.empty?
|
|
154
|
+
|
|
155
|
+
# Validate folder indices
|
|
156
|
+
cabinet.files.each do |file|
|
|
157
|
+
@errors << "File #{file.name} references invalid folder index" if file.folder_index >= cabinet.folders.count
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def validate_chm_structure(chm)
|
|
162
|
+
return unless chm.files.empty?
|
|
163
|
+
|
|
164
|
+
@warnings << "CHM has no files"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def validate_checksums
|
|
168
|
+
case @format
|
|
169
|
+
when :cab
|
|
170
|
+
validate_cab_checksums
|
|
171
|
+
end
|
|
172
|
+
rescue StandardError => e
|
|
173
|
+
@errors << "Checksum validation failed: #{e.message}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def validate_cab_checksums
|
|
177
|
+
parser = Cabriolet::CAB::Parser.new(skip_checksum: false)
|
|
178
|
+
begin
|
|
179
|
+
parser.parse(@path)
|
|
180
|
+
@warnings << "All checksums valid"
|
|
181
|
+
rescue Cabriolet::ChecksumError => e
|
|
182
|
+
@errors << "Checksum error: #{e.message}"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def validate_decompression
|
|
187
|
+
parser_class = FormatDetector.format_to_parser(@format)
|
|
188
|
+
archive = parser_class.new.parse(@path)
|
|
189
|
+
|
|
190
|
+
file_count = 0
|
|
191
|
+
failed_count = 0
|
|
192
|
+
|
|
193
|
+
archive.files.each do |file|
|
|
194
|
+
file_count += 1
|
|
195
|
+
begin
|
|
196
|
+
data = file.data
|
|
197
|
+
if data.nil? || (file.respond_to?(:size) && data.bytesize != file.size)
|
|
198
|
+
@warnings << "File size mismatch: #{file.name}"
|
|
199
|
+
end
|
|
200
|
+
rescue StandardError => e
|
|
201
|
+
failed_count += 1
|
|
202
|
+
@errors << "Failed to decompress #{file.name}: #{e.message}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if failed_count.zero?
|
|
207
|
+
@warnings << "All #{file_count} files decompressed successfully"
|
|
208
|
+
else
|
|
209
|
+
@errors << "#{failed_count} out of #{file_count} files failed to decompress"
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def validate_file_integrity
|
|
214
|
+
# Additional integrity checks could be added here
|
|
215
|
+
# For example: path traversal detection, suspicious file names, etc.
|
|
216
|
+
|
|
217
|
+
parser_class = FormatDetector.format_to_parser(@format)
|
|
218
|
+
archive = parser_class.new.parse(@path)
|
|
219
|
+
|
|
220
|
+
archive.files.each do |file|
|
|
221
|
+
# Check for path traversal attempts
|
|
222
|
+
@warnings << "Suspicious path detected: #{file.name}" if file.name.include?("..") || file.name.start_with?("/")
|
|
223
|
+
|
|
224
|
+
# Check for extremely long file names
|
|
225
|
+
@warnings << "Unusually long filename: #{file.name[0..50]}..." if file.name.length > 255
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def should_validate_checksums?
|
|
230
|
+
@format == :cab # Only CAB format has checksums
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def expected_magic_bytes(format)
|
|
234
|
+
case format
|
|
235
|
+
when :cab
|
|
236
|
+
["MSCF"]
|
|
237
|
+
when :chm
|
|
238
|
+
["ITSF"]
|
|
239
|
+
when :hlp
|
|
240
|
+
["\x3F\x5F", "\x4C\x4E"]
|
|
241
|
+
when :kwaj
|
|
242
|
+
["KWAJ"]
|
|
243
|
+
when :szdd
|
|
244
|
+
["SZDD", "\x88\xF0\x27\x00"]
|
|
245
|
+
when :lit
|
|
246
|
+
["ITOLITLS"]
|
|
247
|
+
else
|
|
248
|
+
[]
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Validation report object
|
|
254
|
+
class ValidationReport
|
|
255
|
+
attr_reader :valid, :format, :level, :errors, :warnings, :path
|
|
256
|
+
|
|
257
|
+
def initialize(valid:, format:, level:, errors:, warnings:, path:)
|
|
258
|
+
@valid = valid
|
|
259
|
+
@format = format
|
|
260
|
+
@level = level
|
|
261
|
+
@errors = errors
|
|
262
|
+
@warnings = warnings
|
|
263
|
+
@path = path
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def valid?
|
|
267
|
+
@valid
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def has_errors?
|
|
271
|
+
!@errors.empty?
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def has_warnings?
|
|
275
|
+
!@warnings.empty?
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def summary
|
|
279
|
+
status = valid? ? "VALID" : "INVALID"
|
|
280
|
+
"#{status} - #{@format} archive (#{@level} validation)\n" \
|
|
281
|
+
"Errors: #{@errors.count}, Warnings: #{@warnings.count}"
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def detailed_report
|
|
285
|
+
report = ["=" * 60]
|
|
286
|
+
report << "Validation Report"
|
|
287
|
+
report << ("=" * 60)
|
|
288
|
+
report << "File: #{@path}"
|
|
289
|
+
report << "Format: #{@format}"
|
|
290
|
+
report << "Level: #{@level}"
|
|
291
|
+
report << "Status: #{valid? ? 'VALID' : 'INVALID'}"
|
|
292
|
+
report << ""
|
|
293
|
+
|
|
294
|
+
if has_errors?
|
|
295
|
+
report << "ERRORS:"
|
|
296
|
+
@errors.each_with_index do |error, i|
|
|
297
|
+
report << " #{i + 1}. #{error}"
|
|
298
|
+
end
|
|
299
|
+
report << ""
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
if has_warnings?
|
|
303
|
+
report << "WARNINGS:"
|
|
304
|
+
@warnings.each_with_index do |warning, i|
|
|
305
|
+
report << " #{i + 1}. #{warning}"
|
|
306
|
+
end
|
|
307
|
+
report << ""
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
report << ("=" * 60)
|
|
311
|
+
report.join("\n")
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def to_h
|
|
315
|
+
{
|
|
316
|
+
valid: @valid,
|
|
317
|
+
format: @format,
|
|
318
|
+
level: @level,
|
|
319
|
+
path: @path,
|
|
320
|
+
error_count: @errors.count,
|
|
321
|
+
warning_count: @warnings.count,
|
|
322
|
+
errors: @errors,
|
|
323
|
+
warnings: @warnings,
|
|
324
|
+
}
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def to_json(*args)
|
|
328
|
+
require "json"
|
|
329
|
+
to_h.to_json(*args)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
data/lib/cabriolet.rb
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "cabriolet/version"
|
|
4
|
+
require_relative "cabriolet/errors"
|
|
5
|
+
require_relative "cabriolet/constants"
|
|
6
|
+
|
|
7
|
+
# Cabriolet is a pure Ruby library for extracting Microsoft Cabinet (.CAB) files,
|
|
8
|
+
# CHM (Compiled HTML Help) files, and related compression formats.
|
|
9
|
+
module Cabriolet
|
|
10
|
+
class << self
|
|
11
|
+
# Enable or disable verbose output
|
|
12
|
+
attr_accessor :verbose
|
|
13
|
+
|
|
14
|
+
# Default buffer size for I/O operations (4KB)
|
|
15
|
+
attr_accessor :default_buffer_size
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
self.verbose = false
|
|
19
|
+
self.default_buffer_size = 4096
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Load core components
|
|
23
|
+
require_relative "cabriolet/system/io_system"
|
|
24
|
+
require_relative "cabriolet/system/file_handle"
|
|
25
|
+
require_relative "cabriolet/system/memory_handle"
|
|
26
|
+
|
|
27
|
+
require_relative "cabriolet/binary/structures"
|
|
28
|
+
require_relative "cabriolet/binary/bitstream"
|
|
29
|
+
require_relative "cabriolet/binary/bitstream_writer"
|
|
30
|
+
require_relative "cabriolet/binary/chm_structures"
|
|
31
|
+
require_relative "cabriolet/binary/szdd_structures"
|
|
32
|
+
require_relative "cabriolet/binary/kwaj_structures"
|
|
33
|
+
require_relative "cabriolet/binary/hlp_structures"
|
|
34
|
+
require_relative "cabriolet/binary/lit_structures"
|
|
35
|
+
require_relative "cabriolet/binary/oab_structures"
|
|
36
|
+
|
|
37
|
+
require_relative "cabriolet/models/cabinet"
|
|
38
|
+
require_relative "cabriolet/models/folder"
|
|
39
|
+
require_relative "cabriolet/models/file"
|
|
40
|
+
require_relative "cabriolet/models/chm_header"
|
|
41
|
+
require_relative "cabriolet/models/chm_file"
|
|
42
|
+
require_relative "cabriolet/models/chm_section"
|
|
43
|
+
require_relative "cabriolet/models/szdd_header"
|
|
44
|
+
require_relative "cabriolet/models/kwaj_header"
|
|
45
|
+
require_relative "cabriolet/models/hlp_header"
|
|
46
|
+
require_relative "cabriolet/models/hlp_file"
|
|
47
|
+
require_relative "cabriolet/models/lit_header"
|
|
48
|
+
require_relative "cabriolet/models/oab_header"
|
|
49
|
+
|
|
50
|
+
require_relative "cabriolet/huffman/tree"
|
|
51
|
+
require_relative "cabriolet/huffman/decoder"
|
|
52
|
+
require_relative "cabriolet/huffman/encoder"
|
|
53
|
+
|
|
54
|
+
require_relative "cabriolet/decompressors/base"
|
|
55
|
+
require_relative "cabriolet/decompressors/none"
|
|
56
|
+
require_relative "cabriolet/decompressors/lzss"
|
|
57
|
+
require_relative "cabriolet/decompressors/mszip"
|
|
58
|
+
require_relative "cabriolet/decompressors/lzx"
|
|
59
|
+
require_relative "cabriolet/decompressors/quantum"
|
|
60
|
+
|
|
61
|
+
require_relative "cabriolet/compressors/base"
|
|
62
|
+
require_relative "cabriolet/compressors/lzss"
|
|
63
|
+
require_relative "cabriolet/compressors/mszip"
|
|
64
|
+
require_relative "cabriolet/compressors/lzx"
|
|
65
|
+
require_relative "cabriolet/compressors/quantum"
|
|
66
|
+
|
|
67
|
+
require_relative "cabriolet/cab/parser"
|
|
68
|
+
require_relative "cabriolet/cab/decompressor"
|
|
69
|
+
require_relative "cabriolet/cab/extractor"
|
|
70
|
+
require_relative "cabriolet/cab/compressor"
|
|
71
|
+
|
|
72
|
+
require_relative "cabriolet/chm/parser"
|
|
73
|
+
require_relative "cabriolet/chm/decompressor"
|
|
74
|
+
require_relative "cabriolet/chm/compressor"
|
|
75
|
+
|
|
76
|
+
require_relative "cabriolet/szdd/parser"
|
|
77
|
+
require_relative "cabriolet/szdd/decompressor"
|
|
78
|
+
require_relative "cabriolet/szdd/compressor"
|
|
79
|
+
|
|
80
|
+
require_relative "cabriolet/kwaj/parser"
|
|
81
|
+
require_relative "cabriolet/kwaj/decompressor"
|
|
82
|
+
require_relative "cabriolet/kwaj/compressor"
|
|
83
|
+
|
|
84
|
+
require_relative "cabriolet/hlp/parser"
|
|
85
|
+
require_relative "cabriolet/hlp/decompressor"
|
|
86
|
+
require_relative "cabriolet/hlp/compressor"
|
|
87
|
+
|
|
88
|
+
require_relative "cabriolet/lit/decompressor"
|
|
89
|
+
require_relative "cabriolet/lit/compressor"
|
|
90
|
+
|
|
91
|
+
require_relative "cabriolet/oab/decompressor"
|
|
92
|
+
require_relative "cabriolet/oab/compressor"
|
|
93
|
+
|
|
94
|
+
# Load new advanced features
|
|
95
|
+
require_relative "cabriolet/format_detector"
|
|
96
|
+
require_relative "cabriolet/auto"
|
|
97
|
+
require_relative "cabriolet/streaming"
|
|
98
|
+
require_relative "cabriolet/validator"
|
|
99
|
+
require_relative "cabriolet/repairer"
|
|
100
|
+
require_relative "cabriolet/modifier"
|
|
101
|
+
require_relative "cabriolet/parallel"
|
|
102
|
+
|
|
103
|
+
# Load CLI (optional, for command-line usage)
|
|
104
|
+
require_relative "cabriolet/cli"
|
metadata
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cabriolet
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ribose Inc.
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-11-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bindata
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.5'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.5'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: thor
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.3'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.3'
|
|
41
|
+
description: |
|
|
42
|
+
Cabriolet is a pure Ruby gem for extracting Microsoft Cabinet (.CAB) files.
|
|
43
|
+
It supports multiple compression algorithms (MSZIP, LZX, Quantum, LZSS) and
|
|
44
|
+
requires no C extensions, making it portable across all Ruby platforms.
|
|
45
|
+
email:
|
|
46
|
+
- open.source@ribose.com
|
|
47
|
+
executables:
|
|
48
|
+
- cabriolet
|
|
49
|
+
extensions: []
|
|
50
|
+
extra_rdoc_files: []
|
|
51
|
+
files:
|
|
52
|
+
- ARCHITECTURE.md
|
|
53
|
+
- CHANGELOG.md
|
|
54
|
+
- LICENSE
|
|
55
|
+
- README.adoc
|
|
56
|
+
- exe/cabriolet
|
|
57
|
+
- lib/cabriolet.rb
|
|
58
|
+
- lib/cabriolet/auto.rb
|
|
59
|
+
- lib/cabriolet/binary/bitstream.rb
|
|
60
|
+
- lib/cabriolet/binary/bitstream_writer.rb
|
|
61
|
+
- lib/cabriolet/binary/chm_structures.rb
|
|
62
|
+
- lib/cabriolet/binary/hlp_structures.rb
|
|
63
|
+
- lib/cabriolet/binary/kwaj_structures.rb
|
|
64
|
+
- lib/cabriolet/binary/lit_structures.rb
|
|
65
|
+
- lib/cabriolet/binary/oab_structures.rb
|
|
66
|
+
- lib/cabriolet/binary/structures.rb
|
|
67
|
+
- lib/cabriolet/binary/szdd_structures.rb
|
|
68
|
+
- lib/cabriolet/cab/compressor.rb
|
|
69
|
+
- lib/cabriolet/cab/decompressor.rb
|
|
70
|
+
- lib/cabriolet/cab/extractor.rb
|
|
71
|
+
- lib/cabriolet/cab/parser.rb
|
|
72
|
+
- lib/cabriolet/chm/compressor.rb
|
|
73
|
+
- lib/cabriolet/chm/decompressor.rb
|
|
74
|
+
- lib/cabriolet/chm/parser.rb
|
|
75
|
+
- lib/cabriolet/cli.rb
|
|
76
|
+
- lib/cabriolet/compressors/base.rb
|
|
77
|
+
- lib/cabriolet/compressors/lzss.rb
|
|
78
|
+
- lib/cabriolet/compressors/lzx.rb
|
|
79
|
+
- lib/cabriolet/compressors/mszip.rb
|
|
80
|
+
- lib/cabriolet/compressors/quantum.rb
|
|
81
|
+
- lib/cabriolet/constants.rb
|
|
82
|
+
- lib/cabriolet/decompressors/base.rb
|
|
83
|
+
- lib/cabriolet/decompressors/lzss.rb
|
|
84
|
+
- lib/cabriolet/decompressors/lzx.rb
|
|
85
|
+
- lib/cabriolet/decompressors/mszip.rb
|
|
86
|
+
- lib/cabriolet/decompressors/none.rb
|
|
87
|
+
- lib/cabriolet/decompressors/quantum.rb
|
|
88
|
+
- lib/cabriolet/errors.rb
|
|
89
|
+
- lib/cabriolet/format_detector.rb
|
|
90
|
+
- lib/cabriolet/hlp/compressor.rb
|
|
91
|
+
- lib/cabriolet/hlp/decompressor.rb
|
|
92
|
+
- lib/cabriolet/hlp/parser.rb
|
|
93
|
+
- lib/cabriolet/huffman/decoder.rb
|
|
94
|
+
- lib/cabriolet/huffman/encoder.rb
|
|
95
|
+
- lib/cabriolet/huffman/tree.rb
|
|
96
|
+
- lib/cabriolet/kwaj/compressor.rb
|
|
97
|
+
- lib/cabriolet/kwaj/decompressor.rb
|
|
98
|
+
- lib/cabriolet/kwaj/parser.rb
|
|
99
|
+
- lib/cabriolet/lit/compressor.rb
|
|
100
|
+
- lib/cabriolet/lit/decompressor.rb
|
|
101
|
+
- lib/cabriolet/models/cabinet.rb
|
|
102
|
+
- lib/cabriolet/models/chm_file.rb
|
|
103
|
+
- lib/cabriolet/models/chm_header.rb
|
|
104
|
+
- lib/cabriolet/models/chm_section.rb
|
|
105
|
+
- lib/cabriolet/models/file.rb
|
|
106
|
+
- lib/cabriolet/models/folder.rb
|
|
107
|
+
- lib/cabriolet/models/folder_data.rb
|
|
108
|
+
- lib/cabriolet/models/hlp_file.rb
|
|
109
|
+
- lib/cabriolet/models/hlp_header.rb
|
|
110
|
+
- lib/cabriolet/models/kwaj_header.rb
|
|
111
|
+
- lib/cabriolet/models/lit_header.rb
|
|
112
|
+
- lib/cabriolet/models/oab_header.rb
|
|
113
|
+
- lib/cabriolet/models/szdd_header.rb
|
|
114
|
+
- lib/cabriolet/modifier.rb
|
|
115
|
+
- lib/cabriolet/oab/compressor.rb
|
|
116
|
+
- lib/cabriolet/oab/decompressor.rb
|
|
117
|
+
- lib/cabriolet/parallel.rb
|
|
118
|
+
- lib/cabriolet/repairer.rb
|
|
119
|
+
- lib/cabriolet/streaming.rb
|
|
120
|
+
- lib/cabriolet/system/file_handle.rb
|
|
121
|
+
- lib/cabriolet/system/io_system.rb
|
|
122
|
+
- lib/cabriolet/system/memory_handle.rb
|
|
123
|
+
- lib/cabriolet/szdd/compressor.rb
|
|
124
|
+
- lib/cabriolet/szdd/decompressor.rb
|
|
125
|
+
- lib/cabriolet/szdd/parser.rb
|
|
126
|
+
- lib/cabriolet/validator.rb
|
|
127
|
+
- lib/cabriolet/version.rb
|
|
128
|
+
homepage: https://github.com/omnizip/cabriolet
|
|
129
|
+
licenses:
|
|
130
|
+
- BSD-3-Clause
|
|
131
|
+
metadata:
|
|
132
|
+
homepage_uri: https://github.com/omnizip/cabriolet
|
|
133
|
+
source_code_uri: https://github.com/omnizip/cabriolet
|
|
134
|
+
changelog_uri: https://github.com/omnizip/cabriolet/blob/main/CHANGELOG.md
|
|
135
|
+
bug_tracker_uri: https://github.com/omnizip/cabriolet/issues
|
|
136
|
+
documentation_uri: https://rubydoc.info/gems/cabriolet
|
|
137
|
+
rubygems_mfa_required: 'true'
|
|
138
|
+
post_install_message:
|
|
139
|
+
rdoc_options: []
|
|
140
|
+
require_paths:
|
|
141
|
+
- lib
|
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: 2.7.0
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
152
|
+
requirements: []
|
|
153
|
+
rubygems_version: 3.5.22
|
|
154
|
+
signing_key:
|
|
155
|
+
specification_version: 4
|
|
156
|
+
summary: Pure Ruby implementation for extracting Microsoft Cabinet files
|
|
157
|
+
test_files: []
|