0

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:

Using 7-Zip from Delphi?

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;
Community
  • 1
  • 1
spurgeon
  • 1,082
  • 11
  • 34

1 Answers1

3

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;
Zoë Peterson
  • 13,094
  • 2
  • 44
  • 64
  • Thanks, I have yet to try the JCL fork, but the `TJclCompressionItem` `Encrypted` property works. – spurgeon Feb 14 '14 at 21:45
  • Craig, finally was able to try out the fork--works for my test cases for password-protected archives where the filenames are encrypted. Thanks much. – spurgeon Feb 17 '14 at 16:22