Zipdownload: various improvements to this plugin - #10260
Conversation
* Apache doesn't trust Content-Length headers by default; it will strip them and, only if length is known (on disk/all buffered), add it back * Brotli already avoided compressing files already compressed, do the same with the deflate method * Don't recompress zips created by the zipdownload plugin
It's already the default if unspecified, and the zip format has supported UTF-8 since 2006, so there's little reason to do otherwise. https://www.loc.gov/preservation/digital/formats/digformatspecs/APPNOTE(20060929)_Version_6.3.0.txt
|
|
||
| $rcmail->output->download_headers($filename, ['length' => filesize($tmpfname)]); | ||
|
|
||
| readfile($tmpfname); |
There was a problem hiding this comment.
The problem is not readfile(), but output buffering. Can't we just disable output buffering before calling readfile()?
There was a problem hiding this comment.
I have a very slight preference to use fread() over readfile() with large files because the latter uses mmap() which means:
- pages mapped by the kernel don't count against PHP's
memory_limit - memory usage is difficult to predict, and can change between kernel versions
- PHP doesn't use
madvise(..., MADV_SEQUENTIAL)which would make the situation better
In practice, mmap() is not some new unoptimized kernel feature, and I doubt its use would cause problems, so I'm happy to move back to readfile() if you'd prefer, just let me know.
| } | ||
|
|
||
| // open zip file | ||
| putenv('TZ=UTC'); // see _datetime_to_ziplocal() comments |
There was a problem hiding this comment.
Will this still be needed if we use setMtimeName() on every file?
There was a problem hiding this comment.
Unfortunately yes. libzip expects times in UTC and always converts them to a local time unless zip_file_set_dostime() is used which ZipArchive doesn't expose. libzip uses localtime() to do the conversion which can be controlled by the TZ environment variable on POSIX and Windows. Different libcs have different ways of setting a default, for example glibc uses /etc/localtime (man tzset). Overriding the default to UTC was the best way I could find to convert these localtime() calls to a no-op.
(Note that I've only tested this on glibc and Windows.)
(Extracted from #10175.)
This includes several improvements to zipdownload. Feel free to cherry-pick what looks useful, or ask me to split this into multiple PRs, or whatever makes most sense.
.htaccess, see 9bd686c for details..emlfile to the IMAP internal time to allow sorting extracted emails.