FIX: Cannot extract symbolic links from ZIP archives (fixes #1332)

(cherry picked from commit d5f3755e61)
This commit is contained in:
Alexander Koblov 2023-11-04 13:24:29 +03:00
commit d6a15d3d97
2 changed files with 41 additions and 15 deletions

View file

@ -162,6 +162,7 @@ uses
AbUtils,
AbZlibPrc,
AbWinZipAes,
DCOSUtils,
DCClassesUtf8;
{ -------------------------------------------------------------------------- }
@ -1191,8 +1192,9 @@ end;
procedure AbUnzip(Sender : TObject; Item : TAbZipItem; const UseName : string);
{create the output filestream and pass it to DoExtract}
var
InStream, OutStream : TStream;
LinkTarget : String;
ZipArchive : TAbZipArchive;
InStream, OutStream : TStream;
begin
ZipArchive := TAbZipArchive(Sender);
@ -1201,18 +1203,38 @@ begin
else begin
InStream := ExtractPrep(ZipArchive, Item);
try
OutStream := TFileStreamEx.Create(UseName, fmCreate or fmShareDenyWrite);
try
try {OutStream}
DoExtract(ZipArchive, Item, InStream, OutStream);
finally {OutStream}
OutStream.Free;
end; {OutStream}
except
if ExceptObject is EAbUserAbort then
ZipArchive.FStatus := asInvalid;
DeleteFile(UseName);
raise;
if FPS_ISLNK(Item.NativeFileAttributes) then
begin
OutStream := TMemoryStream.Create;
try
try {OutStream}
DoExtract(ZipArchive, Item, InStream, OutStream);
SetString(LinkTarget, TMemoryStream(OutStream).Memory, OutStream.Size);
finally {OutStream}
OutStream.Free;
end; {OutStream}
if not CreateSymLink(LinkTarget, UseName) then
RaiseLastOSError;
except
if ExceptObject is EAbUserAbort then
ZipArchive.FStatus := asInvalid;
raise;
end;
end
else begin
OutStream := TFileStreamEx.Create(UseName, fmCreate or fmShareDenyWrite);
try
try {OutStream}
DoExtract(ZipArchive, Item, InStream, OutStream);
finally {OutStream}
OutStream.Free;
end; {OutStream}
except
if ExceptObject is EAbUserAbort then
ZipArchive.FStatus := asInvalid;
DeleteFile(UseName);
raise;
end;
end;
finally
InStream.Free

View file

@ -1179,7 +1179,9 @@ begin
if (Attr and faReadOnly) = 0 then
Result := Result or AB_FPERMISSION_OWNERWRITE;
if (Attr and faDirectory) <> 0 then
if (Attr and faSymLink) <> 0 then
Result := Result or AB_FMODE_FILELINK or AB_FPERMISSION_OWNEREXECUTE
else if (Attr and faDirectory) <> 0 then
Result := Result or AB_FMODE_DIR or AB_FPERMISSION_OWNEREXECUTE
else
Result := Result or AB_FMODE_FILE;
@ -1199,10 +1201,12 @@ begin
AB_FMODE_DIR: { directory }
Result := Result or faDirectory;
AB_FMODE_FILELINK: { symlink}
Result := Result or faSymLink;
AB_FMODE_FIFO,
AB_FMODE_CHARSPECFILE,
AB_FMODE_BLOCKSPECFILE,
AB_FMODE_FILELINK,
AB_FMODE_SOCKET:
Result := Result or faSysFile;
end;