⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kpunzipp.pas

📁 一个delphi中压缩的组件VCLZip
💻 PAS
📖 第 1 页 / 共 3 页
字号:
        {$IFNDEF KPSMALL}
         Application.ProcessMessages;
        {$ELSE}
         YieldProcess;
        {$ENDIF}
        If CancelOperation then
         begin
           CancelOperation := False;
           {$IFDEF NO_RES}
           raise EUserCanceled.Create('User Aborted Operation');
           {$ELSE}
           raise EUserCanceled.Create(LoadStr(IDS_CANCELOPERATION));
           {$ENDIF}
         end;
      end;
     number_to_read := kpmin( file_info.compressed_size, LongInt(INBUFSIZ) );
     file_info.compressed_size := file_info.compressed_size - number_to_read;
     number_read := zip_in_file.Read( outbuf^, number_to_read );
     incnt := number_read;
     If (((ecrec.this_disk = 0) or (not (Assigned(FOnGetNextDisk))))
        and (incnt < number_to_read)) then
           {$IFDEF NO_RES}
           raise EFatalUnzipError.Create('Premature end of file reached');
           {$ELSE}
           raise EFatalUnzipError.Create(LoadStr(IDS_PREMEND));
           {$ENDIF}
     tmpbuf := outbuf;
     While (incnt < number_to_read) do  {2/1/98 Changed If to While}
      begin
        zip_in_file := SwapDisk( CurrentDisk+2 );
        If zip_in_file = nil then  {2/1/98}
           {$IFDEF NO_RES}
           raise EUserCanceled.Create('User Aborted Operation');
           {$ELSE}
           raise EUserCanceled.Create(LoadStr(IDS_CANCELOPERATION));
           {$ENDIF}
        Inc(tmpbuf,number_read);
        number_read := zip_in_file.Read( tmpbuf^, number_to_read-incnt );
        Inc(incnt, number_read);
      end;

 {$IFDEF SKIPCODE}
     if file_info.Encrypted then         { added 11/2/97 }
     begin
           if (not assigned(FOnDecrypt)) then
              decrypt_buff( outbuf, outcnt )  {     KLB       }
           else
            begin
              FOnDecrypt( self, outbuf, outcnt, Password );
            end;
     end;
 {$ENDIF}
     {file_info.compressed_size := file_info.compressed_size - outcnt;}
     xFlushOutput;
     outcnt := kpmin( file_info.compressed_size, OUTBUFSIZ );
  end;
end;

procedure Skip_Rest;
{ skip past current compressed file to the next one }
begin
 {zip_in_file.Seek( file_info.compressed_size, soFromCurrent );} { Removed 4/22/98 2.11 }
  TotalUncompressedSize := TotalUncompressedSize - file_info.compressed_size;
  Dec(FileCount);
end;

procedure Do_Unzip( Index: Integer );
{ Unzips file[Index] }
var
 MsgArray: array [0..300] of char; {For 16 bit's sake}
 zip_out_file_name: String;
 CRCHighByte, DecryptCRCByte: BYTE;
  {CRCHighWord, DecryptCRCWord: WORD;}
 OverWriteIt: Boolean;
  Skip: Boolean;
 FullPath: String;
  FinishedOK: Boolean;
  FileHandle: Integer;
  InternalDir: String;
  NewPassword: String;
  AllocatedBuffer: Boolean;
  testDate: TDateTime;
  GoOn, FirstTime: Boolean;
  attrs: Integer;
  {$IFNDEF NO_RES}
  tmpMStr2: String;
  {$ENDIF}

  function GetFullPath: String;
  begin
    Result := '';
    if (RecreateDirs) and (file_info.directory <> '') then
     begin
        InternalDir := file_info.directory;
        If (RootDir <> '') and (AnsiCompareText(LeftStr(InternalDir,Length(RootDir)),RootDir) = 0) then
              Delete(InternalDir,1,Length(RootDir));
        { The directory in the zip file could be absolute }
        if (InternalDir <> '') and ((InternalDir[1] = '\') or (InternalDir[2] = ':')) then
         begin
           If DestDir = '' then
              Result := InternalDir
           Else
            begin
              If (InternalDir[1] = '\') then
                 Result := DestDir + InternalDir
              Else
                 Result := DestDir + RightStr( InternalDir, Length(InternalDir)-2);
            end;
         end
        else { otherwise just append it to the destination directory }
           Result := DestDir + '\' + InternalDir;
        {if (not DirExists( FullPath )) and (not FTestMode) then
           ForceDirs( FullPath );}  { Create dest directory if it doesn't exist }
     end
    Else
     Result := DestDir + '\';
  end;

begin
  FinishedOK := False;
  AllocatedBuffer := False;
  zip_out_file_name := '';
  Skip := False;
  RepeatFile := False;

  file_info.Assign(sortfiles.Items[Index] as TZipHeaderInfo);  { Make a copy }
  If (file_info.filename <> '') then   { must be a directory entry }
  begin
  If (ecrec.this_disk > 0) and (file_info.disk_number_start <> CurrentDisk) then
        zip_in_file := SwapDisk( file_info.disk_number_start+1 );
  zip_in_file.Seek( file_info.relative_offset, soFromBeginning );
  zip_in_file.Read( lrec, SizeOf(local_file_header) );
  zip_in_file.Seek( lrec.extra_field_length + lrec.filename_length, soFromCurrent );
  end;

  FullPath := GetFullPath;

  If file_info.filename = '' then   { it's just a directory entry }
  begin
     {If (RecreateDirs) and (Assigned( FOnStartUnZip )) then
     FOnStartUnZip( self, Index, FullPath, Skip );}
     { Added following 6/27/99 2.18+ }
     if (not StreamZipping) and (not MemZipping) and
        (RecreateDirs) and (not DirExists( FullPath )) then
        ForceDirs( FullPath );  { Create dest directory if it doesn't exist }
     Inc(NumUnZipped);
     exit;
  end;

  If (not StreamZipping) and (not MemZipping) then
   begin

{$IFDEF SKIPCODE}
    if (RecreateDirs) and (file_info.directory <> '') then
     begin
        InternalDir := file_info.directory;
        If (RootDir <> '') and (AnsiCompareText(LeftStr(InternalDir,Length(RootDir)),RootDir) = 0) then
              Delete(InternalDir,1,Length(RootDir));
        { The directory in the zip file could be absolute }
        if (InternalDir <> '') and ((InternalDir[1] = '\') or (InternalDir[2] = ':')) then
         begin
           If DestDir = '' then
              FullPath := InternalDir
           Else
            begin
              If (InternalDir[1] = '\') then
                 FullPath := DestDir + InternalDir
              Else
                 FullPath := DestDir + RightStr( InternalDir, Length(InternalDir)-2);
            end;
         end
        else { otherwise just append it to the destination directory }
           FullPath := DestDir + '\' + InternalDir;
        {if (not DirExists( FullPath )) and (not FTestMode) then
           ForceDirs( FullPath );}  { Create dest directory if it doesn't exist }
     end
    Else
     FullPath := DestDir + '\';
{$ENDIF}
    zip_out_file_name := FullPath + file_info.filename;
   end;

{ --------------------------------------------------------------------------------------------}
{ Moved to here, before opening the file and changed the filename parameter to VAR so that }
{ the destination of the file can be changed in the OnStartUnZip event. 03/20/99 2.17+     }
  If Assigned( FOnStartUnZip ) then
     FOnStartUnZip( self, Index, zip_out_file_name, Skip );
  If Skip then
     exit;

{ Moved to here since the path and filename might have been changed in the OnStartUnZip event }
{ 03/20/99  2.17+ }
  If (not StreamZipping) and (not MemZipping) and (not FTestMode) then
   begin
     FullPath := ExtractFileDir(zip_out_file_name);
     if (not DirExists( FullPath )) then
        ForceDirs( FullPath );  { Create dest directory if it doesn't exist }
   end;
{ --------------------------------------------------------------------------------------------}

 If (file_info.Encrypted) then
   begin
     NewPassword := Password;
     While NewPassword = Password do
     begin
        If file_info.HasDescriptor then
           CRCHighByte := HIBYTE(LOWORD( file_info.last_mod_file_date_time ))
        Else
           CRCHighByte := HIBYTE(HIWORD( file_info.crc32));
        DecryptCRCByte := DecryptTheHeader( Password, zip_in_file );
        if CRCHighByte <> DecryptCRCByte then
         begin
           NewPassword := Password;
           If Assigned( FOnBadPassword ) then
            begin
              FOnBadPassword( self, Index, NewPassword );
              If NewPassword <> Password then
               begin
                 Password := NewPassword;
                 zip_in_file.Seek(-SizeOf(DecryptHeaderType),soFromCurrent);
                 file_info.compressed_size := file_info.compressed_size + SizeOf(DecryptHeaderType);
                 Continue;
               end;
            end;
           If Assigned( FOnSkippingFile ) then
              FOnSkippingFile( self, srBadPassword, file_info.directory+file_info.filename, Index, Retry );
           Skip_Rest; {skip file}
           exit;
         end
        Else NewPassword := '';
     end;
   end;

 csize := file_info.compressed_size;
 ucsize := file_info.uncompressed_size;

  If (not StreamZipping) and (not MemZipping) then
   begin
	   If (FOverwriteMode <> Always) and (File_Exists(zip_out_file_name)) then
	    begin
		   If FOverwriteMode = Prompt then  { Allow application to determine if overwrite }
		    begin
			   If Assigned( FOnPromptForOverwrite ) then
			    begin
				   OverWriteIt := False;		{ Assume we skip just to be safe }
				   FOnPromptForOverwrite( self, OverWriteIt, Index, zip_out_file_name );
			    end
			   Else  { FOnPromptForOverwrite event not assigned so we have to ask user ourselves }
			    begin
              {$IFDEF NO_RES}
				   StrPCopy( MsgArray, 'Replace existing file ' + Filename[Index] + '?' );
				   OverWriteIt := MessageBox( 0, MsgArray, 'File Exists Alert', MB_YESNO) =  IDYES;
              {$ELSE}
				   StrPCopy( MsgArray, LoadStr(IDS_REPLACEFILE) + Filename[Index] + '?' );
              tmpMStr := LoadStr(IDS_FILEXISTALERT);
				   OverWriteIt := MessageBox( 0, MsgArray, StringAsPChar(tmpMStr), MB_YESNO) =  IDYES;
              {$ENDIF}
			    end;
			   If not OverWriteIt then
			    begin
				   If Assigned( FOnSkippingFile ) then
             	   FOnSkippingFile( self, srNoOverwrite, zip_out_file_name, Index, Retry );
				   Skip_Rest; {skip file}
        	   exit;
            end;
         end
        Else If (FOverwriteMode = Never) then { Never Overwrite }
         begin
           If Assigned( FOnSkippingFile ) then
        	   FOnSkippingFile( self, srNoOverwrite, zip_out_file_name, Index, Retry );
      	   Skip_Rest;  {skip file}
     	   exit;
         end
        Else  { ifNewer and ifOlder   8/2/98  2.14 }
         begin
           testDate := FileDateToDateTime(FileAge(zip_out_file_name));
           If (FOverwriteMode = ifNewer) then
            begin
              If (FileDateToDateTime( file_info.last_mod_file_date_time ) <= testDate) then
               begin
                 If Assigned( FOnSkippingFile ) then
        	         FOnSkippingFile( self, srNoOverwrite, zip_out_file_name, Index, Retry );
      	         Skip_Rest;  {skip file}
     	         exit;
              end;
            end
           Else
            begin
              If (FileDateToDateTime( file_info.last_mod_file_date_time ) >= testDate) then
               begin
                 If Assigned( FOnSkippingFile ) then
        	         FOnSkippingFile( self, srNoOverwrite, zip_out_file_name, Index, Retry );
      	         Skip_Rest;  {skip file}
     	         exit;
               end;
            end;
         end;
	    end;

     GoOn := False;
     FirstTime := True;
     Repeat    { Added ReplaceReadOnly 03/07/99  2.17+ }
        try
	         zip_out_file := TLFNFileStream.CreateFile( zip_out_file_name, fmCreate, FFlushFilesOnClose,
                                                      BufferedStreamSize );
           GoOn := True;
        except
           On EFCreateError do                            {ReadOnly will cause EFCreateError}
            begin
              If FReplaceReadOnly  and FirstTime then
               begin
                 FirstTime := False;                       { We'll only try this once }
                 attrs := FileGetAttr(zip_out_file_name);
                 if ((attrs and faReadOnly) > 0) then
                  begin
                    attrs := attrs and (not faReadOnly);   {Turn off ReadOnly bit}
                    FileSetAttr(zip_out_file_name, attrs)  {And reset the attributes}
                  end;
               end
              else
               begin                                       {Skip if we still can't open or we}
                 If Assigned( FOnSkippingFile ) then       {don't want to replace readonly   }
        	         FOnSkippingFile( self, srCreateError, zip_out_file_name, Index, Retry );
                 Skip_Rest;
                 exit;
               end;
            end;
           else
            begin
              If Assigned( FOnSkippingFile ) then       {can't create the file for some reason }
                 FOnSkippingFile( self, srCreateError, zip_out_file_name, Index, Retry );
              Skip_Rest;
              exit;
            end;
        end;
     Until GoOn;
   end { If not UnZippingToStream }
  Else
   begin
     If (StreamZipping) then
        zip_out_file := ZipStream  { UnZipping to a stream }
     Else
      begin   { UnZipping to memory buffer }
        AllocatedBuffer := False;
        If (MemBuffer = nil) then
         begin
           GetMem( MemBuffer, file_info.uncompressed_size);
           AllocatedBuffer := True;
         end;
        CurrMem := MemBuffer;
        MemLeft := file_info.uncompressed_size;
        MemLen :=  file_info.uncompressed_size;
      end;
   end;
try
try
  bits_left := 0;
  bitbuf := 0;
 outpos := 0;
 incnt := 0;
  outcnt := 0;
 inptr := inbuf;
 outptr := outbuf;
  Crc32Val := $FFFFFFFF;
 {CurrentDisk := 0;}

{  Skip := False;
  If Assigned( FOnStartUnZip ) then
     FOnStartUnZip( self, Index, zip_out_file_name, Skip );
  If Skip then
     exit;
}
  {Just incase they did something in an event that changed the filepointer} {4/9/99 2.18b4+}
  zip_in_file.Seek( file_info.relative_offset, soFromBeginning );
  zip_in_file.Seek( SizeOf(local_file_header) + lrec.extra_field_length +
                    lrec.filename_length, soFromCurrent );
  If (file_info.Encrypted) then
  zip_in_file.Seek( 12, soFromCurrent ); { If the file is encrypted }

  Case file_info.compression_method of
     STORED:  UnStore;
     DEFLATED:   Inflate;
{$IFNDEF INFLATE_ONLY}
     SHRUNK:     UnShrink;
     REDUCED1,
     REDUCED2,
     REDUCED3,
     REDUCED4:   UnReduce;
     IMPLODED:   Explode;
{$ENDIF}
  else
     if (not FTestMode) then
        {$IFDEF NO_RES}
        MessageBox( 0, 'Unknown Compression Method', 'Zip Error', mb_OK );
        {$ELSE}
        TmpMStr := LoadStr(IDS_UNKNOWNMETH);
        TmpMStr2 := LoadStr(IDS_ZIPERROR);
        MessageBox( 0, StringAsPChar(TmpMStr), StringAsPChar(TmpMStr2), mb_OK );
        {$ENDIF}
  end; { Case }
  FinishedOK := True;
except   { 4/16/98 2.11 }
  On EBiggerThanUncompressed do
     FinishedOK := False;  { Bad CRC should be called later }
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -