mirror of
https://github.com/FriendsOfTYPO3/tea.git
synced 2024-11-26 12:56:13 +01:00
ef38d7d84b
PhpStorm by default indexes `*.phar` files. For our current set of tools, we do not want this. (This keeps PhpStorm from complaining about multiple versions of the same class.) Also mark the tools as binary for git.
82760 lines
No EOL
2.4 MiB
Executable file
82760 lines
No EOL
2.4 MiB
Executable file
#!/usr/bin/env php
|
||
<?php
|
||
/**
|
||
* Bundled by phar-composer with the help of php-box.
|
||
*
|
||
* @link https://github.com/clue/phar-composer
|
||
*/
|
||
define('BOX_EXTRACT_PATTERN_DEFAULT', '__HALT' . '_COMPILER(); ?>');
|
||
define('BOX_EXTRACT_PATTERN_OPEN', "__HALT" . "_COMPILER(); ?>\r\n");
|
||
if (class_exists('Phar')) {
|
||
Phar::mapPhar('');
|
||
require 'phar://' . __FILE__ . '/typoscript-lint';
|
||
} else {
|
||
$extract = new Extract(__FILE__, Extract::findStubLength(__FILE__));
|
||
$dir = $extract->go();
|
||
set_include_path($dir . PATH_SEPARATOR . get_include_path());
|
||
require "$dir/typoscript-lint";
|
||
}
|
||
class Extract
|
||
{
|
||
const PATTERN_DEFAULT = BOX_EXTRACT_PATTERN_DEFAULT;
|
||
const PATTERN_OPEN = BOX_EXTRACT_PATTERN_OPEN;
|
||
const GZ = 0x1000;
|
||
const BZ2 = 0x2000;
|
||
const MASK = 0x3000;
|
||
private $file;
|
||
private $handle;
|
||
private $stub;
|
||
public function __construct($file, $stub)
|
||
{
|
||
if (!is_file($file)) {
|
||
throw new InvalidArgumentException(
|
||
sprintf(
|
||
'The path "%s" is not a file or does not exist.',
|
||
$file
|
||
)
|
||
);
|
||
}
|
||
$this->file = $file;
|
||
$this->stub = $stub;
|
||
}
|
||
public static function findStubLength(
|
||
$file,
|
||
$pattern = self::PATTERN_OPEN
|
||
) {
|
||
if (!($fp = fopen($file, 'rb'))) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The phar "%s" could not be opened for reading.',
|
||
$file
|
||
)
|
||
);
|
||
}
|
||
$stub = null;
|
||
$offset = 0;
|
||
$combo = str_split($pattern);
|
||
while (!feof($fp)) {
|
||
if (fgetc($fp) === $combo[$offset]) {
|
||
$offset++;
|
||
if (!isset($combo[$offset])) {
|
||
$stub = ftell($fp);
|
||
break;
|
||
}
|
||
} else {
|
||
$offset = 0;
|
||
}
|
||
}
|
||
fclose($fp);
|
||
if (null === $stub) {
|
||
throw new InvalidArgumentException(
|
||
sprintf(
|
||
'The pattern could not be found in "%s".',
|
||
$file
|
||
)
|
||
);
|
||
}
|
||
return $stub;
|
||
}
|
||
public function go($dir = null)
|
||
{
|
||
if (null === $dir) {
|
||
$dir = rtrim(sys_get_temp_dir(), '\\/')
|
||
. DIRECTORY_SEPARATOR
|
||
. 'pharextract'
|
||
. DIRECTORY_SEPARATOR
|
||
. basename($this->file, '.phar');
|
||
} else {
|
||
$dir = realpath($dir);
|
||
}
|
||
$md5 = $dir . DIRECTORY_SEPARATOR . md5_file($this->file);
|
||
if (file_exists($md5)) {
|
||
return $dir;
|
||
}
|
||
if (!is_dir($dir)) {
|
||
$this->createDir($dir);
|
||
}
|
||
$this->open();
|
||
if (-1 === fseek($this->handle, $this->stub)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'Could not seek to %d in the file "%s".',
|
||
$this->stub,
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
$info = $this->readManifest();
|
||
if ($info['flags'] & self::GZ) {
|
||
if (!function_exists('gzinflate')) {
|
||
throw new RuntimeException(
|
||
'The zlib extension is (gzinflate()) is required for "%s.',
|
||
$this->file
|
||
);
|
||
}
|
||
}
|
||
if ($info['flags'] & self::BZ2) {
|
||
if (!function_exists('bzdecompress')) {
|
||
throw new RuntimeException(
|
||
'The bzip2 extension (bzdecompress()) is required for "%s".',
|
||
$this->file
|
||
);
|
||
}
|
||
}
|
||
self::purge($dir);
|
||
$this->createDir($dir);
|
||
$this->createFile($md5);
|
||
foreach ($info['files'] as $info) {
|
||
$path = $dir . DIRECTORY_SEPARATOR . $info['path'];
|
||
$parent = dirname($path);
|
||
if (!is_dir($parent)) {
|
||
$this->createDir($parent);
|
||
}
|
||
if (preg_match('{/$}', $info['path'])) {
|
||
$this->createDir($path, 0777, false);
|
||
} else {
|
||
$this->createFile(
|
||
$path,
|
||
$this->extractFile($info)
|
||
);
|
||
}
|
||
}
|
||
return $dir;
|
||
}
|
||
public static function purge($path)
|
||
{
|
||
if (is_dir($path)) {
|
||
foreach (scandir($path) as $item) {
|
||
if (('.' === $item) || ('..' === $item)) {
|
||
continue;
|
||
}
|
||
self::purge($path . DIRECTORY_SEPARATOR . $item);
|
||
}
|
||
if (!rmdir($path)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The directory "%s" could not be deleted.',
|
||
$path
|
||
)
|
||
);
|
||
}
|
||
} else {
|
||
if (!unlink($path)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The file "%s" could not be deleted.',
|
||
$path
|
||
)
|
||
);
|
||
}
|
||
}
|
||
}
|
||
private function createDir($path, $chmod = 0777, $recursive = true)
|
||
{
|
||
if (!mkdir($path, $chmod, $recursive)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The directory path "%s" could not be created.',
|
||
$path
|
||
)
|
||
);
|
||
}
|
||
}
|
||
private function createFile($path, $contents = '', $mode = 0666)
|
||
{
|
||
if (false === file_put_contents($path, $contents)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The file "%s" could not be written.',
|
||
$path
|
||
)
|
||
);
|
||
}
|
||
if (!chmod($path, $mode)) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The file "%s" could not be chmodded to %o.',
|
||
$path,
|
||
$mode
|
||
)
|
||
);
|
||
}
|
||
}
|
||
private function extractFile($info)
|
||
{
|
||
if (0 === $info['size']) {
|
||
return '';
|
||
}
|
||
$data = $this->read($info['compressed_size']);
|
||
if ($info['flags'] & self::GZ) {
|
||
if (false === ($data = gzinflate($data))) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The "%s" file could not be inflated (gzip) from "%s".',
|
||
$info['path'],
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
} elseif ($info['flags'] & self::BZ2) {
|
||
if (false === ($data = bzdecompress($data))) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The "%s" file could not be inflated (bzip2) from "%s".',
|
||
$info['path'],
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
}
|
||
if (($actual = strlen($data)) !== $info['size']) {
|
||
throw new UnexpectedValueException(
|
||
sprintf(
|
||
'The size of "%s" (%d) did not match what was expected (%d) in "%s".',
|
||
$info['path'],
|
||
$actual,
|
||
$info['size'],
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
$crc32 = sprintf('%u', crc32($data) & 0xffffffff);
|
||
if ($info['crc32'] != $crc32) {
|
||
throw new UnexpectedValueException(
|
||
sprintf(
|
||
'The crc32 checksum (%s) for "%s" did not match what was expected (%s) in "%s".',
|
||
$crc32,
|
||
$info['path'],
|
||
$info['crc32'],
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
return $data;
|
||
}
|
||
private function open()
|
||
{
|
||
if (null === ($this->handle = fopen($this->file, 'rb'))) {
|
||
$this->handle = null;
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'The file "%s" could not be opened for reading.',
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
}
|
||
private function read($bytes)
|
||
{
|
||
$read = '';
|
||
$total = $bytes;
|
||
while (!feof($this->handle) && $bytes) {
|
||
if (false === ($chunk = fread($this->handle, $bytes))) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'Could not read %d bytes from "%s".',
|
||
$bytes,
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
$read .= $chunk;
|
||
$bytes -= strlen($chunk);
|
||
}
|
||
if (($actual = strlen($read)) !== $total) {
|
||
throw new RuntimeException(
|
||
sprintf(
|
||
'Only read %d of %d in "%s".',
|
||
$actual,
|
||
$total,
|
||
$this->file
|
||
)
|
||
);
|
||
}
|
||
return $read;
|
||
}
|
||
private function readManifest()
|
||
{
|
||
$size = unpack('V', $this->read(4));
|
||
$size = $size[1];
|
||
$raw = $this->read($size);
|
||
$count = unpack('V', substr($raw, 0, 4));
|
||
$count = $count[1];
|
||
$aliasSize = unpack('V', substr($raw, 10, 4));
|
||
$aliasSize = $aliasSize[1];
|
||
$raw = substr($raw, 14 + $aliasSize);
|
||
$metaSize = unpack('V', substr($raw, 0, 4));
|
||
$metaSize = $metaSize[1];
|
||
$offset = 0;
|
||
$start = 4 + $metaSize;
|
||
$manifest = array(
|
||
'files' => array(),
|
||
'flags' => 0,
|
||
);
|
||
for ($i = 0; $i < $count; $i++) {
|
||
$length = unpack('V', substr($raw, $start, 4));
|
||
$length = $length[1];
|
||
$start += 4;
|
||
$path = substr($raw, $start, $length);
|
||
$start += $length;
|
||
$file = unpack(
|
||
'Vsize/Vtimestamp/Vcompressed_size/Vcrc32/Vflags/Vmetadata_length',
|
||
substr($raw, $start, 24)
|
||
);
|
||
$file['path'] = $path;
|
||
$file['crc32'] = sprintf('%u', $file['crc32'] & 0xffffffff);
|
||
$file['offset'] = $offset;
|
||
$offset += $file['compressed_size'];
|
||
$start += 24 + $file['metadata_length'];
|
||
$manifest['flags'] |= $file['flags'] & self::MASK;
|
||
$manifest['files'][] = $file;
|
||
}
|
||
return $manifest;
|
||
}
|
||
}
|
||
|
||
__HALT_COMPILER(); ?>
|
||
u<BD> |