libmspack 0.0.1
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/.gitignore +18 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/README.md +75 -0
- data/Rakefile +22 -0
- data/UNLICENSE +24 -0
- data/ext/Rakefile +16 -0
- data/ext/i386-windows/libmspack.dll +0 -0
- data/ext/libmspack/AUTHORS +12 -0
- data/ext/libmspack/COPYING.LIB +504 -0
- data/ext/libmspack/ChangeLog +491 -0
- data/ext/libmspack/Makefile.am +100 -0
- data/ext/libmspack/NEWS +0 -0
- data/ext/libmspack/README +130 -0
- data/ext/libmspack/TODO +8 -0
- data/ext/libmspack/cleanup.sh +9 -0
- data/ext/libmspack/configure.ac +50 -0
- data/ext/libmspack/debian/changelog +6 -0
- data/ext/libmspack/debian/control +14 -0
- data/ext/libmspack/debian/rules +101 -0
- data/ext/libmspack/doc/Doxyfile.in +22 -0
- data/ext/libmspack/doc/Makefile.in +14 -0
- data/ext/libmspack/doc/szdd_kwaj_format.html +331 -0
- data/ext/libmspack/libmspack.pc.in +10 -0
- data/ext/libmspack/mspack/cab.h +127 -0
- data/ext/libmspack/mspack/cabc.c +24 -0
- data/ext/libmspack/mspack/cabd.c +1444 -0
- data/ext/libmspack/mspack/chm.h +122 -0
- data/ext/libmspack/mspack/chmc.c +24 -0
- data/ext/libmspack/mspack/chmd.c +1392 -0
- data/ext/libmspack/mspack/crc32.c +95 -0
- data/ext/libmspack/mspack/crc32.h +17 -0
- data/ext/libmspack/mspack/des.h +15 -0
- data/ext/libmspack/mspack/hlp.h +33 -0
- data/ext/libmspack/mspack/hlpc.c +24 -0
- data/ext/libmspack/mspack/hlpd.c +24 -0
- data/ext/libmspack/mspack/kwaj.h +118 -0
- data/ext/libmspack/mspack/kwajc.c +24 -0
- data/ext/libmspack/mspack/kwajd.c +561 -0
- data/ext/libmspack/mspack/lit.h +35 -0
- data/ext/libmspack/mspack/litc.c +24 -0
- data/ext/libmspack/mspack/litd.c +24 -0
- data/ext/libmspack/mspack/lzss.h +66 -0
- data/ext/libmspack/mspack/lzssd.c +93 -0
- data/ext/libmspack/mspack/lzx.h +221 -0
- data/ext/libmspack/mspack/lzxc.c +18 -0
- data/ext/libmspack/mspack/lzxd.c +895 -0
- data/ext/libmspack/mspack/mspack.def +28 -0
- data/ext/libmspack/mspack/mspack.h +2353 -0
- data/ext/libmspack/mspack/mszip.h +126 -0
- data/ext/libmspack/mspack/mszipc.c +18 -0
- data/ext/libmspack/mspack/mszipd.c +514 -0
- data/ext/libmspack/mspack/oab.h +60 -0
- data/ext/libmspack/mspack/oabc.c +24 -0
- data/ext/libmspack/mspack/oabd.c +408 -0
- data/ext/libmspack/mspack/qtm.h +128 -0
- data/ext/libmspack/mspack/qtmc.c +18 -0
- data/ext/libmspack/mspack/qtmd.c +489 -0
- data/ext/libmspack/mspack/readbits.h +207 -0
- data/ext/libmspack/mspack/readhuff.h +173 -0
- data/ext/libmspack/mspack/sha.h +15 -0
- data/ext/libmspack/mspack/system.c +239 -0
- data/ext/libmspack/mspack/system.h +124 -0
- data/ext/libmspack/mspack/szdd.h +39 -0
- data/ext/libmspack/mspack/szddc.c +24 -0
- data/ext/libmspack/mspack/szddd.c +247 -0
- data/ext/libmspack/rebuild.sh +8 -0
- data/ext/libmspack/test/cabd_c10 +19 -0
- data/ext/libmspack/test/cabd_compare +34 -0
- data/ext/libmspack/test/cabd_md5.c +161 -0
- data/ext/libmspack/test/cabd_memory.c +179 -0
- data/ext/libmspack/test/cabd_test.c +386 -0
- data/ext/libmspack/test/cabrip.c +81 -0
- data/ext/libmspack/test/chmd_compare +38 -0
- data/ext/libmspack/test/chmd_find.c +95 -0
- data/ext/libmspack/test/chmd_md5.c +67 -0
- data/ext/libmspack/test/chmd_order.c +144 -0
- data/ext/libmspack/test/chminfo.c +284 -0
- data/ext/libmspack/test/chmx.c +216 -0
- data/ext/libmspack/test/error.h +22 -0
- data/ext/libmspack/test/expand.c +79 -0
- data/ext/libmspack/test/md5.c +457 -0
- data/ext/libmspack/test/md5.h +165 -0
- data/ext/libmspack/test/md5_fh.h +123 -0
- data/ext/libmspack/test/msdecompile_md5 +24 -0
- data/ext/libmspack/test/msexpand_md5 +39 -0
- data/ext/libmspack/test/multifh.c +435 -0
- data/ext/libmspack/test/oabx.c +41 -0
- data/ext/libmspack/test/test_files/cabd/1.pl +84 -0
- data/ext/libmspack/test/test_files/cabd/2.pl +75 -0
- data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
- data/ext/libmspack/winbuild.sh +26 -0
- data/ext/x86_64-windows/libmspack.dll +0 -0
- data/lib/libmspack/constants.rb +9 -0
- data/lib/libmspack/exceptions.rb +12 -0
- data/lib/libmspack/mscab.rb +722 -0
- data/lib/libmspack/mschm.rb +301 -0
- data/lib/libmspack/mshlp.rb +15 -0
- data/lib/libmspack/mskwaj.rb +124 -0
- data/lib/libmspack/mslit.rb +18 -0
- data/lib/libmspack/msoab.rb +36 -0
- data/lib/libmspack/mspack.rb +208 -0
- data/lib/libmspack/msszdd.rb +81 -0
- data/lib/libmspack/system.rb +84 -0
- data/lib/libmspack/version.rb +4 -0
- data/lib/libmspack.rb +121 -0
- data/libmspack.gemspec +33 -0
- data/spec/libmspack_spec.rb +26 -0
- data/spec/spec_helper.rb +5 -0
- metadata +309 -0
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
module LibMsPack
|
|
2
|
+
module MsCab
|
|
3
|
+
module Constants
|
|
4
|
+
# Offset from start of cabinet to the reserved header data (if present).
|
|
5
|
+
MSCAB_HDR_RESV_OFFSET = 0x28
|
|
6
|
+
# Cabinet header flag: cabinet has a predecessor.
|
|
7
|
+
MSCAB_HDR_PREVCAB = 0x01
|
|
8
|
+
# Cabinet header flag: cabinet has a successor.
|
|
9
|
+
MSCAB_HDR_NEXTCAB = 0x02
|
|
10
|
+
# Cabinet header flag: cabinet has reserved header space.
|
|
11
|
+
MSCAB_HDR_RESV = 0x04
|
|
12
|
+
|
|
13
|
+
# Compression mode: no compression.
|
|
14
|
+
MSCAB_COMP_NONE = 0
|
|
15
|
+
# Compression mode: MSZIP (deflate) compression.
|
|
16
|
+
MSCAB_COMP_MSZIP = 1
|
|
17
|
+
# Compression mode: Quantum compression.
|
|
18
|
+
MSCAB_COMP_QUANTUM = 2
|
|
19
|
+
# Compression mode: LZX compression.
|
|
20
|
+
MSCAB_COMP_LZX = 3
|
|
21
|
+
|
|
22
|
+
# attribute: file is read-only.
|
|
23
|
+
MSCAB_ATTRIB_RDONLY = 0x01
|
|
24
|
+
# attribute: file is hidden.
|
|
25
|
+
MSCAB_ATTRIB_HIDDEN = 0x02
|
|
26
|
+
# attribute: file is an operating system file.
|
|
27
|
+
MSCAB_ATTRIB_SYSTEM = 0x04
|
|
28
|
+
# attribute: file is "archived".
|
|
29
|
+
MSCAB_ATTRIB_ARCH = 0x20
|
|
30
|
+
# attribute: file is an executable program.
|
|
31
|
+
MSCAB_ATTRIB_EXEC = 0x40
|
|
32
|
+
# attribute: filename is UTF8, not ISO-8859-1.
|
|
33
|
+
MSCAB_ATTRIB_UTF_NAME = 0x80
|
|
34
|
+
|
|
35
|
+
# CabDecompressor#setParam parameter: search buffer size.
|
|
36
|
+
MSCABD_PARAM_SEARCHBUF = 0
|
|
37
|
+
# CabDecompressor#setParam parameter: repair MS-ZIP streams?
|
|
38
|
+
MSCABD_PARAM_FIXMSZIP = 1
|
|
39
|
+
# CabDecompressor#setParam parameter: size of decompression buffer
|
|
40
|
+
MSCABD_PARAM_DECOMPBUF = 2
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns the compression method used by a folder.
|
|
44
|
+
# @param [Fixnum] compType a MsCabdFolder.comp_type value
|
|
45
|
+
# @return [Fixnum] one of MSCAB_COMP_NONE, MSCAB_COMP_MSZIP, MSCAB_COMP_QUANTUM or MSCAB_COMP_LZX
|
|
46
|
+
def MsCabdCompMethod(compType)
|
|
47
|
+
compType & 0x0F
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the compression level used by a folder.
|
|
51
|
+
# @param [Fixnum] compType a MsCabdFolder.comp_type value
|
|
52
|
+
# @return [Fixnum] the compression level. This is only defined by LZX and Quantum compression
|
|
53
|
+
def MsCabdCompLevel(compType)
|
|
54
|
+
((comp_type) >> 8) & 0x1F
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# A structure which represents a single folder in a cabinet or cabinet set.
|
|
58
|
+
#
|
|
59
|
+
# A folder is a single compressed stream of data. When uncompressed, it holds the data of one or more files. A folder may be split across more than one cabinet.
|
|
60
|
+
class MsCabdFolder < FFI::Struct
|
|
61
|
+
layout({
|
|
62
|
+
:next => MsCabdFolder.ptr,
|
|
63
|
+
:comp_type => :int,
|
|
64
|
+
:num_blocks => :uint
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
# A next folder in this cabinet or cabinet set, or nil if this is the final folder.
|
|
68
|
+
#
|
|
69
|
+
# @return [MsCabdFolder, nil]
|
|
70
|
+
def next
|
|
71
|
+
return nil if self[:next].pointer.address.zero?
|
|
72
|
+
self[:next]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The compression format used by this folder.
|
|
76
|
+
#
|
|
77
|
+
# `#MsCabdCompMethod` should be used on this field to get the algorithm used. `#MsCabdCompLevel` should be used to get the "compression level".
|
|
78
|
+
#
|
|
79
|
+
# @return [Fixnum]
|
|
80
|
+
def comp_type
|
|
81
|
+
self[:comp_type]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The total number of data blocks used by this folder.
|
|
85
|
+
#
|
|
86
|
+
# This includes data blocks present in other files, if this folder spans more than one cabinet.
|
|
87
|
+
#
|
|
88
|
+
# @return [Fixnum]
|
|
89
|
+
def num_blocks
|
|
90
|
+
self[:num_blocks]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns the compression method used by a folder.
|
|
94
|
+
#
|
|
95
|
+
# @return [Fixnum] one of MSCAB_COMP_NONE, MSCAB_COMP_MSZIP, MSCAB_COMP_QUANTUM or MSCAB_COMP_LZX
|
|
96
|
+
def compressionMethod
|
|
97
|
+
MsCabdCompMethod(comp_type)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns the compression level used by a folder.
|
|
101
|
+
#
|
|
102
|
+
# @return [Fixnum] the compression level. This is only defined by LZX and Quantum compression
|
|
103
|
+
def compressionLevel
|
|
104
|
+
MsCabdCompLevel(comp_type)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# A structure which represents a single file in a cabinet or cabinet set.
|
|
109
|
+
class MsCabdFile < FFI::Struct
|
|
110
|
+
layout({
|
|
111
|
+
:next => MsCabdFile.ptr,
|
|
112
|
+
:filename => :string,
|
|
113
|
+
:length => :uint,
|
|
114
|
+
:attribs => :int,
|
|
115
|
+
:time_h => :char,
|
|
116
|
+
:time_m => :char,
|
|
117
|
+
:time_s => :char,
|
|
118
|
+
:date_d => :char,
|
|
119
|
+
:date_m => :char,
|
|
120
|
+
:date_y => :int,
|
|
121
|
+
:folder => MsCabdFolder.ptr,
|
|
122
|
+
:offset => :uint
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
# The next file in the cabinet or cabinet set, or nil if this is the final file.
|
|
126
|
+
#
|
|
127
|
+
# @return [MsCabdFile, nil]
|
|
128
|
+
def next
|
|
129
|
+
return nil if self[:next].pointer.address.zero?
|
|
130
|
+
self[:next]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# The filename of the file.
|
|
134
|
+
#
|
|
135
|
+
# String of up to 255 bytes in length, it may be in either ISO-8859-1 or UTF8 format, depending on the file attributes.
|
|
136
|
+
#
|
|
137
|
+
# @return [String]
|
|
138
|
+
def filename
|
|
139
|
+
self[:filename]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# The uncompressed length of the file, in bytes.
|
|
143
|
+
#
|
|
144
|
+
# @return [Fixnum]
|
|
145
|
+
def length
|
|
146
|
+
self[:length]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# File attributes.
|
|
150
|
+
#
|
|
151
|
+
# The following attributes are defined:
|
|
152
|
+
#
|
|
153
|
+
# * MSCAB_ATTRIB_RDONLY indicates the file is write protected.
|
|
154
|
+
# * MSCAB_ATTRIB_HIDDEN indicates the file is hidden.
|
|
155
|
+
# * MSCAB_ATTRIB_SYSTEM indicates the file is a operating system file.
|
|
156
|
+
# * MSCAB_ATTRIB_ARCH indicates the file is "archived".
|
|
157
|
+
# * MSCAB_ATTRIB_EXEC indicates the file is an executable program.
|
|
158
|
+
# * MSCAB_ATTRIB_UTF_NAME indicates the filename is in UTF8 format rather than ISO-8859-1.
|
|
159
|
+
#
|
|
160
|
+
# @return [Fixnum]
|
|
161
|
+
def attribs
|
|
162
|
+
self[:attribs]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# File's last modified datetime.
|
|
166
|
+
#
|
|
167
|
+
# @return [Time]
|
|
168
|
+
def datetime
|
|
169
|
+
Time.gm(self[:date_y], self[:date_m], self[:date_d], self[:time_h], self[:time_m], self[:time_s])
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Folder that contains this file.
|
|
173
|
+
#
|
|
174
|
+
# @return [MsCabdFolder, nil]
|
|
175
|
+
def folder
|
|
176
|
+
return nil if self[:folder].pointer.address.zero?
|
|
177
|
+
self[:folder]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# The uncompressed offset of this file in its folder.
|
|
181
|
+
#
|
|
182
|
+
# @return [Fixnum]
|
|
183
|
+
def offset
|
|
184
|
+
self[:offset]
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# A structure which represents a single cabinet file.
|
|
189
|
+
#
|
|
190
|
+
# If this cabinet is part of a merged cabinet set, the files and folders fields are common to all cabinets in the set, and will be identical.
|
|
191
|
+
class MsCabdCabinet < FFI::Struct
|
|
192
|
+
layout({
|
|
193
|
+
:next => MsCabdCabinet.ptr,
|
|
194
|
+
:filename => :string,
|
|
195
|
+
:base_offset => :off_t,
|
|
196
|
+
:length => :uint,
|
|
197
|
+
:prevcab => MsCabdCabinet.ptr,
|
|
198
|
+
:nextcab => MsCabdCabinet.ptr,
|
|
199
|
+
:prevname => :string,
|
|
200
|
+
:nextname => :string,
|
|
201
|
+
:previnfo => :string,
|
|
202
|
+
:nextinfo => :string,
|
|
203
|
+
:files => MsCabdFile.ptr,
|
|
204
|
+
:folders => MsCabdFolder.ptr,
|
|
205
|
+
:set_id => :ushort,
|
|
206
|
+
:set_index => :ushort,
|
|
207
|
+
:header_resv => :ushort,
|
|
208
|
+
:flags => :int
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
# The next cabinet in a chained list, if this cabinet was opened with MsCabDecompressor#search
|
|
212
|
+
#
|
|
213
|
+
# May be nil to mark the end of the list.
|
|
214
|
+
#
|
|
215
|
+
# @return [MsCabdCabinet, nil]
|
|
216
|
+
def next
|
|
217
|
+
return nil if self[:next].pointer.address.zero?
|
|
218
|
+
self[:next]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# The filename of the cabinet.
|
|
222
|
+
#
|
|
223
|
+
# More correctly, the filename of the physical file that the cabinet resides in. This is given by the library user and may be in any format.
|
|
224
|
+
#
|
|
225
|
+
# @return [String]
|
|
226
|
+
def filename
|
|
227
|
+
self[:filename]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# The file offset of cabinet within the physical file it resides in.
|
|
231
|
+
#
|
|
232
|
+
# @return [Fixnum]
|
|
233
|
+
def base_offset
|
|
234
|
+
self[:base_offset]
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# The length of the cabinet file in bytes.
|
|
238
|
+
#
|
|
239
|
+
# @return [Fixnum]
|
|
240
|
+
def length
|
|
241
|
+
self[:length]
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# The previous cabinet in a cabinet set, or nil.
|
|
245
|
+
#
|
|
246
|
+
# @return [MsCabdCabinet, nil]
|
|
247
|
+
def prevcab
|
|
248
|
+
return nil if self[:prevcab].pointer.address.zero?
|
|
249
|
+
self[:prevcab]
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# The next cabinet in a cabinet set, or nil.
|
|
253
|
+
#
|
|
254
|
+
# @return [MsCabdCabinet, nil]
|
|
255
|
+
def nextcab
|
|
256
|
+
return nil if self[:nextcab].pointer.address.zero?
|
|
257
|
+
self[:nextcab]
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# The filename of the previous cabinet in a cabinet set, or nil.
|
|
261
|
+
#
|
|
262
|
+
# @return [String]
|
|
263
|
+
def prevname
|
|
264
|
+
self[:prevname]
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# The filename of the next cabinet in a cabinet set, or nil.
|
|
268
|
+
#
|
|
269
|
+
# @return [String]
|
|
270
|
+
def nextname
|
|
271
|
+
self[:nextname]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# The name of the disk containing the previous cabinet in a cabinet set, or nil.
|
|
275
|
+
#
|
|
276
|
+
# @return [String]
|
|
277
|
+
def previnfo
|
|
278
|
+
self[:previnfo]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# The name of the disk containing the next cabinet in a cabinet set, or nil.
|
|
282
|
+
#
|
|
283
|
+
# @return [String]
|
|
284
|
+
def nextinfo
|
|
285
|
+
self[:nextinfo]
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# A list of all files in the cabinet or cabinet set.
|
|
289
|
+
#
|
|
290
|
+
# @return [MsCabdFile, nil]
|
|
291
|
+
def files
|
|
292
|
+
return nil if self[:files].pointer.address.zero?
|
|
293
|
+
self[:files]
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# A list of all folders in the cabinet or cabinet set.
|
|
297
|
+
#
|
|
298
|
+
# @return [MsCabdFolder, nil]
|
|
299
|
+
def folders
|
|
300
|
+
return nil if self[:folders].pointer.address.zero?
|
|
301
|
+
self[:folders]
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# The set ID of the cabinet.
|
|
305
|
+
#
|
|
306
|
+
# All cabinets in the same set should have the same set ID.
|
|
307
|
+
#
|
|
308
|
+
# @return [Fixnum]
|
|
309
|
+
def set_id
|
|
310
|
+
self[:set_id]
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# The index number of the cabinet within the set.
|
|
314
|
+
#
|
|
315
|
+
# Numbering should start from 0 for the first cabinet in the set, and increment by 1 for each following cabinet.
|
|
316
|
+
#
|
|
317
|
+
# @return [Fixnum]
|
|
318
|
+
def set_index
|
|
319
|
+
self[:set_index]
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# The number of bytes reserved in the header area of the cabinet.
|
|
323
|
+
#
|
|
324
|
+
# If this is non-zero and flags has MSCAB_HDR_RESV set, this data can be read by the calling application. It is of the given length, located at offset (base_offset + MSCAB_HDR_RESV_OFFSET) in the cabinet file.
|
|
325
|
+
#
|
|
326
|
+
# @see #flags flags
|
|
327
|
+
# @return [Fixnum]
|
|
328
|
+
def header_resv
|
|
329
|
+
self[:header_resv]
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# Header flags.
|
|
333
|
+
#
|
|
334
|
+
# * MSCAB_HDR_PREVCAB indicates the cabinet is part of a cabinet set, and has a predecessor cabinet.
|
|
335
|
+
# * MSCAB_HDR_NEXTCAB indicates the cabinet is part of a cabinet set, and has a successor cabinet.
|
|
336
|
+
# * MSCAB_HDR_RESV indicates the cabinet has reserved header space.
|
|
337
|
+
#
|
|
338
|
+
# @see #prevname prevname
|
|
339
|
+
# @see #previnfo previnfo
|
|
340
|
+
# @see #nextname nextname
|
|
341
|
+
# @see #nextinfo nextinfo
|
|
342
|
+
# @see #header_resv header_resv
|
|
343
|
+
# @return [Fixnum]
|
|
344
|
+
def flags
|
|
345
|
+
self[:flags]
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# CAB compressor
|
|
350
|
+
class MsCabCompressor < FFI::Struct
|
|
351
|
+
layout({:dummy => :int})
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# CAB decompressor
|
|
355
|
+
class MsCabDecompressor < FFI::Struct
|
|
356
|
+
layout({
|
|
357
|
+
:open => callback([ MsCabDecompressor.ptr, :string ], MsCabdCabinet.ptr),
|
|
358
|
+
:close => callback([ MsCabDecompressor.ptr, MsCabdCabinet.ptr ], :void),
|
|
359
|
+
:search => callback([ MsCabDecompressor.ptr, :string ], MsCabdCabinet.ptr),
|
|
360
|
+
:append => callback([ MsCabDecompressor.ptr, MsCabdCabinet.ptr, MsCabdCabinet.ptr ], :int),
|
|
361
|
+
:prepend => callback([ MsCabDecompressor.ptr, MsCabdCabinet.ptr, MsCabdCabinet.ptr ], :int),
|
|
362
|
+
:extract => callback([ MsCabDecompressor.ptr, MsCabdFile.ptr, :string ], :int),
|
|
363
|
+
:set_param => callback([ MsCabDecompressor.ptr, :int, :int ], :int),
|
|
364
|
+
:last_error => callback([ MsCabDecompressor.ptr ], :int)
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
# Opens a cabinet file and reads its contents.
|
|
368
|
+
#
|
|
369
|
+
# If the file opened is a valid cabinet file, all headers will be read and a MsCabdCabinet structure will be returned, with a full list of folders and files.
|
|
370
|
+
#
|
|
371
|
+
# In the case of an error occuring, nil is returned and the error code is available from #last_error
|
|
372
|
+
#
|
|
373
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
374
|
+
# @param [String] filename name of the cabinet file
|
|
375
|
+
# @return [MsCabdCabinet, nil]
|
|
376
|
+
# @see #close close
|
|
377
|
+
# @see #search search
|
|
378
|
+
# @see #last_error last_error
|
|
379
|
+
def open(decompressor, filename)
|
|
380
|
+
self[:open].call(decompressor, filename)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# Closes a previously opened cabinet or cabinet set.
|
|
384
|
+
#
|
|
385
|
+
# This closes a cabinet, all cabinets associated with it via the MsCabdCabinet#next, MsCabdCabinet#prevcab and MsCabdCabinet#nextcab, and all folders and files. All memory used by these entities is freed.
|
|
386
|
+
#
|
|
387
|
+
# The cabinet is now invalid and cannot be used again. All MsCabdFolder and MsCabdFile from that cabinet or cabinet set are also now invalid, and cannot be used again.
|
|
388
|
+
#
|
|
389
|
+
# If the cabinet given was created using #search, it MUST be the cabinet returned by #search and not one of the later cabinet pointers further along the MsCabdCabinet::next chain.
|
|
390
|
+
#
|
|
391
|
+
# If extra cabinets have been added using #append or #prepend, these will all be freed, even if the cabinet given is not the first cabinet in the set. Do NOT #close more than one cabinet in the set.
|
|
392
|
+
#
|
|
393
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
394
|
+
# @param [MsCabdCabinet] cabinet the cabinet to close
|
|
395
|
+
# @see #open open
|
|
396
|
+
# @see #search search
|
|
397
|
+
# @see #append append
|
|
398
|
+
# @see #prepend prepend
|
|
399
|
+
def close(decompressor, cabinet)
|
|
400
|
+
self[:close].call(decompressor, cabinet)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Searches a regular file for embedded cabinets.
|
|
404
|
+
#
|
|
405
|
+
# This opens a normal file with the given filename and will search the entire file for embedded cabinet files
|
|
406
|
+
#
|
|
407
|
+
# If any cabinets are found, the equivalent of #open is called on each potential cabinet file at the offset it was found. All successfully #open'ed cabinets are kept in a list.
|
|
408
|
+
#
|
|
409
|
+
# The first cabinet found will be returned directly as the result of this method. Any further cabinets found will be chained in a list using the MsCabdCabinet#next field.
|
|
410
|
+
#
|
|
411
|
+
# In the case of an error occuring anywhere other than the simulated #open, nil is returned and the error code is available from #last_error
|
|
412
|
+
#
|
|
413
|
+
# If no error occurs, but no cabinets can be found in the file, nil is returned and #last_error returns MSPACK_ERR_OK
|
|
414
|
+
#
|
|
415
|
+
# `#close` should only be called on the result of #search, not on any subsequent cabinets in the MsCabdCabinet#next chain.
|
|
416
|
+
#
|
|
417
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
418
|
+
# @param [String] filename the filename of the file to search for cabinets
|
|
419
|
+
# @return [MsCabdCabinet, nil]
|
|
420
|
+
# @see #close close
|
|
421
|
+
# @see #open open
|
|
422
|
+
# @see #last_error last_error
|
|
423
|
+
def search(decompressor, filename)
|
|
424
|
+
self[:search].call(decompressor, filename)
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
# Appends one MsCabdCabinet to another, forming or extending a cabinet set.
|
|
428
|
+
#
|
|
429
|
+
# This will attempt to append one cabinet to another such that (cab.nextcab == nextcab) && (nextcab.prevcab == cab) and any folders split between the two cabinets are merged.
|
|
430
|
+
#
|
|
431
|
+
# The cabinets MUST be part of a cabinet set -- a cabinet set is a cabinet that spans more than one physical cabinet file on disk -- and must be appropriately matched.
|
|
432
|
+
#
|
|
433
|
+
# It can be determined if a cabinet has further parts to load by examining the MsCabdCabinet.flags field:
|
|
434
|
+
#
|
|
435
|
+
# * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to #open and #prepend. Its MS-DOS case-insensitive filename is MsCabdCabinet.prevname
|
|
436
|
+
# * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to #open and #append. Its MS-DOS case-insensitive filename is MsCabdCabinet.nextname
|
|
437
|
+
#
|
|
438
|
+
# If the cabinets do not match, an error code will be returned. Neither cabinet has been altered, and both should be closed seperately.
|
|
439
|
+
#
|
|
440
|
+
# Files and folders in a cabinet set are a single entity. All cabinets in a set use the same file list, which is updated as cabinets in the set are added.
|
|
441
|
+
#
|
|
442
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
443
|
+
# @param [MsCabdCabinet] cab the cabinet which will be appended to, predecessor of nextcab
|
|
444
|
+
# @param [MsCabdCabinet] nextcab the cabinet which will be appended, successor of cab
|
|
445
|
+
# @return [Fixnum] an error code, or MSPACK_ERR_OK if successful
|
|
446
|
+
# @see #prepend prepend
|
|
447
|
+
# @see #open open
|
|
448
|
+
# @see #close close
|
|
449
|
+
def append(decompressor, cab, nextcab)
|
|
450
|
+
self[:append].call(decompressor, cab, nextcab)
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# Prepends one MsCabdCabinet to another, forming or extending a cabinet set.
|
|
454
|
+
#
|
|
455
|
+
# This will attempt to prepend one cabinet to another, such that (cab.prevcab == prevcab) && (prevcab.nextcab == cab).
|
|
456
|
+
# In all other respects, it is identical to #append.
|
|
457
|
+
#
|
|
458
|
+
# @see #append #append for the full documentation
|
|
459
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
460
|
+
# @param [MsCabdCabinet] cab the cabinet which will be prepended to, successor of prevcab
|
|
461
|
+
# @param [MsCabdCabinet] prevcab the cabinet which will be prepended, predecessor of cab
|
|
462
|
+
# @see #append append
|
|
463
|
+
# @see #open open
|
|
464
|
+
# @see #close close
|
|
465
|
+
def prepend(decompressor, cab, prevcab)
|
|
466
|
+
self[:prepend].call(decompressor, cab, prevcab)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
# Extracts a file from a cabinet or cabinet set.
|
|
470
|
+
#
|
|
471
|
+
# This extracts a compressed file in a cabinet and writes it to the given filename.
|
|
472
|
+
#
|
|
473
|
+
# The MS-DOS filename of the file, MsCabdCabinet.filename, is NOT USED by #extract. The caller must examine this MS-DOS filename, copy and change it as necessary, create directories as necessary, and provide the correct filename as a parameter, which will be passed unchanged to the decompressor's MsPackSystem#open
|
|
474
|
+
#
|
|
475
|
+
# If the file belongs to a split folder in a multi-part cabinet set, and not enough parts of the cabinet set have been loaded and appended or prepended, an error will be returned immediately.
|
|
476
|
+
#
|
|
477
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
478
|
+
# @param [MsCabdFile] cabfile the file to be decompressed
|
|
479
|
+
# @param [String] filename the filename of the file being written to
|
|
480
|
+
# @return [Fixnum] an error code, or MSPACK_ERR_OK if successful
|
|
481
|
+
def extract(decompressor, cabfile, filename)
|
|
482
|
+
self[:extract].call(decompressor, cabfile, filename)
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
# Sets a CAB decompression engine parameter.
|
|
486
|
+
#
|
|
487
|
+
# The following parameters are defined:
|
|
488
|
+
#
|
|
489
|
+
# * MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a buffer when using #search ? The minimum value is 4. The default value is 32768.
|
|
490
|
+
# * MSCABD_PARAM_FIXMSZIP: If non-zero, #extract will ignore bad checksums and recover from decompression errors in MS-ZIP compressed folders. The default value is 0 (don't recover).
|
|
491
|
+
# * MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input bit buffer by decompressors? The minimum value is 4. The default value is 4096.
|
|
492
|
+
#
|
|
493
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
494
|
+
# @param [Fixnum] param the parameter to set
|
|
495
|
+
# @param [Fixnum] value the value to set the parameter to
|
|
496
|
+
# @see #close close
|
|
497
|
+
# @see #open open
|
|
498
|
+
def set_param(decompressor, param, value)
|
|
499
|
+
self[:set_param].call(decompressor, param, value)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
# Returns the error code set by the most recently called method
|
|
503
|
+
# @param [MsCabDecompressor] decompressor MsCabDecompressor instance being called
|
|
504
|
+
# @return [Fixnum] the most recent error code
|
|
505
|
+
# @see #open open
|
|
506
|
+
# @see #search search
|
|
507
|
+
def last_error(decompressor)
|
|
508
|
+
self[:last_error].call(decompressor)
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
# CAB Compressor
|
|
514
|
+
class CabCompressor
|
|
515
|
+
attr_reader :Compressor
|
|
516
|
+
# Creates a new CAB compressor.
|
|
517
|
+
#
|
|
518
|
+
# @param [MsPack::MsPackSystem, nil] system is a custom mspack system, or nil to use the default
|
|
519
|
+
def initialize(system = nil)
|
|
520
|
+
@Compressor = nil
|
|
521
|
+
init(system)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
# @private
|
|
525
|
+
def init(system = MsPack::RubyPackSystem)
|
|
526
|
+
raise Exceptions::AlreadyInitializedError if @Compressor
|
|
527
|
+
@Compressor = LibMsPack.CreateCabCompressor(system)
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
# Destroys an existing CAB compressor
|
|
531
|
+
def destroy
|
|
532
|
+
raise Exceptions::NotInitializedError unless @Compressor
|
|
533
|
+
LibMsPack.DestroyCabCompressor(@Compressor)
|
|
534
|
+
@Compressor = nil
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# CAB decompressor
|
|
539
|
+
class CabDecompressor
|
|
540
|
+
attr_reader :Decompressor
|
|
541
|
+
# Creates a new CAB decompressor.
|
|
542
|
+
#
|
|
543
|
+
# @param [MsPack::MsPackSystem, nil] system a custom mspack system, or nil to use the default
|
|
544
|
+
def initialize(system = nil)
|
|
545
|
+
@Decompressor = nil
|
|
546
|
+
init(system)
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
# @private
|
|
550
|
+
def init(system = MsPack::RubyPackSystem)
|
|
551
|
+
raise Exceptions::AlreadyInitializedError if @Decompressor
|
|
552
|
+
@Decompressor = LibMsPack.CreateCabDecompressor(system)
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
# Opens a cabinet file and reads its contents.
|
|
556
|
+
#
|
|
557
|
+
# If the file opened is a valid cabinet file, all headers will be read and a MsCabdCabinet structure will be returned, with a full list of folders and files.
|
|
558
|
+
#
|
|
559
|
+
# In the case of an error occuring, exception will be raised.
|
|
560
|
+
#
|
|
561
|
+
# @param [String] filename name of the cabinet file
|
|
562
|
+
# @return [MsCabdCabinet]
|
|
563
|
+
# @raise [Exceptions::LibMsPackError]
|
|
564
|
+
# @see #close close
|
|
565
|
+
# @see #search search
|
|
566
|
+
def open(filename)
|
|
567
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
568
|
+
cabinet = @Decompressor.open(@Decompressor, filename)
|
|
569
|
+
error = lastError
|
|
570
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
571
|
+
cabinet
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
# Closes a previously opened cabinet or cabinet set.
|
|
575
|
+
#
|
|
576
|
+
# This closes a cabinet, all cabinets associated with it via the MsCabdCabinet#next, MsCabdCabinet#prevcab and MsCabdCabinet#nextcab, and all folders and files. All memory used by these entities is freed.
|
|
577
|
+
#
|
|
578
|
+
# The cabinet is now invalid and cannot be used again. All MsCabdFolder and MsCabdFile from that cabinet or cabinet set are also now invalid, and cannot be used again.
|
|
579
|
+
#
|
|
580
|
+
# If the cabinet given was created using #search, it MUST be the cabinet returned by #search and not one of the later cabinet pointers further along the MsCabdCabinet::next chain.
|
|
581
|
+
#
|
|
582
|
+
# If extra cabinets have been added using #append or #prepend, these will all be freed, even if the cabinet given is not the first cabinet in the set. Do NOT #close more than one cabinet in the set.
|
|
583
|
+
#
|
|
584
|
+
# @param [MsCabdCabinet] cabinet the cabinet to close
|
|
585
|
+
# @see #open open
|
|
586
|
+
# @see #search search
|
|
587
|
+
# @see #append append
|
|
588
|
+
# @see #prepend prepend
|
|
589
|
+
def close(cabinet)
|
|
590
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
591
|
+
@Decompressor.close(@Decompressor, cabinet)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
# Searches a regular file for embedded cabinets.
|
|
595
|
+
#
|
|
596
|
+
# This opens a normal file with the given filename and will search the entire file for embedded cabinet files
|
|
597
|
+
#
|
|
598
|
+
# If any cabinets are found, the equivalent of #open is called on each potential cabinet file at the offset it was found. All successfully #open'ed cabinets are kept in a list.
|
|
599
|
+
#
|
|
600
|
+
# The first cabinet found will be returned directly as the result of this method. Any further cabinets found will be chained in a list using the MsCabdCabinet#next field.
|
|
601
|
+
#
|
|
602
|
+
# In the case of an error occuring anywhere other than the simulated #open, exception will be raised.
|
|
603
|
+
#
|
|
604
|
+
# If no error occurs, but no cabinets can be found in the file, nil is returned.
|
|
605
|
+
#
|
|
606
|
+
# `#close` should only be called on the result of #search, not on any subsequent cabinets in the MsCabdCabinet#next chain.
|
|
607
|
+
#
|
|
608
|
+
# @param [String] filename the filename of the file to search for cabinets
|
|
609
|
+
# @return [MsCabdCabinet]
|
|
610
|
+
# @raise [Exceptions::LibMsPackError]
|
|
611
|
+
# @see #close close
|
|
612
|
+
# @see #open open
|
|
613
|
+
def search(filename)
|
|
614
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
615
|
+
cabinet = @Decompressor.search(@Decompressor, filename)
|
|
616
|
+
error = lastError
|
|
617
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
618
|
+
cabinet
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# Appends one MsCabdCabinet to another, forming or extending a cabinet set.
|
|
622
|
+
#
|
|
623
|
+
# This will attempt to append one cabinet to another such that (cab.nextcab == nextcab) && (nextcab.prevcab == cab) and any folders split between the two cabinets are merged.
|
|
624
|
+
#
|
|
625
|
+
# The cabinets MUST be part of a cabinet set -- a cabinet set is a cabinet that spans more than one physical cabinet file on disk -- and must be appropriately matched.
|
|
626
|
+
#
|
|
627
|
+
# It can be determined if a cabinet has further parts to load by examining the MsCabdCabinet.flags field:
|
|
628
|
+
#
|
|
629
|
+
# * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to #open and #prepend. Its MS-DOS case-insensitive filename is MsCabdCabinet.prevname
|
|
630
|
+
# * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to #open and #append. Its MS-DOS case-insensitive filename is MsCabdCabinet.nextname
|
|
631
|
+
#
|
|
632
|
+
# If the cabinets do not match, an exception will be raised. Neither cabinet has been altered, and both should be closed seperately.
|
|
633
|
+
#
|
|
634
|
+
# Files and folders in a cabinet set are a single entity. All cabinets in a set use the same file list, which is updated as cabinets in the set are added.
|
|
635
|
+
#
|
|
636
|
+
# @param [MsCabdCabinet] cab the cabinet which will be appended to, predecessor of nextcab
|
|
637
|
+
# @param [MsCabdCabinet] nextcab the cabinet which will be appended, successor of cab
|
|
638
|
+
# @raise [Exceptions::LibMsPackError]
|
|
639
|
+
# @see #prepend prepend
|
|
640
|
+
# @see #open open
|
|
641
|
+
# @see #close close
|
|
642
|
+
def append(cab, nextcab)
|
|
643
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
644
|
+
error = @Decompressor.append(@Decompressor, cab, nextcab)
|
|
645
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
646
|
+
error
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
# Prepends one MsCabdCabinet to another, forming or extending a cabinet set.
|
|
650
|
+
#
|
|
651
|
+
# This will attempt to prepend one cabinet to another, such that (cab.prevcab == prevcab) && (prevcab.nextcab == cab).
|
|
652
|
+
# In all other respects, it is identical to #append.
|
|
653
|
+
#
|
|
654
|
+
# @see #append #append for the full documentation
|
|
655
|
+
# @param [MsCabdCabinet] cab the cabinet which will be prepended to, successor of prevcab
|
|
656
|
+
# @param [MsCabdCabinet] prevcab the cabinet which will be prepended, predecessor of cab
|
|
657
|
+
# @raise [Exceptions::LibMsPackError]
|
|
658
|
+
# @see #append append
|
|
659
|
+
# @see #open open
|
|
660
|
+
# @see #close close
|
|
661
|
+
def prepend(cab, prevcab)
|
|
662
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
663
|
+
error = @Decompressor.prepend(@Decompressor, cab, prevcab)
|
|
664
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
665
|
+
error
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# Extracts a file from a cabinet or cabinet set.
|
|
669
|
+
#
|
|
670
|
+
# This extracts a compressed file in a cabinet and writes it to the given filename.
|
|
671
|
+
#
|
|
672
|
+
# The MS-DOS filename of the file, MsCabdCabinet.filename, is NOT USED by #extract. The caller must examine this MS-DOS filename, copy and change it as necessary, create directories as necessary, and provide the correct filename as a parameter, which will be passed unchanged to the decompressor's MsPackSystem#open
|
|
673
|
+
#
|
|
674
|
+
# If the file belongs to a split folder in a multi-part cabinet set, and not enough parts of the cabinet set have been loaded and appended or prepended, an exception will be raised immediately.
|
|
675
|
+
#
|
|
676
|
+
# @param [MsCabdFile] cabfile the file to be decompressed
|
|
677
|
+
# @param [String] filename the filename of the file being written to
|
|
678
|
+
# @raise [Exceptions::LibMsPackError]
|
|
679
|
+
def extract(cabfile, filename)
|
|
680
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
681
|
+
error = @Decompressor.extract(@Decompressor, cabfile, filename)
|
|
682
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
683
|
+
error
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
# Sets a CAB decompression engine parameter.
|
|
687
|
+
#
|
|
688
|
+
# The following parameters are defined:
|
|
689
|
+
#
|
|
690
|
+
# * MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a buffer when using #search ? The minimum value is 4. The default value is 32768.
|
|
691
|
+
# * MSCABD_PARAM_FIXMSZIP: If non-zero, #extract will ignore bad checksums and recover from decompression errors in MS-ZIP compressed folders. The default value is 0 (don't recover).
|
|
692
|
+
# * MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input bit buffer by decompressors? The minimum value is 4. The default value is 4096.
|
|
693
|
+
#
|
|
694
|
+
# @param [Fixnum] param the parameter to set
|
|
695
|
+
# @param [Fixnum] value the value to set the parameter to
|
|
696
|
+
# @raise [Exceptions::LibMsPackError]
|
|
697
|
+
# @see #close close
|
|
698
|
+
# @see #open open
|
|
699
|
+
def setParam(param, value)
|
|
700
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
701
|
+
error = @Decompressor.set_param(@Decompressor, param, value)
|
|
702
|
+
raise Exceptions::LibMsPackError.new(error) unless error == LibMsPack::MSPACK_ERR_OK
|
|
703
|
+
error
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
# Returns the error code set by the most recently called method
|
|
707
|
+
# @return [Fixnum] the most recent error code
|
|
708
|
+
def lastError
|
|
709
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
710
|
+
@Decompressor.last_error(@Decompressor)
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
# Destroys an existing CAB decompressor
|
|
714
|
+
def destroy
|
|
715
|
+
raise Exceptions::NotInitializedError unless @Decompressor
|
|
716
|
+
LibMsPack.DestroyCabDecompressor(@Decompressor)
|
|
717
|
+
@Decompressor = nil
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
end
|
|
722
|
+
end
|