Can you detect whether an archive is password protected with JclCompression from the JEDI Code Library (JCL)? I want to extract various archives, but obviously I don't want to show a password prompt unless the archive requires a password. I can set a password correctly, just not detect whether an archive needs one. The following SO post shows how to set the password:
It's possible the option doesn't exist since there's a TODO in the procedure that appears to get archive properties such as ipEncrypted
(from JCL 2.5):
procedure TJclDecompressItem.CheckGetProperty(
AProperty: TJclCompressionItemProperty);
begin
// TODO
end;
If the items within the archive are encrypted but the filenames aren't, just call ListFiles and after it returns loop over the items and check their Encrypted
property. If any of them are true prompt the user for the password and assign it afterwards.
If the filenames are encrypted too then no, the stock JCL distribution doesn't support detecting that beforehand. I have a fork of the JCL on github, and the sevenzip_error_handling branch contains a bunch of enhancements/fixes to TJclCompressionArchive
, including the addition of an OnOpenPassword
callback that's called if the filenames are encrypted. With that, the basic load looks like this:
type
TMyObject = class
private
FArchive: TJcl7zDecompressArchive;
FEncryptedFilenames: Boolean;
procedure GetOpenPassword(Sender: TObject;
var APassword: WideString): Boolean;
public
procedure OpenArchive;
end;
...
procedure TMyObject.GetOpenPassword(Sender: TObject;
var APassword: WideString): Boolean;
var
Dlg: TPasswordDialog;
begin
Dlg := TPasswordDialog.Create(nil);
try
Result := Dlg.ShowModal = mrOk;
if Result then
begin
FEncryptedFilenames := True;
FArchive.Password := Dlg.Password;
end;
finally
Dlg.Free;
end;
end;
...
procedure TMyObject.OpenArchive;
begin
FArchive := TJcl7zUpdateArchive.Create(Filename);
FArchive.OnOpenPassword := GetOpenPassword;
while True do
begin
FEncryptedFilenames := False;
try
FArchive.ListFiles;
Break;
except
on E: EJclCompressionFalse do
if FEncryptedFilenames then
// User probably entered incorrect password, loop
else
raise;
end;
end;
end;