Как в Lazarus узнать, запаролен ли ZIP/Rar архив?
Пытаюсь узнать запаролен ли конкретный архив или нет. Для этого пробовал использовать библиотеку paszlib, а именно TZipper. Но я не смог найти ни одного метода или свойства, который был возвращал признак наличия пароля у архива. Библиотека в целом очень скудна.
Потом я решил попробовать библиотеку FreePascalArchivePackage. Создал экземпляр TAbUnZipper. В нем есть три свойства: Password, PasswordRetries и OnNeedPassword. Первое устанавливает пароль для разархивирования, второе возвращает 3 байта, что они значат, не знаю, третье устанавливает событие.
Каким способом можно узнать в Lazarus (FPC) признак пароля на архиве?
Ответы (2 шт):
Подпишитесь на событие и попробуйте открыть архив. Если событие сработает, то архив запаролен.
Задачу решил с помощью 7zip. Немного пришлось схитрить, т.к. для Лазаруса нет Враппера. Зато он есть для Дельфи.
Сделал так:
- Нашел Враппер для Делфи (здесь есть подходящий: https://github.com/zedalaye/d7zip).
- Внутренним сервисом Лазаруса переконвертировал модуль Враппера для Лазаруса. 2.1 Добавил нужные пакеты по запросу компилятора. 2.2 В методе T7zOutArchive.AddFile необходимо отказаться от преобразования GetFileSize(Handle, nil); т.е. оставить, как есть.
- Положил в рабочую папку с проектом сам 7z.dll. 3.1 7z.dll должен иметь такую же битность, как и проект. Если проект 64-бита, 32-х битную DLL не загрузит, естественно.
После этого можно пользоваться библиотекой.
Наличие пароля я проверил на архиве посредством установки функции обратного вызова (CallBack function). Реализация выглядит так:
function ArchiveSearcher.isArchEncrypted(FileName: string; ClassId: TGUID): boolean;
begin
// CLSID_CFormatZip for ZIP
// CLSID_CFormatRar for Rar
result:= false;
with CreateInArchive(ClassId) do
begin
bArchEncrypted:=false;
SetPasswordCallback(nil, @PasswordCallback); // Установка обратной фун-ции
OpenFile(FileName); // Открытие файла архива
ExtractTo('', 1); // Тест архива
result := bArchEncrypted;
end;
end;
// Сама обратная функция
function PasswordCallback(sender: Pointer; var password: WideString): HRESULT; stdcall;
begin
//cout('Пароль нужен!');
bArchEncrypted := true;
password := 'password';
Result := S_OK;
end;