ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
ZipStream\File Class Reference
+ Collaboration diagram for ZipStream\File:

Public Member Functions

 __construct (ZipStream $zip, string $name, ?FileOptions $opt=null)
 
 processPath (string $path)
 
 processData (string $data)
 
 addFileHeader ()
 Create and send zip header for this file. More...
 
 addFileFooter ()
 Create and send data descriptor footer for this file. More...
 
 processStream (StreamInterface $stream)
 
 getCdrFile ()
 Send CDR record for specified file. More...
 
 getTotalLength ()
 

Static Public Member Functions

static filterFilename (string $filename)
 Strip characters that are not legal in Windows filenames to prevent compatibility issues. More...
 

Data Fields

const HASH_ALGORITHM = 'crc32b'
 
const BIT_ZERO_HEADER = 0x0008
 
const BIT_EFS_UTF8 = 0x0800
 
const COMPUTE = 1
 
const SEND = 2
 
 $name
 
 $opt
 
 $len
 
 $zlen
 
 $crc
 
 $hlen
 
 $ofs
 
 $bits
 
 $version
 
 $zip
 

Protected Member Functions

 buildZip64ExtraBlock (bool $force=false)
 
 processStreamWithZeroHeader (StreamInterface $stream)
 
 readStream (StreamInterface $stream, ?int $options=null)
 
 deflateInit ()
 
 deflateData (StreamInterface $stream, string &$data, ?int $options=null)
 
 deflateFinish (?int $options=null)
 
 processStreamWithComputedHeader (StreamInterface $stream)
 

Static Protected Member Functions

static dosTime (int $when)
 Convert a UNIX timestamp to a DOS timestamp. More...
 

Private Attributes

const CHUNKED_READ_BLOCK_SIZE = 1048576
 
 $deflate
 
 $hash
 
 $method
 
 $totalLength
 

Detailed Description

Definition at line 15 of file File.php.

Constructor & Destructor Documentation

◆ __construct()

ZipStream\File::__construct ( ZipStream  $zip,
string  $name,
?FileOptions  $opt = null 
)

Definition at line 93 of file File.php.

References $name.

94  {
95  $this->zip = $zip;
96 
97  $this->name = $name;
98  $this->opt = $opt ?: new FileOptions();
99  $this->method = $this->opt->getMethod();
100  $this->version = Version::STORE();
101  $this->ofs = new Bigint();
102  }

Member Function Documentation

◆ addFileFooter()

ZipStream\File::addFileFooter ( )

Create and send data descriptor footer for this file.

Returns
void

Definition at line 303 of file File.php.

References init().

303  : void
304  {
305 
306  if ($this->bits & self::BIT_ZERO_HEADER) {
307  // compressed and uncompressed size
308  $sizeFormat = 'V';
309  if ($this->zip->opt->isEnableZip64()) {
310  $sizeFormat = 'P';
311  }
312  $fields = [
314  ['V', $this->crc], // CRC32
315  [$sizeFormat, $this->zlen], // Length of compressed data
316  [$sizeFormat, $this->len], // Length of original data
317  ];
318 
319  $footer = ZipStream::packFields($fields);
320  $this->zip->send($footer);
321  } else {
322  $footer = '';
323  }
324  $this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer)));
325  $this->zip->addToCdr($this);
326  }
const DATA_DESCRIPTOR_SIGNATURE
Definition: ZipStream.php:93
static init(int $value=0)
Get an instance.
Definition: Bigint.php:47
static packFields(array $fields)
Create a format string and argument list for pack(), then call pack() and return the result...
Definition: ZipStream.php:416
+ Here is the call graph for this function:

◆ addFileHeader()

ZipStream\File::addFileHeader ( )

Create and send zip header for this file.

Returns
void
Exceptions

Definition at line 146 of file File.php.

References $comment, $data, $header, $name, $time, and init().

146  : void
147  {
148  $name = static::filterFilename($this->name);
149 
150  // calculate name length
151  $nameLength = strlen($name);
152 
153  // create dos timestamp
154  $time = static::dosTime($this->opt->getTime()->getTimestamp());
155 
156  $comment = $this->opt->getComment();
157 
158  if (!mb_check_encoding($name, 'ASCII') ||
159  !mb_check_encoding($comment, 'ASCII')) {
160  // Sets Bit 11: Language encoding flag (EFS). If this bit is set,
161  // the filename and comment fields for this file
162  // MUST be encoded using UTF-8. (see APPENDIX D)
163  if (!mb_check_encoding($name, 'UTF-8') ||
164  !mb_check_encoding($comment, 'UTF-8')) {
165  throw new EncodingException(
166  'File name and comment should use UTF-8 ' .
167  'if one of them does not fit into ASCII range.'
168  );
169  }
170  $this->bits |= self::BIT_EFS_UTF8;
171  }
172 
173  if ($this->method->equals(Method::DEFLATE())) {
174  $this->version = Version::DEFLATE();
175  }
176 
177  $force = (boolean)($this->bits & self::BIT_ZERO_HEADER) &&
178  $this->zip->opt->isEnableZip64();
179 
180  $footer = $this->buildZip64ExtraBlock($force);
181 
182  // If this file will start over 4GB limit in ZIP file,
183  // CDR record will have to use Zip64 extension to describe offset
184  // to keep consistency we use the same value here
185  if ($this->zip->ofs->isOver32()) {
186  $this->version = Version::ZIP64();
187  }
188 
189  $fields = [
191  ['v', $this->version->getValue()], // Version needed to Extract
192  ['v', $this->bits], // General purpose bit flags - data descriptor flag set
193  ['v', $this->method->getValue()], // Compression method
194  ['V', $time], // Timestamp (DOS Format)
195  ['V', $this->crc], // CRC32 of data (0 -> moved to data descriptor footer)
196  ['V', $this->zlen->getLowFF($force)], // Length of compressed data (forced to 0xFFFFFFFF for zero header)
197  ['V', $this->len->getLowFF($force)], // Length of original data (forced to 0xFFFFFFFF for zero header)
198  ['v', $nameLength], // Length of filename
199  ['v', strlen($footer)], // Extra data (see above)
200  ];
201 
202  // pack fields and calculate "total" length
203  $header = ZipStream::packFields($fields);
204 
205  // print header and filename
206  $data = $header . $name . $footer;
207  $this->zip->send($data);
208 
209  // save header length
210  $this->hlen = Bigint::init(strlen($data));
211  }
static init(int $value=0)
Get an instance.
Definition: Bigint.php:47
$time
Definition: cron.php:21
buildZip64ExtraBlock(bool $force=false)
Definition: File.php:265
$comment
Definition: buildRTE.php:83
static packFields(array $fields)
Create a format string and argument list for pack(), then call pack() and return the result...
Definition: ZipStream.php:416
const FILE_HEADER_SIGNATURE
The following signatures end with 0x4b50, which in ASCII isĀ PK, the initials of the inventor Phil Kat...
Definition: ZipStream.php:90
$data
Definition: bench.php:6
+ Here is the call graph for this function:

◆ buildZip64ExtraBlock()

ZipStream\File::buildZip64ExtraBlock ( bool  $force = false)
protected

Definition at line 265 of file File.php.

265  : string
266  {
267 
268  $fields = [];
269  if ($this->len->isOver32($force)) {
270  $fields[] = ['P', $this->len]; // Length of original data
271  }
272 
273  if ($this->len->isOver32($force)) {
274  $fields[] = ['P', $this->zlen]; // Length of compressed data
275  }
276 
277  if ($this->ofs->isOver32()) {
278  $fields[] = ['P', $this->ofs]; // Offset of local header record
279  }
280 
281  if (!empty($fields)) {
282  if (!$this->zip->opt->isEnableZip64()) {
283  throw new OverflowException();
284  }
285 
286  array_unshift(
287  $fields,
288  ['v', 0x0001], // 64 bit extension
289  ['v', count($fields) * 8] // Length of data block
290  );
291  $this->version = Version::ZIP64();
292  }
293 
294  return ZipStream::packFields($fields);
295  }
static packFields(array $fields)
Create a format string and argument list for pack(), then call pack() and return the result...
Definition: ZipStream.php:416

◆ deflateData()

ZipStream\File::deflateData ( StreamInterface  $stream,
string &  $data,
?int  $options = null 
)
protected

Definition at line 378 of file File.php.

References PHPMailer\PHPMailer\$options, Psr\Http\Message\StreamInterface\eof(), GuzzleHttp\Psr7\hash(), and init().

378  : void
379  {
380  if ($options & self::COMPUTE) {
381  $this->len = $this->len->add(Bigint::init(strlen($data)));
382  hash_update($this->hash, $data);
383  }
384  if ($this->deflate) {
385  $data = deflate_add(
386  $this->deflate,
387  $data,
388  $stream->eof()
389  ? ZLIB_FINISH
390  : ZLIB_NO_FLUSH
391  );
392  }
393  if ($options & self::COMPUTE) {
394  $this->zlen = $this->zlen->add(Bigint::init(strlen($data)));
395  }
396  }
static init(int $value=0)
Get an instance.
Definition: Bigint.php:47
$stream
PHP stream implementation.
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
$data
Definition: bench.php:6
+ Here is the call graph for this function:

◆ deflateFinish()

ZipStream\File::deflateFinish ( ?int  $options = null)
protected

Definition at line 398 of file File.php.

References PHPMailer\PHPMailer\$options, and GuzzleHttp\Psr7\hash().

398  : void
399  {
400  if ($options & self::COMPUTE) {
401  $this->crc = hexdec(hash_final($this->hash));
402  }
403  }
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
+ Here is the call graph for this function:

◆ deflateInit()

ZipStream\File::deflateInit ( )
protected

Definition at line 367 of file File.php.

References GuzzleHttp\Psr7\hash().

367  : void
368  {
369  $this->hash = hash_init(self::HASH_ALGORITHM);
370  if ($this->method->equals(Method::DEFLATE())) {
371  $this->deflate = deflate_init(
372  ZLIB_ENCODING_RAW,
373  ['level' => $this->opt->getDeflateLevel()]
374  );
375  }
376  }
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
+ Here is the call graph for this function:

◆ dosTime()

static ZipStream\File::dosTime ( int  $when)
staticfinalprotected

Convert a UNIX timestamp to a DOS timestamp.

Parameters
int$when
Returns
int DOS Timestamp

Definition at line 235 of file File.php.

References $d.

235  : int
236  {
237  // get date array for timestamp
238  $d = getdate($when);
239 
240  // set lower-bound on dates
241  if ($d['year'] < 1980) {
242  $d = array(
243  'year' => 1980,
244  'mon' => 1,
245  'mday' => 1,
246  'hours' => 0,
247  'minutes' => 0,
248  'seconds' => 0
249  );
250  }
251 
252  // remove extra years from 1980
253  $d['year'] -= 1980;
254 
255  // return date string
256  return
257  ($d['year'] << 25) |
258  ($d['mon'] << 21) |
259  ($d['mday'] << 16) |
260  ($d['hours'] << 11) |
261  ($d['minutes'] << 5) |
262  ($d['seconds'] >> 1);
263  }
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296

◆ filterFilename()

static ZipStream\File::filterFilename ( string  $filename)
static

Strip characters that are not legal in Windows filenames to prevent compatibility issues.

Parameters
string$filenameUnprocessed filename
Returns
string

Definition at line 220 of file File.php.

220  : string
221  {
222  // strip leading slashes from file name
223  // (fixes bug in windows archive viewer)
224  $filename = preg_replace('/^\\/+/', '', $filename);
225 
226  return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $filename);
227  }
$filename
Definition: buildRTE.php:89

◆ getCdrFile()

ZipStream\File::getCdrFile ( )

Send CDR record for specified file.

Returns
string

Definition at line 433 of file File.php.

References $comment, $header, $name, and $time.

Referenced by ZipStream\ZipStream\addToCdr().

433  : string
434  {
435  $name = static::filterFilename($this->name);
436 
437  // get attributes
438  $comment = $this->opt->getComment();
439 
440  // get dos timestamp
441  $time = static::dosTime($this->opt->getTime()->getTimestamp());
442 
443  $footer = $this->buildZip64ExtraBlock();
444 
445  $fields = [
446  ['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature
447  ['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version
448  ['v', $this->version->getValue()], // Extract by version
449  ['v', $this->bits], // General purpose bit flags - data descriptor flag set
450  ['v', $this->method->getValue()], // Compression method
451  ['V', $time], // Timestamp (DOS Format)
452  ['V', $this->crc], // CRC32
453  ['V', $this->zlen->getLowFF()], // Compressed Data Length
454  ['V', $this->len->getLowFF()], // Original Data Length
455  ['v', strlen($name)], // Length of filename
456  ['v', strlen($footer)], // Extra data len (see above)
457  ['v', strlen($comment)], // Length of comment
458  ['v', 0], // Disk number
459  ['v', 0], // Internal File Attributes
460  ['V', 32], // External File Attributes
461  ['V', $this->ofs->getLowFF()] // Relative offset of local header
462  ];
463 
464  // pack fields, then append name and comment
465  $header = ZipStream::packFields($fields);
466 
467  return $header . $name . $footer . $comment;
468  }
const CDR_FILE_SIGNATURE
Definition: ZipStream.php:91
$time
Definition: cron.php:21
const ZIP_VERSION_MADE_BY
This number corresponds to the ZIP version/OS used (2 bytes) From: https://www.iana.org/assignments/media-types/application/zip The upper byte (leftmost one) indicates the host system (OS) for the file.
Definition: ZipStream.php:83
buildZip64ExtraBlock(bool $force=false)
Definition: File.php:265
$comment
Definition: buildRTE.php:83
static packFields(array $fields)
Create a format string and argument list for pack(), then call pack() and return the result...
Definition: ZipStream.php:416
+ Here is the caller graph for this function:

◆ getTotalLength()

ZipStream\File::getTotalLength ( )
Returns
Bigint

Definition at line 473 of file File.php.

Referenced by ZipStream\ZipStream\addToCdr().

473  : Bigint
474  {
475  return $this->totalLength;
476  }
+ Here is the caller graph for this function:

◆ processData()

ZipStream\File::processData ( string  $data)

Definition at line 124 of file File.php.

124  : void
125  {
126  $this->len = new Bigint(strlen($data));
127  $this->crc = crc32($data);
128 
129  // compress data if needed
130  if ($this->method->equals(Method::DEFLATE())) {
131  $data = gzdeflate($data);
132  }
133 
134  $this->zlen = new Bigint(strlen($data));
135  $this->addFileHeader();
136  $this->zip->send($data);
137  $this->addFileFooter();
138  }
addFileFooter()
Create and send data descriptor footer for this file.
Definition: File.php:303
addFileHeader()
Create and send zip header for this file.
Definition: File.php:146
$data
Definition: bench.php:6

◆ processPath()

ZipStream\File::processPath ( string  $path)

Definition at line 104 of file File.php.

References $data, and GuzzleHttp\Psr7\$stream.

104  : void
105  {
106  if (!is_readable($path)) {
107  if (!file_exists($path)) {
108  throw new FileNotFoundException($path);
109  }
110  throw new FileNotReadableException($path);
111  }
112  if ($this->zip->isLargeFile($path) === false) {
113  $data = file_get_contents($path);
114  $this->processData($data);
115  } else {
116  $this->method = $this->zip->opt->getLargeFileMethod();
117 
118  $stream = new DeflateStream(fopen($path, 'rb'));
119  $this->processStream($stream);
120  $stream->close();
121  }
122  }
$path
Definition: aliased.php:25
processStream(StreamInterface $stream)
Definition: File.php:328
$stream
PHP stream implementation.
processData(string $data)
Definition: File.php:124
$data
Definition: bench.php:6

◆ processStream()

ZipStream\File::processStream ( StreamInterface  $stream)

Definition at line 328 of file File.php.

328  : void
329  {
330  $this->zlen = new Bigint();
331  $this->len = new Bigint();
332 
333  if ($this->zip->opt->isZeroHeader()) {
335  } else {
337  }
338  }
$stream
PHP stream implementation.
processStreamWithZeroHeader(StreamInterface $stream)
Definition: File.php:340
processStreamWithComputedHeader(StreamInterface $stream)
Definition: File.php:405

◆ processStreamWithComputedHeader()

ZipStream\File::processStreamWithComputedHeader ( StreamInterface  $stream)
protected

Definition at line 405 of file File.php.

References $data, Psr\Http\Message\StreamInterface\eof(), init(), Psr\Http\Message\StreamInterface\read(), and Psr\Http\Message\StreamInterface\rewind().

405  : void
406  {
407  $this->readStream($stream, self::COMPUTE);
408  $stream->rewind();
409 
410  // incremental compression with deflate_add
411  // makes this second read unnecessary
412  // but it is only available from PHP 7.0
413  if (!$this->deflate && $stream instanceof DeflateStream && $this->method->equals(Method::DEFLATE())) {
414  $stream->addDeflateFilter($this->opt);
415  $this->zlen = new Bigint();
416  while (!$stream->eof()) {
417  $data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE);
418  $this->zlen = $this->zlen->add(Bigint::init(strlen($data)));
419  }
420  $stream->rewind();
421  }
422 
423  $this->addFileHeader();
424  $this->readStream($stream, self::SEND);
425  $this->addFileFooter();
426  }
static init(int $value=0)
Get an instance.
Definition: Bigint.php:47
readStream(StreamInterface $stream, ?int $options=null)
Definition: File.php:348
$stream
PHP stream implementation.
addFileFooter()
Create and send data descriptor footer for this file.
Definition: File.php:303
addFileHeader()
Create and send zip header for this file.
Definition: File.php:146
$data
Definition: bench.php:6
+ Here is the call graph for this function:

◆ processStreamWithZeroHeader()

ZipStream\File::processStreamWithZeroHeader ( StreamInterface  $stream)
protected

Definition at line 340 of file File.php.

340  : void
341  {
342  $this->bits |= self::BIT_ZERO_HEADER;
343  $this->addFileHeader();
344  $this->readStream($stream, self::COMPUTE | self::SEND);
345  $this->addFileFooter();
346  }
readStream(StreamInterface $stream, ?int $options=null)
Definition: File.php:348
$stream
PHP stream implementation.
addFileFooter()
Create and send data descriptor footer for this file.
Definition: File.php:303
addFileHeader()
Create and send zip header for this file.
Definition: File.php:146

◆ readStream()

ZipStream\File::readStream ( StreamInterface  $stream,
?int  $options = null 
)
protected

Definition at line 348 of file File.php.

References $data, PHPMailer\PHPMailer\$options, $size, $total, Psr\Http\Message\StreamInterface\eof(), and Psr\Http\Message\StreamInterface\read().

348  : void
349  {
350  $this->deflateInit();
351  $total = 0;
352  $size = $this->opt->getSize();
353  while (!$stream->eof() && ($size === 0 || $total < $size)) {
354  $data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE);
355  $total += strlen($data);
356  if ($size > 0 && $total > $size) {
357  $data = substr($data, 0 , strlen($data)-($total - $size));
358  }
359  $this->deflateData($stream, $data, $options);
360  if ($options & self::SEND) {
361  $this->zip->send($data);
362  }
363  }
364  $this->deflateFinish($options);
365  }
$size
Definition: RandomTest.php:84
deflateData(StreamInterface $stream, string &$data, ?int $options=null)
Definition: File.php:378
$stream
PHP stream implementation.
$total
Definition: Utf8Test.php:87
deflateFinish(?int $options=null)
Definition: File.php:398
$data
Definition: bench.php:6
+ Here is the call graph for this function:

Field Documentation

◆ $bits

ZipStream\File::$bits

Definition at line 62 of file File.php.

◆ $crc

ZipStream\File::$crc

Definition at line 47 of file File.php.

◆ $deflate

ZipStream\File::$deflate
private

Definition at line 77 of file File.php.

◆ $hash

ZipStream\File::$hash
private

Definition at line 81 of file File.php.

◆ $hlen

ZipStream\File::$hlen

Definition at line 52 of file File.php.

◆ $len

ZipStream\File::$len

Definition at line 40 of file File.php.

◆ $method

ZipStream\File::$method
private

Definition at line 86 of file File.php.

◆ $name

ZipStream\File::$name

Definition at line 30 of file File.php.

◆ $ofs

ZipStream\File::$ofs

Definition at line 57 of file File.php.

◆ $opt

ZipStream\File::$opt

Definition at line 35 of file File.php.

◆ $totalLength

ZipStream\File::$totalLength
private

Definition at line 91 of file File.php.

◆ $version

ZipStream\File::$version

Definition at line 67 of file File.php.

◆ $zip

ZipStream\File::$zip

Definition at line 72 of file File.php.

◆ $zlen

ZipStream\File::$zlen

Definition at line 44 of file File.php.

◆ BIT_EFS_UTF8

const ZipStream\File::BIT_EFS_UTF8 = 0x0800

Definition at line 20 of file File.php.

◆ BIT_ZERO_HEADER

const ZipStream\File::BIT_ZERO_HEADER = 0x0008

Definition at line 19 of file File.php.

◆ CHUNKED_READ_BLOCK_SIZE

const ZipStream\File::CHUNKED_READ_BLOCK_SIZE = 1048576
private

Definition at line 25 of file File.php.

◆ COMPUTE

const ZipStream\File::COMPUTE = 1

Definition at line 22 of file File.php.

◆ HASH_ALGORITHM

const ZipStream\File::HASH_ALGORITHM = 'crc32b'

Definition at line 17 of file File.php.

◆ SEND

const ZipStream\File::SEND = 2

Definition at line 23 of file File.php.


The documentation for this class was generated from the following file: