0

I am trying to offer download of a whole directory from an apache using php I use the answer from this question Zip Stream in PHP

But when I compare (with cksum) the downloaded zip and the zip created with the same command from the command line the resuts are different.

Here is what I do from PHP :

<?php
$dir = "/path/to/myfolder";
$ficzip = basename($name) . ".zip";
header('Content-Transfer-Encoding: binary');
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . $ficzip. '"');
chdir( $dir );
$stream = popen( "/usr/bin/zip -qr -1 - .", "r" );
if( $stream )
{
    fpassthru( $stream );
    fclose( $stream );
}
?>

Here is what I do from the command line :

cd "/path/to/myfolder"
/usr/bin/zip -qr -1 - . > /tmp/myfolder.zip

I want both cksum are the same but they are not. What am I missing ? What to do so that they are the same ?

EDIT

Here is a diff between zipinfo for both files (on the left downloaded file and on the right command line file).

7,9c7,9
<   Zip archive file size:                 248145030 (000000000ECA6486h)
<   Actual end-cent-dir record offset:     248145008 (000000000ECA6470h)
<   Expected end-cent-dir record offset:   248145008 (000000000ECA6470h)
---
>   Zip archive file size:                 248144998 (000000000ECA6466h)
>   Actual end-cent-dir record offset:     248144976 (000000000ECA6450h)
>   Expected end-cent-dir record offset:   248144976 (000000000ECA6450h)
16c16
<   is 248144779 (000000000ECA638Bh).
---
>   is 248144747 (000000000ECA636Bh).
31c31
<   compression sub-type (deflation):               normal
---
>   compression sub-type (deflation):               fast
33c33
<   extended local header:                          yes
---
>   extended local header:                          no
59,60d58
<   There are an extra 16 bytes preceding this file.
< 
63,64c61,62
<   offset of local header from start of archive:   248143809
<                                                   (000000000ECA5FC1h) bytes
---
>   offset of local header from start of archive:   248143793
>                                                   (000000000ECA5FB1h) bytes
70c68
<   compression sub-type (deflation):               normal
---
>   compression sub-type (deflation):               fast
72c70
<   extended local header:                          yes
---
>   extended local header:                          no

EDIT2

replacing the -1 for fastest compression by -Z store for no compression reduces the differences, but still not OK.

7,9c7,9
<   Zip archive file size:                 249693306 (000000000EE2047Ah)
<   Actual end-cent-dir record offset:     249693284 (000000000EE20464h)
<   Expected end-cent-dir record offset:   249693284 (000000000EE20464h)
---
>   Zip archive file size:                 249693274 (000000000EE2045Ah)
>   Actual end-cent-dir record offset:     249693252 (000000000EE20444h)
>   Expected end-cent-dir record offset:   249693252 (000000000EE20444h)
16c16
<   is 249693055 (000000000EE2037Fh).
---
>   is 249693023 (000000000EE2035Fh).
32c32
<   extended local header:                          yes
---
>   extended local header:                          no
58,59d57
<   There are an extra 16 bytes preceding this file.
< 
62,63c60,61
<   offset of local header from start of archive:   249690256
<                                                   (000000000EE1F890h) bytes
---
>   offset of local header from start of archive:   249690240
>                                                   (000000000EE1F880h) bytes
70c68
<   extended local header:                          yes
---
>   extended local header:                          no

Solution

Here is the command I am using to get identical results. I keep the question opened so that someone can explain differences between popen and terminal execution of the command.

/usr/bin/zip -qr -0 -fd -fz- - .
Tuckbros
  • 417
  • 3
  • 13
  • Have you confirmed that you can even produce byte-identical archives if you run the command twice on the shell? It doesn't on my machine, at least not without the --no-extra option. – Peter Apr 21 '20 at 11:47
  • Yes they are, but I will try with the `--no-extra` ( `-X`) option maybe it will not set any local header. Tried but it didn't prevent the local header from being created from the php – Tuckbros Apr 21 '20 at 12:15
  • The `CRC32` fields from zipinfo are not showing in your diff output. That means the payload data stored in the zip files is identical. Looks like the two versions of `zip` are used . The `--no-extra` option should sort out the differences. – pmqs Apr 21 '20 at 12:36
  • the zip version are exactly the same as on my own private personal home computer hosting the apache, php and zip executable. The -X and -X- options have been used with no success. I also checked if any ZIPOPT environment variable were set, and there is none, from command line as well as from php – Tuckbros Apr 21 '20 at 12:42
  • Check the `ZIP` and `ZIP_OPT` environment variables as well. – pmqs Apr 21 '20 at 14:18
  • I did and they are not set anywhere. I also tried with preceding my command with `env -i` and there is still the difference. – Tuckbros Apr 21 '20 at 14:21
  • I could make it work by adding the `-fd` and `-fz-` options to the zip command. but I don't understand why the behavior changes from popen or from a terminal. – Tuckbros Apr 21 '20 at 14:55
  • Assume you tried prefixing with `zip -v` to check that the versions match? – pmqs Apr 21 '20 at 14:57
  • yes it does. It matches, and also same OS and so on. I am running the apache/php on my computer ("localhost") and also running the terminal on this same computer. `This is Zip 3.0 (July 5th 2008), by Info-ZIP.` – Tuckbros Apr 21 '20 at 15:05
  • Aaah, that's it. When you run zip with a pipe the program doesn't know the size of the input data, so it assumes the worst and creates a Zip64 archive. When you run it interactively it can check the fiesystem and only create a zip64 archive when needed. The `-fz-` option disables Zip64. – pmqs Apr 21 '20 at 15:06
  • I disagree, running zip from popen assume it can access the filesystem the same way as the terminal. it is a pity these options don't appear in the man page. – Tuckbros Apr 21 '20 at 15:24
  • popen isn't the problem. You have given zip the special filename "-" to get it to to read data from STDIN. Zip has no idea about where the input data came from. – pmqs Apr 21 '20 at 15:32
  • no, data are not read from stdin, data are in the . (dot) the - is for redirecting the result to stdout – Tuckbros Apr 21 '20 at 15:34
  • Sorry it is writing to stdout, not reading from it. Not clear why it would need to force Zip64 for one use-case and not the other – pmqs Apr 21 '20 at 15:56

0 Answers0