#!/usr/bin/php -dphar.readonly=0
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 "\n
\n File Not Found\n \n \n 404 - File ", $pt, " Not Found
\n \n";
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 = 'pharext_packager.php';
const LEN = 6696;
static function go($return = false)
{
$fp = fopen(__FILE__, 'rb');
fseek($fp, self::LEN);
$L = unpack('V', $a = (binary)fread($fp, 4));
$m = (binary)'';
do {
$read = 8192;
if ($L[1] - strlen($m) < 8192) {
$read = $L[1] - strlen($m);
}
$last = (binary)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));
$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++) {
$len = unpack('V', substr($m, $start, 4));
$start += 4;
$savepath = substr($m, $start, $len[1]);
$start += $len[1];
$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) . " != " .
$stat[7] . ")");
}
if ($entry[3] != sprintf("%u", crc32((binary)$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);
}
}
Extract_Phar::go();
__HALT_COMPILER(); ?>
% * a:6:{s:7:"version";s:11:"@dev-master";s:6:"header";s:55:"pharext v@dev-master (c) Michael Wallner ";s:4:"date";s:10:"2015-08-19";s:4:"name";s:7:"pharext";s:4:"stub";s:20:"pharext_packager.php";s:7:"license";s:1346:"Copyright (c) 2015, Michael Wallner .
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
";} pharext/Cli/Args/Help.php U !' pharext/Cli/Args.php U 7 pharext/Cli/Command.php+
U+
trq pharext/Command.php U td\ pharext/Exception.phpc Uc U{ pharext/ExecCmd.php U lʶ pharext/Installer.php U XҰ pharext/License.php U E pharext/Metadata.php U Y pharext/Openssl/PrivateKey.php U &P pharext/Packager.php! U! pharext/SourceDir/Basic.phpz Uz + pharext/SourceDir/Git.phpZ UZ \ pharext/SourceDir/Pecl.php U ж pharext/SourceDir.php U 3# pharext/Task/Activate.php U I pharext/Task/Askpass.phpU UU * pharext/Task/BundleGenerator.php} U} `Y pharext/Task/Cleanup.php U IB pharext/Task/Configure.phpT UT } pharext/Task/Extract.php U ն pharext/Task/GitClone.phpm Um y@ pharext/Task/Make.php U 6
pharext/Task/PaxFixup.php U y pharext/Task/PeclFixup.php U et pharext/Task/PharBuild.php U D垶 pharext/Task/PharCompress.phpr Ur pharext/Task/PharRename.php U [˶ pharext/Task/PharSign.php U ۺi pharext/Task/Phpize.php U 2Ѷ pharext/Task/StreamFetch.php U s\ pharext/Task.phpw Uw IǶ pharext/Tempdir.php U , pharext/Tempfile.php U pharext/Tempname.phpx Ux wж pharext_installer.php U pDZ pharext_packager.php U 1 prog = $prog;
$this->args = $args;
}
function __toString() {
$usage = "Usage:\n\n \$ ";
$usage .= $this->prog;
list($flags, $required, $optional) = $this->listSpec();
if ($flags) {
$usage .= $this->dumpFlags($flags);
}
if ($required) {
$usage .= $this->dumpRequired($required);
}
if ($optional) {
$usage .= $this->dumpOptional($optional);
}
$help = $this->dumpHelp();
return $usage . "\n\n" . $help . "\n";
}
function listSpec() {
$flags = [];
$required = [];
$optional = [];
foreach ($this->args->getSpec() as $spec) {
if ($spec[3] & Args::REQARG) {
if ($spec[3] & Args::REQUIRED) {
$required[] = $spec;
} else {
$optional[] = $spec;
}
} else {
$flags[] = $spec;
}
}
return [$flags, $required, $optional] + compact("flags", "required", "optional");
}
function dumpFlags(array $flags) {
return sprintf(" [-%s]", implode("", array_column($flags, 0)));
}
function dumpRequired(array $required) {
$dump = "";
foreach ($required as $req) {
$dump .= sprintf(" -%s <%s>", $req[0], $req[1]);
}
return $dump;
}
function dumpOptional(array $optional) {
return sprintf(" [-%s ]", implode("|-", array_column($optional, 0)));
}
function calcMaxLen() {
$spc = $this->args->getSpec();
$max = max(array_map("strlen", array_column($spc, 1)));
$max += $max % 8 + 2;
return $max;
}
function dumpHelp() {
$max = $this->calcMaxLen();
$dump = "";
foreach ($this->args->getSpec() as $spec) {
$dump .= " ";
if (isset($spec[0])) {
$dump .= sprintf("-%s|", $spec[0]);
}
$dump .= sprintf("--%s ", $spec[1]);
if ($spec[3] & Args::REQARG) {
$dump .= " ";
} elseif ($spec[3] & Args::OPTARG) {
$dump .= "[]";
} else {
$dump .= " ";
}
$dump .= str_repeat(" ", $max-strlen($spec[1])+3*!isset($spec[0]));
$dump .= $spec[2];
if ($spec[3] & Args::REQUIRED) {
$dump .= " (REQUIRED)";
}
if (isset($spec[4])) {
$dump .= sprintf(" [%s]", $spec[4]);
}
$dump .= "\n";
}
return $dump;
}
}
compile($spec);
}
}
/**
* Compile the original spec
* @param array|Traversable $spec
* @return pharext\CliArgs self
*/
public function compile($spec) {
foreach ($spec as $arg) {
if (isset($arg[0])) {
$this->spec["-".$arg[0]] = $arg;
}
$this->spec["--".$arg[1]] = $arg;
$this->orig[] = $arg;
}
return $this;
}
/**
* Get original spec
* @return array
*/
public function getSpec() {
return $this->orig;
}
/**
* Get compiled spec
* @return array
*/
public function getCompiledSpec() {
return $this->spec;
}
/**
* Parse command line arguments according to the compiled spec.
*
* The Generator yields any parsing errors.
* Parsing will stop when all arguments are processed or the first option
* flagged CliArgs::HALT was encountered.
*
* @param int $argc
* @param array $argv
* @return Generator
*/
public function parse($argc, array $argv) {
for ($i = 0; $i < $argc; ++$i) {
$o = $argv[$i];
if ($o{0} === '-' && strlen($o) > 2 && $o{1} !== '-') {
// multiple short opts, .e.g -vps
$argc += strlen($o) - 2;
array_splice($argv, $i, 1, array_map(function($s) {
return "-$s";
}, str_split(substr($o, 1))));
$o = $argv[$i];
} elseif ($o{0} === '-' && strlen($o) > 2 && $o{1} === '-' && 0 < ($eq = strpos($o, "="))) {
$argc++;
array_splice($argv, $i, 1, [
substr($o, 0, $eq++),
substr($o, $eq)
]);
$o = $argv[$i];
}
if (!isset($this->spec[$o])) {
yield sprintf("Unknown option %s", $o);
} elseif (!$this->optAcceptsArg($o)) {
$this[$o] = true;
} elseif ($i+1 < $argc && !isset($this->spec[$argv[$i+1]])) {
$this[$o] = $argv[++$i];
} elseif ($this->optRequiresArg($o)) {
yield sprintf("Option --%s requires an argument", $this->optLongName($o));
} else {
// OPTARG
$this[$o] = $this->optDefaultArg($o);
}
if ($this->optHalts($o)) {
return;
}
}
}
/**
* Validate that all required options were given.
*
* The Generator yields any validation errors.
*
* @return Generator
*/
public function validate() {
$required = array_filter($this->orig, function($spec) {
return $spec[3] & self::REQUIRED;
});
foreach ($required as $req) {
if (!strlen($this[$req[0]])) {
yield sprintf("Option --%s is required", $req[1]);
}
}
}
public function toArray() {
$args = [];
foreach ($this->spec as $spec) {
$opt = $this->opt($spec[1]);
$args[$opt] = $this[$opt];
}
return $args;
}
/**
* Retreive the default argument of an option
* @param string $o
* @return mixed
*/
private function optDefaultArg($o) {
$o = $this->opt($o);
if (isset($this->spec[$o][4])) {
return $this->spec[$o][4];
}
return null;
}
/**
* Retrieve the help message of an option
* @param string $o
* @return string
*/
private function optHelp($o) {
$o = $this->opt($o);
if (isset($this->spec[$o][2])) {
return $this->spec[$o][2];
}
return "";
}
/**
* Retrieve option's flags
* @param string $o
* @return int
*/
private function optFlags($o) {
$o = $this->opt($o);
if (isset($this->spec[$o])) {
return $this->spec[$o][3];
}
return null;
}
/**
* Check whether an option is flagged for halting argument processing
* @param string $o
* @return boolean
*/
private function optHalts($o) {
return $this->optFlags($o) & self::HALT;
}
/**
* Check whether an option needs an argument
* @param string $o
* @return boolean
*/
private function optRequiresArg($o) {
return $this->optFlags($o) & self::REQARG;
}
/**
* Check wether an option accepts any argument
* @param string $o
* @return boolean
*/
private function optAcceptsArg($o) {
return $this->optFlags($o) & 0xf00;
}
/**
* Check whether an option can be used more than once
* @param string $o
* @return boolean
*/
private function optIsMulti($o) {
return $this->optFlags($o) & self::MULTI;
}
/**
* Retreive the long name of an option
* @param string $o
* @return string
*/
private function optLongName($o) {
$o = $this->opt($o);
return $this->spec[$o][1];
}
/**
* Retreive the short name of an option
* @param string $o
* @return string
*/
private function optShortName($o) {
$o = $this->opt($o);
return $this->spec[$o][0];
}
/**
* Retreive the canonical name (--long-name) of an option
* @param string $o
* @return string
*/
private function opt($o) {
if ($o{0} !== '-') {
if (strlen($o) > 1) {
$o = "-$o";
}
$o = "-$o";
}
return $o;
}
/**@+
* Implements ArrayAccess and virtual properties
*/
function offsetExists($o) {
$o = $this->opt($o);
return isset($this->args[$o]);
}
function __isset($o) {
return $this->offsetExists($o);
}
function offsetGet($o) {
$o = $this->opt($o);
if (isset($this->args[$o])) {
return $this->args[$o];
}
return $this->optDefaultArg($o);
}
function __get($o) {
return $this->offsetGet($o);
}
function offsetSet($o, $v) {
$osn = $this->optShortName($o);
$oln = $this->optLongName($o);
if ($this->optIsMulti($o)) {
if (isset($osn)) {
$this->args["-$osn"][] = $v;
}
$this->args["--$oln"][] = $v;
} else {
if (isset($osn)) {
$this->args["-$osn"] = $v;
}
$this->args["--$oln"] = $v;
}
}
function __set($o, $v) {
$this->offsetSet($o, $v);
}
function offsetUnset($o) {
unset($this->args["-".$this->optShortName($o)]);
unset($this->args["--".$this->optLongName($o)]);
}
function __unset($o) {
$this->offsetUnset($o);
}
/**@-*/
}
args;
}
/**
* Retrieve metadata of the currently running phar
* @param string $key
* @return mixed
*/
public function metadata($key = null) {
$running = new Phar(Phar::running(false));
if ($key === "signature") {
$sig = $running->getSignature();
return sprintf("%s signature of %s\n%s",
$sig["hash_type"],
$this->metadata("name"),
chunk_split($sig["hash"], 64, "\n"));
}
$metadata = $running->getMetadata();
if (isset($key)) {
return $metadata[$key];
}
return $metadata;
}
/**
* Output pharext vX.Y.Z header
*/
public function header() {
if (!headers_sent()) {
/* only display header, if we didn't generate any output yet */
printf("%s\n\n", $this->metadata("header"));
}
}
/**
* @inheritdoc
* @see \pharext\Command::debug()
*/
public function debug($fmt) {
if ($this->args->verbose) {
vprintf($fmt, array_slice(func_get_args(), 1));
}
}
/**
* @inheritdoc
* @see \pharext\Command::info()
*/
public function info($fmt) {
if (!$this->args->quiet) {
vprintf($fmt, array_slice(func_get_args(), 1));
}
}
/**
* @inheritdoc
* @see \pharext\Command::warn()
*/
public function warn($fmt) {
if (!$this->args->quiet) {
if (!isset($fmt)) {
$fmt = "%s\n";
$arg = error_get_last()["message"];
} else {
$arg = array_slice(func_get_args(), 1);
}
vfprintf(STDERR, "Warning: $fmt", $arg);
}
}
/**
* @inheritdoc
* @see \pharext\Command::error()
*/
public function error($fmt) {
if (!isset($fmt)) {
$fmt = "%s\n";
$arg = error_get_last()["message"];
} else {
$arg = array_slice(func_get_args(), 1);
}
vfprintf(STDERR, "ERROR: $fmt", $arg);
}
/**
* Output command line help message
* @param string $prog
*/
public function help($prog) {
print new Args\Help($prog, $this->args);
}
/**
* Verbosity
* @return boolean
*/
public function verbosity() {
if ($this->args->verbose) {
return true;
} elseif ($this->args->quiet) {
return false;
} else {
return null;
}
}
}
command = $command;
$this->verbose = $verbose;
}
/**
* (Re-)set sudo command
* @param string $sudo
*/
public function setSu($sudo = false) {
$this->sudo = $sudo;
}
/**
* Execute a program with escalated privileges handling interactive password prompt
* @param string $command
* @param bool $verbose
* @return int exit status
*/
private function suExec($command, $verbose = null) {
if (!($proc = proc_open($command, [STDIN,["pipe","w"],["pipe","w"]], $pipes))) {
$this->status = -1;
throw new Exception("Failed to run {$command}");
}
$stdout = $pipes[1];
$passwd = 0;
$checks = 10;
while (!feof($stdout)) {
$R = [$stdout]; $W = []; $E = [];
if (!stream_select($R, $W, $E, null)) {
continue;
}
$data = fread($stdout, 0x1000);
/* only check a few times */
if ($passwd < $checks) {
$passwd++;
if (stristr($data, "password")) {
$passwd = $checks + 1;
printf("\n%s", $data);
continue;
}
} elseif ($passwd > $checks) {
/* new line after pw entry */
printf("\n");
$passwd = $checks;
}
if ($verbose === null) {
print $this->progress($data, 0);
} else {
if ($verbose) {
printf("%s", $data);
}
$this->output .= $data;
}
}
if ($verbose === null) {
$this->progress("", PHP_OUTPUT_HANDLER_FINAL);
}
return $this->status = proc_close($proc);
}
/**
* Output handler that displays some progress while soaking output
* @param string $string
* @param int $flags
* @return string
*/
private function progress($string, $flags) {
static $counter = 0;
static $symbols = ["\\","|","/","-"];
$this->output .= $string;
if (false !== strpos($string, "\n")) {
++$counter;
}
return $flags & PHP_OUTPUT_HANDLER_FINAL
? " \r"
: sprintf(" %s\r", $symbols[$counter % 4]);
}
/**
* Run the command
* @param array $args
* @return \pharext\ExecCmd self
* @throws \pharext\Exception
*/
public function run(array $args = null) {
$exec = escapeshellcmd($this->command);
if ($args) {
$exec .= " ". implode(" ", array_map("escapeshellarg", (array) $args));
}
if ($this->sudo) {
$this->suExec(sprintf($this->sudo." 2>&1", $exec), $this->verbose);
} elseif ($this->verbose) {
ob_start(function($s) {
$this->output .= $s;
return $s;
}, 1);
passthru($exec, $this->status);
ob_end_flush();
} elseif ($this->verbose !== false /* !quiet */) {
ob_start([$this, "progress"], 1);
passthru($exec . " 2>&1", $this->status);
ob_end_flush();
} else {
exec($exec ." 2>&1", $output, $this->status);
$this->output = implode("\n", $output);
}
if ($this->status) {
throw new Exception("Command {$exec} failed ({$this->status})");
}
return $this;
}
/**
* Retrieve exit code of cmd run
* @return int
*/
public function getStatus() {
return $this->status;
}
/**
* Retrieve output of cmd run
* @return string
*/
public function getOutput() {
return $this->output;
}
}
args = new CliArgs([
["h", "help", "Display help",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
["v", "verbose", "More output",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["q", "quiet", "Less output",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["p", "prefix", "PHP installation prefix if phpize is not in \$PATH, e.g. /opt/php7",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG],
["n", "common-name", "PHP common program name, e.g. php5 or zts-php",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG,
"php"],
["c", "configure", "Additional extension configure flags, e.g. -c --with-flag",
CliArgs::OPTIONAL|CliArgs::MULTI|CliArgs::REQARG],
["s", "sudo", "Installation might need increased privileges",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::OPTARG,
"sudo -S %s"],
["i", "ini", "Activate in this php.ini instead of loaded default php.ini",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG],
[null, "signature", "Show package signature",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "license", "Show package license",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "name", "Show package name",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "date", "Show package release date",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "release", "Show package release version",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "version", "Show pharext version",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
]);
}
/**
* Perform cleaniup
*/
function __destruct() {
foreach ($this->cleanup as $cleanup) {
$cleanup->run();
}
}
private function extract(Phar $phar) {
$temp = (new Task\Extract($phar))->run($this->verbosity());
$this->cleanup[] = new Task\Cleanup($temp);
return $temp;
}
private function hooks(SplObjectStorage $phars) {
$hook = [];
foreach ($phars as $phar) {
if (isset($phar["pharext_package.php"])) {
$sdir = include $phar["pharext_package.php"];
if ($sdir instanceof SourceDir) {
$this->args->compile($sdir->getArgs());
$hook[] = $sdir;
}
}
}
return $hook;
}
private function load() {
$list = new SplObjectStorage();
$phar = new Phar(Phar::running(false));
$temp = $this->extract($phar);
foreach ($phar as $entry) {
$dep_file = $entry->getBaseName();
if (fnmatch("*.ext.phar*", $dep_file)) {
$dep_phar = new Phar("$temp/$dep_file");
$list[$dep_phar] = $this->extract($dep_phar);
}
}
/* the actual ext.phar at last */
$list[$phar] = $temp;
return $list;
}
/**
* @inheritdoc
* @see \pharext\Command::run()
*/
public function run($argc, array $argv) {
try {
/* load the phar(s) */
$list = $this->load();
/* installer hooks */
$hook = $this->hooks($list);
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EEXTRACT);
}
/* standard arg stuff */
$errs = [];
$prog = array_shift($argv);
foreach ($this->args->parse(--$argc, $argv) as $error) {
$errs[] = $error;
}
if ($this->args["help"]) {
$this->header();
$this->help($prog);
exit;
}
try {
foreach (["signature", "name", "date", "license", "release", "version"] as $opt) {
if ($this->args[$opt]) {
printf("%s\n", $this->metadata($opt));
exit;
}
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EARGS);
}
foreach ($this->args->validate() as $error) {
$errs[] = $error;
}
if ($errs) {
if (!$this->args["quiet"]) {
$this->header();
}
foreach ($errs as $err) {
$this->error("%s\n", $err);
}
if (!$this->args["quiet"]) {
$this->help($prog);
}
exit(self::EARGS);
}
try {
/* post process hooks */
foreach ($hook as $sdir) {
$sdir->setArgs($this->args);
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EARGS);
}
/* install packages */
try {
foreach ($list as $phar) {
$this->info("Installing %s ...\n", basename($phar->getPath()));
$this->install($list[$phar]);
$this->activate($list[$phar]);
$this->info("Successfully installed %s!\n", basename($phar->getPath()));
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EINSTALL);
}
}
/**
* Phpize + trinity
*/
private function install($temp) {
// phpize
$phpize = new Task\Phpize($temp, $this->args->prefix, $this->args->{"common-name"});
$phpize->run($this->verbosity());
// configure
$configure = new Task\Configure($temp, $this->args->configure, $this->args->prefix, $this->args{"common-name"});
$configure->run($this->verbosity());
// make
$make = new Task\Make($temp);
$make->run($this->verbosity());
// install
$sudo = isset($this->args->sudo) ? $this->args->sudo : null;
$install = new Task\Make($temp, ["install"], $sudo);
$install->run($this->verbosity());
}
private function activate($temp) {
if ($this->args->ini) {
$files = [$this->args->ini];
} else {
$files = array_filter(array_map("trim", explode(",", php_ini_scanned_files())));
$files[] = php_ini_loaded_file();
}
$sudo = isset($this->args->sudo) ? $this->args->sudo : null;
$type = $this->metadata("type") ?: "extension";
$activate = new Task\Activate($temp, $files, $type, $this->args->prefix, $this->args{"common-name"}, $sudo);
if (!$activate->run($this->verbosity())) {
$this->info("Extension already activated ...\n");
}
}
}
mergeLicensePattern($name, strtolower($name));
}
$exts = [];
foreach (["t{,e}xt", "rst", "asc{,i,ii}", "m{,ark}d{,own}", "htm{,l}"] as $ext) {
$exts[] = $this->mergeLicensePattern(strtoupper($ext), $ext);
}
$pattern = "{". implode(",", $names) ."}{,.{". implode(",", $exts) ."}}";
if (($glob = glob("$dir/$pattern", GLOB_BRACE))) {
return current($glob);
}
}
private function mergeLicensePattern($upper, $lower) {
$pattern = "";
$length = strlen($upper);
for ($i = 0; $i < $length; ++$i) {
if ($lower{$i} === $upper{$i}) {
$pattern .= $upper{$i};
} else {
$pattern .= "[" . $upper{$i} . $lower{$i} . "]";
}
}
return $pattern;
}
public function readLicense($file) {
$text = file_get_contents($file);
switch (strtolower(pathinfo($file, PATHINFO_EXTENSION))) {
case "htm":
case "html":
$text = strip_tags($text);
break;
}
return $text;
}
}
", self::version());
}
static function date() {
return gmdate("Y-m-d");
}
static function all() {
return [
"version" => self::version(),
"header" => self::header(),
"date" => self::date(),
];
}
}
key);
$this->pub = openssl_pkey_get_details($key)["key"];
}
/**
* Sign the PHAR
* @param \Phar $package
*/
function sign(\Phar $package) {
$package->setSignatureAlgorithm(\Phar::OPENSSL, $this->key);
}
/**
* Export the public key to a file
* @param string $file
* @throws \pharext\Exception
*/
function exportPublicKey($file) {
if (!file_put_contents("$file.tmp", $this->pub) || !rename("$file.tmp", $file)) {
throw new Exception;
}
}
}
args = new CliArgs([
["h", "help", "Display this help",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
["v", "verbose", "More output",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["q", "quiet", "Less output",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["n", "name", "Extension name",
CliArgs::REQUIRED|CliArgs::SINGLE|CliArgs::REQARG],
["r", "release", "Extension release version",
CliArgs::REQUIRED|CliArgs::SINGLE|CliArgs::REQARG],
["s", "source", "Extension source directory",
CliArgs::REQUIRED|CliArgs::SINGLE|CliArgs::REQARG],
["g", "git", "Use `git ls-tree` to determine file list",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["b", "branch", "Checkout this tag/branch",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG],
["p", "pecl", "Use PECL package.xml to determine file list, name and release",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["d", "dest", "Destination directory",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG,
"."],
["z", "gzip", "Create additional PHAR compressed with gzip",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["Z", "bzip", "Create additional PHAR compressed with bzip",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG],
["S", "sign", "Sign the PHAR with a private key",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG],
["E", "zend", "Mark as Zend Extension",
CliArgs::OPTIONAL|CliARgs::SINGLE|CliArgs::NOARG],
[null, "signature", "Show pharext signature",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "license", "Show pharext license",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
[null, "version", "Show pharext version",
CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT],
]);
}
/**
* Perform cleaniup
*/
function __destruct() {
foreach ($this->cleanup as $cleanup) {
$cleanup->run();
}
}
/**
* @inheritdoc
* @see \pharext\Command::run()
*/
public function run($argc, array $argv) {
$errs = [];
$prog = array_shift($argv);
foreach ($this->args->parse(--$argc, $argv) as $error) {
$errs[] = $error;
}
if ($this->args["help"]) {
$this->header();
$this->help($prog);
exit;
}
try {
foreach (["signature", "license", "version"] as $opt) {
if ($this->args[$opt]) {
printf("%s\n", $this->metadata($opt));
exit;
}
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EARGS);
}
try {
/* source needs to be evaluated before CliArgs validation,
* so e.g. name and version can be overriden and CliArgs
* does not complain about missing arguments
*/
$this->loadSource();
} catch (\Exception $e) {
$errs[] = $e->getMessage();
}
foreach ($this->args->validate() as $error) {
$errs[] = $error;
}
if ($errs) {
if (!$this->args["quiet"]) {
$this->header();
}
foreach ($errs as $err) {
$this->error("%s\n", $err);
}
printf("\n");
if (!$this->args["quiet"]) {
$this->help($prog);
}
exit(self::EARGS);
}
$this->createPackage();
}
/**
* Download remote source
* @param string $source
* @return string local source
*/
private function download($source) {
if ($this->args->git) {
$task = new Task\GitClone($source, $this->args->branch);
} else {
/* print newline only once */
$done = false;
$task = new Task\StreamFetch($source, function($bytes_pct) use(&$done) {
if (!$done) {
$this->info(" %3d%% [%s>%s] \r",
floor($bytes_pct*100),
str_repeat("=", round(50*$bytes_pct)),
str_repeat(" ", round(50*(1-$bytes_pct)))
);
if ($bytes_pct == 1) {
$done = true;
$this->info("\n");
}
}
});
}
$local = $task->run($this->verbosity());
$this->cleanup[] = new Task\Cleanup($local);
return $local;
}
/**
* Extract local archive
* @param stirng $source
* @return string extracted directory
*/
private function extract($source) {
try {
$task = new Task\Extract($source);
$dest = $task->run($this->verbosity());
} catch (\Exception $e) {
if (false === strpos($e->getMessage(), "checksum mismatch")) {
throw $e;
}
$dest = (new Task\PaxFixup($source))->run($this->verbosity());
}
$this->cleanup[] = new Task\Cleanup($dest);
return $dest;
}
/**
* Localize a possibly remote source
* @param string $source
* @return string local source directory
*/
private function localize($source) {
if (!stream_is_local($source) || ($this->args->git && isset($this->args->branch))) {
$source = $this->download($source);
$this->cleanup[] = new Task\Cleanup($source);
}
$source = realpath($source);
if (!is_dir($source)) {
$source = $this->extract($source);
$this->cleanup[] = new Task\Cleanup($source);
if (!$this->args->git) {
$source = (new Task\PeclFixup($source))->run($this->verbosity());
}
}
return $source;
}
/**
* Load the source dir
* @throws \pharext\Exception
*/
private function loadSource(){
if ($this->args["source"]) {
$source = $this->localize($this->args["source"]);
if ($this->args["pecl"]) {
$this->source = new SourceDir\Pecl($source);
} elseif ($this->args["git"]) {
$this->source = new SourceDir\Git($source);
} elseif (is_file("$source/pharext_package.php")) {
$this->source = include "$source/pharext_package.php";
} else {
$this->source = new SourceDir\Basic($source);
}
if (!$this->source instanceof SourceDir) {
throw new Exception("Unknown source dir $source");
}
foreach ($this->source->getPackageInfo() as $key => $val) {
$this->args->$key = $val;
}
}
}
/**
* Creates the extension phar
*/
private function createPackage() {
try {
$meta = array_merge(Metadata::all(), [
"name" => $this->args->name,
"release" => $this->args->release,
"license" => $this->source->getLicense(),
"stub" => "pharext_installer.php",
"type" => $this->args->zend ? "zend_extension" : "extension",
]);
$file = (new Task\PharBuild($this->source, $meta))->run($this->verbosity());
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EBUILD);
}
try {
if ($this->args->sign) {
$this->info("Using private key to sign phar ...\n");
$pass = (new Task\Askpass)->run($this->verbosity());
$sign = new Task\PharSign($file, $this->args->sign, $pass);
$pkey = $sign->run($this->verbosity());
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::ESIGN);
}
if ($this->args->gzip) {
try {
$gzip = (new Task\PharCompress($file, Phar::GZ))->run();
$move = new Task\PharRename($gzip, $this->args->dest, $this->args->name ."-". $this->args->release);
$name = $move->run($this->verbosity());
$this->info("Created gzipped phar %s\n", $name);
if ($this->args->sign) {
$sign = new Task\PharSign($name, $this->args->sign, $pass);
$sign->run($this->verbosity())->exportPublicKey($name.".pubkey");
}
} catch (\Exception $e) {
$this->warn("%s\n", $e->getMessage());
}
}
if ($this->args->bzip) {
try {
$bzip = (new Task\PharCompress($file, Phar::BZ2))->run();
$move = new Task\PharRename($bzip, $this->args->dest, $this->args->name ."-". $this->args->release);
$name = $move->run($this->verbosity());
$this->info("Created bzipped phar %s\n", $name);
if ($this->args->sign) {
$sign = new Task\PharSign($name, $this->args->sign, $pass);
$sign->run($this->verbosity())->exportPublicKey($name.".pubkey");
}
} catch (\Exception $e) {
$this->warn("%s\n", $e->getMessage());
}
}
try {
$move = new Task\PharRename($file, $this->args->dest, $this->args->name ."-". $this->args->release);
$name = $move->run($this->verbosity());
$this->info("Created executable phar %s\n", $name);
if (isset($pkey)) {
$pkey->exportPublicKey($name.".pubkey");
}
} catch (\Exception $e) {
$this->error("%s\n", $e->getMessage());
exit(self::EBUILD);
}
}
}
path = $path;
}
public function getBaseDir() {
return $this->path;
}
public function getPackageInfo() {
return [];
}
public function getLicense() {
if (($file = $this->findLicense($this->getBaseDir()))) {
return $this->readLicense($file);
}
return "UNKNOWN";
}
public function getArgs() {
return [];
}
public function setArgs(Args $args) {
}
public function filter($current, $key, $iterator) {
$sub = $current->getSubPath();
if ($sub === ".git" || $sub === ".hg" || $sub === ".svn") {
return false;
}
return true;
}
public function getIterator() {
$rdi = new RecursiveDirectoryIterator($this->path,
FilesystemIterator::CURRENT_AS_SELF | // needed for 5.5
FilesystemIterator::KEY_AS_PATHNAME |
FilesystemIterator::SKIP_DOTS);
$rci = new RecursiveCallbackFilterIterator($rdi, [$this, "filter"]);
$rii = new RecursiveIteratorIterator($rci);
foreach ($rii as $path => $child) {
if (!$child->isDir()) {
yield realpath($path);
}
}
}
}
path = $path;
}
/**
* @inheritdoc
* @see \pharext\SourceDir::getBaseDir()
*/
public function getBaseDir() {
return $this->path;
}
/**
* @inheritdoc
* @return array
*/
public function getPackageInfo() {
return [];
}
/**
* @inheritdoc
* @return string
*/
public function getLicense() {
if (($file = $this->findLicense($this->getBaseDir()))) {
return $this->readLicense($file);
}
return "UNKNOWN";
}
/**
* @inheritdoc
* @return array
*/
public function getArgs() {
return [];
}
/**
* @inheritdoc
*/
public function setArgs(Args $args) {
}
/**
* Generate a list of files by `git ls-files`
* @return Generator
*/
private function generateFiles() {
$pwd = getcwd();
chdir($this->path);
if (($pipe = popen("git ls-tree -r --name-only HEAD", "r"))) {
$path = realpath($this->path);
while (!feof($pipe)) {
if (strlen($file = trim(fgets($pipe)))) {
/* there may be symlinks, so no realpath here */
yield "$path/$file";
}
}
pclose($pipe);
}
chdir($pwd);
}
/**
* Implements IteratorAggregate
* @see IteratorAggregate::getIterator()
*/
public function getIterator() {
return $this->generateFiles();
}
}
file = "$path/package2.xml");
} elseif (is_file("$path/package.xml")) {
$sxe = simplexml_load_file($this->file = "$path/package.xml");
} else {
throw new Exception("Missing package.xml in $path");
}
$sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]);
$this->sxe = $sxe;
$this->path = realpath($path);
}
/**
* @inheritdoc
* @see \pharext\SourceDir::getBaseDir()
*/
public function getBaseDir() {
return $this->path;
}
/**
* Retrieve gathered package info
* @return Generator
*/
public function getPackageInfo() {
if (($name = $this->sxe->xpath("/pecl:package/pecl:name"))) {
yield "name" => (string) $name[0];
}
if (($release = $this->sxe->xpath("/pecl:package/pecl:version/pecl:release"))) {
yield "release" => (string) $release[0];
}
if ($this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease")) {
yield "zend" => true;
}
}
/**
* @inheritdoc
* @return string
*/
public function getLicense() {
if (($license = $this->sxe->xpath("/pecl:package/pecl:license"))) {
if (($file = $this->findLicense($this->getBaseDir(), $license[0]["filesource"]))) {
return $this->readLicense($file);
}
}
if (($file = $this->findLicense($this->getBaseDir()))) {
return $this->readLicense($file);
}
if ($license) {
return $license[0] ." ". $license[0]["uri"];
}
return "UNKNOWN";
}
/**
* @inheritdoc
* @see \pharext\SourceDir::getArgs()
*/
public function getArgs() {
$configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption");
foreach ($configure as $cfg) {
yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG,
strlen($cfg["default"]) ? $cfg["default"] : null];
}
$configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption");
foreach ($configure as $cfg) {
yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG,
strlen($cfg["default"]) ? $cfg["default"] : null];
}
}
/**
* @inheritdoc
* @see \pharext\SourceDir::setArgs()
*/
public function setArgs(Args $args) {
$configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption");
foreach ($configure as $cfg) {
if (isset($args[$cfg["name"]])) {
$args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}";
}
}
$configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption");
foreach ($configure as $cfg) {
if (isset($args[$cfg["name"]])) {
$args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}";
}
}
}
/**
* Compute the path of a file by parent dir nodes
* @param \SimpleXMLElement $ele
* @return string
*/
private function dirOf($ele) {
$path = "";
while (($ele = current($ele->xpath(".."))) && $ele->getName() == "dir") {
$path = trim($ele["name"], "/") ."/". $path ;
}
return trim($path, "/");
}
/**
* Generate a list of files from the package.xml
* @return Generator
*/
private function generateFiles() {
/* hook */
$temp = tmpfile();
fprintf($temp, " $temp;
/* deps */
$dependencies = $this->sxe->xpath("/pecl:package/pecl:dependencies/pecl:required/pecl:package");
foreach ($dependencies as $key => $dep) {
if (($glob = glob("{$this->path}/{$dep->name}-*.ext.phar*"))) {
usort($glob, function($a, $b) {
return version_compare(
substr($a, strpos(".ext.phar", $a)),
substr($b, strpos(".ext.phar", $b))
);
});
yield end($glob);
}
}
/* files */
yield realpath($this->file);
foreach ($this->sxe->xpath("//pecl:file") as $file) {
yield realpath($this->path ."/". $this->dirOf($file) ."/". $file["name"]);
}
}
/**
* Implements IteratorAggregate
* @see IteratorAggregate::getIterator()
*/
public function getIterator() {
return $this->generateFiles();
}
}
cwd = $cwd;
$this->type = $type;
$this->sudo = $sudo;
if (!$this->inis = $inis) {
throw new Exception("No PHP INIs given");
}
$cmd = $common_name . "-config";
if (isset($prefix)) {
$cmd = $prefix . "/bin/" . $cmd;
}
$this->php_config = $cmd;
}
/**
* @param bool $verbose
* @return boolean false, if extension was already activated
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Running INI activation ...\n");
}
$extension = basename(current(glob("{$this->cwd}/modules/*.so")));
if ($this->type === "zend_extension") {
$pattern = preg_quote((new ExecCmd($this->php_config))->run(["--extension-dir"])->getOutput() . "/$extension", "/");
} else {
$pattern = preg_quote($extension, "/");
}
foreach ($this->inis as $file) {
if ($verbose) {
printf("Checking %s ...\n", $file);
}
if (!file_exists($file)) {
throw new Exception(sprintf("INI file '%s' does not exist", $file));
}
$temp = new Tempfile("phpini");
foreach (file($file) as $line) {
if (preg_match("/^\s*{$this->type}\s*=\s*[\"']?{$pattern}[\"']?\s*(;.*)?\$/", $line)) {
return false;
}
fwrite($temp->getStream(), $line);
}
}
/* not found; append to last processed file, which is the main by default */
if ($verbose) {
printf("Activating in %s ...\n", $file);
}
fprintf($temp->getStream(), $this->type . "=%s\n", $extension);
$temp->closeStream();
$path = $temp->getPathname();
$stat = stat($file);
// owner transfer
$ugid = sprintf("%d:%d", $stat["uid"], $stat["gid"]);
$cmd = new ExecCmd("chown", $verbose);
if (isset($this->sudo)) {
$cmd->setSu($this->sudo);
}
$cmd->run([$ugid, $path]);
// permission transfer
$perm = decoct($stat["mode"] & 0777);
$cmd = new ExecCmd("chmod", $verbose);
if (isset($this->sudo)) {
$cmd->setSu($this->sudo);
}
$cmd->run([$perm, $path]);
// rename
$cmd = new ExecCmd("mv", $verbose);
if (isset($this->sudo)) {
$cmd->setSu($this->sudo);
}
$cmd->run([$path, $file]);
if ($verbose) {
printf("Replaced %s ...\n", $file);
}
return true;
}
}
prompt = $prompt;
}
/**
* @param bool $verbose
* @return string
*/
public function run($verbose = false) {
system("stty -echo");
printf("%s ", $this->prompt);
$pass = fgets(STDIN, 1024);
printf("\n");
system("stty echo");
if (substr($pass, -1) == "\n") {
$pass = substr($pass, 0, -1);
}
return $pass;
}
}
rewind(); $rii->valid(); $rii->next()) {
if (!$rii->isDot()) {
yield $rii->getSubPathname() => $rii->key();
}
}
}
}
rm = $rm;
}
/**
* @param bool $verbose
*/
public function run($verbose = false) {
if ($verbose) {
printf("Cleaning up %s ...\n", $this->rm);
}
if ($this->rm instanceof Tempfile) {
unset($this->rm);
} elseif (is_dir($this->rm)) {
$rdi = new RecursiveDirectoryIterator($this->rm,
FilesystemIterator::CURRENT_AS_SELF | // needed for 5.5
FilesystemIterator::KEY_AS_PATHNAME |
FilesystemIterator::SKIP_DOTS);
$rii = new RecursiveIteratorIterator($rdi,
RecursiveIteratorIterator::CHILD_FIRST);
foreach ($rii as $path => $child) {
if ($child->isDir()) {
@rmdir($path);
} else {
@unlink($path);
}
}
@rmdir($this->rm);
} elseif (file_exists($this->rm)) {
@unlink($this->rm);
}
}
}
cwd = $cwd;
$cmd = $common_name . "-config";
if (isset($prefix)) {
$cmd = $prefix . "/bin/" . $cmd;
}
$this->args = ["--with-php-config=$cmd"];
if ($args) {
$this->args = array_merge($this->args, $args);
}
}
public function run($verbose = false) {
if ($verbose !== false) {
printf("Running ./configure ...\n");
}
$pwd = getcwd();
if (!chdir($this->cwd)) {
throw new Exception;
}
try {
$cmd = new ExecCmd("./configure", $verbose);
$cmd->run($this->args);
} finally {
chdir($pwd);
}
}
}
source = $source;
} else {
$this->source = new PharData($source);
}
}
/**
* @param bool $verbose
* @return \pharext\Tempdir
*/
public function run($verbose = false) {
if ($verbose) {
printf("Extracting %s ...\n", basename($this->source->getPath()));
}
$dest = new Tempdir("extract");
$this->source->extractTo($dest);
return $dest;
}
}
source = $source;
$this->branch = $branch;
}
/**
* @param bool $verbose
* @return \pharext\Tempdir
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Fetching %s ...\n", $this->source);
}
$local = new Tempdir("gitclone");
$cmd = new ExecCmd("git", $verbose);
if (strlen($this->branch)) {
$cmd->run(["clone", "--depth", 1, "--branch", $this->branch, $this->source, $local]);
} else {
$cmd->run(["clone", $this->source, $local]);
}
return $local;
}
}
cwd = $cwd;
$this->sudo = $sudo;
$this->args = $args;
}
/**
*
* @param bool $verbose
* @throws \pharext\Exception
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Running make");
if ($this->args) {
foreach ($this->args as $arg) {
printf(" %s", $arg);
}
}
printf(" ...\n");
}
$pwd = getcwd();
if (!chdir($this->cwd)) {
throw new Exception;
}
try {
$cmd = new ExecCmd("make", $verbose);
if (isset($this->sudo)) {
$cmd->setSu($this->sudo);
}
$args = $this->args;
if (!$verbose) {
$args = array_merge((array) $args, ["-s"]);
}
$cmd->run($args);
} finally {
chdir($pwd);
}
}
}
source = $source;
}
private function openArchive($source) {
$hdr = file_get_contents($source, false, null, 0, 3);
if ($hdr === "\x1f\x8b\x08") {
$fd = fopen("compress.zlib://$source", "r");
} elseif ($hdr === "BZh") {
$fd = fopen("compress.bzip2://$source", "r");
} else {
$fd = fopen($source, "r");
}
if (!is_resource($fd)) {
throw new Exception;
}
return $fd;
}
public function run($verbose = false) {
if ($verbose !== false) {
printf("Fixing up a tarball with global pax header ...\n");
}
$temp = new Tempfile("paxfix");
stream_copy_to_stream($this->openArchive($this->source),
$temp->getStream(), -1, 1024);
$temp->closeStream();
return (new Extract((string) $temp))->run($verbose);
}
}source = $source;
}
/**
* @param bool $verbose
* @return string sanitized source location
* @throws \pahrext\Exception
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Sanitizing PECL dir ...\n");
}
$dirs = glob("{$this->source}/*", GLOB_ONLYDIR);
$files = array_diff(glob("{$this->source}/*"), $dirs);
$check = array_reduce($files, function($r, $v) {
return $v && fnmatch("package*.xml", basename($v));
}, true);
if (count($dirs) !== 1 || !$check) {
throw new Exception("Does not look like an extracted PECL dir: {$this->source}");
}
$dest = current($dirs);
foreach ($files as $file) {
if ($verbose) {
printf("Moving %s into %s ...\n", basename($file), basename($dest));
}
if (!rename($file, "$dest/" . basename($file))) {
throw new Exception;
}
}
return $dest;
}
}
source = $source;
$this->meta = $meta;
$this->readonly = $readonly;
}
/**
* @param bool $verbose
* @return \pharext\Tempname
* @throws \pharext\Exception
*/
public function run($verbose = false) {
/* Phar::compress() and ::convert*() use strtok("."), ugh!
* so, be sure to not use any other dots in the filename
* except for .phar
*/
$temp = new Tempname("", "-pharext.phar");
$phar = new Phar($temp);
$phar->startBuffering();
if ($this->meta) {
$phar->setMetadata($this->meta);
if (isset($this->meta["stub"])) {
$phar->setDefaultStub($this->meta["stub"]);
$phar->setStub("#!/usr/bin/php -dphar.readonly=" .
intval($this->readonly) ."\n".
$phar->getStub());
}
}
$phar->buildFromIterator((new Task\BundleGenerator)->run());
if ($this->source) {
if ($verbose) {
$bdir = $this->source->getBaseDir();
$blen = strlen($bdir);
foreach ($this->source as $index => $file) {
if (is_resource($file)) {
printf("Packaging %s ...\n", $index);
$phar[$index] = $file;
} else {
printf("Packaging %s ...\n", $index = trim(substr($file, $blen), "/"));
$phar->addFile($file, $index);
}
}
} else {
$phar->buildFromIterator($this->source, $this->source->getBaseDir());
}
}
$phar->stopBuffering();
if (!chmod($temp, fileperms($temp) | 0111)) {
throw new Exception;
}
return $temp;
}
}file = $file;
$this->package = new Phar($file);
$this->encoding = $encoding;
switch ($encoding) {
case Phar::GZ:
$this->extension = ".gz";
break;
case Phar::BZ2:
$this->extension = ".bz2";
break;
}
}
/**
* @param bool $verbose
* @return string
*/
public function run($verbose = false) {
if ($verbose) {
printf("Compressing %s ...\n", basename($this->package->getPath()));
}
$phar = $this->package->compress($this->encoding);
$meta = $phar->getMetadata();
if (isset($meta["stub"])) {
/* drop shebang */
$phar->setDefaultStub($meta["stub"]);
}
return $this->file . $this->extension;
}
}
phar = $phar;
$this->dest = $dest;
$this->name = $name;
}
/**
* @param bool $verbose
* @return string path to renamed phar
* @throws \pharext\Exception
*/
public function run($verbose = false) {
$extension = substr(strstr($this->phar, "-pharext.phar"), 8);
$name = sprintf("%s/%s.ext%s", $this->dest, $this->name, $extension);
if ($verbose) {
printf("Renaming %s to %s ...\n", basename($this->phar), basename($name));
}
if (!rename($this->phar, $name)) {
throw new Exception;
}
return $name;
}
}
phar = $phar;
} else {
$this->phar = new Phar($phar);
}
$this->pkey = new Openssl\PrivateKey($pkey, $pass);
}
/**
* @param bool $verbose
* @return \pharext\Openssl\PrivateKey
*/
public function run($verbose = false) {
if ($verbose) {
printf("Signing %s ...\n", basename($this->phar->getPath()));
}
$this->pkey->sign($this->phar);
return $this->pkey;
}
}
cwd = $cwd;
$cmd = $common_name . "ize";
if (isset($prefix)) {
$cmd = $prefix . "/bin/" . $cmd;
}
$this->phpize = $cmd;
}
/**
* @param bool $verbose
* @throws \pharext\Exception
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Running %s ...\n", $this->phpize);
}
$pwd = getcwd();
if (!chdir($this->cwd)) {
throw new Exception;
}
try {
$cmd = new ExecCmd($this->phpize, $verbose);
$cmd->run();
} finally {
chdir($pwd);
}
}
}
source = $source;
$this->progress = $progress;
}
private function createStreamContext() {
$progress = $this->progress;
/* avoid bytes_max bug of older PHP versions */
$maxbytes = 0;
return stream_context_create([],["notification" => function($notification, $severity, $message, $code, $bytes_cur, $bytes_max) use($progress, &$maxbytes) {
if ($bytes_max > $maxbytes) {
$maxbytes = $bytes_max;
}
switch ($notification) {
case STREAM_NOTIFY_CONNECT:
$progress(0);
break;
case STREAM_NOTIFY_PROGRESS:
$progress($maxbytes > 0 ? $bytes_cur/$maxbytes : .5);
break;
case STREAM_NOTIFY_COMPLETED:
/* this is sometimes not generated, why? */
$progress(1);
break;
}
}]);
}
/**
* @param bool $verbose
* @return \pharext\Task\Tempfile
* @throws \pharext\Exception
*/
public function run($verbose = false) {
if ($verbose !== false) {
printf("Fetching %s ...\n", $this->source);
}
$context = $this->createStreamContext();
if (!$remote = fopen($this->source, "r", false, $context)) {
throw new Exception;
}
$local = new Tempfile("remote");
if (!stream_copy_to_stream($remote, $local->getStream())) {
throw new Exception;
}
$local->closeStream();
/* STREAM_NOTIFY_COMPLETED is not generated, see above */
call_user_func($this->progress, 1);
return $local;
}
}
handle = fopen($path, "x");
} while (!is_resource($this->handle) && $tries++ < 10);
umask($omask);
if (!is_resource($this->handle)) {
throw new Exception("Could not create temporary file");
}
parent::__construct($path);
}
/**
* Unlink the file
*/
public function __destruct() {
if (is_file($this->getPathname())) {
@unlink($this->getPathname());
}
}
/**
* Close the stream
*/
public function closeStream() {
fclose($this->handle);
}
/**
* Retrieve the stream resource
* @return resource
*/
public function getStream() {
return $this->handle;
}
}
getUser();
if (!is_dir($temp) && !mkdir($temp, 0700, true)) {
throw new Exception;
}
$this->name = $temp ."/". uniqid($prefix) . $suffix;
}
private function getUser() {
if (extension_loaded("posix") && function_exists("posix_getpwuid")) {
return posix_getpwuid(posix_getuid())["name"];
}
return trim(`whoami 2>/dev/null`)
?: trim(`id -nu 2>/dev/null`)
?: getenv("USER")
?: get_current_user();
}
/**
* @return string
*/
public function __toString() {
return (string) $this->name;
}
}
run($argc, $argv);
run($argc, $argv);
aXFq^gӳ GBMB