1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 // grouping files with packing:
16 // zip, pk3: PKZIP-compatible archives (store, deflate)
17 // dfwad : D2D:F wad archives
18 //
19 {.$DEFINE SFS_DEBUG_ZIPFS}
20 {$INCLUDE ../shared/a_modes.inc}
21 {$SCOPEDENUMS OFF}
22 {.$R+}
25 interface
27 uses
31 type
35 protected
43 public
48 public
55 implementation
57 uses
61 type
63 public
82 {.$IFDEF ENDIAN_LITTLE}
83 begin
98 var
100 begin
110 var
112 begin
124 { TSFSZipVolume }
126 var
142 begin
143 // search for central dir pointer
149 try
152 begin
154 begin
155 cdsize := LongWord(buf[f+8])+(LongWord(buf[f+9])<<8)+(LongWord(buf[f+10])<<16)+(LongWord(buf[f+11])<<24);
157 break;
160 finally
165 begin
166 // wow, we got central directory! process it
169 begin
173 begin
176 // skip uninteresting fields
181 // skip uninteresting fields
184 // now skip name, extra and comment
190 //writeln('file #', high(fileOffsets), ' found at ', hdrofs);
191 end
193 begin
197 end
198 else
199 begin
200 break;
205 end
206 else
207 begin
211 // read local directory
212 repeat
214 begin
216 //writeln('reading file #', fileIdx, ' at ', fileOffsets[fileIdx]);
222 begin
224 // skip data descriptor
226 begin
228 continue;
230 break;
244 begin
249 // here we should process extra field: it may contain utf8 filename
251 begin
256 // Info-ZIP Unicode Path Extra Field?
258 begin
263 begin
264 //writeln('!!!!!!!!!!!!');
271 //writeln('++++++ [', fi.fName, ']');
275 // skip it
277 begin
282 // skip the rest
286 begin
287 // encrypted file: skip it
292 begin
293 // not stored. not deflated. skip.
297 if (length(fi.fName) = 0) or (fname[length(fi.fName)] = '/') or (fname[length(fi.fName)] = '\') then
298 begin
300 end
301 else
302 begin
312 // skip packed data
316 (*
317 if (sign <> 'PK'#1#2) and (sign <> 'PK'#5#6) then
318 begin
319 {$IFDEF SFS_DEBUG_ZIPFS}
320 WriteLn(ErrOutput, 'end: $', IntToHex(fFileStream.Position, 8));
321 WriteLn(ErrOutput, 'sign: $', sign[0], sign[1], '#', ord(sign[2]), '#', ord(sign[3]));
322 {$ENDIF}
323 raise ESFSError.Create('invalid .ZIP archive (no central dir)');
324 end;
325 *)
330 // idiotic format
331 var
338 begin
343 // read files
345 begin
352 begin
358 // new directory?
360 begin
363 continue;
366 //writeln('DFWAD: [', curpath, '] [', fname, '] at ', fofs, ', size ', fpksize);
367 // create file record
379 begin
388 var
390 begin
395 try
397 begin
398 result := TSFSPartialStream.Create(fFileStream, TSFSZipFileInfo(fFiles[index]).fOfs, TSFSZipFileInfo(fFiles[index]).fSize, false);
399 end
400 else
401 begin
402 rs := TSFSPartialStream.Create(fFileStream, TSFSZipFileInfo(fFiles[index]).fOfs, TSFSZipFileInfo(fFiles[index]).fPackSz, false);
403 result := TUnZStream.Create(rs, TSFSZipFileInfo(fFiles[index]).fSize, true, (TSFSZipFileInfo(fFiles[index]).fMethod <> 255));
405 except
408 exit;
413 { TSFSZipVolumeFactory }
415 begin
416 result :=
425 begin
429 function TSFSZipVolumeFactory.Produce (const prefix, fileName: AnsiString; st: TStream): TSFSVolume;
430 var
432 begin
438 begin
441 try
445 {$ENDIF}
450 end
451 else
452 begin
458 var
460 initialization
463 //finalization
464 // SFSUnregisterVolumeFactory(zipf);