cabriolet 0.1.2 → 0.2.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +700 -38
  3. data/lib/cabriolet/algorithm_factory.rb +250 -0
  4. data/lib/cabriolet/base_compressor.rb +206 -0
  5. data/lib/cabriolet/binary/bitstream.rb +154 -14
  6. data/lib/cabriolet/binary/bitstream_writer.rb +129 -17
  7. data/lib/cabriolet/binary/chm_structures.rb +2 -2
  8. data/lib/cabriolet/binary/hlp_structures.rb +258 -37
  9. data/lib/cabriolet/binary/lit_structures.rb +231 -65
  10. data/lib/cabriolet/binary/oab_structures.rb +17 -1
  11. data/lib/cabriolet/cab/command_handler.rb +226 -0
  12. data/lib/cabriolet/cab/compressor.rb +35 -43
  13. data/lib/cabriolet/cab/decompressor.rb +14 -19
  14. data/lib/cabriolet/cab/extractor.rb +140 -31
  15. data/lib/cabriolet/chm/command_handler.rb +227 -0
  16. data/lib/cabriolet/chm/compressor.rb +7 -3
  17. data/lib/cabriolet/chm/decompressor.rb +39 -21
  18. data/lib/cabriolet/chm/parser.rb +5 -2
  19. data/lib/cabriolet/cli/base_command_handler.rb +127 -0
  20. data/lib/cabriolet/cli/command_dispatcher.rb +140 -0
  21. data/lib/cabriolet/cli/command_registry.rb +83 -0
  22. data/lib/cabriolet/cli.rb +356 -607
  23. data/lib/cabriolet/compressors/base.rb +1 -1
  24. data/lib/cabriolet/compressors/lzx.rb +241 -54
  25. data/lib/cabriolet/compressors/mszip.rb +35 -3
  26. data/lib/cabriolet/compressors/quantum.rb +34 -45
  27. data/lib/cabriolet/decompressors/base.rb +1 -1
  28. data/lib/cabriolet/decompressors/lzss.rb +13 -3
  29. data/lib/cabriolet/decompressors/lzx.rb +70 -33
  30. data/lib/cabriolet/decompressors/mszip.rb +126 -39
  31. data/lib/cabriolet/decompressors/quantum.rb +3 -2
  32. data/lib/cabriolet/errors.rb +3 -0
  33. data/lib/cabriolet/file_entry.rb +156 -0
  34. data/lib/cabriolet/file_manager.rb +144 -0
  35. data/lib/cabriolet/hlp/command_handler.rb +282 -0
  36. data/lib/cabriolet/hlp/compressor.rb +28 -238
  37. data/lib/cabriolet/hlp/decompressor.rb +107 -147
  38. data/lib/cabriolet/hlp/parser.rb +52 -101
  39. data/lib/cabriolet/hlp/quickhelp/compression_stream.rb +138 -0
  40. data/lib/cabriolet/hlp/quickhelp/compressor.rb +626 -0
  41. data/lib/cabriolet/hlp/quickhelp/decompressor.rb +558 -0
  42. data/lib/cabriolet/hlp/quickhelp/huffman_stream.rb +74 -0
  43. data/lib/cabriolet/hlp/quickhelp/huffman_tree.rb +167 -0
  44. data/lib/cabriolet/hlp/quickhelp/parser.rb +274 -0
  45. data/lib/cabriolet/hlp/winhelp/btree_builder.rb +289 -0
  46. data/lib/cabriolet/hlp/winhelp/compressor.rb +400 -0
  47. data/lib/cabriolet/hlp/winhelp/decompressor.rb +192 -0
  48. data/lib/cabriolet/hlp/winhelp/parser.rb +484 -0
  49. data/lib/cabriolet/hlp/winhelp/zeck_lz77.rb +271 -0
  50. data/lib/cabriolet/huffman/tree.rb +85 -1
  51. data/lib/cabriolet/kwaj/command_handler.rb +213 -0
  52. data/lib/cabriolet/kwaj/compressor.rb +7 -3
  53. data/lib/cabriolet/kwaj/decompressor.rb +18 -12
  54. data/lib/cabriolet/lit/command_handler.rb +221 -0
  55. data/lib/cabriolet/lit/compressor.rb +633 -38
  56. data/lib/cabriolet/lit/decompressor.rb +518 -152
  57. data/lib/cabriolet/lit/parser.rb +670 -0
  58. data/lib/cabriolet/models/hlp_file.rb +130 -29
  59. data/lib/cabriolet/models/hlp_header.rb +105 -17
  60. data/lib/cabriolet/models/lit_header.rb +212 -25
  61. data/lib/cabriolet/models/szdd_header.rb +10 -2
  62. data/lib/cabriolet/models/winhelp_header.rb +127 -0
  63. data/lib/cabriolet/oab/command_handler.rb +257 -0
  64. data/lib/cabriolet/oab/compressor.rb +17 -8
  65. data/lib/cabriolet/oab/decompressor.rb +41 -10
  66. data/lib/cabriolet/offset_calculator.rb +81 -0
  67. data/lib/cabriolet/plugin.rb +233 -0
  68. data/lib/cabriolet/plugin_manager.rb +453 -0
  69. data/lib/cabriolet/plugin_validator.rb +422 -0
  70. data/lib/cabriolet/system/io_system.rb +3 -0
  71. data/lib/cabriolet/system/memory_handle.rb +17 -4
  72. data/lib/cabriolet/szdd/command_handler.rb +217 -0
  73. data/lib/cabriolet/szdd/compressor.rb +15 -11
  74. data/lib/cabriolet/szdd/decompressor.rb +18 -9
  75. data/lib/cabriolet/version.rb +1 -1
  76. data/lib/cabriolet.rb +67 -17
  77. metadata +33 -2
@@ -14,8 +14,10 @@ module Cabriolet
14
14
  #
15
15
  # @param io_system [System::IOSystem, nil] Custom I/O system or nil for
16
16
  # default
17
- def initialize(io_system = nil)
17
+ # @param algorithm_factory [AlgorithmFactory, nil] Custom algorithm factory or nil for default
18
+ def initialize(io_system = nil, algorithm_factory = nil)
18
19
  @io_system = io_system || System::IOSystem.new
20
+ @algorithm_factory = algorithm_factory || Cabriolet.algorithm_factory
19
21
  end
20
22
 
21
23
  # Compress a file to SZDD format
@@ -59,12 +61,14 @@ module Cabriolet
59
61
  Compressors::LZSS::MODE_QBASIC
60
62
  end
61
63
 
62
- compressor = Compressors::LZSS.new(
64
+ compressor = @algorithm_factory.create(
65
+ :lzss,
66
+ :compressor,
63
67
  @io_system,
64
68
  input_handle,
65
69
  output_handle,
66
70
  2048,
67
- lzss_mode,
71
+ mode: lzss_mode,
68
72
  )
69
73
 
70
74
  compressed_bytes = compressor.compress
@@ -107,18 +111,18 @@ module Cabriolet
107
111
  )
108
112
 
109
113
  # Compress data using LZSS
110
- lzss_mode = if format == :normal
111
- Compressors::LZSS::MODE_EXPAND
112
- else
113
- Compressors::LZSS::MODE_QBASIC
114
- end
115
-
116
- compressor = Compressors::LZSS.new(
114
+ compressor = @algorithm_factory.create(
115
+ :lzss,
116
+ :compressor,
117
117
  @io_system,
118
118
  input_handle,
119
119
  output_handle,
120
120
  2048,
121
- lzss_mode,
121
+ mode: if format == :normal
122
+ Compressors::LZSS::MODE_EXPAND
123
+ else
124
+ Compressors::LZSS::MODE_QBASIC
125
+ end,
122
126
  )
123
127
 
124
128
  compressed_bytes = compressor.compress
@@ -17,8 +17,10 @@ module Cabriolet
17
17
  #
18
18
  # @param io_system [System::IOSystem, nil] Custom I/O system or nil for
19
19
  # default
20
- def initialize(io_system = nil)
20
+ # @param algorithm_factory [AlgorithmFactory, nil] Custom algorithm factory or nil for default
21
+ def initialize(io_system = nil, algorithm_factory = nil)
21
22
  @io_system = io_system || System::IOSystem.new
23
+ @algorithm_factory = algorithm_factory || Cabriolet.algorithm_factory
22
24
  @parser = Parser.new(@io_system)
23
25
  @buffer_size = DEFAULT_BUFFER_SIZE
24
26
  end
@@ -70,16 +72,18 @@ module Cabriolet
70
72
  end
71
73
 
72
74
  # Create LZSS decompressor
73
- decompressor = Decompressors::LZSS.new(
75
+ decompressor = @algorithm_factory.create(
76
+ :lzss,
77
+ :decompressor,
74
78
  @io_system,
75
79
  input_handle,
76
80
  output_handle,
77
81
  @buffer_size,
78
- lzss_mode,
82
+ mode: lzss_mode,
79
83
  )
80
84
 
81
- # Decompress
82
- bytes_written = decompressor.decompress(header.length)
85
+ # Decompress (SZDD reads until EOF, no compressed size stored)
86
+ bytes_written = decompressor.decompress(nil)
83
87
 
84
88
  # Verify decompressed size matches expected
85
89
  if bytes_written != header.length && Cabriolet.verbose && Cabriolet.verbose
@@ -118,16 +122,18 @@ module Cabriolet
118
122
  end
119
123
 
120
124
  # Create LZSS decompressor
121
- decompressor = Decompressors::LZSS.new(
125
+ decompressor = @algorithm_factory.create(
126
+ :lzss,
127
+ :decompressor,
122
128
  @io_system,
123
129
  input_handle,
124
130
  output_handle,
125
131
  @buffer_size,
126
- lzss_mode,
132
+ mode: lzss_mode,
127
133
  )
128
134
 
129
- # Decompress
130
- decompressor.decompress(header.length)
135
+ # Decompress (SZDD reads until EOF, no compressed size stored)
136
+ decompressor.decompress(nil)
131
137
 
132
138
  # Return the decompressed data
133
139
  output_handle.data
@@ -175,6 +181,9 @@ module Cabriolet
175
181
  # Use header's suggested filename method
176
182
  suggested = header.suggested_filename(base)
177
183
 
184
+ # Strip null bytes which can occur in malformed SZDD files
185
+ suggested = suggested.delete("\0")
186
+
178
187
  # Combine with original directory
179
188
  dir = ::File.dirname(input_path)
180
189
  ::File.join(dir, suggested)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cabriolet
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/cabriolet.rb CHANGED
@@ -1,8 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Cabriolet - Pure Ruby implementation of Microsoft compression formats
3
4
  require_relative "cabriolet/version"
4
- require_relative "cabriolet/platform"
5
5
  require_relative "cabriolet/constants"
6
+ require_relative "cabriolet/errors"
7
+ require_relative "cabriolet/platform"
8
+
9
+ # System layer
10
+ require_relative "cabriolet/system/io_system"
11
+ require_relative "cabriolet/system/file_handle"
12
+ require_relative "cabriolet/system/memory_handle"
13
+
14
+ # Binary structures
15
+ require_relative "cabriolet/binary/bitstream"
16
+ require_relative "cabriolet/binary/bitstream_writer"
17
+ require_relative "cabriolet/binary/structures"
18
+ require_relative "cabriolet/binary/chm_structures"
19
+ require_relative "cabriolet/binary/szdd_structures"
20
+ require_relative "cabriolet/binary/kwaj_structures"
21
+ require_relative "cabriolet/binary/hlp_structures"
22
+ require_relative "cabriolet/binary/lit_structures"
23
+ require_relative "cabriolet/binary/oab_structures"
24
+
25
+ # Foundation classes (architectural improvements)
26
+ require_relative "cabriolet/file_entry"
27
+ require_relative "cabriolet/file_manager"
28
+ require_relative "cabriolet/base_compressor"
6
29
 
7
30
  # Cabriolet is a pure Ruby library for extracting Microsoft Cabinet (.CAB) files,
8
31
  # CHM (Compiled HTML Help) files, and related compression formats.
@@ -13,40 +36,62 @@ module Cabriolet
13
36
 
14
37
  # Default buffer size for I/O operations (4KB)
15
38
  attr_accessor :default_buffer_size
39
+
40
+ # Get the global algorithm factory instance
41
+ #
42
+ # @return [AlgorithmFactory] The algorithm factory
43
+ def algorithm_factory
44
+ @algorithm_factory ||= AlgorithmFactory.new
45
+ end
46
+
47
+ # Set the global algorithm factory instance
48
+ #
49
+ # @param factory [AlgorithmFactory] The algorithm factory to use
50
+ # @return [AlgorithmFactory] The factory
51
+ def algorithm_factory=(factory)
52
+ @algorithm_factory = factory
53
+ end
54
+
55
+ # Get the global plugin manager instance
56
+ #
57
+ # @return [PluginManager] The plugin manager
58
+ def plugin_manager
59
+ PluginManager.instance
60
+ end
16
61
  end
17
62
 
18
63
  self.verbose = false
19
64
  self.default_buffer_size = 4096
20
65
  end
21
66
 
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
-
67
+ # Models
37
68
  require_relative "cabriolet/models/cabinet"
38
69
  require_relative "cabriolet/models/folder"
70
+ require_relative "cabriolet/models/folder_data"
39
71
  require_relative "cabriolet/models/file"
40
72
  require_relative "cabriolet/models/chm_header"
41
- require_relative "cabriolet/models/chm_file"
42
73
  require_relative "cabriolet/models/chm_section"
74
+ require_relative "cabriolet/models/chm_file"
43
75
  require_relative "cabriolet/models/szdd_header"
44
76
  require_relative "cabriolet/models/kwaj_header"
45
77
  require_relative "cabriolet/models/hlp_header"
46
78
  require_relative "cabriolet/models/hlp_file"
79
+ require_relative "cabriolet/models/winhelp_header"
47
80
  require_relative "cabriolet/models/lit_header"
48
81
  require_relative "cabriolet/models/oab_header"
49
82
 
83
+ # Load errors first (needed by algorithm_factory)
84
+
85
+ # Load plugin system
86
+ require_relative "cabriolet/plugin"
87
+ require_relative "cabriolet/plugin_validator"
88
+ require_relative "cabriolet/plugin_manager"
89
+
90
+ # Load algorithm factory
91
+ require_relative "cabriolet/algorithm_factory"
92
+
93
+ # Load core components
94
+
50
95
  require_relative "cabriolet/huffman/tree"
51
96
  require_relative "cabriolet/huffman/decoder"
52
97
  require_relative "cabriolet/huffman/encoder"
@@ -85,6 +130,11 @@ require_relative "cabriolet/hlp/parser"
85
130
  require_relative "cabriolet/hlp/decompressor"
86
131
  require_relative "cabriolet/hlp/compressor"
87
132
 
133
+ require_relative "cabriolet/hlp/winhelp/parser"
134
+ require_relative "cabriolet/hlp/winhelp/zeck_lz77"
135
+ require_relative "cabriolet/hlp/winhelp/decompressor"
136
+ require_relative "cabriolet/hlp/winhelp/compressor"
137
+
88
138
  require_relative "cabriolet/lit/decompressor"
89
139
  require_relative "cabriolet/lit/compressor"
90
140
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cabriolet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-14 00:00:00.000000000 Z
11
+ date: 2026-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -53,7 +53,9 @@ files:
53
53
  - README.adoc
54
54
  - exe/cabriolet
55
55
  - lib/cabriolet.rb
56
+ - lib/cabriolet/algorithm_factory.rb
56
57
  - lib/cabriolet/auto.rb
58
+ - lib/cabriolet/base_compressor.rb
57
59
  - lib/cabriolet/binary/bitstream.rb
58
60
  - lib/cabriolet/binary/bitstream_writer.rb
59
61
  - lib/cabriolet/binary/chm_structures.rb
@@ -63,14 +65,19 @@ files:
63
65
  - lib/cabriolet/binary/oab_structures.rb
64
66
  - lib/cabriolet/binary/structures.rb
65
67
  - lib/cabriolet/binary/szdd_structures.rb
68
+ - lib/cabriolet/cab/command_handler.rb
66
69
  - lib/cabriolet/cab/compressor.rb
67
70
  - lib/cabriolet/cab/decompressor.rb
68
71
  - lib/cabriolet/cab/extractor.rb
69
72
  - lib/cabriolet/cab/parser.rb
73
+ - lib/cabriolet/chm/command_handler.rb
70
74
  - lib/cabriolet/chm/compressor.rb
71
75
  - lib/cabriolet/chm/decompressor.rb
72
76
  - lib/cabriolet/chm/parser.rb
73
77
  - lib/cabriolet/cli.rb
78
+ - lib/cabriolet/cli/base_command_handler.rb
79
+ - lib/cabriolet/cli/command_dispatcher.rb
80
+ - lib/cabriolet/cli/command_registry.rb
74
81
  - lib/cabriolet/compressors/base.rb
75
82
  - lib/cabriolet/compressors/lzss.rb
76
83
  - lib/cabriolet/compressors/lzx.rb
@@ -84,18 +91,35 @@ files:
84
91
  - lib/cabriolet/decompressors/none.rb
85
92
  - lib/cabriolet/decompressors/quantum.rb
86
93
  - lib/cabriolet/errors.rb
94
+ - lib/cabriolet/file_entry.rb
95
+ - lib/cabriolet/file_manager.rb
87
96
  - lib/cabriolet/format_detector.rb
97
+ - lib/cabriolet/hlp/command_handler.rb
88
98
  - lib/cabriolet/hlp/compressor.rb
89
99
  - lib/cabriolet/hlp/decompressor.rb
90
100
  - lib/cabriolet/hlp/parser.rb
101
+ - lib/cabriolet/hlp/quickhelp/compression_stream.rb
102
+ - lib/cabriolet/hlp/quickhelp/compressor.rb
103
+ - lib/cabriolet/hlp/quickhelp/decompressor.rb
104
+ - lib/cabriolet/hlp/quickhelp/huffman_stream.rb
105
+ - lib/cabriolet/hlp/quickhelp/huffman_tree.rb
106
+ - lib/cabriolet/hlp/quickhelp/parser.rb
107
+ - lib/cabriolet/hlp/winhelp/btree_builder.rb
108
+ - lib/cabriolet/hlp/winhelp/compressor.rb
109
+ - lib/cabriolet/hlp/winhelp/decompressor.rb
110
+ - lib/cabriolet/hlp/winhelp/parser.rb
111
+ - lib/cabriolet/hlp/winhelp/zeck_lz77.rb
91
112
  - lib/cabriolet/huffman/decoder.rb
92
113
  - lib/cabriolet/huffman/encoder.rb
93
114
  - lib/cabriolet/huffman/tree.rb
115
+ - lib/cabriolet/kwaj/command_handler.rb
94
116
  - lib/cabriolet/kwaj/compressor.rb
95
117
  - lib/cabriolet/kwaj/decompressor.rb
96
118
  - lib/cabriolet/kwaj/parser.rb
119
+ - lib/cabriolet/lit/command_handler.rb
97
120
  - lib/cabriolet/lit/compressor.rb
98
121
  - lib/cabriolet/lit/decompressor.rb
122
+ - lib/cabriolet/lit/parser.rb
99
123
  - lib/cabriolet/models/cabinet.rb
100
124
  - lib/cabriolet/models/chm_file.rb
101
125
  - lib/cabriolet/models/chm_header.rb
@@ -109,16 +133,23 @@ files:
109
133
  - lib/cabriolet/models/lit_header.rb
110
134
  - lib/cabriolet/models/oab_header.rb
111
135
  - lib/cabriolet/models/szdd_header.rb
136
+ - lib/cabriolet/models/winhelp_header.rb
112
137
  - lib/cabriolet/modifier.rb
138
+ - lib/cabriolet/oab/command_handler.rb
113
139
  - lib/cabriolet/oab/compressor.rb
114
140
  - lib/cabriolet/oab/decompressor.rb
141
+ - lib/cabriolet/offset_calculator.rb
115
142
  - lib/cabriolet/parallel.rb
116
143
  - lib/cabriolet/platform.rb
144
+ - lib/cabriolet/plugin.rb
145
+ - lib/cabriolet/plugin_manager.rb
146
+ - lib/cabriolet/plugin_validator.rb
117
147
  - lib/cabriolet/repairer.rb
118
148
  - lib/cabriolet/streaming.rb
119
149
  - lib/cabriolet/system/file_handle.rb
120
150
  - lib/cabriolet/system/io_system.rb
121
151
  - lib/cabriolet/system/memory_handle.rb
152
+ - lib/cabriolet/szdd/command_handler.rb
122
153
  - lib/cabriolet/szdd/compressor.rb
123
154
  - lib/cabriolet/szdd/decompressor.rb
124
155
  - lib/cabriolet/szdd/parser.rb