phpphp-ziparchive

Php, ZipArchive deletes an empty file?


here is a little code I wrote:

file_put_contents('a.upl', '');
try
{
    $x = new \ZipArchive();
    $x->open('a.upl');
}
catch(\Exception $e)
{
    echo $e->getMessage();
}

it throws a ZipArchive::open(): Using empty file as ZipArchive is deprecated message, which is not surprising. What suprising is, this a.upl file gets deleted, which is a little bit strange. Why does it do that? And how to prevent this "x-files, magic"?


Solution

  • Did some poking around in the source, sequence of events is this:

    PHP sees the file you gave is empty, the latest version of libzip doesn't allow this, so in preparation for this BC break, PHP sets the ZIP_TRUNCATE flag when calling libzip's zip_open

    https://github.com/php/php-src/blob/master/ext/zip/php_zip.c#L1500

    libzip, on receiving this flag, creates a new zip object in memory, linked to this file as the source.

    When you then add no files to this and the script exits, libzip calls zip_close, and because the ZIP_TRUNCATE flag is set and there are no entries in the zip, the source file is removed.

    https://github.com/nih-at/libzip/blob/cf7bf43ba2f85f936705231903aa0d5cfb2fdf11/lib/zip_close.c#L68

    You can avoid the x files magic by setting this global flag: https://www.php.net/manual/en/zip.constants.php#ziparchive.constants.afl-create-or-keep-file-for-empty-archive (if your version of libzip is >=1.10)