mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
* Fixes to phar stub
There were a couple of issues with the phar stub. It seems that in the
past people did not realise they had to change shortarc.php and run
makestub.php to generate the stubfile and instead they modified stub.h
manually. This meant that there were a couple of mistakes in the stub
which are fixed in this patch. In particular:
* The title tag was not closed
* The length of the stub was wrong in stub.h
* This PR syncs previous changes to stub.h back to shortarc.php
and vice versa.
* Adds a note such that hopefully no mistakes against updating the stubs
are made in the future (hopefully).
* The makestub.php script was actually broken because the expected
signature of the stub got changed in b874f1a73d
* Verify that the phar stub is up-to-date in CI
* Update stub again after master changes
* size_t changes
* Update test after stub changes (canonical casts)
---------
Co-authored-by: Joe Watkins <krakjoe@php.net>
296 lines
8.9 KiB
PHP
296 lines
8.9 KiB
PHP
<?php
|
|
|
|
$web = '000';
|
|
|
|
if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
|
|
Phar::interceptFileFuncs();
|
|
set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
|
|
Phar::webPhar(null, $web);
|
|
include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
|
|
return;
|
|
}
|
|
|
|
if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) {
|
|
Extract_Phar::go(true);
|
|
$mimes = array(
|
|
'phps' => 2,
|
|
'c' => 'text/plain',
|
|
'cc' => 'text/plain',
|
|
'cpp' => 'text/plain',
|
|
'c++' => 'text/plain',
|
|
'dtd' => 'text/plain',
|
|
'h' => 'text/plain',
|
|
'log' => 'text/plain',
|
|
'rng' => 'text/plain',
|
|
'txt' => 'text/plain',
|
|
'xsd' => 'text/plain',
|
|
'php' => 1,
|
|
'inc' => 1,
|
|
'avi' => 'video/avi',
|
|
'bmp' => 'image/bmp',
|
|
'css' => 'text/css',
|
|
'gif' => 'image/gif',
|
|
'htm' => 'text/html',
|
|
'html' => 'text/html',
|
|
'htmls' => 'text/html',
|
|
'ico' => 'image/x-ico',
|
|
'jpe' => 'image/jpeg',
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'js' => 'application/x-javascript',
|
|
'midi' => 'audio/midi',
|
|
'mid' => 'audio/midi',
|
|
'mod' => 'audio/mod',
|
|
'mov' => 'movie/quicktime',
|
|
'mp3' => 'audio/mp3',
|
|
'mpg' => 'video/mpeg',
|
|
'mpeg' => 'video/mpeg',
|
|
'pdf' => 'application/pdf',
|
|
'png' => 'image/png',
|
|
'swf' => 'application/shockwave-flash',
|
|
'tif' => 'image/tiff',
|
|
'tiff' => 'image/tiff',
|
|
'wav' => 'audio/wav',
|
|
'xbm' => 'image/xbm',
|
|
'xml' => 'text/xml',
|
|
);
|
|
|
|
header("Cache-Control: no-cache, must-revalidate");
|
|
header("Pragma: no-cache");
|
|
|
|
$basename = basename(__FILE__);
|
|
if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
|
|
chdir(Extract_Phar::$temp);
|
|
include $web;
|
|
return;
|
|
}
|
|
$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
|
|
if (!$pt || $pt == '/') {
|
|
$pt = $web;
|
|
header('HTTP/1.1 301 Moved Permanently');
|
|
header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
|
|
exit;
|
|
}
|
|
$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
|
|
if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
|
|
header('HTTP/1.0 404 Not Found');
|
|
echo "<html>\n <head>\n <title>File Not Found</title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>";
|
|
exit;
|
|
}
|
|
$b = pathinfo($a);
|
|
if (!isset($b['extension'])) {
|
|
header('Content-Type: text/plain');
|
|
header('Content-Length: ' . filesize($a));
|
|
readfile($a);
|
|
exit;
|
|
}
|
|
if (isset($mimes[$b['extension']])) {
|
|
if ($mimes[$b['extension']] === 1) {
|
|
include $a;
|
|
exit;
|
|
}
|
|
if ($mimes[$b['extension']] === 2) {
|
|
highlight_file($a);
|
|
exit;
|
|
}
|
|
header('Content-Type: ' .$mimes[$b['extension']]);
|
|
header('Content-Length: ' . filesize($a));
|
|
readfile($a);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
class Extract_Phar
|
|
{
|
|
static $temp;
|
|
static $origdir;
|
|
const GZ = 0x1000;
|
|
const BZ2 = 0x2000;
|
|
const MASK = 0x3000;
|
|
const START = 'index.php';
|
|
const LEN = XXXX;
|
|
|
|
static function go($return = false)
|
|
{
|
|
$fp = fopen(__FILE__, 'rb');
|
|
fseek($fp, self::LEN);
|
|
$L = unpack('V', $a = (string)fread($fp, 4));
|
|
$m = '';
|
|
|
|
do {
|
|
$read = 8192;
|
|
if ($L[1] - strlen($m) < 8192) {
|
|
$read = $L[1] - strlen($m);
|
|
}
|
|
$last = (string)fread($fp, $read);
|
|
$m .= $last;
|
|
} while (strlen($last) && strlen($m) < $L[1]);
|
|
|
|
if (strlen($m) < $L[1]) {
|
|
die('ERROR: manifest length read was "' .
|
|
strlen($m) .'" should be "' .
|
|
$L[1] . '"');
|
|
}
|
|
|
|
$info = self::_unpack($m);
|
|
$f = $info['c'];
|
|
|
|
if ($f & self::GZ) {
|
|
if (!function_exists('gzinflate')) {
|
|
die('Error: zlib extension is not enabled -' .
|
|
' gzinflate() function needed for zlib-compressed .phars');
|
|
}
|
|
}
|
|
|
|
if ($f & self::BZ2) {
|
|
if (!function_exists('bzdecompress')) {
|
|
die('Error: bzip2 extension is not enabled -' .
|
|
' bzdecompress() function needed for bz2-compressed .phars');
|
|
}
|
|
}
|
|
|
|
$temp = self::tmpdir();
|
|
|
|
if (!$temp || !is_writable($temp)) {
|
|
$sessionpath = session_save_path();
|
|
if (strpos ($sessionpath, ";") !== false)
|
|
$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
|
|
if (!file_exists($sessionpath) || !is_dir($sessionpath)) {
|
|
die('Could not locate temporary directory to extract phar');
|
|
}
|
|
$temp = $sessionpath;
|
|
}
|
|
|
|
$temp .= '/pharextract/'.basename(__FILE__, '.phar');
|
|
self::$temp = $temp;
|
|
self::$origdir = getcwd();
|
|
@mkdir($temp, 0777, true);
|
|
$temp = realpath($temp);
|
|
|
|
if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {
|
|
self::_removeTmpFiles($temp, getcwd());
|
|
@mkdir($temp, 0777, true);
|
|
@file_put_contents($temp . '/' . md5_file(__FILE__), '');
|
|
|
|
foreach ($info['m'] as $path => $file) {
|
|
$a = !file_exists(dirname($temp . '/' . $path));
|
|
@mkdir(dirname($temp . '/' . $path), 0777, true);
|
|
clearstatcache();
|
|
|
|
if ($path[strlen($path) - 1] == '/') {
|
|
@mkdir($temp . '/' . $path, 0777);
|
|
} else {
|
|
file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
|
|
@chmod($temp . '/' . $path, 0666);
|
|
}
|
|
}
|
|
}
|
|
|
|
chdir($temp);
|
|
|
|
if (!$return) {
|
|
include self::START;
|
|
}
|
|
}
|
|
|
|
static function tmpdir()
|
|
{
|
|
if (strpos(PHP_OS, 'WIN') !== false) {
|
|
if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {
|
|
return $var;
|
|
}
|
|
if (is_dir('/temp') || mkdir('/temp')) {
|
|
return realpath('/temp');
|
|
}
|
|
return false;
|
|
}
|
|
if ($var = getenv('TMPDIR')) {
|
|
return $var;
|
|
}
|
|
return realpath('/tmp');
|
|
}
|
|
|
|
static function _unpack($m)
|
|
{
|
|
$info = unpack('V', substr($m, 0, 4));
|
|
// skip API version, phar flags, alias, metadata
|
|
$l = unpack('V', substr($m, 10, 4));
|
|
$m = substr($m, 14 + $l[1]);
|
|
$s = unpack('V', substr($m, 0, 4));
|
|
$o = 0;
|
|
$start = 4 + $s[1];
|
|
$ret['c'] = 0;
|
|
|
|
for ($i = 0; $i < $info[1]; $i++) {
|
|
// length of the file name
|
|
$len = unpack('V', substr($m, $start, 4));
|
|
$start += 4;
|
|
// file name
|
|
$savepath = substr($m, $start, $len[1]);
|
|
$start += $len[1];
|
|
// retrieve manifest data:
|
|
// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags
|
|
// 5 = metadata length
|
|
$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
|
|
$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
|
|
& 0xffffffff);
|
|
$ret['m'][$savepath][7] = $o;
|
|
$o += $ret['m'][$savepath][2];
|
|
$start += 24 + $ret['m'][$savepath][5];
|
|
$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
static function extractFile($path, $entry, $fp)
|
|
{
|
|
$data = '';
|
|
$c = $entry[2];
|
|
|
|
while ($c) {
|
|
if ($c < 8192) {
|
|
$data .= @fread($fp, $c);
|
|
$c = 0;
|
|
} else {
|
|
$c -= 8192;
|
|
$data .= @fread($fp, 8192);
|
|
}
|
|
}
|
|
|
|
if ($entry[4] & self::GZ) {
|
|
$data = gzinflate($data);
|
|
} elseif ($entry[4] & self::BZ2) {
|
|
$data = bzdecompress($data);
|
|
}
|
|
|
|
if (strlen($data) != $entry[0]) {
|
|
die("Invalid internal .phar file (size error " . strlen($data) . " != " .
|
|
$entry[0] . ")");
|
|
}
|
|
|
|
if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) {
|
|
die("Invalid internal .phar file (checksum error)");
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
static function _removeTmpFiles($temp, $origdir)
|
|
{
|
|
chdir($temp);
|
|
|
|
foreach (glob('*') as $f) {
|
|
if (file_exists($f)) {
|
|
is_dir($f) ? @rmdir($f) : @unlink($f);
|
|
if (file_exists($f) && is_dir($f)) {
|
|
self::_removeTmpFiles($f, getcwd());
|
|
}
|
|
}
|
|
}
|
|
|
|
@rmdir($temp);
|
|
clearstatcache();
|
|
chdir($origdir);
|
|
}
|
|
}
|