Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/seld/phar-utils/src/Timestamps.php
<?php

/*
 * This file is part of PHAR Utils.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Seld\PharUtils;

class
Timestamps
{
    private
$contents;

   
/**
     * @param string $file path to the phar file to use
     */
   
public function __construct($file)
    {
       
$this->contents = file_get_contents($file);
    }

   
/**
     * Updates each file's unix timestamps in the PHAR
     *
     * The PHAR signature can then be produced in a reproducible manner.
     *
     * @param int|DateTime|string $timestamp Date string or DateTime or unix timestamp to use
     */
   
public function updateTimestamps($timestamp = null)
    {
        if (
$timestamp instanceof \DateTime) {
           
$timestamp = $timestamp->getTimestamp();
        } elseif (
is_string($timestamp)) {
           
$timestamp = strtotime($timestamp);
        } elseif (!
is_int($timestamp)) {
           
$timestamp = strtotime('1984-12-24T00:00:00Z');
        }

       
// detect manifest offset / end of stub
       
if (!preg_match('{__HALT_COMPILER\(\);(?: +\?>)?\r?\n}', $this->contents, $match, PREG_OFFSET_CAPTURE)) {
            throw new \
RuntimeException('Could not detect the stub\'s end in the phar');
        }

       
// set starting position and skip past manifest length
       
$pos = $match[0][1] + strlen($match[0][0]);
       
$stubEnd = $pos + $this->readUint($pos, 4);
       
$pos += 4;

       
$numFiles = $this->readUint($pos, 4);
       
$pos += 4;

       
// skip API version (YOLO)
       
$pos += 2;

       
// skip PHAR flags
       
$pos += 4;

       
$aliasLength = $this->readUint($pos, 4);
       
$pos += 4 + $aliasLength;

       
$metadataLength = $this->readUint($pos, 4);
       
$pos += 4 + $metadataLength;

        while (
$pos < $stubEnd) {
           
$filenameLength = $this->readUint($pos, 4);
           
$pos += 4 + $filenameLength;

           
// skip filesize
           
$pos += 4;

           
// update timestamp to a fixed value
           
$this->contents = substr_replace($this->contents, pack('L', $timestamp), $pos, 4);

           
// skip timestamp, compressed file size, crc32 checksum and file flags
           
$pos += 4*4;

           
$metadataLength = $this->readUint($pos, 4);
           
$pos += 4 + $metadataLength;

           
$numFiles--;
        }

        if (
$numFiles !== 0) {
            throw new \
LogicException('All files were not processed, something must have gone wrong');
        }
    }

   
/**
     * Saves the updated phar file, optionally with an updated signature.
     *
     * @param  string $path
     * @param  int $signatureAlgo One of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512
     * @return bool
     */
   
public function save($path, $signatureAlgo)
    {
       
$pos = $this->determineSignatureBegin();

       
$algos = array(
            \
Phar::MD5 => 'md5',
            \
Phar::SHA1 => 'sha1',
            \
Phar::SHA256 => 'sha256',
            \
Phar::SHA512 => 'sha512',
        );

        if (!isset(
$algos[$signatureAlgo])) {
            throw new \
UnexpectedValueException('Invalid hash algorithm given: '.$signatureAlgo.' expected one of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512');
        }
       
$algo = $algos[$signatureAlgo];

       
// re-sign phar
        //           signature
       
$signature = hash($algo, substr($this->contents, 0, $pos), true)
           
// sig type
           
. pack('L', $signatureAlgo)
           
// ohai Greg & Marcus
           
. 'GBMB';

       
$this->contents = substr($this->contents, 0, $pos) . $signature;

        return
file_put_contents($path, $this->contents);
    }

    private function
readUint($pos, $bytes)
    {
       
$res = unpack('V', substr($this->contents, $pos, $bytes));

        return
$res[1];
    }

   
/**
     * Determine the beginning of the signature.
     *
     * @return int
     */
   
private function determineSignatureBegin()
    {
       
// detect signature position
       
if (!preg_match('{__HALT_COMPILER\(\);(?: +\?>)?\r?\n}', $this->contents, $match, PREG_OFFSET_CAPTURE)) {
            throw new \
RuntimeException('Could not detect the stub\'s end in the phar');
        }

       
// set starting position and skip past manifest length
       
$pos = $match[0][1] + strlen($match[0][0]);
       
$manifestEnd = $pos + 4 + $this->readUint($pos, 4);

       
$pos += 4;
       
$numFiles = $this->readUint($pos, 4);

       
$pos += 4;

       
// skip API version (YOLO)
       
$pos += 2;

       
// skip PHAR flags
       
$pos += 4;

       
$aliasLength = $this->readUint($pos, 4);
       
$pos += 4 + $aliasLength;

       
$metadataLength = $this->readUint($pos, 4);
       
$pos += 4 + $metadataLength;

       
$compressedSizes = 0;
        while ((
$numFiles > 0) && ($pos < $manifestEnd - 24)) {
           
$filenameLength = $this->readUint($pos, 4);
           
$pos += 4 + $filenameLength;

           
// skip filesize and timestamp
           
$pos += 2*4;

           
$compressedSizes += $this->readUint($pos, 4);
           
// skip compressed file size, crc32 checksum and file flags
           
$pos += 3*4;

           
$metadataLength = $this->readUint($pos, 4);
           
$pos += 4 + $metadataLength;

           
$numFiles--;
        }

        if (
$numFiles !== 0) {
            throw new \
LogicException('All files were not processed, something must have gone wrong');
        }

        return
$manifestEnd + $compressedSizes;
    }
}