ADD: Zip - save password to cache (issue #1254)

This commit is contained in:
Alexander Koblov 2023-09-09 14:55:04 +03:00
commit 0115f01430
2 changed files with 151 additions and 3 deletions

View file

@ -0,0 +1,126 @@
unit ZipCache;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, SyncObjs, fpTimer;
type
{ TPasswordCache }
TPasswordCache = class
private
FTimer: TFPTimer;
FArchiveSize: Int64;
FArchiveName: String;
FArchiveTime: Integer;
FMutex: TCriticalSection;
FArchivePassword: String;
const FInterval: Cardinal = 120000;
private
procedure ResetTimer;
procedure ZeroPassword;
procedure TimerEvent(Sender: TObject);
public
constructor Create;
destructor Destroy; override;
function GetPassword(const Archive: String): String;
procedure SetPassword(const Archive: String; const Password: String);
end;
implementation
uses
LazFileUtils;
{ TPasswordCache }
procedure TPasswordCache.ResetTimer;
begin
if FTimer.Interval > FInterval then
FTimer.Interval:= FTimer.Interval - 1
else
FTimer.Interval:= FTimer.Interval + 1;
end;
procedure TPasswordCache.ZeroPassword;
begin
if (Length(FArchivePassword) > 0) then
begin
FillChar(FArchivePassword[1], Length(FArchivePassword), #0);
SetLength(FArchivePassword, 0);
end;
end;
procedure TPasswordCache.TimerEvent(Sender: TObject);
begin
FMutex.Acquire;
try
ZeroPassword;
FTimer.Enabled:= False;
finally
FMutex.Release;
end;
end;
function TPasswordCache.GetPassword(const Archive: String): String;
begin
FMutex.Acquire;
try
if (SameText(FArchiveName, Archive)) and
(FArchiveSize = FileSizeUtf8(Archive)) and
(FArchiveTime = FileAgeUtf8(Archive)) then
begin
ResetTimer;
Result:= FArchivePassword
end
else begin
FTimer.Enabled:= False;
Result:= EmptyStr;
ZeroPassword;
end;
finally
FMutex.Release;
end;
end;
procedure TPasswordCache.SetPassword(const Archive: String; const Password: String);
begin
FMutex.Acquire;
try
if (Length(Password) = 0) then
FArchiveName:= EmptyStr
else begin
FArchiveName:= Archive;
FArchivePassword:= Password;
FArchiveTime:= FileAgeUtf8(Archive);
FArchiveSize:= FileSizeUtf8(Archive);
FTimer.Enabled:= True;
ResetTimer;
end;
finally
FMutex.Release;
end;
end;
constructor TPasswordCache.Create;
begin
FTimer:= TFPTimer.Create(nil);
FTimer.UseTimerThread:= True;
FTimer.OnTimer:= @TimerEvent;
FTimer.Interval:= FInterval;
FMutex:= TCriticalSection.Create;
end;
destructor TPasswordCache.Destroy;
begin
FTimer.Free;
FMutex.Free;
inherited Destroy;
end;
end.

View file

@ -3,7 +3,7 @@
-------------------------------------------------------------------------
WCX plugin for working with *.zip, *.gz, *.tar, *.tgz archives
Copyright (C) 2007-2022 Alexander Koblov (alexx2000@mail.ru)
Copyright (C) 2007-2023 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -40,6 +40,7 @@ type
TAbZipKitEx = class (TAbZipKit)
private
FNeedPassword: Boolean;
FOperationResult: LongInt;
FChangeVolProcW: TChangeVolProcW;
FProcessDataProcW : TProcessDataProcW;
@ -88,7 +89,10 @@ implementation
uses
SysUtils, LazUTF8, ZipConfDlg, AbBrowse, DCConvertEncoding, DCOSUtils, ZipOpt,
ZipLng;
ZipLng, ZipCache;
var
PasswordCache: TPasswordCache;
threadvar
gProcessDataProcW : TProcessDataProcW;
@ -170,6 +174,7 @@ begin
Arc.TarAutoHandle := gTarAutoHandle;
Arc.OpenArchive(UTF16ToUTF8(UnicodeString(ArchiveData.ArcName)));
Arc.Password := PasswordCache.GetPassword(Arc.FileName);
Arc.Tag := 0;
Result := TArcHandle(Arc);
except
@ -243,6 +248,12 @@ begin
begin
Arc.TestItemAt(Arc.Tag);
if (Arc.FNeedPassword) and (Arc.FOperationResult = E_SUCCESS) and Arc.Items[Arc.Tag].IsEncrypted then
begin
Arc.FNeedPassword:= False;
PasswordCache.SetPassword(Arc.FileName, Arc.Password);
end;
// Show progress and ask if aborting.
if Assigned(Arc.FProcessDataProcW) then
begin
@ -263,6 +274,13 @@ begin
Arc.FOperationResult := E_SUCCESS;
Arc.ExtractAt(Arc.Tag, DestNameUtf8);
until (Arc.FOperationResult <> maxLongint);
if (Arc.FNeedPassword) and (Arc.FOperationResult = E_SUCCESS) and Arc.Items[Arc.Tag].IsEncrypted then
begin
Arc.FNeedPassword:= False;
PasswordCache.SetPassword(Arc.FileName, Arc.Password);
end;
// Show progress and ask if aborting.
if Assigned(Arc.FProcessDataProcW) then
begin
@ -511,6 +529,8 @@ begin
// Load configuration from ini file
LoadConfiguration;
TranslateResourceStrings;
// Create password cache object
PasswordCache:= TPasswordCache.Create;
end;
{ TAbZipKitEx }
@ -648,8 +668,10 @@ begin
Result:= gStartupInfo.InputBox('Zip', 'Please enter the password:', True, PAnsiChar(aNewPassword), MAX_PATH);
if Result then
NewPassword := aNewPassword
else
else begin
raise EAbUserAbort.Create;
end;
FNeedPassword:= True;
end;
end.