php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66445 ZipArchive doesn't set external file attributes
Submitted: 2014-01-08 21:00 UTC Modified: 2014-01-17 20:59 UTC
From: cmbecker69 at gmx dot de Assigned: ab (profile)
Status: Closed Package: Zip Related
PHP Version: 5.5.7 OS: Windows
Private report: No CVE-ID: None
 [2014-01-08 21:00 UTC] cmbecker69 at gmx dot de
Description:
------------
The ZipArchive class doesn't set the external file attributes,
what is a particular problem regarding directories which are 
displayed as files in Windows XP's explorer (works fine in Win 7,
though; can't tests other Windows versions).

According to the PKWARE Zip specification[1], section 4.4.15:

| The mapping of the external attributes is
| host-system dependent (see 'version made by').  For
| MS-DOS, the low order byte is the MS-DOS directory
| attribute byte.

The "version made by" field in the created ZIP file is 0, what 
signals MSDOS, but the low order byte of the "external file 
attributes" field is always 0 (should be 0x10 for directories). 

[1] <http://www.pkware.com/documents/casestudies/APPNOTE.TXT>

Test script:
---------------
$zip = new ZipArchive();
$zip->open('foo.zip', ZipArchive::CREATE);
$zip->addEmptyDir('bar');
$zip->close();


Expected result:
----------------
A ZIP file conforming to the PKWARE specification is created.

Actual result:
--------------
The created ZIP file doesn't conform to the PKWARE specification.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-01-10 07:42 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2014-01-10 07:42 UTC] ab@php.net
libzip is the one responsible for that.

Btw. how do you check that programmatically? Looks impossible, as one would need to reparse the whole file manually.
 [2014-01-10 12:14 UTC] cmbecker69 at gmx dot de
-Status: Feedback +Status: Open
 [2014-01-10 12:14 UTC] cmbecker69 at gmx dot de
For automated testing it might be sufficient to scan the zip file
for central file header signatures (section 4.3.12 of the PKWARE
specification) and inspect the first byte of the external file 
attributes.  Telling files and directories apart seems to be harder
in the general case.  Assuming there are no empty files in the 
archive, it would suffice to check for the (un)compressed size.
Alternatively, one might check the last character of the file name,
assuming all directory names are stored with a trailing slash.
 [2014-01-16 18:57 UTC] cmbecker69 at gmx dot de
-Status: Open +Status: Closed
 [2014-01-16 18:57 UTC] cmbecker69 at gmx dot de
I had a look at libzip.  Apparently, the respective member ext_attrib
of struct zip_dirent is always set to 0 (unless read from an already
existing archive).  This happens in _zip_dirent_init()[1] and a few
other places in the same file.

I have compared that with the latest release of libzip[2] (0.11.2),
and there the member is initialized to ZIP_EXT_ATTRIB_DEFAULT, which
doesn't set the low byte (neither does ZIP_EXT_ATTRIB_DEFAULT_DIR).
However, there is a new function zip_file_set_external_attributes()[3]
which might do so.

Then I noticed that libzip in the PHP 5.6 branch was updated.
Running the test script above showed that the "version made by" is
now 0x0314, what means UNIX.  This change was introduced in libzip
0.11.2.[4]  AFAICT this is conforming to the PKWARE specification,
but newly created archives have the same issues in Windows XP's
explorer---apparently, this is a bug in XP's explorer, so I closed
the bug report.

[1] <http://lxr.php.net/xref/PHP_5_5/ext/zip/lib/zip_dirent.c#184>
[2] <http://nih.at/libzip/index.html>
[3] <http://hg.nih.at/libzip/file/5e14f593fbdd/lib/zip_file_set_external_attributes.c>
[4] <http://hg.nih.at/libzip/rev/2cb9b3e21031>
 [2014-01-17 07:41 UTC] ab@php.net
-Assigned To: +Assigned To: ab
 [2014-01-17 07:41 UTC] ab@php.net
Hi, thanks for investing so much time in this. libzip 0.11.2 is the base also for the latest zip ext released on PECL. It could be used with PHP <= 5.6, too.
 [2014-01-17 07:44 UTC] ab@php.net
Ah, and check this commit https://github.com/pierrejoye/php_zip/commit/54a2044f2beab17de77446958fdb11d683f4e61a , external attributes can be now manipulated in PHP.
 [2014-01-17 20:59 UTC] cmbecker69 at gmx dot de
Thanks for the information.  Particularly being able to change the
external attributes from PHP is a welcome improvement.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 14:01:30 2024 UTC