Oihana PHP

unzip.php

Table of Contents

Functions

unzip()  : true|array<string|int, string>
Extracts a zip archive into a destination directory.

Functions

unzip()

Extracts a zip archive into a destination directory.

unzip(string $zipFile, string $outputPath[, array{dryRun?: bool, overwrite?: bool, maxEntries?: int|null, maxSize?: int|null, keepPermissions?: bool, allowUnsafeLinks?: bool} $options = [] ]) : true|array<string|int, string>

This function mirrors untar(). It guards against path traversal (Zip Slip) and decompression bombs, can preview the contents without writing anything (dry run), and can refuse to overwrite existing files.

Symbolic links are restored as links. An entry whose stored Unix mode carries the link type bits — what zip() writes for every link it meets — is recreated with symlink() and its content read as the target. Such a target is refused when it is absolute or when it escapes the destination directory, since a link is the one entry whose content is itself a path and the Zip Slip guard on entry names does not cover it. The allowUnsafeLinks option lifts that refusal for an archive the caller answers for — a backup of a tree whose links were absolute on the disk it was taken from, which zip() stores faithfully and which could otherwise not be restored.

Parameters
$zipFile : string

Path to the zip archive to extract.

$outputPath : string

Directory where the archive is extracted. Created if missing.

$options : array{dryRun?: bool, overwrite?: bool, maxEntries?: int|null, maxSize?: int|null, keepPermissions?: bool, allowUnsafeLinks?: bool} = []

Optional flags, keyed by ZipOption:

  • dryRun: If true, no file is written; returns the list of file entries that would be extracted (directory entries excluded). Default: false.
  • overwrite: If false, extraction fails when a target file already exists. Default: true.
  • maxEntries: If a positive integer, the archive is rejected when it declares more entries than this limit (decompression-bomb guard). Default: null (no limit).
  • maxSize: If a positive integer, the archive is pre-scanned and rejected before any file is written when the sum of the entries' uncompressed sizes exceeds this limit (decompression-bomb guard). Default: null (no limit).
  • allowUnsafeLinks: If true, recreates a symbolic link whose target is absolute or escapes the destination directory, which is refused by default. Only for an archive the caller answers for: once such a link stands in the destination, the entries written after it can reach through it, outside. Default: false.
  • keepPermissions: If true, restores the Unix file mode stored in each entry's external attributes (OPSYS_UNIX) via chmod(). Entries without Unix permissions are left with the default mode, and a symbolic link is left alone, since chmod() would follow it and change the permissions of its target. Best-effort: a failing chmod() is ignored. Default: false.
Tags
throws
FileException

If the archive does not exist, cannot be opened, an entry escapes the destination (Zip Slip), an entry is a symbolic link whose target is absolute or escapes the destination while allowUnsafeLinks is off, an entry is a symbolic link without a target, a link cannot be created, a bomb guard trips, a target already exists while overwrite is disabled, an entry cannot be read or does not match its recorded checksum, or an extracted file cannot be written.

DirectoryException

If the destination directory (or an entry's parent) cannot be created.

example
// Basic extraction
unzip( '/path/to/archive.zip' , '/output/dir' );

// Dry-run: preview contents without extracting
$files = unzip( '/path/to/archive.zip' , '/output/dir' , [ 'dryRun' => true ] );

// Refuse to overwrite, and guard against decompression bombs
unzip( '/path/to/archive.zip' , '/output/dir' , [
    'overwrite'  => false,
    'maxEntries' => 10_000,
    'maxSize'    => 500 * 1024 * 1024,
]);
author

Marc Alcaraz (ekameleon)

since
1.2.0
Return values
true|array<string|int, string> —

Returns true on successful extraction, or the list of file entries (relative to the archive root) when dryRun is enabled.

On this page

Search results