home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / unity / d5 / JRZIP.ZIP / Zlib / UNZIP.PAS < prev    next >
Pascal/Delphi Source File  |  2000-03-25  |  49KB  |  1,630 lines

  1. Unit Unzip;
  2. { ----------------------------------------------------------------- }
  3. { unzip.c -- IO on .zip files using zlib
  4.    Version 0.15 beta, Mar 19th, 1998,
  5.   unzip.h -- IO for uncompress .zip files using zlib
  6.   Version 0.15 beta, Mar 19th, 1998,
  7.  
  8.   Copyright (C) 1998 Gilles Vollant <info@winimage.com>
  9.   http://www.winimage.com/zLibDll/zip.htm
  10.  
  11.    This unzip package allow extract file from .ZIP file, compatible
  12.    with PKZip 2.04g, WinZip, InfoZip tools and compatible.
  13.    Encryption and multi volume ZipFile (span) are not supported.
  14.    Old compressions used by old PKZip 1.x are not supported
  15.  
  16.   Pascal tranlastion
  17.   Copyright (C) 2000 by Jacques Nomssi Nzali
  18.   For conditions of distribution and use, see copyright notice in readme.txt }
  19.  
  20.  
  21. interface
  22.  
  23. {$ifdef WIN32}
  24.   {$define Delphi}
  25. {$endif}
  26.  
  27. uses
  28.   zutil,
  29.   zLib,
  30.   ziputils;
  31.  
  32.  
  33. const
  34.   UNZ_OK = (0);
  35.   UNZ_END_OF_LIST_OF_FILE = (-100);
  36.   UNZ_ERRNO = (Z_ERRNO);
  37.   UNZ_EOF = (0);
  38.   UNZ_PARAMERROR = (-102);
  39.   UNZ_BADZIPFILE = (-103);
  40.   UNZ_INTERNALERROR = (-104);
  41.   UNZ_CRCERROR = (-105);
  42. (*
  43. { tm_unz contain date/time info }
  44. type
  45.  tm_unz = record
  46.    tm_sec : uInt;       { seconds after the minute - [0,59] }
  47.    tm_min : uInt;       { minutes after the hour - [0,59] }
  48.    tm_hour : uInt;      { hours since midnight - [0,23] }
  49.    tm_mday : uInt;      { day of the month - [1,31] }
  50.    tm_mon : uInt;       { months since January - [0,11] }
  51.    tm_year : uInt;      { years - [1980..2044] }
  52.   end;
  53. *)
  54. { unz_global_info structure contain global data about the ZIPfile
  55.   These data comes from the end of central dir }
  56. type
  57.   unz_global_info = record
  58.     number_entry : uLong;   { total number of entries in
  59.                               the central dir on this disk }
  60.     size_comment : uLong;   { size of the global comment of the zipfile }
  61.   end;
  62.  
  63.  
  64. { unz_file_info contain information about a file in the zipfile }
  65. type
  66.   unz_file_info = record
  67.     version : uLong;              { version made by                 2 bytes }
  68.     version_needed : uLong;       { version needed to extract       2 bytes }
  69.     flag : uLong;                 { general purpose bit flag        2 bytes }
  70.     compression_method : uLong;   { compression method              2 bytes }
  71.     dosDate : uLong;              { last mod file date in Dos fmt   4 bytes }
  72.     crc : uLong;                  { crc-32                          4 bytes }
  73.     compressed_size : uLong;      { compressed size                 4 bytes }
  74.     uncompressed_size : uLong;    { uncompressed size               4 bytes }
  75.     size_filename : uLong;        { filename length                 2 bytes }
  76.     size_file_extra : uLong;      { extra field length              2 bytes }
  77.     size_file_comment : uLong;    { file comment length             2 bytes }
  78.  
  79.     disk_num_start : uLong;       { disk number start               2 bytes }
  80.     internal_fa : uLong;          { internal file attributes        2 bytes }
  81.     external_fa : uLong;          { external file attributes        4 bytes }
  82.  
  83.     tmu_date : tm_unz;
  84.   end;
  85.   unz_file_info_ptr = ^unz_file_info;
  86.  
  87.  
  88. function unzStringFileNameCompare(const fileName1 : PChar;
  89.                                   const fileName2 : PChar;
  90.                                   iCaseSensitivity : int) : int;
  91. { Compare two filename (fileName1,fileName2).
  92.   If iCaseSenisivity = 1 (1=true),
  93.     comparision is case sensitive (like strcmp)
  94.   If iCaseSenisivity = 2 (0=false),
  95.     comparision is not case sensitive (like strcmpi or strcasecmp)
  96.   If iCaseSenisivity = 0, case sensitivity is defaut of your
  97.     operating system like 1 on Unix, 2 on Windows)
  98. }
  99.  
  100.  
  101. function unzOpen (const path : PChar) : unzFile;
  102.  
  103. { Open a Zip file. path contain the full pathname (by example,
  104.   on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
  105.   "zlib/zlib111.zip".
  106.   If the zipfile cannot be opened (file don't exist or in not valid), the
  107.   return value is NIL.
  108.   Else, the return value is a unzFile Handle, usable with other function
  109.        of this unzip package.
  110. }
  111.  
  112. function unzClose (afile : unzFile) : int;
  113.  
  114. { Close a ZipFile opened with unzipOpen.
  115.   If there are files inside the .Zip opened with unzOpenCurrentFile()
  116.   (see later), these files MUST be closed with unzipCloseCurrentFile()
  117.   before a call unzipClose.
  118.   return UNZ_OK if there is no problem. }
  119.  
  120. function unzGetGlobalInfo (afile : unzFile;
  121.                            var pglobal_info : unz_global_info) : int;
  122.  
  123. { Write info about the ZipFile in the *pglobal_info structure.
  124.   No preparation of the structure is needed
  125.   return UNZ_OK if there is no problem. }
  126.  
  127. function unzGetGlobalComment (afile : unzFile;
  128.                               szComment : PChar;
  129.                   uSizeBuf : uLong) : int;
  130.  
  131. { Get the global comment string of the ZipFile, in the szComment buffer.
  132.   uSizeBuf is the size of the szComment buffer.
  133.   return the number of byte copied or an error code <0 }
  134.  
  135. {***************************************************************************}
  136. { Unzip package allow you browse the directory of the zipfile }
  137.  
  138. function unzGoToFirstFile(afile : unzFile) : int;
  139.  
  140. { Set the current file of the zipfile to the first file.
  141.   return UNZ_OK if there is no problem }
  142.  
  143. function unzGoToNextFile(afile : unzFile) : int;
  144.  
  145. { Set the current file of the zipfile to the next file.
  146.   return UNZ_OK if there is no problem
  147.   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. }
  148.  
  149.  
  150. function unzLocateFile(afile : unzFile;
  151.                        const szFileName : PChar;
  152.                iCaseSensitivity : int) : int; { ZEXPORT }
  153.  
  154. { Try locate the file szFileName in the zipfile.
  155.   For the iCaseSensitivity signification, see unzStringFileNameCompare
  156.  
  157.   return value :
  158.   UNZ_OK if the file is found. It becomes the current file.
  159.   UNZ_END_OF_LIST_OF_FILE if the file is not found }
  160.  
  161.  
  162. function unzGetCurrentFileInfo(afile : unzFile;
  163.                                pfile_info : unz_file_info_ptr;
  164.                    szFileName : PChar;
  165.                    fileNameBufferSize : uLong;
  166.                    extraField : voidp;
  167.                    extraFieldBufferSize : uLong;
  168.                    szComment : PChar;
  169.                    commentBufferSize : uLong) : int; { ZEXPORT }
  170.  
  171. { Get Info about the current file
  172.   if pfile_info<>NIL, the pfile_info^ structure will contain somes
  173.   info about the current file
  174.   if szFileName<>NIL, the filemane string will be copied in szFileName
  175.             (fileNameBufferSize is the size of the buffer)
  176.   if extraField<>NIL, the extra field information will be copied in
  177.     extraField    (extraFieldBufferSize is the size of the buffer).
  178.     This is the Central-header version of the extra field
  179.   if szComment<>NIL, the comment string of the file will be copied in
  180.     szComment (commentBufferSize is the size of the buffer) }
  181.  
  182.  
  183. {***************************************************************************}
  184. {* for reading the content of the current zipfile, you can open it, read data
  185.    from it, and close it (you can close it before reading all the file) }
  186.  
  187.  
  188. function unzOpenCurrentFile(afile : unzFile) : int; { ZEXPORT }
  189.  
  190. { Open for reading data the current file in the zipfile.
  191.   If there is no error, the return value is UNZ_OK. }
  192.  
  193.  
  194. function unzCloseCurrentFile(afile : unzFile) : int; { ZEXPORT }
  195.  
  196. { Close the file in zip opened with unzOpenCurrentFile
  197.   Return UNZ_CRCERROR if all the file was read but the CRC is not good }
  198.  
  199.  
  200. function unzReadCurrentFile(afile : unzFile;
  201.                             buf : voidp;
  202.                 len : unsigned) : int; { ZEXPORT }
  203.  
  204. { Read bytes from the current file (opened by unzOpenCurrentFile)
  205.   buf contain buffer where data must be copied
  206.   len the size of buf.
  207.  
  208.   return the number of byte copied if somes bytes are copied
  209.   return 0 if the end of file was reached
  210.   return <0 with error code if there is an error
  211.     (UNZ_ERRNO for IO error, or zLib error for uncompress error) }
  212.  
  213. function unztell(afile : unzFile) : z_off_t;
  214.  
  215. { Give the current position in uncompressed data }
  216.  
  217. function unzeof(afile : unzFile) : int;
  218.  
  219. { return 1 if the end of file was reached, 0 elsewhere
  220.   ! checks for valid params }
  221.  
  222. function unzGetLocalExtrafield (afile : unzFile;
  223.                                 buf : voidp;
  224.                                 len : unsigned) : int;
  225. { Read extra field from the current file (opened by unzOpenCurrentFile)
  226.   This is the local-header version of the extra field (sometimes, there is
  227.     more info in the local-header version than in the central-header)
  228.  
  229.   if buf=NIL, it return the size of the local extra field
  230.  
  231.   if buf<>NIL, len is the size of the buffer, the extra header is copied in
  232.     buf.
  233.   the return value is the number of bytes copied in buf, or (if <0)
  234.     the error code }
  235.  
  236.  
  237. { ----------------------------------------------------------------- }
  238.  
  239. implementation
  240.  
  241. uses
  242.   {$ifdef Delphi}
  243.   SysUtils,
  244.   {$else}
  245.   strings,
  246.   {$endif}
  247.   zInflate, crc;
  248.  
  249. {$ifdef unix and not def (CASESENSITIVITYDEFAULT_YES) and \
  250.                       !defined(CASESENSITIVITYDEFAULT_NO)}
  251. {$define CASESENSITIVITYDEFAULT_NO}
  252. {$endif}
  253.  
  254.  
  255. const
  256.   UNZ_BUFSIZE = Z_BUFSIZE;
  257.   UNZ_MAXFILENAMEINZIP = Z_MAXFILENAMEINZIP;
  258.  
  259. const
  260.   unz_copyright : PChar = ' unzip 0.15 Copyright 1998 Gilles Vollant ';
  261.  
  262. { unz_file_info_internal contain internal info about a file in zipfile }
  263. type
  264.   unz_file_info_internal = record
  265.     offset_curfile : uLong; { relative offset of local header 4 bytes }
  266.   end;
  267.   unz_file_info_internal_ptr = ^unz_file_info_internal;
  268.  
  269.  
  270. { file_in_zip_read_info_s contain internal information about a file
  271.   in zipfile, when reading and decompress it }
  272. type
  273.   file_in_zip_read_info_s = record
  274.     read_buffer : PChar;  { internal buffer for compressed data }
  275.     stream : z_stream;    { zLib stream structure for inflate }
  276.  
  277.     pos_in_zipfile : uLong;       { position in byte on the zipfile, for fseek}
  278.     stream_initialised : boolean;   { flag set if stream structure is initialised}
  279.  
  280.     offset_local_extrafield : uLong;{ offset of the local extra field }
  281.     size_local_extrafield : uInt;{ size of the local extra field }
  282.     pos_local_extrafield : uLong;   { position in the local extra field in read}
  283.  
  284.     crc32 : uLong;                { crc32 of all data uncompressed }
  285.     crc32_wait : uLong;           { crc32 we must obtain after decompress all }
  286.     rest_read_compressed : uLong; { number of byte to be decompressed }
  287.     rest_read_uncompressed : uLong;{number of byte to be obtained after decomp}
  288.     afile : FILEptr;              { io structure of the zipfile }
  289.     compression_method : uLong;   { compression method (0=store) }
  290.     byte_before_the_zipfile : uLong;{ byte before the zipfile, (>0 for sfx) }
  291.   end;
  292.   file_in_zip_read_info_s_ptr = ^file_in_zip_read_info_s;
  293.  
  294.  
  295. { unz_s contain internal information about the zipfile }
  296. type
  297.   unz_s = record
  298.    afile : FILEptr;                 { io structore of the zipfile }
  299.    gi : unz_global_info;       { public global information }
  300.    byte_before_the_zipfile : uLong;{ byte before the zipfile, (>0 for sfx)}
  301.    num_file : uLong;             { number of the current file in the zipfile}
  302.    pos_in_central_dir : uLong;   { pos of the current file in the central dir}
  303.    current_file_ok : boolean;      { flag about the usability of the current file}
  304.    central_pos : uLong;          { position of the beginning of the central dir}
  305.  
  306.    size_central_dir : uLong;     { size of the central directory  }
  307.    offset_central_dir : uLong;   { offset of start of central directory with
  308.                                    respect to the starting disk number }
  309.  
  310.    cur_file_info : unz_file_info; { public info about the current file in zip}
  311.    cur_file_info_internal : unz_file_info_internal; { private info about it}
  312.    pfile_in_zip_read : file_in_zip_read_info_s_ptr; { structure about the current
  313.                                         file if we are decompressing it }
  314.   end;
  315.   unz_s_ptr = ^unz_s;
  316.  
  317.  
  318. { ===========================================================================
  319.   Read a byte from a gz_stream; update next_in and avail_in. Return EOF
  320.   for end of file.
  321.   IN assertion: the stream s has been sucessfully opened for reading. }
  322.  
  323.  
  324. function unzlocal_getByte(fin : FILEptr; var pi : int) : int;
  325. var
  326.   c : Byte;
  327.   err : int;
  328. begin
  329.   err := fread(@c, 1, 1, fin);
  330.  
  331.   if (err = 1) then
  332.   begin
  333.     pi := int(c);
  334.     unzlocal_getByte := UNZ_OK;
  335.     {exit;}
  336.   end
  337.   else
  338.   begin
  339.     if feof(fin)=1 then    {if ferror(fin) then}
  340.       unzlocal_getByte := UNZ_ERRNO
  341.     else
  342.       unzlocal_getByte := UNZ_EOF;
  343.     {exit;}
  344.   end;
  345. end;
  346.  
  347.  
  348. { ===========================================================================
  349.    Reads a long in LSB order from the given gz_stream. Sets }
  350.  
  351. function unzlocal_getShort (fin : FILEptr;
  352.                             var pX : uLong) : int;
  353. var
  354.   x : uLong;
  355.   i : int;
  356.   err : int;
  357. begin
  358.   err := unzlocal_getByte(fin, i);
  359.   x := uLong(i);
  360.  
  361.   if (err=UNZ_OK) then
  362.     err := unzlocal_getByte(fin,i);
  363.   Inc(x, uLong(i) shl 8);
  364.  
  365.   if (err=UNZ_OK) then
  366.     pX := x
  367.   else
  368.     pX := 0;
  369.   unzlocal_getShort := err;
  370. end;
  371.  
  372. function unzlocal_getLong (fin : FILEptr; var pX : uLong) : int;
  373. var
  374.   x : uLong;
  375.   i : int;
  376.   err : int;
  377. begin
  378.   err := unzlocal_getByte(fin,i);
  379.   x := uLong(i);
  380.  
  381.   if (err=UNZ_OK) then
  382.     err := unzlocal_getByte(fin,i);
  383.   Inc(x, uLong(i) shl 8);
  384.  
  385.   if (err=UNZ_OK) then
  386.     err := unzlocal_getByte(fin,i);
  387.   Inc(x, uLong(i) shl 16);
  388.  
  389.   if (err=UNZ_OK) then
  390.     err := unzlocal_getByte(fin,i);
  391.   Inc(x, uLong(i) shl 24);
  392.  
  393.   if (err=UNZ_OK) then
  394.     pX := x
  395.   else
  396.     pX := 0;
  397.   unzlocal_getLong := err;
  398. end;
  399.  
  400.  
  401. { My own strcmpi / strcasecmp }
  402. function strcmpcasenosensitive_internal (fileName1 : PChar;
  403.                                          fileName2 : PChar) : int;
  404. var
  405.   c1, c2 : char;
  406. begin
  407.   repeat
  408.     c1 := fileName1^; Inc(fileName1);
  409.     c2 := fileName2^; Inc(fileName2);
  410.     if (c1>='a') and (c1<='z') then
  411.       Dec(c1,$20);
  412.     if (c2>='a') and (c2<='z') then
  413.       Dec(c2, $20);
  414.     if (c1=#0) then
  415.     begin
  416.       if c2=#0 then
  417.         strcmpcasenosensitive_internal := 0
  418.       else
  419.         strcmpcasenosensitive_internal := -1;
  420.       exit;
  421.     end;
  422.     if (c2=#0) then
  423.     begin
  424.       strcmpcasenosensitive_internal := 1;
  425.       exit;
  426.     end;
  427.     if (c1<c2) then
  428.     begin
  429.       strcmpcasenosensitive_internal := -1;
  430.       exit;
  431.     end;
  432.     if (c1>c2) then
  433.     begin
  434.       strcmpcasenosensitive_internal := 1;
  435.       exit;
  436.     end;
  437.   until false;
  438. end;
  439.  
  440.  
  441. const
  442.   CASESENSITIVITYDEFAULTVALUE = 2;
  443.  
  444. function unzStringFileNameCompare(const fileName1 : PChar;
  445.                                   const fileName2 : PChar;
  446.                                   iCaseSensitivity : int) : int; { ZEXPORT }
  447. { Compare two filename (fileName1,fileName2).
  448.   If iCaseSenisivity = 1 (1=true),
  449.     comparision is case sensitive (like strcmp)
  450.   If iCaseSenisivity = 2 (0=false),
  451.     comparision is not case sensitive (like strcmpi or strcasecmp)
  452.   If iCaseSenisivity = 0, case sensitivity is defaut of your
  453.     operating system like 1 on Unix, 2 on Windows)
  454. }
  455. begin
  456.   if (iCaseSensitivity=0) then
  457.     iCaseSensitivity := CASESENSITIVITYDEFAULTVALUE;
  458.  
  459.   if (iCaseSensitivity=1) then
  460.   begin
  461.     unzStringFileNameCompare := strComp(fileName1,fileName2);
  462.     exit;
  463.   end;
  464.  
  465.   unzStringFileNameCompare := strcmpcasenosensitive_internal(fileName1,fileName2);
  466. end;
  467.  
  468. const
  469.   BUFREADCOMMENT = $400;
  470.  
  471. { Locate the Central directory of a zipfile (at the end, just before
  472.   the global comment) }
  473.  
  474. function unzlocal_SearchCentralDir(fin : FILEptr) : uLong;
  475. var
  476.   buf : pzByteArray;
  477.   uSizeFile : uLong;
  478.   uBackRead : uLong;
  479.   uMaxBack : uLong;
  480.   uPosFound : uLong;
  481. var
  482.   uReadSize,uReadPos : uLong;
  483.   i : int;
  484. begin
  485.   uMaxBack := $ffff; { maximum size of global comment }
  486.   uPosFound := 0;
  487.  
  488.   if (fseek(fin,0,SEEK_END) <> 0) then
  489.   begin
  490.     unzlocal_SearchCentralDir := 0;
  491.     exit;
  492.   end;
  493.  
  494.   uSizeFile := ftell(fin);
  495.  
  496.   if (uMaxBack>uSizeFile) then
  497.     uMaxBack := uSizeFile;
  498.  
  499.   buf := pzByteArray(ALLOC(BUFREADCOMMENT+4));
  500.   if (buf=NIL) then
  501.   begin
  502.     unzlocal_SearchCentralDir := 0;
  503.     exit;
  504.   end;
  505.  
  506.   uBackRead := 4;
  507.   while (uBackRead<uMaxBack) do
  508.   begin
  509.  
  510.     if (uBackRead+BUFREADCOMMENT>uMaxBack) then
  511.       uBackRead := uMaxBack
  512.     else
  513.       Inc(uBackRead, BUFREADCOMMENT);
  514.     uReadPos := uSizeFile-uBackRead ;
  515.  
  516.     if ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) then
  517.       uReadSize := (BUFREADCOMMENT+4)
  518.     else
  519.       uReadSize := (uSizeFile-uReadPos);
  520.  
  521.     if fseek(fin,uReadPos,SEEK_SET)<>0 then
  522.       break;
  523.  
  524.     if fread(buf, uInt(uReadSize), 1, fin)<>1 then
  525.       break;
  526.  
  527.     i := int(uReadSize)-3;
  528.     while (i>0) do
  529.     begin
  530.       Dec(i);
  531.       if (buf^[i] = $50) and (buf^[i+1] = $4b) and    { ENDHEADERMAGIC }
  532.           (buf^[i+2] = $05) and (buf^[i+3] = $06) then
  533.       begin
  534.         uPosFound := uReadPos+uInt(i);
  535.         break;
  536.       end;
  537.     end;
  538.  
  539.     if (uPosFound <> 0) then
  540.       break;
  541.   end;
  542.   TRYFREE(buf);
  543.   unzlocal_SearchCentralDir := uPosFound;
  544. end;
  545.  
  546.  
  547. { Open a Zip file. path contain the full pathname (by example,
  548.   on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
  549.   "zlib/zlib111.zip".
  550.   If the zipfile cannot be opened (file don't exist or in not valid), the
  551.   return value is NIL.
  552.   Else, the return value is a unzFile Handle, usable with other function
  553.        of this unzip package.
  554. }
  555.  
  556. function unzOpen (const path : PChar) : unzFile; { ZEXPORT }
  557. var
  558.   us : unz_s;
  559.   s : unz_s_ptr;
  560.   central_pos,uL : uLong;
  561.   fin : FILEptr;
  562.  
  563.   number_disk : uLong; { number of the current dist, used for spaning ZIP,
  564.                          unsupported, always 0 }
  565.   number_disk_with_CD : uLong; { number the the disk with central dir,
  566.                         used for spaning ZIP, unsupported, always 0 }
  567.   number_entry_CD : uLong; { total number of entries in the central dir
  568.                                    (same than number_entry on nospan) }
  569.  
  570.   err : int;
  571. begin
  572.   err := UNZ_OK;
  573.  
  574.   if (unz_copyright[0]<>' ') then
  575.   begin
  576.     unzOpen := NIL;
  577.     exit;
  578.   end;
  579.  
  580.   fin := fopen(path,fopenread);
  581.   if (fin=NIL) then
  582.   begin
  583.     unzOpen := NIL;
  584.     exit;
  585.   end;
  586.  
  587.   central_pos := unzlocal_SearchCentralDir(fin);
  588.   if (central_pos = 0) then
  589.     err := UNZ_ERRNO;
  590.  
  591.   if (fseek(fin,central_pos,SEEK_SET) <> 0) then
  592.     err := UNZ_ERRNO;
  593.  
  594.   { the signature, already checked }
  595.   if (unzlocal_getLong(fin,uL) <> UNZ_OK) then
  596.     err := UNZ_ERRNO;
  597.  
  598.   { number of this disk }
  599.   if (unzlocal_getShort(fin,number_disk) <> UNZ_OK) then
  600.     err := UNZ_ERRNO;
  601.  
  602.   { number of the disk with the start of the central directory }
  603.   if (unzlocal_getShort(fin,number_disk_with_CD) <> UNZ_OK) then
  604.     err := UNZ_ERRNO;
  605.  
  606.   { total number of entries in the central dir on this disk }
  607.   if (unzlocal_getShort(fin,us.gi.number_entry) <> UNZ_OK) then
  608.     err := UNZ_ERRNO;
  609.  
  610.   { total number of entries in the central dir }
  611.   if (unzlocal_getShort(fin,number_entry_CD) <> UNZ_OK) then
  612.     err := UNZ_ERRNO;
  613.  
  614.   if ((number_entry_CD <> us.gi.number_entry) or
  615.         (number_disk_with_CD <> 0) or
  616.         (number_disk <> 0)) then
  617.     err := UNZ_BADZIPFILE;
  618.  
  619.   { size of the central directory }
  620.   if (unzlocal_getLong(fin,us.size_central_dir)<>UNZ_OK) then
  621.     err := UNZ_ERRNO;
  622.  
  623.   { offset of start of central directory with respect to the
  624.           starting disk number }
  625.   if (unzlocal_getLong(fin,us.offset_central_dir)<>UNZ_OK) then
  626.     err := UNZ_ERRNO;
  627.  
  628.   { zipfile comment length }
  629.   if (unzlocal_getShort(fin,us.gi.size_comment)<>UNZ_OK) then
  630.     err := UNZ_ERRNO;
  631.  
  632.   if ((central_pos < us.offset_central_dir+us.size_central_dir) and
  633.     (err = UNZ_OK)) then
  634.     err := UNZ_BADZIPFILE;
  635.  
  636.   if (err<>UNZ_OK) then
  637.   begin
  638.     fclose(fin);
  639.     unzOpen := NIL;
  640.     exit;
  641.   end;
  642.  
  643.   us.afile := fin;
  644.   us.byte_before_the_zipfile := central_pos -
  645.       (us.offset_central_dir + us.size_central_dir);
  646.   us.central_pos := central_pos;
  647.   us.pfile_in_zip_read := NIL;
  648.  
  649.   s := unz_s_ptr(ALLOC(sizeof(unz_s)));
  650.   s^ := us;
  651.   unzGoToFirstFile(unzFile(s));
  652.   unzOpen := unzFile(s);
  653. end;
  654.  
  655.  
  656. { Close a ZipFile opened with unzipOpen.
  657.   If there are files inside the .Zip opened with unzOpenCurrentFile()
  658.   (see later), these files MUST be closed with unzipCloseCurrentFile()
  659.   before a call unzipClose.
  660.   return UNZ_OK if there is no problem. }
  661.  
  662. function unzClose (afile : unzFile) : int; { ZEXPORT }
  663. var
  664.   s : unz_s_ptr;
  665. begin
  666.   if (afile=NIL) then
  667.   begin
  668.     unzClose := UNZ_PARAMERROR;
  669.     exit;
  670.   end;
  671.   s := unz_s_ptr(afile);
  672.  
  673.   if (s^.pfile_in_zip_read<>NIL) then
  674.     unzCloseCurrentFile(afile);
  675.  
  676.   fclose(s^.afile);
  677.   TRYFREE(s);
  678.   unzClose := UNZ_OK;
  679. end;
  680.  
  681. { Write info about the ZipFile in the pglobal_info structure.
  682.   No preparation of the structure is needed
  683.   return UNZ_OK if there is no problem. }
  684.  
  685. function unzGetGlobalInfo (afile : unzFile;
  686.                        var pglobal_info : unz_global_info) : int; { ZEXPORT }
  687. var
  688.  s : unz_s_ptr;
  689. begin
  690.   if (afile=NIL) then
  691.   begin
  692.     unzGetGlobalInfo := UNZ_PARAMERROR;
  693.     exit;
  694.   end;
  695.   s := unz_s_ptr(afile);
  696.   pglobal_info := s^.gi;
  697.   unzGetGlobalInfo := UNZ_OK;
  698. end;
  699.  
  700.  
  701. { Translate date/time from Dos format to tm_unz (more easily readable) }
  702. procedure unzlocal_DosDateToTmuDate (ulDosDate : uLong;
  703.                                      var ptm : tm_unz);
  704. var
  705.   uDate : uLong;
  706. begin
  707.   uDate := uLong(ulDosDate shr 16);
  708.   ptm.tm_mday := uInt(uDate and $1f) ;
  709.   ptm.tm_mon :=  uInt((( (uDate) and $1E0) div $20)-1) ;
  710.   ptm.tm_year := uInt(((uDate and $0FE00) div $0200)+1980) ;
  711.  
  712.   ptm.tm_hour := uInt ((ulDosDate and $F800) div $800);
  713.   ptm.tm_min :=  uInt ((ulDosDate and $7E0) div $20) ;
  714.   ptm.tm_sec :=  uInt (2*(ulDosDate and $1f)) ;
  715. end;
  716.  
  717. { Get Info about the current file in the zipfile, with internal only info }
  718. function unzlocal_GetCurrentFileInfoInternal (
  719.     afile : unzFile;
  720.     pfile_info : unz_file_info_ptr;
  721.     pfile_info_internal : unz_file_info_internal_ptr;
  722.     szFileName : PChar;
  723.     fileNameBufferSize : uLong;
  724.     extraField : voidp;
  725.     extraFieldBufferSize : uLong;
  726.     szComment : PChar;
  727.     commentBufferSize : uLong ) : int;
  728.   var
  729.     s : unz_s_ptr;
  730.     file_info : unz_file_info;
  731.     file_info_internal : unz_file_info_internal;
  732.     err : int;
  733.     uMagic : uLong;
  734.     lSeek : long;
  735.   var
  736.     uSizeRead : uLong;
  737.   begin
  738.     err := UNZ_OK;
  739.     lSeek := 0;
  740.     if (afile = NIL) then
  741.     begin
  742.       unzlocal_GetCurrentFileInfoInternal := UNZ_PARAMERROR;
  743.       exit;
  744.     end;
  745.     s := unz_s_ptr(afile);
  746.     
  747.     if (fseek(s^.afile,
  748.       s^.pos_in_central_dir+s^.byte_before_the_zipfile,SEEK_SET)<>0) then
  749.       err := UNZ_ERRNO;
  750.  
  751.     { we check the magic }
  752.     if (err=UNZ_OK) then
  753.       if (unzlocal_getLong(s^.afile, uMagic) <> UNZ_OK) then
  754.         err := UNZ_ERRNO
  755.       else
  756.         if (uMagic<> CENTRALHEADERMAGIC) then
  757.       err := UNZ_BADZIPFILE;
  758.  
  759.     if (unzlocal_getShort(s^.afile, file_info.version) <> UNZ_OK) then
  760.       err := UNZ_ERRNO;
  761.  
  762.     if (unzlocal_getShort(s^.afile, file_info.version_needed) <> UNZ_OK) then
  763.       err := UNZ_ERRNO;
  764.  
  765.     if (unzlocal_getShort(s^.afile, file_info.flag) <> UNZ_OK) then
  766.       err := UNZ_ERRNO;
  767.  
  768.     if (unzlocal_getShort(s^.afile, file_info.compression_method) <> UNZ_OK) then
  769.       err := UNZ_ERRNO;
  770.  
  771.     if (unzlocal_getLong(s^.afile, file_info.dosDate) <> UNZ_OK) then
  772.       err := UNZ_ERRNO;
  773.  
  774.     unzlocal_DosDateToTmuDate(file_info.dosDate, file_info.tmu_date);
  775.  
  776.     if (unzlocal_getLong(s^.afile, file_info.crc) <> UNZ_OK) then
  777.       err := UNZ_ERRNO;
  778.  
  779.     if (unzlocal_getLong(s^.afile, file_info.compressed_size) <> UNZ_OK) then
  780.       err := UNZ_ERRNO;
  781.  
  782.     if (unzlocal_getLong(s^.afile, file_info.uncompressed_size) <> UNZ_OK) then
  783.       err := UNZ_ERRNO;
  784.  
  785.     if (unzlocal_getShort(s^.afile, file_info.size_filename) <> UNZ_OK) then
  786.       err := UNZ_ERRNO;
  787.  
  788.     if (unzlocal_getShort(s^.afile, file_info.size_file_extra) <> UNZ_OK) then
  789.       err := UNZ_ERRNO;
  790.  
  791.     if (unzlocal_getShort(s^.afile, file_info.size_file_comment) <> UNZ_OK) then
  792.       err := UNZ_ERRNO;
  793.  
  794.     if (unzlocal_getShort(s^.afile, file_info.disk_num_start) <> UNZ_OK) then
  795.       err := UNZ_ERRNO;
  796.  
  797.     if (unzlocal_getShort(s^.afile, file_info.internal_fa) <> UNZ_OK) then
  798.       err := UNZ_ERRNO;
  799.  
  800.     if (unzlocal_getLong(s^.afile, file_info.external_fa) <> UNZ_OK) then
  801.       err := UNZ_ERRNO;
  802.  
  803.     if (unzlocal_getLong(s^.afile, file_info_internal.offset_curfile) <> UNZ_OK) then
  804.       err := UNZ_ERRNO;
  805.  
  806.     Inc(lSeek, file_info.size_filename);
  807.     if ((err=UNZ_OK) and (szFileName<>NIL)) then
  808.     begin
  809.       if (file_info.size_filename<fileNameBufferSize) then
  810.       begin
  811.         (szFileName+file_info.size_filename)^:=#0;
  812.     uSizeRead := file_info.size_filename;
  813.       end
  814.       else
  815.         uSizeRead := fileNameBufferSize;
  816.  
  817.       if (file_info.size_filename>0) and (fileNameBufferSize>0) then
  818.       begin
  819.         if fread(szFileName, uInt(uSizeRead),1,s^.afile)<>1 then
  820.       err := UNZ_ERRNO;
  821.       end;
  822.       Dec(lSeek, uSizeRead);
  823.     end;
  824.  
  825.     if ((err=UNZ_OK) and (extraField<>NIL)) then
  826.     begin
  827.       if (file_info.size_file_extra<extraFieldBufferSize) then
  828.         uSizeRead := file_info.size_file_extra
  829.       else
  830.         uSizeRead := extraFieldBufferSize;
  831.  
  832.       if (lSeek<>0) then
  833.       begin
  834.         if (fseek(s^.afile,lSeek,SEEK_CUR)=0) then
  835.       lSeek := 0
  836.     else
  837.       err := UNZ_ERRNO;
  838.       end;
  839.  
  840.       if ((file_info.size_file_extra>0) and (extraFieldBufferSize>0)) then
  841.       begin
  842.         if fread(extraField, uInt(uSizeRead),1, s^.afile)<>1 then
  843.           err := UNZ_ERRNO;
  844.       end;
  845.       Inc(lSeek, file_info.size_file_extra - uSizeRead);
  846.     end
  847.     else
  848.       Inc(lSeek, file_info.size_file_extra);
  849.  
  850.     if ((err=UNZ_OK) and (szComment<>NIL)) then
  851.     begin
  852.       if (file_info.size_file_comment<commentBufferSize) then
  853.       begin
  854.         (szComment+file_info.size_file_comment)^ := #0;
  855.     uSizeRead := file_info.size_file_comment;
  856.       end
  857.       else
  858.         uSizeRead := commentBufferSize;
  859.  
  860.       if (lSeek<>0) then
  861.       begin
  862.         if (fseek(s^.afile,lSeek,SEEK_CUR)=0) then
  863.       lSeek := 0
  864.     else
  865.       err := UNZ_ERRNO;
  866.       end;
  867.       if ((file_info.size_file_comment>0) and (commentBufferSize>0)) then
  868.       begin
  869.         if fread(szComment, uInt(uSizeRead),1,s^.afile)<>1 then
  870.       err := UNZ_ERRNO;
  871.       end;
  872.       Inc(lSeek, file_info.size_file_comment - uSizeRead);
  873.     end
  874.     else
  875.       Inc(lSeek, file_info.size_file_comment);
  876.  
  877.     if ((err=UNZ_OK) and (pfile_info<>NIL)) then
  878.       pfile_info^ := file_info;
  879.  
  880.     if ((err=UNZ_OK) and (pfile_info_internal<>NIL)) then
  881.       pfile_info_internal^ := file_info_internal;
  882.  
  883.     unzlocal_GetCurrentFileInfoInternal := err;
  884.   end;
  885.  
  886.  
  887. { Write info about the ZipFile in the *pglobal_info structure.
  888.   No preparation of the structure is needed
  889.   return UNZ_OK if there is no problem. }
  890.  
  891. function unzGetCurrentFileInfo(afile : unzFile;
  892.                                pfile_info : unz_file_info_ptr;
  893.                    szFileName : PChar;
  894.                    fileNameBufferSize : uLong;
  895.                    extraField : voidp;
  896.                    extraFieldBufferSize : uLong;
  897.                    szComment : PChar;
  898.                    commentBufferSize : uLong) : int; { ZEXPORT }
  899.  
  900. { Get Info about the current file
  901.   if pfile_info<>NIL, the pfile_info^ structure will contain somes
  902.   info about the current file
  903.   if szFileName<>NIL, the filemane string will be copied in szFileName
  904.             (fileNameBufferSize is the size of the buffer)
  905.   if extraField<>NIL, the extra field information will be copied in
  906.     extraField    (extraFieldBufferSize is the size of the buffer).
  907.     This is the Central-header version of the extra field
  908.   if szComment<>NIL, the comment string of the file will be copied in
  909.     szComment (commentBufferSize is the size of the buffer) }
  910.  
  911. begin
  912.   unzGetCurrentFileInfo := unzlocal_GetCurrentFileInfoInternal(afile,
  913.             pfile_info,NIL,szFileName,fileNameBufferSize, extraField,
  914.             extraFieldBufferSize, szComment,commentBufferSize);
  915. end;
  916.  
  917.  
  918. { Set the current file of the zipfile to the first file.
  919.   return UNZ_OK if there is no problem }
  920.  
  921. function unzGoToFirstFile(afile : unzFile) : int;  { ZEXPORT }
  922. var
  923.   err : int;
  924.   s : unz_s_ptr;
  925. begin
  926.   if (afile=NIL) then
  927.   begin
  928.     unzGoToFirstFile := UNZ_PARAMERROR;
  929.     exit;
  930.   end;
  931.   s := unz_s_ptr(afile);
  932.   s^.pos_in_central_dir := s^.offset_central_dir;
  933.   s^.num_file := 0;
  934.   err := unzlocal_GetCurrentFileInfoInternal(afile, @s^.cur_file_info,
  935.         @s^.cur_file_info_internal, NIL,0,NIL,0,NIL,0);
  936.   s^.current_file_ok := (err = UNZ_OK);
  937.   unzGoToFirstFile := err;
  938. end;
  939.  
  940.  
  941. { Set the current file of the zipfile to the next file.
  942.   return UNZ_OK if there is no problem
  943.   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. }
  944.  
  945. function unzGoToNextFile(afile : unzFile) : int; { ZEXPORT }
  946. var
  947.   s : unz_s_ptr;
  948.   err : int;
  949. begin
  950.   if (afile=NIL) then
  951.   begin
  952.     unzGoToNextFile := UNZ_PARAMERROR;
  953.     exit;
  954.   end;
  955.   s := unz_s_ptr(afile);
  956.   if not s^.current_file_ok then
  957.   begin
  958.     unzGoToNextFile := UNZ_END_OF_LIST_OF_FILE;
  959.     exit;
  960.   end;
  961.   if (s^.num_file+1 = s^.gi.number_entry) then
  962.   begin
  963.     unzGoToNextFile := UNZ_END_OF_LIST_OF_FILE;
  964.     exit;
  965.   end;
  966.  
  967.   Inc(s^.pos_in_central_dir,
  968.     SIZECENTRALDIRITEM + s^.cur_file_info.size_filename +
  969.     s^.cur_file_info.size_file_extra + s^.cur_file_info.size_file_comment);
  970.   Inc(s^.num_file);
  971.   err := unzlocal_GetCurrentFileInfoInternal(afile, @s^.cur_file_info,
  972.        @s^.cur_file_info_internal, NIL,0,NIL,0,NIL,0);
  973.   s^.current_file_ok := (err = UNZ_OK);
  974.   unzGoToNextFile := err;
  975. end;
  976.  
  977.  
  978. { Try locate the file szFileName in the zipfile.
  979.   For the iCaseSensitivity signification, see unzStringFileNameCompare
  980.  
  981.   return value :
  982.   UNZ_OK if the file is found. It becomes the current file.
  983.   UNZ_END_OF_LIST_OF_FILE if the file is not found }
  984.  
  985. function unzLocateFile(afile : unzFile;
  986.                        const szFileName : PChar;
  987.                iCaseSensitivity : int) : int; { ZEXPORT }
  988. var
  989.   s : unz_s_ptr;
  990.   err : int;
  991.   num_fileSaved : uLong;
  992.   pos_in_central_dirSaved : uLong;
  993. var
  994.   szCurrentFileName : array[0..UNZ_MAXFILENAMEINZIP+1-1] of char;
  995. begin
  996.   if (afile=NIL) then
  997.   begin
  998.     unzLocateFile := UNZ_PARAMERROR;
  999.     exit;
  1000.   end;
  1001.  
  1002.   if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) then
  1003.   begin
  1004.     unzLocateFile := UNZ_PARAMERROR;
  1005.     exit;
  1006.   end;
  1007.  
  1008.   s := unz_s_ptr(afile);
  1009.   if (not s^.current_file_ok) then
  1010.   begin
  1011.     unzLocateFile := UNZ_END_OF_LIST_OF_FILE;
  1012.     exit;
  1013.   end;
  1014.   num_fileSaved := s^.num_file;
  1015.   pos_in_central_dirSaved := s^.pos_in_central_dir;
  1016.  
  1017.   err := unzGoToFirstFile(afile);
  1018.  
  1019.   while (err = UNZ_OK) do
  1020.   begin
  1021.     unzGetCurrentFileInfo(afile,NIL,
  1022.         szCurrentFileName,sizeof(szCurrentFileName)-1, NIL,0,NIL,0);
  1023.     if (unzStringFileNameCompare(szCurrentFileName,
  1024.          szFileName,iCaseSensitivity)=0) then
  1025.     begin
  1026.       unzLocateFile := UNZ_OK;
  1027.       exit;
  1028.     end;
  1029.     err := unzGoToNextFile(afile);
  1030.   end;
  1031.  
  1032.   s^.num_file := num_fileSaved;
  1033.   s^.pos_in_central_dir := pos_in_central_dirSaved;
  1034.   unzLocateFile := err;
  1035. end;
  1036.  
  1037.  
  1038. { Read the local header of the current zipfile
  1039.   Check the coherency of the local header and info in the end of central
  1040.         directory about this file
  1041.   store in *piSizeVar the size of extra info in local header
  1042.         (filename and size of extra field data) }
  1043.  
  1044. function unzlocal_CheckCurrentFileCoherencyHeader (
  1045.                 s : unz_s_ptr;
  1046.                 var piSizeVar : uInt;
  1047.         var poffset_local_extrafield : uLong;
  1048.         var psize_local_extrafield : uInt) : int;
  1049. var
  1050.   uMagic,uData,uFlags : uLong;
  1051.   size_filename : uLong;
  1052.   size_extra_field : uLong;
  1053.   err : int;
  1054. begin
  1055.   err := UNZ_OK;
  1056.  
  1057.   piSizeVar := 0;
  1058.   poffset_local_extrafield := 0;
  1059.   psize_local_extrafield := 0;
  1060.  
  1061.   if (fseek(s^.afile,s^.cur_file_info_internal.offset_curfile +
  1062.     s^.byte_before_the_zipfile,SEEK_SET)<>0) then
  1063.   begin
  1064.     unzlocal_CheckCurrentFileCoherencyHeader := UNZ_ERRNO;
  1065.     exit;
  1066.   end;
  1067.  
  1068.   if (err=UNZ_OK) then
  1069.     if (unzlocal_getLong(s^.afile, uMagic) <> UNZ_OK) then
  1070.       err := UNZ_ERRNO
  1071.     else
  1072.       if (uMagic<> $04034b50) then
  1073.         err := UNZ_BADZIPFILE;
  1074.  
  1075.   if (unzlocal_getShort(s^.afile, uData) <> UNZ_OK) then
  1076.     err := UNZ_ERRNO;
  1077. {
  1078.   else
  1079.     if ((err=UNZ_OK) and (uData<>s^.cur_file_info.wVersion)) then
  1080.       err := UNZ_BADZIPFILE;
  1081. }
  1082.   if (unzlocal_getShort(s^.afile, uFlags) <> UNZ_OK) then
  1083.     err := UNZ_ERRNO;
  1084.  
  1085.   if (unzlocal_getShort(s^.afile, uData) <> UNZ_OK) then
  1086.     err := UNZ_ERRNO
  1087.   else
  1088.     if ((err=UNZ_OK) and (uData<>s^.cur_file_info.compression_method)) then
  1089.       err := UNZ_BADZIPFILE;
  1090.  
  1091.   if ((err=UNZ_OK) and (s^.cur_file_info.compression_method<>0) and
  1092.       (s^.cur_file_info.compression_method<>Z_DEFLATED)) then
  1093.     err := UNZ_BADZIPFILE;
  1094.  
  1095.   if (unzlocal_getLong(s^.afile, uData) <> UNZ_OK) then { date/time }
  1096.     err := UNZ_ERRNO;
  1097.  
  1098.   if (unzlocal_getLong(s^.afile, uData) <> UNZ_OK) then { crc }
  1099.     err := UNZ_ERRNO
  1100.   else
  1101.     if ((err=UNZ_OK) and (uData<>s^.cur_file_info.crc) and
  1102.        ((uFlags and 8)=0)) then
  1103.       err := UNZ_BADZIPFILE;
  1104.  
  1105.   if (unzlocal_getLong(s^.afile, uData) <> UNZ_OK) then { size compr }
  1106.     err := UNZ_ERRNO
  1107.   else
  1108.     if ((err=UNZ_OK) and (uData<>s^.cur_file_info.compressed_size) and
  1109.       ((uFlags and 8)=0)) then
  1110.       err := UNZ_BADZIPFILE;
  1111.  
  1112.   if (unzlocal_getLong(s^.afile, uData) <> UNZ_OK) then { size uncompr }
  1113.     err := UNZ_ERRNO
  1114.   else
  1115.     if ((err=UNZ_OK) and (uData<>s^.cur_file_info.uncompressed_size) and
  1116.       ((uFlags and 8)=0)) then
  1117.       err := UNZ_BADZIPFILE;
  1118.  
  1119.  
  1120.   if (unzlocal_getShort(s^.afile, size_filename) <> UNZ_OK) then
  1121.     err := UNZ_ERRNO
  1122.   else
  1123.     if ((err=UNZ_OK) and (size_filename<>s^.cur_file_info.size_filename)) then
  1124.       err := UNZ_BADZIPFILE;
  1125.  
  1126.   Inc(piSizeVar, uInt(size_filename));
  1127.  
  1128.   if (unzlocal_getShort(s^.afile, size_extra_field) <> UNZ_OK) then
  1129.     err := UNZ_ERRNO;
  1130.   poffset_local_extrafield := s^.cur_file_info_internal.offset_curfile +
  1131.             SIZEZIPLOCALHEADER + size_filename;
  1132.   psize_local_extrafield := uInt(size_extra_field);
  1133.  
  1134.   Inc(piSizeVar, uInt(size_extra_field));
  1135.  
  1136.   unzlocal_CheckCurrentFileCoherencyHeader := err;
  1137. end;
  1138.  
  1139. { Open for reading data the current file in the zipfile.
  1140.   If there is no error, the return value is UNZ_OK. }
  1141.  
  1142. function unzOpenCurrentFile(afile : unzFile) : int; { ZEXPORT }
  1143. var
  1144.   err : int;
  1145.   Store : boolean;
  1146.   iSizeVar : uInt;
  1147.   s : unz_s_ptr;
  1148.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1149.   offset_local_extrafield : uLong;  { offset of the local extra field }
  1150.   size_local_extrafield : uInt;    { size of the local extra field }
  1151. begin
  1152.   err := UNZ_OK;
  1153.  
  1154.   if (afile=NIL) then
  1155.   begin
  1156.     unzOpenCurrentFile := UNZ_PARAMERROR;
  1157.     exit;
  1158.   end;
  1159.   s := unz_s_ptr(afile);
  1160.   if not s^.current_file_ok then
  1161.   begin
  1162.     unzOpenCurrentFile := UNZ_PARAMERROR;
  1163.     exit;
  1164.   end;
  1165.  
  1166.   if (s^.pfile_in_zip_read <> NIL) then
  1167.     unzCloseCurrentFile(afile);
  1168.  
  1169.   if (unzlocal_CheckCurrentFileCoherencyHeader(s, iSizeVar,
  1170.     offset_local_extrafield, size_local_extrafield)<>UNZ_OK) then
  1171.   begin
  1172.     unzOpenCurrentFile := UNZ_BADZIPFILE;
  1173.     exit;
  1174.   end;
  1175.  
  1176.   pfile_in_zip_read_info := file_in_zip_read_info_s_ptr(
  1177.     ALLOC(sizeof(file_in_zip_read_info_s)) );
  1178.   if (pfile_in_zip_read_info=NIL) then
  1179.   begin
  1180.     unzOpenCurrentFile := UNZ_INTERNALERROR;
  1181.     exit;
  1182.   end;
  1183.  
  1184.   pfile_in_zip_read_info^.read_buffer := PChar(ALLOC(UNZ_BUFSIZE));
  1185.   pfile_in_zip_read_info^.offset_local_extrafield := offset_local_extrafield;
  1186.   pfile_in_zip_read_info^.size_local_extrafield := size_local_extrafield;
  1187.   pfile_in_zip_read_info^.pos_local_extrafield := 0;
  1188.  
  1189.   if (pfile_in_zip_read_info^.read_buffer=NIL) then
  1190.   begin
  1191.     TRYFREE(pfile_in_zip_read_info);
  1192.     unzOpenCurrentFile := UNZ_INTERNALERROR;
  1193.     exit;
  1194.   end;
  1195.  
  1196.   pfile_in_zip_read_info^.stream_initialised := false;
  1197.  
  1198.   if ((s^.cur_file_info.compression_method<>0) and
  1199.       (s^.cur_file_info.compression_method<>Z_DEFLATED)) then
  1200.     err := UNZ_BADZIPFILE;
  1201.   Store := s^.cur_file_info.compression_method = 0;
  1202.  
  1203.   pfile_in_zip_read_info^.crc32_wait := s^.cur_file_info.crc;
  1204.   pfile_in_zip_read_info^.crc32 := 0;
  1205.   pfile_in_zip_read_info^.compression_method := s^.cur_file_info.compression_method;
  1206.   pfile_in_zip_read_info^.afile := s^.afile;
  1207.   pfile_in_zip_read_info^.byte_before_the_zipfile := s^.byte_before_the_zipfile;
  1208.  
  1209.   pfile_in_zip_read_info^.stream.total_out := 0;
  1210.  
  1211.   if (not Store) then
  1212.   begin
  1213.     pfile_in_zip_read_info^.stream.zalloc := NIL;
  1214.     pfile_in_zip_read_info^.stream.zfree := NIL;
  1215.     pfile_in_zip_read_info^.stream.opaque := voidpf(NIL);
  1216.  
  1217.     err := inflateInit2(pfile_in_zip_read_info^.stream, -MAX_WBITS);
  1218.  
  1219.     if (err = Z_OK) then
  1220.       pfile_in_zip_read_info^.stream_initialised := true;
  1221.         { windowBits is passed < 0 to tell that there is no zlib header.
  1222.           Note that in this case inflate *requires* an extra "dummy" byte
  1223.           after the compressed stream in order to complete decompression and
  1224.           return Z_STREAM_END.
  1225.           In unzip, i don't wait absolutely Z_STREAM_END because I known the
  1226.           size of both compressed and uncompressed data }
  1227.   end;
  1228.   pfile_in_zip_read_info^.rest_read_compressed := s^.cur_file_info.compressed_size ;
  1229.   pfile_in_zip_read_info^.rest_read_uncompressed := s^.cur_file_info.uncompressed_size ;
  1230.  
  1231.  
  1232.   pfile_in_zip_read_info^.pos_in_zipfile :=
  1233.     s^.cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
  1234.  
  1235.   pfile_in_zip_read_info^.stream.avail_in := uInt(0);
  1236.  
  1237.  
  1238.   s^.pfile_in_zip_read := pfile_in_zip_read_info;
  1239.   unzOpenCurrentFile := UNZ_OK;
  1240. end;
  1241.  
  1242.  
  1243. { Read bytes from the current file (opened by unzOpenCurrentFile)
  1244.   buf contain buffer where data must be copied
  1245.   len the size of buf.
  1246.  
  1247.   return the number of byte copied if somes bytes are copied
  1248.   return 0 if the end of file was reached
  1249.   return <0 with error code if there is an error
  1250.     (UNZ_ERRNO for IO error, or zLib error for uncompress error) }
  1251.  
  1252. function unzReadCurrentFile(afile : unzFile;
  1253.                             buf : voidp;
  1254.                 len : unsigned) : int; { ZEXPORT }
  1255.  
  1256. var
  1257.   err : int;
  1258.   iRead: uInt;
  1259.   s : unz_s_ptr;
  1260.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1261. var
  1262.   uReadThis : uInt;
  1263. var
  1264.   uDoCopy,i : uInt;
  1265. var
  1266.   uTotalOutBefore,uTotalOutAfter : uLong;
  1267.   bufBefore : pBytef;
  1268.   uOutThis : uLong;
  1269.   flush : int;
  1270. begin
  1271.   err := UNZ_OK;
  1272.   iRead := 0;
  1273.   if (afile=NIL) then
  1274.   begin
  1275.     unzReadCurrentFile := UNZ_PARAMERROR;
  1276.     exit;
  1277.   end;
  1278.   s := unz_s_ptr(afile);
  1279.   pfile_in_zip_read_info := s^.pfile_in_zip_read;
  1280.  
  1281.   if (pfile_in_zip_read_info=NIL) then
  1282.   begin
  1283.     unzReadCurrentFile := UNZ_PARAMERROR;
  1284.     exit;
  1285.   end;
  1286.  
  1287.   if ((pfile_in_zip_read_info^.read_buffer = NIL)) then
  1288.   begin
  1289.     unzReadCurrentFile := UNZ_END_OF_LIST_OF_FILE;
  1290.     exit;
  1291.   end;
  1292.  
  1293.   if (len=0) then
  1294.   begin
  1295.     unzReadCurrentFile := 0;
  1296.     exit;
  1297.   end;
  1298.  
  1299.   pfile_in_zip_read_info^.stream.next_out := pBytef(buf);
  1300.  
  1301.   pfile_in_zip_read_info^.stream.avail_out := uInt(len);
  1302.  
  1303.   if (len>pfile_in_zip_read_info^.rest_read_uncompressed) then
  1304.       pfile_in_zip_read_info^.stream.avail_out :=
  1305.         uInt(pfile_in_zip_read_info^.rest_read_uncompressed);
  1306.  
  1307.   while (pfile_in_zip_read_info^.stream.avail_out>0) do
  1308.   begin
  1309.     if ((pfile_in_zip_read_info^.stream.avail_in = 0) and
  1310.         (pfile_in_zip_read_info^.rest_read_compressed>0) ) then
  1311.     begin
  1312.       uReadThis := UNZ_BUFSIZE;
  1313.       if (pfile_in_zip_read_info^.rest_read_compressed<uReadThis) then
  1314.     uReadThis := uInt(pfile_in_zip_read_info^.rest_read_compressed);
  1315.       if (uReadThis = 0) then
  1316.       begin
  1317.     unzReadCurrentFile := UNZ_EOF;
  1318.         exit;
  1319.       end;
  1320.       if (fseek(pfile_in_zip_read_info^.afile,
  1321.           pfile_in_zip_read_info^.pos_in_zipfile +
  1322.           pfile_in_zip_read_info^.byte_before_the_zipfile,SEEK_SET)<>0) then
  1323.       begin
  1324.     unzReadCurrentFile := UNZ_ERRNO;
  1325.         exit;
  1326.       end;
  1327.       if fread(pfile_in_zip_read_info^.read_buffer, uReadThis, 1,
  1328.              pfile_in_zip_read_info^.afile)<>1 then
  1329.       begin
  1330.     unzReadCurrentFile := UNZ_ERRNO;
  1331.         exit;
  1332.       end;
  1333.       Inc(pfile_in_zip_read_info^.pos_in_zipfile, uReadThis);
  1334.  
  1335.       Dec(pfile_in_zip_read_info^.rest_read_compressed, uReadThis);
  1336.  
  1337.       pfile_in_zip_read_info^.stream.next_in :=
  1338.          pBytef(pfile_in_zip_read_info^.read_buffer);
  1339.       pfile_in_zip_read_info^.stream.avail_in := uInt(uReadThis);
  1340.     end;
  1341.  
  1342.     if (pfile_in_zip_read_info^.compression_method=0) then
  1343.     begin
  1344.       if (pfile_in_zip_read_info^.stream.avail_out <
  1345.           pfile_in_zip_read_info^.stream.avail_in) then
  1346.         uDoCopy := pfile_in_zip_read_info^.stream.avail_out
  1347.       else
  1348.         uDoCopy := pfile_in_zip_read_info^.stream.avail_in;
  1349.  
  1350.       for i:=0 to uDoCopy-1 do
  1351.         pzByteArray(pfile_in_zip_read_info^.stream.next_out)^[i] :=
  1352.           pzByteArray(pfile_in_zip_read_info^.stream.next_in)^[i];
  1353.  
  1354.       pfile_in_zip_read_info^.crc32 := crc32(pfile_in_zip_read_info^.crc32,
  1355.       pfile_in_zip_read_info^.stream.next_out, uDoCopy);
  1356.       Dec(pfile_in_zip_read_info^.rest_read_uncompressed, uDoCopy);
  1357.       Dec(pfile_in_zip_read_info^.stream.avail_in, uDoCopy);
  1358.       Dec(pfile_in_zip_read_info^.stream.avail_out, uDoCopy);
  1359.       Inc(pfile_in_zip_read_info^.stream.next_out, uDoCopy);
  1360.       Inc(pfile_in_zip_read_info^.stream.next_in, uDoCopy);
  1361.       Inc(pfile_in_zip_read_info^.stream.total_out, uDoCopy);
  1362.       Inc(iRead, uDoCopy);
  1363.     end
  1364.     else
  1365.     begin
  1366.       flush := Z_SYNC_FLUSH;
  1367.  
  1368.       uTotalOutBefore := pfile_in_zip_read_info^.stream.total_out;
  1369.       bufBefore := pfile_in_zip_read_info^.stream.next_out;
  1370.  
  1371.       {
  1372.       if ((pfile_in_zip_read_info^.rest_read_uncompressed =
  1373.        pfile_in_zip_read_info^.stream.avail_out) and
  1374.       (pfile_in_zip_read_info^.rest_read_compressed = 0)) then
  1375.         flush := Z_FINISH;
  1376.       }
  1377.       err := inflate(pfile_in_zip_read_info^.stream,flush);
  1378.  
  1379.       uTotalOutAfter := pfile_in_zip_read_info^.stream.total_out;
  1380.       uOutThis := uTotalOutAfter-uTotalOutBefore;
  1381.  
  1382.       pfile_in_zip_read_info^.crc32 :=
  1383.         crc32(pfile_in_zip_read_info^.crc32,bufBefore, uInt(uOutThis));
  1384.  
  1385.       Dec(pfile_in_zip_read_info^.rest_read_uncompressed, uOutThis);
  1386.  
  1387.       Inc(iRead, uInt(uTotalOutAfter - uTotalOutBefore));
  1388.  
  1389.       if (err=Z_STREAM_END) then
  1390.       begin
  1391.         if iRead=0 then
  1392.           unzReadCurrentFile := UNZ_EOF
  1393.         else
  1394.           unzReadCurrentFile := iRead;
  1395.         exit;
  1396.       end;
  1397.       if (err<>Z_OK) then
  1398.         break;
  1399.     end;
  1400.   end; { while }
  1401.  
  1402.   if (err=Z_OK) then
  1403.   begin
  1404.     unzReadCurrentFile := iRead;
  1405.     exit;
  1406.   end;
  1407.   unzReadCurrentFile := err;
  1408. end;
  1409.  
  1410. { Give the current position in uncompressed data }
  1411.  
  1412. function unztell(afile : unzFile) : z_off_t; { ZEXPORT }
  1413. var
  1414.   s : unz_s_ptr;
  1415.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1416. begin
  1417.   if (afile=NIL) then
  1418.   begin
  1419.     unztell := UNZ_PARAMERROR;
  1420.     exit;
  1421.   end;
  1422.  
  1423.   s := unz_s_ptr(afile);
  1424.   pfile_in_zip_read_info := s^.pfile_in_zip_read;
  1425.  
  1426.   if (pfile_in_zip_read_info=NIL) then
  1427.   begin
  1428.     unztell := UNZ_PARAMERROR;
  1429.     exit;
  1430.   end;
  1431.  
  1432.   unztell := z_off_t(pfile_in_zip_read_info^.stream.total_out);
  1433. end;
  1434.  
  1435.  
  1436. { return 1 (TRUE) if the end of file was reached, 0 elsewhere }
  1437.  
  1438. function unzeof(afile : unzFile) : int;
  1439. var
  1440.   s : unz_s_ptr;
  1441.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1442. begin
  1443.   if (afile=NIL) then
  1444.   begin
  1445.     unzeof := UNZ_PARAMERROR;
  1446.     exit;
  1447.   end;
  1448.  
  1449.   s := unz_s_ptr(afile);
  1450.   pfile_in_zip_read_info := s^.pfile_in_zip_read;
  1451.  
  1452.   if (pfile_in_zip_read_info = NIL) then
  1453.   begin
  1454.     unzeof := UNZ_PARAMERROR;
  1455.     exit;
  1456.   end;
  1457.  
  1458.   if (pfile_in_zip_read_info^.rest_read_uncompressed = 0) then
  1459.     unzeof := 1
  1460.   else
  1461.     unzeof := 0;
  1462. end;
  1463.  
  1464.  
  1465. { Read extra field from the current file (opened by unzOpenCurrentFile)
  1466.   This is the local-header version of the extra field (sometimes, there is
  1467.     more info in the local-header version than in the central-header)
  1468.  
  1469.   if buf=NIL, it return the size of the local extra field
  1470.  
  1471.   if buf<>NIL, len is the size of the buffer, the extra header is copied in
  1472.     buf.
  1473.   the return value is the number of bytes copied in buf, or (if <0)
  1474.     the error code }
  1475.  
  1476. function unzGetLocalExtrafield (afile : unzFile;
  1477.                                 buf : voidp;
  1478.                                 len : unsigned) : int;
  1479. var
  1480.   s : unz_s_ptr;
  1481.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1482.   read_now : uInt;
  1483.   size_to_read : uLong;
  1484. begin
  1485.   if (afile=NIL) then
  1486.   begin
  1487.     unzGetLocalExtrafield := UNZ_PARAMERROR;
  1488.     exit;
  1489.   end;
  1490.  
  1491.   s := unz_s_ptr(afile);
  1492.   pfile_in_zip_read_info := s^.pfile_in_zip_read;
  1493.  
  1494.   if (pfile_in_zip_read_info=NIL) then
  1495.   begin
  1496.     unzGetLocalExtrafield := UNZ_PARAMERROR;
  1497.     exit;
  1498.   end;
  1499.  
  1500.   size_to_read := (pfile_in_zip_read_info^.size_local_extrafield -
  1501.                    pfile_in_zip_read_info^.pos_local_extrafield);
  1502.  
  1503.   if (buf=NIL) then
  1504.   begin
  1505.     unzGetLocalExtrafield := int(size_to_read);
  1506.     exit;
  1507.   end;
  1508.  
  1509.   if (len>size_to_read) then
  1510.     read_now := uInt(size_to_read)
  1511.   else
  1512.     read_now := uInt(len);
  1513.  
  1514.   if (read_now=0) then
  1515.   begin
  1516.     unzGetLocalExtrafield := 0;
  1517.     exit;
  1518.   end;
  1519.  
  1520.   if (fseek(pfile_in_zip_read_info^.afile,
  1521.             pfile_in_zip_read_info^.offset_local_extrafield +
  1522.         pfile_in_zip_read_info^.pos_local_extrafield,SEEK_SET)<>0) then
  1523.   begin
  1524.     unzGetLocalExtrafield := UNZ_ERRNO;
  1525.     exit;
  1526.   end;
  1527.  
  1528.   if fread(buf,uInt(size_to_read),1, pfile_in_zip_read_info^.afile)<>1 then
  1529.   begin
  1530.     unzGetLocalExtrafield := UNZ_ERRNO;
  1531.     exit;
  1532.   end;
  1533.  
  1534.   unzGetLocalExtrafield := int(read_now);
  1535. end;
  1536.  
  1537. { Close the file in zip opened with unzOpenCurrentFile
  1538.   Return UNZ_CRCERROR if all the file was read but the CRC is not good }
  1539.  
  1540. function unzCloseCurrentFile(afile : unzFile) : int; { ZEXPORT }
  1541. var
  1542.   err : int;
  1543.   s : unz_s_ptr;
  1544.   pfile_in_zip_read_info : file_in_zip_read_info_s_ptr;
  1545. begin
  1546.   err := UNZ_OK;
  1547.  
  1548.   if (afile=NIL) then
  1549.   begin
  1550.     unzCloseCurrentFile := UNZ_PARAMERROR;
  1551.     exit;
  1552.   end;
  1553.   s := unz_s_ptr(afile);
  1554.   pfile_in_zip_read_info := s^.pfile_in_zip_read;
  1555.  
  1556.   if (pfile_in_zip_read_info=NIL) then
  1557.   begin
  1558.     unzCloseCurrentFile := UNZ_PARAMERROR;
  1559.     exit;
  1560.   end;
  1561.  
  1562.  
  1563.   if (pfile_in_zip_read_info^.rest_read_uncompressed = 0) then
  1564.   begin
  1565.     if (pfile_in_zip_read_info^.crc32 <> pfile_in_zip_read_info^.crc32_wait) then
  1566.       err :=UNZ_CRCERROR;
  1567.   end;
  1568.  
  1569.  
  1570.   TRYFREE(pfile_in_zip_read_info^.read_buffer);
  1571.   pfile_in_zip_read_info^.read_buffer := NIL;
  1572.   if (pfile_in_zip_read_info^.stream_initialised) then
  1573.     inflateEnd(pfile_in_zip_read_info^.stream);
  1574.  
  1575.   pfile_in_zip_read_info^.stream_initialised := false;
  1576.   TRYFREE(pfile_in_zip_read_info);
  1577.  
  1578.   s^.pfile_in_zip_read := NIL;
  1579.  
  1580.   unzCloseCurrentFile := err;
  1581. end;
  1582.  
  1583.  
  1584. { Get the global comment string of the ZipFile, in the szComment buffer.
  1585.   uSizeBuf is the size of the szComment buffer.
  1586.   return the number of byte copied or an error code <0 }
  1587.  
  1588. function unzGetGlobalComment (afile : unzFile;
  1589.                               szComment : PChar;
  1590.                   uSizeBuf : uLong) : int; { ZEXPORT }
  1591.  
  1592. var
  1593.   s : unz_s_ptr;
  1594.   uReadThis : uLong;
  1595. begin
  1596.   if (afile=NIL) then
  1597.   begin
  1598.     unzGetGlobalComment := UNZ_PARAMERROR;
  1599.     exit;
  1600.   end;
  1601.   s := unz_s_ptr(afile);
  1602.  
  1603.   uReadThis := uSizeBuf;
  1604.   if (uReadThis>s^.gi.size_comment) then
  1605.     uReadThis := s^.gi.size_comment;
  1606.  
  1607.   if (fseek(s^.afile,s^.central_pos+22,SEEK_SET)<>0) then
  1608.   begin
  1609.     unzGetGlobalComment := UNZ_ERRNO;
  1610.     exit;
  1611.   end;
  1612.  
  1613.   if (uReadThis>0) then
  1614.   begin
  1615.     szComment^ := #0;
  1616.     if fread(szComment, uInt(uReadThis), 1,s^.afile)<>1 then
  1617.     begin
  1618.       unzGetGlobalComment := UNZ_ERRNO;
  1619.       exit;
  1620.     end;
  1621.   end;
  1622.  
  1623.   if ((szComment <> NIL) and (uSizeBuf > s^.gi.size_comment)) then
  1624.     (szComment+s^.gi.size_comment)^ := #0;
  1625.  
  1626.   unzGetGlobalComment := int(uReadThis);
  1627. end;
  1628.  
  1629. end.
  1630.