summaryrefslogtreecommitdiffstats
path: root/lib/private/Streamer.php
diff options
context:
space:
mode:
authorDaniel Calviño Sánchez <danxuliu@gmail.com>2018-02-06 14:03:50 +0100
committerRoeland Jago Douma <roeland@famdouma.nl>2018-04-06 15:59:30 +0200
commit90fdf83ca7648418f899e28490f65de53fcd31d1 (patch)
tree50d98da38954e800576d75e34da47301df891cec /lib/private/Streamer.php
parent4a73f645e5a60d8adece72e6c231c2a1be13473d (diff)
downloadnextcloud-server-90fdf83ca7648418f899e28490f65de53fcd31d1.tar.gz
nextcloud-server-90fdf83ca7648418f899e28490f65de53fcd31d1.zip
Use zip32 only if there are less than 65536 files
A zip32 file can contain, at most, 65535 files (and folders), so take that constraint into account. Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'lib/private/Streamer.php')
-rw-r--r--lib/private/Streamer.php28
1 files changed, 24 insertions, 4 deletions
diff --git a/lib/private/Streamer.php b/lib/private/Streamer.php
index 3b033e265e7..51c2c923c23 100644
--- a/lib/private/Streamer.php
+++ b/lib/private/Streamer.php
@@ -40,14 +40,34 @@ class Streamer {
*
* @param IRequest $request
* @param int $size The size of the files in bytes
+ * @param int $numberOfFiles The number of files (and directories) that will
+ * be included in the streamed file
*/
- public function __construct(IRequest $request, int $size){
+ public function __construct(IRequest $request, int $size, int $numberOfFiles){
/**
- * If the size if below 4GB always use zip32
- * Use 4*1000*1000*1000 so we have a buffer for all the extra zip data
+ * zip32 constraints for a basic (without compression, volumes nor
+ * encryption) zip file according to the Zip specification:
+ * - No file size is larger than 4 bytes (file size < 4294967296); see
+ * 4.4.9 uncompressed size
+ * - The size of all files plus their local headers is not larger than
+ * 4 bytes; see 4.4.16 relative offset of local header and 4.4.24
+ * offset of start of central directory with respect to the starting
+ * disk number
+ * - The total number of entries (files and directories) in the zip file
+ * is not larger than 2 bytes (number of entries < 65536); see 4.4.22
+ * total number of entries in the central dir
+ * - The size of the central directory is not larger than 4 bytes; see
+ * 4.4.23 size of the central directory
+ *
+ * Due to all that, zip32 is used if the size is below 4GB and there are
+ * less than 65536 files; the margin between 4*1000^3 and 4*1024^3
+ * should give enough room for the extra zip metadata. Technically, it
+ * would still be possible to create an invalid zip32 file (for example,
+ * a zip file from files smaller than 4GB with a central directory
+ * larger than 4GiB), but it should not happen in the real world.
*/
- if ($size < 4 * 1000 * 1000 * 1000) {
+ if ($size < 4 * 1000 * 1000 * 1000 && $numberOfFiles < 65536) {
$this->streamerInstance = new ZipStreamer(['zip64' => false]);
} else if ($request->isUserAgent($this->preferTarFor)) {
$this->streamerInstance = new TarStreamer();