Advertisement
Guest User

GZip Delphi XE2

a guest
Jan 11th, 2013
1,379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 25.59 KB | None | 0 0
  1. {*****************************************************************************
  2. *  ZLibExGZ.pas                                                              *
  3. *                                                                            *
  4. *  copyright (c) 2000-2007 base2 technologies                                *
  5. *  copyright (c) 1995-2002 Borland Software Corporation                      *
  6. *                                                                            *
  7. *  revision history                                                          *
  8. *    2007.07.18  fixed GZCompressStr filename and comment processing         *
  9. *    2007.03.18  modified naming convention for gzip routines GZ*            *
  10. *                deprecated previous gzip routines *G                        *
  11. *    2007.03.15  created separate unit for gzip routines/objects             *
  12. *                added ZDecompressStreamG                                    *
  13. *                added overloaded ZCompressStrG                              *
  14. *                added overloaded ZCompressStreamG                           *
  15. *    2007.02.24  added PWord declaration for delphi 5-                       *
  16. *    2006.08.10  added ZDecompressStrG                                       *
  17. *    2006.06.02  added DateTimeToUnix for delphi 5-                          *
  18. *    2006.03.27  added ZCompressStreamG                                      *
  19. *    2006.03.24  added ZCompressStrG                                         *
  20. *                                                                            *
  21. *  acknowledgments                                                           *
  22. *    ralf wenske                                                             *
  23. *      2006.03.24  prototyping and assisting with ZCompressStrG and          *
  24. *                    ZCompressStreamG                                        *
  25. *                                                                            *
  26. *    roman krupicka                                                          *
  27. *      2006.06.02  pointing out the DateUtils unit and the DateTimeToUnix    *
  28. *                    function wasn't available prior to delphi 6             *                     *
  29. *                                                                            *
  30. *    marcin treffler                                                         *
  31. *      2007.02.24  pointing out the missing PWord declaration for delphi 5   *
  32. *                                                                            *
  33. *    jean-jacques esquirol                                                   *
  34. *      2007.07.18  pointing out the "result" address issue when processing   *
  35. *                    filename and comment flags/content in GZCompressStr     *
  36. *****************************************************************************}
  37.  
  38. unit ZLibExGZ;
  39.  
  40. interface
  41.  
  42. uses
  43.   ZLib, SysUtils, Classes {$IFDEF Version6Plus}, DateUtils {$ENDIF};
  44.  
  45.  
  46.  
  47.  
  48. type
  49.   {** TGZHeader *************************************************************}
  50.     TZStrategy = (
  51.     zsDefault,
  52.     zsFiltered,
  53.     zsHuffman,
  54.     zsRLE,
  55.     zsFixed
  56.   );
  57.     TZError = (
  58.     zeError,
  59.     zeStreamError,
  60.     zeDataError,
  61.     zeMemoryError,
  62.     zeBufferError,
  63.     zeVersionError
  64.   );
  65.  
  66.  
  67.   PGZHeader = ^TGZHeader;
  68.   TGZHeader = packed record
  69.     Id1       : Byte;
  70.     Id2       : Byte;
  71.     Method    : Byte;
  72.     Flags     : Byte;
  73.     Time      : Cardinal;
  74.     ExtraFlags: Byte;
  75.     OS        : Byte;
  76.   end;
  77.  
  78.   {** TGZTrailer ************************************************************}
  79.  
  80.   PGZTrailer = ^TGZTrailer;
  81.   TGZTrailer = packed record
  82.     Crc : Cardinal;
  83.     Size: Cardinal;
  84.   end;
  85.  
  86. {** string routines *********************************************************}
  87. Const
  88.   ZStrategies: Array [TZStrategy] of Shortint = (
  89.     Z_DEFAULT_STRATEGY,     // zsDefault
  90.     Z_FILTERED,             // zsFiltered
  91.     Z_HUFFMAN_ONLY,         // zsHuffman
  92.     Z_RLE,                  // zsRLE
  93.     Z_FIXED                 // zsFixed
  94.   );
  95. {*****************************************************************************
  96. *  GZCompressStr                                                             *
  97. *                                                                            *
  98. *  pre-conditions                                                            *
  99. *    s          = uncompressed data string                                   *
  100. *    fileName   = filename                                                   *
  101. *    comment    = comment                                                    *
  102. *    dateTime   = date/time                                                  *
  103. *                                                                            *
  104. *  return                                                                    *
  105. *    compressed data string in gzip format                                   *
  106. *****************************************************************************}
  107.  
  108. function  GZCompressStr(const s: String; const fileName, comment: String;
  109.   dateTime: TDateTime): String; overload;
  110.  
  111. function  GZCompressStr(const s: String): String; overload;
  112.  
  113. {*****************************************************************************
  114. *  GZDecompressStr                                                           *
  115. *                                                                            *
  116. *  pre-conditions                                                            *
  117. *    s = compressed data string in gzip format                               *
  118. *                                                                            *
  119. *  post-conditions                                                           *
  120. *    fileName   = filename                                                   *
  121. *    comment    = comment                                                    *
  122. *    dateTime   = date/time                                                  *
  123. *                                                                            *
  124. *  return                                                                    *
  125. *    uncompressed data string                                                *
  126. *****************************************************************************}
  127.  
  128. function  GZDecompressStr(const s: String; var fileName, comment: String;
  129.   var dateTime: TDateTime): String; overload;
  130.  
  131. function  GZDecompressStr(const s: String): String; overload;
  132.  
  133. {** stream routines *********************************************************}
  134.  
  135. procedure GZCompressStream(inStream, outStream: TStream; const fileName,
  136.   comment: String; dateTime: TDateTime); overload;
  137.  
  138. procedure GZCompressStream(inStream, outStream: TStream); overload;
  139.  
  140. procedure GZDecompressStream(inStream, outStream: TStream; var fileName,
  141.   comment: String; var dateTime: TDateTime); overload;
  142.  
  143. procedure GZDecompressStream(inStream, outStream: TStream); overload;
  144.  
  145. {** deprecated routines *****************************************************}
  146.  
  147. function  ZCompressStrG(const s: String; const fileName, comment: String;
  148.   dateTime: TDateTime): String; overload;
  149.  
  150. function  ZCompressStrG(const s: String): String; overload;
  151.  
  152. function  ZDecompressStrG(const s: String; var fileName, comment: String;
  153.   var dateTime: TDateTime): String; overload;
  154.  
  155. function  ZDecompressStrG(const s: String): String; overload;
  156.  
  157. procedure ZCompressStreamG(inStream, outStream: TStream; const fileName,
  158.   comment: String; dateTime: TDateTime); overload;
  159.  
  160. procedure ZCompressStreamG(inStream, outStream: TStream); overload;
  161.  
  162. procedure ZDecompressStreamG(inStream, outStream: TStream; var fileName,
  163.   comment: String; var dateTime: TDateTime); overload;
  164.  
  165. procedure ZDecompressStreamG(inStream, outStream: TStream); overload;
  166.  
  167. implementation
  168.  
  169. const
  170.   GZ_ASCII_TEXT  = $01;
  171.   GZ_HEADER_CRC  = $02;
  172.   GZ_EXTRA_FIELD = $04;
  173.   GZ_FILENAME    = $08;
  174.   GZ_COMMENT     = $10;
  175.   GZ_RESERVED    = $E0;
  176.  
  177.   GZ_EXTRA_DEFAULT = 0;
  178.   GZ_EXTRA_MAX     = 2;
  179.   GZ_EXTRA_FASTEST = 4;
  180.  
  181.   SGZInvalid = 'Invalid GZStream operation!';
  182.  
  183. {$IFNDEF Version6Plus}
  184.  
  185. type
  186.   PWord = ^Word;
  187.  
  188. {$ENDIF}
  189.  
  190. {** DateTimeToUnix **********************************************************}
  191.  
  192. {$IFNDEF Version6Plus}
  193.  
  194. { Days between TDateTime basis (12/31/1899) and Unix time_t basis (1/1/1970) }
  195.  
  196. const
  197.   UnixDateDelta = 25569;
  198.  
  199. function DateTimeToUnix(const AValue: TDateTime): Cardinal;
  200. begin
  201.   Result := Round((AValue - UnixDateDelta) * SecsPerDay);
  202. end;
  203.  
  204. function UnixToDateTime(const AValue: Cardinal): TDateTime;
  205. begin
  206.   Result := AValue / SecsPerDay + UnixDateDelta;
  207. end;
  208.  
  209. {$ENDIF}
  210. function ZCompressCheck(code: Integer): Integer;
  211. begin
  212.   result := code;
  213.  
  214.   if code < 0 then
  215.   begin
  216.     raise EZCompressionError.Create(IntToStr(code));
  217.   end;
  218. end;
  219. procedure ZInternalCompress(var zstream: TZStreamRec; const inBuffer: Pointer;
  220.   inSize: Integer; out outBuffer: Pointer; out outSize: Integer);
  221. const
  222.   delta = 256;
  223. begin
  224.   outSize := ((inSize + (inSize div 10) + 12) + 255) and not 255;
  225.   GetMem(outBuffer,outSize);
  226.  
  227.   try
  228.     try
  229.       zstream.next_in := inBuffer;
  230.       zstream.avail_in := inSize;
  231.       zstream.next_out := outBuffer;
  232.       zstream.avail_out := outSize;
  233.  
  234.       while ZCompressCheck(deflate(zstream,Z_FINISH)) <> Z_STREAM_END do
  235.       begin
  236.         Inc(outSize,delta);
  237.         ReallocMem(outBuffer,outSize);
  238.  
  239.         zstream.next_out := PByte(Integer(outBuffer) + zstream.total_out);
  240.         zstream.avail_out := delta;
  241.       end;
  242.     finally
  243.       ZCompressCheck(deflateEnd(zstream));
  244.     end;
  245.  
  246.     ReallocMem(outBuffer,zstream.total_out);
  247.     outSize := zstream.total_out;
  248.   except
  249.     FreeMem(outBuffer);
  250.     raise;
  251.   end;
  252. end;
  253.  
  254.  
  255. procedure ZCompress2(const inBuffer: Pointer; inSize: Integer;
  256.   out outBuffer: Pointer; out outSize: Integer; level: TZCompressionLevel;
  257.   windowBits, memLevel: Integer; strategy: TZStrategy);
  258. var
  259.   zstream: TZStreamRec;
  260. begin
  261.   FillChar(zstream,SizeOf(TZStreamRec),0);
  262.  
  263.   ZCompressCheck(DeflateInit2(zstream,ZLevels[level],Z_DEFLATED,windowBits,
  264.     memLevel,ZStrategies[strategy]));
  265.  
  266.   ZInternalCompress(zstream,inBuffer,inSize,outBuffer,outSize);
  267. end;
  268.  
  269.  
  270.  
  271. function ZCompressStr2(const s: String; level: TZCompressionLevel;
  272.   windowBits, memLevel: Integer; strategy: TZStrategy): String;
  273. var
  274.   buffer: Pointer;
  275.   size  : Integer;
  276. begin
  277.   ZCompress2(PChar(s),Length(s),buffer,size,level,windowBits,memLevel,
  278.     strategy);
  279.  
  280.   SetLength(result,size);
  281.   Move(buffer^,result[1],size);
  282.  
  283.   FreeMem(buffer);
  284. end;
  285.  
  286. {** string routines *********************************************************}
  287. function ZCrc32(crc: Longint; const buffer; size: Integer): Longint;
  288. begin
  289.   result := crc32(crc,@buffer,size);
  290. end;
  291.  
  292. function GZCompressStr(const s: String; const fileName, comment: String;
  293.   dateTime: TDateTime): String;
  294. var
  295.   header : PGZHeader;
  296.   trailer: PGZTrailer;
  297.   len    : Integer;
  298. begin
  299.   SetLength(result,SizeOf(TGZHeader));
  300.  
  301.   header := PGZHeader(@result[1]);
  302.  
  303.   FillChar(header^,SizeOf(TGZHeader),0);
  304.  
  305.   header^.Id1 := $1F;
  306.   header^.Id2 := $8B;
  307.   header^.Method := Z_DEFLATED;
  308.  
  309.   if dateTime <> 0 then header^.Time := DateTimeToUnix(dateTime);
  310.  
  311.   header^.ExtraFlags := GZ_EXTRA_DEFAULT;
  312.   header^.OS := 0;
  313.  
  314.   // build all flags first so "result" address doesn't change
  315.  
  316.   header^.Flags := 0;
  317.  
  318.   if Length(fileName) > 0 then
  319.   begin
  320.     header^.Flags := header^.Flags or GZ_FILENAME;
  321.   end;
  322.  
  323.   if Length(comment) > 0 then
  324.   begin
  325.     header^.Flags := header^.Flags or GZ_COMMENT;
  326.   end;
  327.  
  328.   // continue with content
  329.  
  330.   if Length(fileName) > 0 then
  331.   begin
  332.     result := result + fileName + #$00;
  333.   end;
  334.  
  335.   if Length(comment) > 0 then
  336.   begin
  337.     result := result + comment + #$00;
  338.   end;
  339.  
  340.   result := result + ZCompressStr2(s,zcDefault,-15,6,zsDefault);
  341.  
  342.   len := Length(result);
  343.  
  344.   SetLength(result,len + SizeOf(TGZTrailer));
  345.  
  346.   trailer := PGZTrailer(@result[len + 1]);
  347.  
  348.   FillChar(trailer^,SizeOf(TGZTrailer),0);
  349.  
  350.   trailer^.Crc := ZCrc32(0,s[1],Length(s));
  351.   trailer^.Size := Length(s);
  352. end;
  353.  
  354. function GZCompressStr(const s: String): String;
  355. begin
  356.   result := GZCompressStr(s,'','',0);
  357. end;
  358.  
  359. function ZDecompressCheck(code: Integer): Integer;
  360. begin
  361.   Result := code;
  362.  
  363.   if code < 0 then
  364.   begin
  365.     raise EZDecompressionError.Create(IntToStr(code));
  366.   end;
  367. end;
  368.  
  369. procedure ZInternalDecompress(zstream: TZStreamRec; const inBuffer: Pointer;
  370.   inSize: Integer; out outBuffer: Pointer; out outSize: Integer;
  371.   outEstimate: Integer);
  372. var
  373.   delta: Integer;
  374. begin
  375.   delta := (inSize + 255) and not 255;
  376.  
  377.   if outEstimate = 0 then outSize := delta
  378.   else outSize := outEstimate;
  379.  
  380.   GetMem(outBuffer,outSize);
  381.  
  382.   try
  383.     try
  384.       zstream.next_in := inBuffer;
  385.       zstream.avail_in := inSize;
  386.       zstream.next_out := outBuffer;
  387.       zstream.avail_out := outSize;
  388.  
  389.       while ZDecompressCheck(inflate(zstream,Z_NO_FLUSH)) <> Z_STREAM_END do
  390.       begin
  391.         Inc(outSize,delta);
  392.         ReallocMem(outBuffer,outSize);
  393.  
  394.         zstream.next_out := pByte(Integer(outBuffer) + zstream.total_out);
  395.         zstream.avail_out := delta;
  396.       end;
  397.     finally
  398.       ZDecompressCheck(inflateEnd(zstream));
  399.     end;
  400.  
  401.     ReallocMem(outBuffer,zstream.total_out);
  402.     outSize := zstream.total_out;
  403.   except
  404.     FreeMem(outBuffer);
  405.     raise;
  406.   end;
  407. end;
  408.  
  409.  
  410.  
  411. procedure ZDecompress2(const inBuffer: Pointer; inSize: Integer;
  412.   out outBuffer: Pointer; out outSize: Integer; windowBits: Integer;
  413.   outEstimate: Integer);
  414. var
  415.   zstream: TZStreamRec;
  416. begin
  417.   FillChar(zstream,SizeOf(TZStreamRec),0);
  418.  
  419.   ZDecompressCheck(InflateInit2(zstream,windowBits));
  420.  
  421.   ZInternalDecompress(zstream,inBuffer,inSize,outBuffer,outSize,outEstimate);
  422. end;
  423.  
  424. function ZDecompressStr2(const s: String; windowBits: Integer): String;
  425. var
  426.   buffer: Pointer;
  427.   size  : Integer;
  428. begin
  429.   ZDecompress2(PChar(s),Length(s),buffer,size,windowBits,0);
  430.  
  431.   SetLength(result,size);
  432.   Move(buffer^,result[1],size);
  433.  
  434.   FreeMem(buffer);
  435. end;
  436.  
  437.  
  438.  
  439. function GZDecompressStr(const s: String; var fileName, comment: String;
  440.   var dateTime: TDateTime): String;
  441. var
  442.   header  : PGZHeader;
  443.   trailer : PGZTrailer;
  444.   index   : Integer;
  445.   maxIndex: Integer;
  446.   endIndex: Integer;
  447.   size    : Integer;
  448. begin
  449.   result := '';
  450.  
  451.   if Length(s) < SizeOf(TGZHeader) then
  452.   begin
  453.     raise EZDecompressionError.Create('zeDataError');
  454.   end;
  455.  
  456.   header := PGZHeader(@s[1]);
  457.  
  458.   if (header^.Id1 <> $1F)
  459.     or (header^.Id2 <> $8B)
  460.     or (header^.Method <> Z_DEFLATED)
  461.     or ((header^.Flags and GZ_RESERVED) <> 0) then
  462.   begin
  463.     raise EZDecompressionError.Create('zeDataError');
  464.   end;
  465.  
  466.   if header^.Time <> 0 then dateTime := UnixToDateTime(header^.Time)
  467.   else dateTime := 0;
  468.  
  469.   maxIndex := Length(s) - SizeOf(TGZTrailer);
  470.  
  471.   index := SizeOf(TGZHeader) + 1;
  472.  
  473.   if (header^.Flags and GZ_EXTRA_FIELD) <> 0 then
  474.   begin
  475.     if index <= (maxIndex - 1) then
  476.     begin
  477.       size := PWord(@s[index])^;
  478.  
  479.       Inc(index,2);
  480.  
  481.       if (size >= 0) and ((index + size) <= maxIndex) then Inc(index,size)
  482.       else index := maxIndex + 1;
  483.     end
  484.     else index := maxIndex + 1;
  485.   end;
  486.  
  487.   if (header^.Flags and GZ_FILENAME) <> 0 then
  488.   begin
  489.     endIndex := index;
  490.  
  491.     while (endIndex <= maxIndex) and (s[endIndex] <> #$00) do Inc(endIndex);
  492.  
  493.     SetLength(fileName,endIndex - index);
  494.     Move(s[index],fileName[1],endIndex - index);
  495.  
  496.     index := endIndex;
  497.  
  498.     if index <= maxIndex then Inc(index);
  499.   end
  500.   else fileName := '';
  501.  
  502.   if (header^.Flags and GZ_COMMENT) <> 0 then
  503.   begin
  504.     endIndex := index;
  505.  
  506.     while (endIndex <= maxIndex) and (s[endIndex] <> #$00) do Inc(endIndex);
  507.  
  508.     SetLength(comment,endIndex - index);
  509.     Move(s[index],comment[1],endIndex - index);
  510.  
  511.     index := endIndex;
  512.  
  513.     if index <= maxIndex then Inc(index);
  514.   end
  515.   else comment := '';
  516.  
  517.   if (header^.Flags and GZ_HEADER_CRC) <> 0 then
  518.   begin
  519.     if index <= (maxIndex - 1) then
  520.     begin
  521.       // todo: validate header crc
  522.  
  523.       Inc(index,2);
  524.     end
  525.     else index := maxIndex + 1; // force eof
  526.   end;
  527.  
  528.   if index > maxIndex then
  529.   begin
  530.     raise EZDecompressionError.Create('zeDataError');
  531.   end;
  532.  
  533.   size := maxIndex - index + 1;
  534.  
  535.   result := ZDecompressStr2(Copy(s,index,size),-15);
  536.  
  537.   Inc(index,size);
  538.  
  539.   trailer := PGZTrailer(@s[index]);
  540.  
  541.   if (trailer^.Crc <> Cardinal(ZCrc32(0,result[1],Length(result))))
  542.     or (trailer^.Size <> Cardinal(Length(result))) then
  543.   begin
  544.     raise EZDecompressionError.Create('zeDataError');
  545.   end;
  546. end;
  547.  
  548. function GZDecompressStr(const s: String): String;
  549. var
  550.   fileName: String;
  551.   comment : String;
  552.   dateTime: TDateTime;
  553. begin
  554.   result := GZDecompressStr(s,fileName,comment,dateTime);
  555. end;
  556.  
  557. {** stream routines *********************************************************}
  558. procedure ZInternalCompressStream(zstream: TZStreamRec; inStream,
  559.   outStream: TStream);
  560. const
  561.   bufferSize = 32768;
  562. var
  563.   zresult  : Integer;
  564.   inBuffer : Array [0..bufferSize-1] of Char;
  565.   outBuffer: Array [0..bufferSize-1] of Char;
  566.   outSize  : Integer;
  567. begin
  568.   zresult := Z_STREAM_END;
  569.  
  570.   zstream.avail_in := inStream.Read(inBuffer,bufferSize);
  571.  
  572.   while zstream.avail_in > 0 do
  573.   begin
  574.     zstream.next_in := @inBuffer;
  575.  
  576.     repeat
  577.       zstream.next_out := @outBuffer;
  578.       zstream.avail_out := bufferSize;
  579.  
  580.       zresult := ZCompressCheck(deflate(zstream,Z_NO_FLUSH));
  581.  
  582.       outSize := bufferSize - zstream.avail_out;
  583.  
  584.       outStream.Write(outBuffer,outSize);
  585.     until (zresult = Z_STREAM_END) or (zstream.avail_in = 0);
  586.  
  587.     zstream.avail_in := inStream.Read(inBuffer,bufferSize);
  588.   end;
  589.  
  590.   while zresult <> Z_STREAM_END do
  591.   begin
  592.     zstream.next_out := @outBuffer;
  593.     zstream.avail_out := bufferSize;
  594.  
  595.     zresult := ZCompressCheck(deflate(zstream,Z_FINISH));
  596.  
  597.     outSize := bufferSize - zstream.avail_out;
  598.  
  599.     outStream.Write(outBuffer,outSize);
  600.   end;
  601.  
  602.   ZCompressCheck(deflateEnd(zstream));
  603. end;
  604.  
  605. procedure ZCompressStream2(inStream, outStream: TStream;
  606.   level: TZCompressionLevel; windowBits, memLevel: Integer;
  607.   strategy: TZStrategy);
  608. var
  609.   zstream: TZStreamRec;
  610. begin
  611.   FillChar(zstream,SizeOf(TZStreamRec),0);
  612.  
  613.   ZCompressCheck(DeflateInit2(zstream,ZLevels[level],Z_DEFLATED,windowBits,
  614.     memLevel,ZStrategies[strategy]));
  615.  
  616.   ZInternalCompressStream(zstream,inStream,outStream);
  617. end;
  618.  
  619.  
  620. procedure GZCompressStream(inStream, outStream: TStream; const fileName,
  621.   comment: String; dateTime: TDateTime);
  622. const
  623.   bufferSize = 32768;
  624. var
  625.   header    : TGZHeader;
  626.   trailer   : TGZTrailer;
  627.   buffer    : Array [0..bufferSize-1] of Char;
  628.   count     : Integer;
  629.   position  : {$ifdef Version6Plus} Int64 {$else} Longint {$endif};
  630.   nullString: String;
  631. begin
  632.   FillChar(header,SizeOf(TGZHeader),0);
  633.  
  634.   header.Id1 := $1F;
  635.   header.Id2 := $8B;
  636.   header.Method := Z_DEFLATED;
  637.  
  638.   if dateTime <> 0 then header.Time := DateTimeToUnix(dateTime);
  639.  
  640.   header.ExtraFlags := GZ_EXTRA_DEFAULT;
  641.   header.OS := 0;
  642.  
  643.   header.Flags := 0;
  644.  
  645.   if Length(fileName) > 0 then header.Flags := header.Flags or GZ_FILENAME;
  646.   if Length(comment) > 0 then header.Flags := header.Flags or GZ_COMMENT;
  647.  
  648.   FillChar(trailer,SizeOf(TGZTrailer),0);
  649.  
  650.   trailer.Crc := 0;
  651.  
  652.   position := inStream.Position;
  653.  
  654.   while inStream.Position < inStream.Size do
  655.   begin
  656.     count := inStream.Read(buffer[0],bufferSize);
  657.  
  658.     trailer.Crc := ZCrc32(trailer.Crc,buffer[0],count);
  659.   end;
  660.  
  661.   inStream.Position := position;
  662.  
  663.   trailer.Size := inStream.Size - inStream.Position;
  664.  
  665.   outStream.Write(header,SizeOf(TGZHeader));
  666.  
  667.   if Length(filename) > 0 then
  668.   begin
  669.     nullString := fileName + #$00;
  670.  
  671.     outStream.Write(nullString[1],Length(nullString));
  672.   end;
  673.  
  674.   if Length(comment) > 0 then
  675.   begin
  676.     nullString := comment + #$00;
  677.  
  678.     outStream.Write(nullString[1],Length(nullString));
  679.   end;
  680.  
  681.   ZCompressStream2(inStream,outStream,zcDefault,-15,6,zsDefault);
  682.  
  683.   outStream.Write(trailer,SizeOf(TGZTrailer));
  684. end;
  685.  
  686. procedure GZCompressStream(inStream, outStream: TStream);
  687. begin
  688.   GZCompressStream(inStream,outStream,'','',0);
  689. end;
  690.  
  691.  
  692. procedure ZInternalDecompressStream(zstream: TZStreamRec; inStream,
  693.   outStream: TStream);
  694. const
  695.   bufferSize = 32768;
  696. var
  697.   zresult  : Integer;
  698.   inBuffer : Array [0..bufferSize-1] of Char;
  699.   outBuffer: Array [0..bufferSize-1] of Char;
  700.   outSize  : Integer;
  701. begin
  702.   zresult := Z_STREAM_END;
  703.  
  704.   zstream.avail_in := inStream.Read(inBuffer,bufferSize);
  705.  
  706.   while zstream.avail_in > 0 do
  707.   begin
  708.     zstream.next_in := @inBuffer;
  709.  
  710.     repeat
  711.       zstream.next_out := @outBuffer;
  712.       zstream.avail_out := bufferSize;
  713.  
  714.       zresult := ZDecompressCheck(inflate(zstream,Z_NO_FLUSH));
  715.  
  716.       outSize := bufferSize - zstream.avail_out;
  717.  
  718.       outStream.Write(outBuffer,outSize);
  719.     until (zresult = Z_STREAM_END) or (zstream.avail_in = 0);
  720.  
  721.     if zresult <> Z_STREAM_END then
  722.     begin
  723.       zstream.avail_in := inStream.Read(inBuffer,bufferSize);
  724.     end
  725.     else if zstream.avail_in > 0 then
  726.     begin
  727.       inStream.Position := inStream.Position - zstream.avail_in;
  728.       zstream.avail_in := 0;
  729.     end;
  730.   end;
  731.  
  732.   while zresult <> Z_STREAM_END do
  733.   begin
  734.     zstream.next_out := @outBuffer;
  735.     zstream.avail_out := bufferSize;
  736.  
  737.     zresult := ZDecompressCheck(inflate(zstream,Z_FINISH));
  738.  
  739.     outSize := bufferSize - zstream.avail_out;
  740.  
  741.     outStream.Write(outBuffer,outSize);
  742.   end;
  743.  
  744.   ZDecompressCheck(inflateEnd(zstream));
  745. end;
  746.  
  747.  
  748.  
  749. procedure ZDecompressStream2(inStream, outStream: TStream;
  750.   windowBits: Integer);
  751. var
  752.   zstream: TZStreamRec;
  753. begin
  754.   FillChar(zstream,SizeOf(TZStreamRec),0);
  755.  
  756.   ZDecompressCheck(InflateInit2(zstream,windowBits));
  757.  
  758.   ZInternalDecompressStream(zstream,inStream,outStream);
  759. end;
  760.  
  761.  
  762. procedure GZDecompressStream(inStream, outStream: TStream; var fileName,
  763.   comment: String; var dateTime: TDateTime);
  764. const
  765.   bufferSize = 32768;
  766. var
  767.   header  : TGZHeader;
  768.   trailer : TGZTrailer;
  769.   buffer  : Array [0..bufferSize-1] of Char;
  770.   count   : Integer;
  771.   position: {$ifdef Version6Plus} Int64 {$else} Longint {$endif};
  772.   size    : Integer;
  773.   crc     : Cardinal;
  774.   c       : Char;
  775. begin
  776.   if inStream.Read(header,SizeOf(TGZHeader)) <> SizeOf(TGZHeader) then
  777.   begin
  778.     raise EZDecompressionError.Create('zeDataError');
  779.   end;
  780.  
  781.   if (header.Id1 <> $1F)
  782.     or (header.Id2 <> $8B)
  783.     or (header.Method <> Z_DEFLATED)
  784.     or ((header.Flags and GZ_RESERVED) <> 0) then
  785.   begin
  786.     raise EZDecompressionError.Create('zeDataError');
  787.   end;
  788.  
  789.   if header.Time <> 0 then dateTime := UnixToDateTime(header.Time)
  790.   else dateTime := 0;
  791.  
  792.   if (header.Flags and GZ_EXTRA_FIELD) <> 0 then
  793.   begin
  794.     if inStream.Read(size,SizeOf(Word)) <> SizeOf(Word) then
  795.     begin
  796.       raise EZDecompressionError.Create('zeDataError');
  797.     end;
  798.  
  799.     inStream.Position := inStream.Position + size;
  800.   end;
  801.  
  802.   fileName := '';
  803.  
  804.   if (header.Flags and GZ_FILENAME) <> 0 then
  805.   begin
  806.     c := ' ';
  807.  
  808.     while (inStream.Position < inStream.Size) and (c <> #$00) do
  809.     begin
  810.       inStream.Read(c,1);
  811.  
  812.       if c <> #$00 then fileName := fileName + c;
  813.     end;
  814.   end;
  815.  
  816.   comment := '';
  817.  
  818.   if (header.Flags and GZ_COMMENT) <> 0 then
  819.   begin
  820.     c := ' ';
  821.  
  822.     while (inStream.Position < inStream.Size) and (c <> #$00) do
  823.     begin
  824.       inStream.Read(c,1);
  825.  
  826.       if c <> #$00 then comment := comment + c;
  827.     end;
  828.   end;
  829.  
  830.   if (header.Flags and GZ_HEADER_CRC) <> 0 then
  831.   begin
  832.     // todo: validate header crc
  833.  
  834.     inStream.Position := inStream.Position + SizeOf(Word);
  835.   end;
  836.  
  837.   if inStream.Position >= inStream.Size then
  838.   begin
  839.     raise EZDecompressionError.Create('zeDataError');
  840.   end;
  841.  
  842.   position := outStream.Position;
  843.  
  844.   ZDecompressStream2(inStream,outStream,-15);
  845.  
  846.   if inStream.Read(trailer,SizeOf(TGZTrailer)) <> SizeOf(TGZTrailer) then
  847.   begin
  848.     raise EZDecompressionError.Create('zeDataError');
  849.   end;
  850.  
  851.   outStream.Position := position;
  852.  
  853.   crc := 0;
  854.  
  855.   while outStream.Position < outStream.Size do
  856.   begin
  857.     count := outStream.Read(buffer[0],bufferSize);
  858.  
  859.     crc := ZCrc32(crc,buffer[0],count);
  860.   end;
  861.  
  862.   if (trailer.Crc <> crc)
  863.     or (trailer.Size <> Cardinal(outStream.Size - position)) then
  864.   begin
  865.     raise EZDecompressionError.Create('zeDataError');
  866.   end;
  867. end;
  868.  
  869. procedure GZDecompressStream(inStream, outStream: TStream);
  870. var
  871.   fileName: String;
  872.   comment : String;
  873.   dateTime: TDateTime;
  874. begin
  875.   GZDecompressStream(inStream,outStream,fileName,comment,dateTime);
  876. end;
  877.  
  878. {** deprecated routines *****************************************************}
  879.  
  880. function ZCompressStrG(const s: String; const fileName, comment: String;
  881.   dateTime: TDateTime): String;
  882. begin
  883.   result := GZCompressStr(s,fileName,comment,dateTime);
  884. end;
  885.  
  886. function ZCompressStrG(const s: String): String;
  887. begin
  888.   result := GZCompressStr(s);
  889. end;
  890.  
  891. function ZDecompressStrG(const s: String; var fileName, comment: String;
  892.   var dateTime: TDateTime): String;
  893. begin
  894.   result := GZDecompressStr(s,fileName,comment,dateTime);
  895. end;
  896.  
  897. function ZDecompressStrG(const s: String): String;
  898. begin
  899.   result := GZDecompressStr(s);
  900. end;
  901.  
  902. procedure ZCompressStreamG(inStream, outStream: TStream; const fileName,
  903.   comment: String; dateTime: TDateTime);
  904. begin
  905.   GZCompressStream(inStream,outStream,fileName,comment,dateTime);
  906. end;
  907.  
  908. procedure ZCompressStreamG(inStream, outStream: TStream);
  909. begin
  910.   GZCompressStream(inStream,outStream);
  911. end;
  912.  
  913. procedure ZDecompressStreamG(inStream, outStream: TStream; var fileName,
  914.   comment: String; var dateTime: TDateTime);
  915. begin
  916.   GZDecompressStream(inStream,outStream,fileName,comment,dateTime);
  917. end;
  918.  
  919. procedure ZDecompressStreamG(inStream, outStream: TStream);
  920. begin
  921.   GZDecompressStream(inStream,outStream);
  922. end;
  923.  
  924. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement