mORMot and Open Source friends
Check-in [bf4577eccf]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:fixed unexpected error when adding files e.g. via TZipWrite.CreateForm() to an empty archive - thanks Gigo for the feedback!
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bf4577eccfb3790ab4549257be180787afb2ef2c
User & Date: abouchez 2013-09-24 11:36:55
Context
2013-09-27
11:55
added some connection break error codes for Oracle check-in: 95d1e2b4a8 user: abouchez tags: trunk
2013-09-24
11:36
fixed unexpected error when adding files e.g. via TZipWrite.CreateForm() to an empty archive - thanks Gigo for the feedback! check-in: bf4577eccf user: abouchez tags: trunk
2013-09-20
12:57
introducing JavaScript execution using the SpiderMonkey library in mORMot framework! Thanks a lot Pavel for all this GREAT contribution! :) check-in: 744111d689 user: abouchez tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SynZip.pas.

26
27
28
29
30
31
32

33
34
35
36
37
38
39
...
127
128
129
130
131
132
133


134
135
136
137
138
139
140
...
625
626
627
628
629
630
631
632
633
634
635
636





637
638
639
640
641
642
643
...
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
...
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
...
991
992
993
994
995
996
997
998

999
1000
1001
1002







1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
  The Initial Developer of the Original Code is Arnaud Bouchez.

  Portions created by the Initial Developer are Copyright (C) 2013
  the Initial Developer. All Rights Reserved.

  Contributor(s):
   - jpdk


  Alternatively, the contents of this file may be used under the terms of
  either the GNU General Public License Version 2 or later (the "GPL"), or
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  in which case the provisions of the GPL or the LGPL are applicable instead
  of those above. If you wish to allow use of your version of this file only
  under the terms of either the GPL or the LGPL, and not to allow others to
................................................................................
     of in-memory compression (will handle huge files much efficiently, e.g.
     log files as for EventArchiveZip)

   Version 1.18
   - added TFileHeader.IsFolder and TLocalFileHeader.LocalData methods
   - fixed CompressDeflate() function, which was in fact creating zlib content
   - fixed TZipWrite.AddDeflated() to handle data > 200 MB - thanks jpdk!


   - addded CompressZLib() function, as expected by web browsers
   - unit fixed and tested with Delphi XE2/XE3 64-bit compiler

}

{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64

................................................................................
    /// release associated memory, and close destination file
    destructor Destroy; override;
  end;

/// a TSynLogArchiveEvent handler which will compress older .log files
// into .zip archive files
// - resulting file will be named YYYYMM.zip and will be located in the
// aDestinationPath directory, i.e. TSynLogFamily.ArchivePath+'\log\YYYYMM.zip' 
function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean;


implementation






{ TZipWrite }

var
  EventArchiveZipWrite: TZipWrite = nil;

function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean;
................................................................................
  fAppendOffset := length(Content);
  FileWrite(Handle,pointer(Content)^,fAppendOffset);
end;

constructor TZipWrite.Create(const aFileName: TFileName);
begin
  fFileName := aFileName;
  fMagic := $04034b50+1; // +1 to avoid finding it in the exe generated code
  dec(fMagic);
  if Handle=0 then
    Handle := FileCreate(aFileName);
end;

constructor TZipWrite.CreateFrom(const aFileName: TFileName);
var R: TZipRead;
................................................................................
end;

destructor TZipWrite.Destroy;
var lhr: TLastHeader;
    i: integer;
begin
  fillchar(lhr,sizeof(lhr),0);

  lhr.signature := $06054b50+1; dec(lhr.signature); // +1 to avoid finding it in the exe
  lhr.thisFiles := Count;
  lhr.totalFiles := Count;
  lhr.headerOffset := SetFilePointer(Handle,0,nil,FILE_CURRENT)-fAppendOffset;
  for i := 0 to Count-1 do
  with Entry[i] do begin
    assert(fhr.fileInfo.nameLen=length(intName));
    inc(lhr.headerSize,sizeof(TFileHeader)+fhr.fileInfo.nameLen);
................................................................................
    tmp: UTF8String;
    {$else}
    tmp: RawByteString;
    {$endif}
begin
  for i := 0 to 31 do begin // resources size may be rounded up to alignment
    lhr := @BufZip[Size-sizeof(TLastHeader)];
    if lhr^.signature+1=$06054b51 then
      break;
    dec(Size);
    if Size<=sizeof(lhr^) then
      break;
  end;
  if lhr^.signature+1<>$06054b51 then begin
    UnMap;
    raise Exception.Create('ZIP format');
    exit;
  end;
  SetLength(Entry,lhr^.totalFiles); // fill Entry[] with the Zip headers
  H := @BufZip[lhr^.headerOffset];
  ReadOffset := lhr^.headerOffset;
................................................................................
  if map=0 then begin
    Unmap;
    raise Exception.Create('Missing File');
    exit;
  end;
  Buf := MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
  ExeOffset := -1;
  for i := ZipStartOffset to Size-5 do

    if PCardinal(@buf[i])^+1=$04034b51 then begin // +1 to avoid finding it in the exe part
      ExeOffset := i;
      break;
    end;







  if ExeOffset<0 then begin
    Unmap;
    raise Exception.Create('No ZIP found');
    exit;
  end;
  Create(@Buf[ExeOffset],integer(Size)-ExeOffset);
end;

constructor TZipRead.Create(const aFileName: TFileName; ZipStartOffset, Size: cardinal);
begin






>







 







>
>







 







|




>
>
>
>
>







 







|







 







>
|







 







|





|







 







|
>
|



>
>
>
>
>
>
>


|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
...
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
....
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
  The Initial Developer of the Original Code is Arnaud Bouchez.

  Portions created by the Initial Developer are Copyright (C) 2013
  the Initial Developer. All Rights Reserved.

  Contributor(s):
   - jpdk
   - Gigo

  Alternatively, the contents of this file may be used under the terms of
  either the GNU General Public License Version 2 or later (the "GPL"), or
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  in which case the provisions of the GPL or the LGPL are applicable instead
  of those above. If you wish to allow use of your version of this file only
  under the terms of either the GPL or the LGPL, and not to allow others to
................................................................................
     of in-memory compression (will handle huge files much efficiently, e.g.
     log files as for EventArchiveZip)

   Version 1.18
   - added TFileHeader.IsFolder and TLocalFileHeader.LocalData methods
   - fixed CompressDeflate() function, which was in fact creating zlib content
   - fixed TZipWrite.AddDeflated() to handle data > 200 MB - thanks jpdk!
   - fixed unexpected error when adding files e.g. via TZipWrite.CreateForm()
     to an empty archive - thanks Gigo for the feedback!
   - addded CompressZLib() function, as expected by web browsers
   - unit fixed and tested with Delphi XE2/XE3 64-bit compiler

}

{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64

................................................................................
    /// release associated memory, and close destination file
    destructor Destroy; override;
  end;

/// a TSynLogArchiveEvent handler which will compress older .log files
// into .zip archive files
// - resulting file will be named YYYYMM.zip and will be located in the
// aDestinationPath directory, i.e. TSynLogFamily.ArchivePath+'\log\YYYYMM.zip'
function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean;


implementation

const
  FIRSTHEADER_SIGNATURE = $04034b50;  // PK#3#4
  LASTHEADER_SIGNATURE  = $06054b50;  // PK#5#6;


{ TZipWrite }

var
  EventArchiveZipWrite: TZipWrite = nil;

function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean;
................................................................................
  fAppendOffset := length(Content);
  FileWrite(Handle,pointer(Content)^,fAppendOffset);
end;

constructor TZipWrite.Create(const aFileName: TFileName);
begin
  fFileName := aFileName;
  fMagic := (FIRSTHEADER_SIGNATURE+1); // +1 to avoid finding it in the exe generated code
  dec(fMagic);
  if Handle=0 then
    Handle := FileCreate(aFileName);
end;

constructor TZipWrite.CreateFrom(const aFileName: TFileName);
var R: TZipRead;
................................................................................
end;

destructor TZipWrite.Destroy;
var lhr: TLastHeader;
    i: integer;
begin
  fillchar(lhr,sizeof(lhr),0);
  lhr.signature := LASTHEADER_SIGNATURE+1;
  dec(lhr.signature); // +1 to avoid finding it in the exe
  lhr.thisFiles := Count;
  lhr.totalFiles := Count;
  lhr.headerOffset := SetFilePointer(Handle,0,nil,FILE_CURRENT)-fAppendOffset;
  for i := 0 to Count-1 do
  with Entry[i] do begin
    assert(fhr.fileInfo.nameLen=length(intName));
    inc(lhr.headerSize,sizeof(TFileHeader)+fhr.fileInfo.nameLen);
................................................................................
    tmp: UTF8String;
    {$else}
    tmp: RawByteString;
    {$endif}
begin
  for i := 0 to 31 do begin // resources size may be rounded up to alignment
    lhr := @BufZip[Size-sizeof(TLastHeader)];
    if lhr^.signature+1=(LASTHEADER_SIGNATURE+1) then
      break;
    dec(Size);
    if Size<=sizeof(lhr^) then
      break;
  end;
  if lhr^.signature+1<>(LASTHEADER_SIGNATURE+1) then begin
    UnMap;
    raise Exception.Create('ZIP format');
    exit;
  end;
  SetLength(Entry,lhr^.totalFiles); // fill Entry[] with the Zip headers
  H := @BufZip[lhr^.headerOffset];
  ReadOffset := lhr^.headerOffset;
................................................................................
  if map=0 then begin
    Unmap;
    raise Exception.Create('Missing File');
    exit;
  end;
  Buf := MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
  ExeOffset := -1;
  for i := ZipStartOffset to Size-5 do // search for first local header
    if PCardinal(@buf[i])^+1=(FIRSTHEADER_SIGNATURE+1) then begin
      // +1 above to avoid finding it in the exe part
      ExeOffset := i;
      break;
    end;
  if ExeOffset<0 then // try if adding files to an empty archive
    for i := ZipStartOffset to Size-5 do
      if PCardinal(@buf[i])^+1=(LASTHEADER_SIGNATURE+1) then begin
        // +1 avoids false positive
        ExeOffset := i;
        break;
      end;
  if ExeOffset<0 then begin
    Unmap;
    raise Exception.Create('No ZIP header found');
    exit;
  end;
  Create(@Buf[ExeOffset],integer(Size)-ExeOffset);
end;

constructor TZipRead.Create(const aFileName: TFileName; ZipStartOffset, Size: cardinal);
begin