root/phar/phar.php

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __construct
  2. current
  3. __call
  4. __construct
  5. accept
  6. __construct
  7. notice
  8. error
  9. checkArgTyp
  10. getSubFuncs
  11. getCommands
  12. getArgTyps
  13. cli_arg_typ_bool
  14. cli_arg_typ_int
  15. cli_arg_typ_regex
  16. cli_arg_typ_select
  17. cli_arg_typ_dir
  18. cli_arg_typ_file
  19. cli_arg_typ_filenew
  20. cli_arg_typ_filecont
  21. cli_get_SP2
  22. cli_get_SP3
  23. cli_cmd_inf_help
  24. cli_wordwrap
  25. cli_help_get_args
  26. cli_cmd_arg_help
  27. cli_cmd_run_help
  28. cli_cmd_inf_help_list
  29. cli_cmd_run_help_list
  30. cli_get_SP2
  31. cli_get_SP3
  32. phar_args
  33. strEndsWith
  34. cli_arg_typ_loader
  35. cli_arg_typ_pharnew
  36. cli_arg_typ_pharfile
  37. cli_arg_typ_pharurl
  38. cli_arg_typ_phar
  39. cli_arg_typ_entry
  40. cli_arg_typ_compalg
  41. cli_arg_typ_privkey
  42. phar_check_hash
  43. cli_cmd_inf_pack
  44. cli_cmd_arg_pack
  45. phar_set_stub_begin
  46. phar_set_stub_end
  47. cli_cmd_run_pack
  48. phar_add
  49. phar_add_file
  50. phar_dir_echo
  51. phar_dir_operation
  52. cli_cmd_inf_list
  53. cli_cmd_arg_list
  54. cli_cmd_run_list
  55. cli_cmd_inf_tree
  56. cli_cmd_arg_tree
  57. cli_cmd_run_tree
  58. cli_cmd_inf_extract
  59. cli_cmd_arg_extract
  60. cli_cmd_run_extract
  61. phar_dir_extract
  62. cli_cmd_inf_delete
  63. cli_cmd_arg_delete
  64. cli_cmd_run_delete
  65. cli_cmd_inf_add
  66. cli_cmd_arg_add
  67. cli_cmd_run_add
  68. cli_cmd_inf_stub_set
  69. cli_cmd_arg_stub_set
  70. cli_cmd_run_stub_set
  71. cli_cmd_inf_stub_get
  72. cli_cmd_arg_stub_get
  73. cli_cmd_run_stub_get
  74. cli_cmd_inf_compress
  75. cli_cmd_arg_compress
  76. cli_cmd_run_compress
  77. cli_cmd_inf_sign
  78. cli_cmd_arg_sign
  79. cli_cmd_run_sign
  80. cli_cmd_inf_meta_set
  81. cli_cmd_arg_meta_set
  82. cli_cmd_run_meta_set
  83. cli_cmd_inf_meta_get
  84. cli_cmd_arg_meta_get
  85. cli_cmd_run_meta_get
  86. cli_cmd_inf_meta_del
  87. cli_cmd_arg_meta_del
  88. cli_cmd_run_meta_del
  89. cli_cmd_inf_info
  90. cli_cmd_arg_info
  91. cli_cmd_run_info
  92. cli_cmd_inf_version
  93. cli_cmd_arg_version
  94. cli_cmd_run_version

<?php
/** @file phar.php
 * @ingroup Phar
 * @brief class Phar Pre Command
 * @author  Marcus Boerger
 * @date    2007 - 2008
 *
 * Phar Command
 */
foreach(array("SPL", "Reflection", "Phar") as $ext) {
        if (!extension_loaded($ext)) {
                echo "$argv[0] requires PHP extension $ext.\n";
                exit(1);
        }
}

if (!class_exists('DirectoryTreeIterator', 0))
{

/** @file directorytreeiterator.inc
 * @ingroup Examples
 * @brief class DirectoryTreeIterator
 * @author  Marcus Boerger
 * @date    2003 - 2008
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   DirectoryIterator to generate ASCII graphic directory trees
 * @author  Marcus Boerger
 * @version 1.1
 */
class DirectoryTreeIterator extends RecursiveIteratorIterator
{
        /** Construct from a path.
         * @param $path directory to iterate
         */
        function __construct($path)
        {
                parent::__construct(
                        new RecursiveCachingIterator(
                                new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_FILENAME
                                ),
                                CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD
                        ),
                        parent::SELF_FIRST
                );
        }

        /** @return the current element prefixed with ASCII graphics
         */
        function current()
        {
                $tree = '';
                for ($l=0; $l < $this->getDepth(); $l++) {
                        $tree .= $this->getSubIterator($l)->hasNext() ? '| ' : '  ';
                }
                return $tree . ($this->getSubIterator($l)->hasNext() ? '|-' : '\-')
                                         . $this->getSubIterator($l)->__toString();
        }

        /** Aggregates the inner iterator
         */
        function __call($func, $params)
        {
                return call_user_func_array(array($this->getSubIterator(), $func), $params);
        }
}

}

if (!class_exists('DirectoryGraphIterator', 0))
{

/** @file directorygraphiterator.inc
 * @ingroup Examples
 * @brief class DirectoryGraphIterator
 * @author  Marcus Boerger
 * @date    2003 - 2008
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   A tree iterator that only shows directories.
 * @author  Marcus Boerger
 * @version 1.1
 */
class DirectoryGraphIterator extends DirectoryTreeIterator
{
        function __construct($path)
        {
                RecursiveIteratorIterator::__construct(
                        new RecursiveCachingIterator(
                                new ParentIterator(
                                        new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_FILENAME
                                        )
                                ),
                                CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD
                        ),
                        parent::SELF_FIRST
                );
        }
}

}

if (!class_exists('InvertedRegexIterator', 0))
{

/** @file invertedregexiterator.inc
 * @ingroup Phar
 * @brief class InvertedRegexIterator
 * @author  Marcus Boerger
 * @date    2007 - 2008
 *
 * Inverted RegexIterator
 */

/** @ingroup Phar
 * @brief   Inverted RegexIterator
 * @author  Marcus Boerger
 * @version 1.0
 */
class InvertedRegexIterator extends RegexIterator
{
        /** @return !RegexIterator::accept()
         */
        function accept()
        {
                return !RegexIterator::accept();
        }
}

}

if (!class_exists('CLICommand', 0))
{

/** @file clicommand.inc
 * @ingroup Phar
 * @brief class CLICommand
 * @author  Marcus Boerger
 * @date    2007 - 2008
 *
 * Phar Command
 */

/** @ingroup Phar
 * @brief   Abstract base console command implementation
 * @author  Marcus Boerger
 * @version 1.0
 */
abstract class CLICommand
{
        protected $argc;
        protected $argv;
        protected $cmds = array();
        protected $args = array();
        protected $typs = array();

        function __construct($argc, array $argv)
        {
                $this->argc = $argc;
                $this->argv = $argv;
                $this->cmds = self::getCommands($this);
                $this->typs = self::getArgTyps($this);

                if ($argc < 2) {
                        self::error("No command given, check ${argv[0]} help\n");
                } elseif (!isset($this->cmds[$argv[1]]['run'])) {
                        self::error("Unknown command '${argv[1]}', check ${argv[0]} help\n");
                } else {
                        $command = $argv[1];
                }

                if (isset($this->cmds[$command]['arg'])) {
                        $this->args = call_user_func(array($this, $this->cmds[$command]['arg']));
                        $i = 1;
                        $missing = false;
                        while (++$i < $argc) {
                                if ($argv[$i][0] == '-') {
                                        if (strlen($argv[$i]) == 2 && isset($this->args[$argv[$i][1]])) {
                                                $arg = $argv[$i][1];
                                                if (++$i >= $argc) {
                                                        self::error("Missing argument to parameter '$arg' of command '$command', check ${argv[0]} help\n");
                                                } else {
                                                        $this->args[$arg]['val'] = $this->checkArgTyp($arg, $i, $argc, $argv);
                                                }
                                        }  else {
                                                self::error("Unknown parameter '${argv[$i]}' to command $command, check ${argv[0]} help\n");
                                        }
                                } else {
                                        break;
                                }
                        }

                        if (isset($this->args[''])) {
                                if ($i >= $argc) {
                                        if (isset($this->args['']['require']) && $this->args['']['require']) {
                                                self::error("Missing default trailing arguments to command $command, check ${argv[0]} help\n");
                                        }
                                } else {
                                        $this->args['']['val'] = array();
                                        while($i < $argc) {
                                                $this->args['']['val'][] = $argv[$i++];
                                        }
                                }
                        } else if ($i < $argc) {
                                self::error("Unexpected default arguments to command $command, check ${argv[0]} help\n");
                        }

                        foreach($this->args as $arg => $inf) {
                                if (strlen($arg) && !isset($inf['val']) && isset($inf['required']) && $inf['required']) {
                                        $missing .=  "Missing parameter '-$arg' to command $command, check ${argv[0]} help\n";
                                }
                        }

                        if (strlen($missing)) {
                                self::error($missing);
                        }
                }

                call_user_func(array($this, $this->cmds[$command]['run']), $this->args);
        }

        static function notice ($msg)
        {
                fprintf(STDERR, $msg);
        }

        static function error ($msg, $exit_code = 1)
        {
                self::notice($msg);
                exit($exit_code);
        }

        function checkArgTyp($arg, $i, $argc, $argv)
        {
                $typ = $this->args[$arg]['typ'];

                if (isset($this->typs[$typ]['typ'])) {
                        return call_user_func(array($this, $this->typs[$typ]['typ']), $argv[$i], $this->args[$arg], $arg);
                } else {
                        return $argv[$i];
                }
        }

        static function getSubFuncs(CLICommand $cmdclass, $prefix, array $subs)
        {
                $a = array();
                $r = new ReflectionClass($cmdclass);
                $l = strlen($prefix);

                foreach($r->getMethods() as $m) {
                        if (substr($m->name, 0, $l) == $prefix) {
                                foreach($subs as $sub) {
                                        $what = substr($m->name, $l+strlen($sub)+1);
                                        $func = $prefix . $sub . '_' . $what;
                                        $what = str_replace('_', '-', $what);
                                        if ($r->hasMethod($func)) {
                                                if (!isset($a[$what])) {
                                                        $a[$what] = array();
                                                }
                                                $a[$what][$sub] = /*$m->class . '::' .*/ $func;
                                        }
                                }
                        }
                }
                return $a;
        }

        static function getCommands(CLICommand $cmdclass)
        {
                return self::getSubFuncs($cmdclass, 'cli_cmd_', array('arg','inf','run'));
        }

        static function getArgTyps(CLICommand $cmdclass)
        {
                return self::getSubFuncs($cmdclass, 'cli_arg_', array('typ'));
        }

        static function cli_arg_typ_bool($arg, $cfg, $key)
        {
                return (bool)$arg;
        }

        static function cli_arg_typ_int($arg, $cfg, $key)
        {
                if ((int)$arg != $arg) {
                        self::error("Argument to -$key must be an integer.\n");
                }

                return (int)$arg;
        }

        static function cli_arg_typ_regex($arg, $cfg, $key)
        {
                if (strlen($arg)) {
                        if (strlen($arg) > 1 && $arg[0] == $arg[strlen($arg)-1] && strpos('/,', $arg) !== false) {
                                return $arg;
                        } else {
                                return '/' . $arg . '/';
                        }
                } else {
                        return NULL;
                }
        }

        static function cli_arg_typ_select($arg, $cfg, $key)
        {
                if (!in_array($arg, array_keys($cfg['select']))) {
                        self::error("Parameter value '$arg' not one of '" . join("', '", array_keys($cfg['select'])) . "'.\n");
                }
                return $arg;
        }

        static function cli_arg_typ_dir($arg, $cfg, $key)
        {
                $f = realpath($arg);

                if ($f===false || !file_exists($f) || !is_dir($f)) {
                        self::error("Requested path '$arg' does not exist.\n");
                }
                return $f;
        }

        static function cli_arg_typ_file($arg)
        {
                $f = new SplFileInfo($arg);
                $f = $f->getRealPath();
                if ($f===false || !file_exists($f)) {
                        echo "Requested file '$arg' does not exist.\n";
                        exit(1);
                }
                return $f;
        }

        static function cli_arg_typ_filenew($arg, $cfg, $key)
        {
                $d = dirname($arg);
                $f = realpath($d);

                if ($f === false) {
                        self::error("Path for file '$arg' does not exist.\n");
                }
                return $f . '/' . basename($arg);
        }

        static function cli_arg_typ_filecont($arg, $cfg, $key)
        {
                return file_get_contents(self::cli_arg_typ_file($arg, $cfg, $key));
        }

        function cli_get_SP2($l1, $arg_inf)
        {
                return str_repeat(' ', $l1 + 2 + 4 + 8);
        }

        function cli_get_SP3($l1, $l2, $arg_inf)
        {
                return str_repeat(' ', $l1 + 2 + 4 + 8 + 2 + $l2 + 2);
        }

        static function cli_cmd_inf_help()
        {
                return "This help or help for a selected command.";
        }

        private function cli_wordwrap($what, $l, $sp)
        {
                $p = max(79 - $l, 40);     // minimum length for paragraph
                $b = substr($what, 0, $l); // strip out initial $l
                $r = substr($what, $l);    // remainder
                $r = str_replace("\n", "\n".$sp, $r); // in remainder replace \n's
                return $b . wordwrap($r, $p, "\n".$sp);
        }

        private function cli_help_get_args($func, $l, $sp, $required)
        {
                $inf = "";
                foreach(call_user_func($func, $l, $sp) as $arg => $conf) {
                        if ((isset($conf['required']) && $conf['required']) != $required) {
                                continue;
                        }

                        if (strlen($arg)) {
                                $arg = "-$arg  ";
                        } else {
                                $arg = "... ";
                        }

                        $sp2 = $this->cli_get_SP2($l, $inf);
                        $l2  = strlen($sp2);
                        $inf .= $this->cli_wordwrap($sp . $arg . $conf['inf'], $l2, $sp2) . "\n";

                        if (isset($conf['select']) && count($conf['select'])) {
                                $ls = 0;
                                foreach($conf['select'] as $opt => $what) {
                                        $ls = max($ls, strlen($opt));
                                }
                                $sp3 = $this->cli_get_SP3($l, $ls, $inf);
                                $l3  = strlen($sp3);
                                foreach($conf['select'] as $opt => $what) {
                                        $inf .= $this->cli_wordwrap($sp2 . "  " . sprintf("%-${ls}s  ", $opt) . $what, $l3, $sp3) . "\n";
                                }
                        }
                }
                if (strlen($inf)) {
                        if ($required) {
                                return $sp . "Required arguments:\n\n" . $inf;
                        } else {
                                return $sp . "Optional arguments:\n\n". $inf;
                        }
                }
        }

        function cli_cmd_arg_help()
        {
                return array('' => array('typ'=>'any','val'=>NULL,'inf'=>'Optional command to retrieve help for.'));
        }

        function cli_cmd_run_help()
        {
                $argv  = $this->argv;
                $which = $this->args['']['val'];
                if (isset($which)) {
                        if (count($which) != 1) {
                                self::error("More than one command given.\n");
                        }

                        $which = $which[0];
                        if (!array_key_exists($which, $this->cmds)) {
                                if (strtolower($which) == 'commands') {
                                        self::cli_cmd_run_help_list();
                                        exit(0);
                                }
                                self::error("Unknown command, cannot retrieve help.\n");
                        }

                        $l = strlen($which);
                        $cmds = array($which => $this->cmds[$which]);
                } else {
                        echo "\n$argv[0] <command> [options]\n\n";
                        $l = 0;
                        ksort($this->cmds);
                        foreach($this->cmds as $name => $funcs) {
                                $l = max($l, strlen($name));
                        }
                        $inf = "Commands:";
                        $lst = "";
                        $ind = strlen($inf) + 1;
                        foreach($this->cmds as $name => $funcs) {
                                $lst .= ' ' . $name;
                        }
                        echo $this->cli_wordwrap($inf.$lst, $ind, str_repeat(' ', $ind)) . "\n\n";
                        $cmds = $this->cmds;
                }
                $sp = str_repeat(' ', $l + 2);
                foreach($cmds as $name => $funcs) {
                        $inf = $name . substr($sp, strlen($name));
                        if (isset($funcs['inf'])) {
                                $inf .= $this->cli_wordwrap(call_user_func(array($this, $funcs['inf'])), $l, $sp) . "\n";
                                if (isset($funcs['arg'])) {
                                        $inf .= "\n";
                                        $inf .= $this->cli_help_get_args(array($this, $funcs['arg']), $l, $sp, true);
                                        $inf .= "\n";
                                        $inf .= $this->cli_help_get_args(array($this, $funcs['arg']), $l, $sp, false);
                                }
                        }
                        echo "$inf\n\n";
                }
                exit(0);
        }

        static function cli_cmd_inf_help_list()
        {
                return "Lists available commands.";
        }

        function cli_cmd_run_help_list()
        {
                ksort($this->cmds);
                echo join(' ', array_keys($this->cmds)) . "\n";
        }
}

}

if (!class_exists('PharCommand', 0))
{

/**
 * @file pharcommand.inc
 * @ingroup Phar
 * @brief class CLICommand
 * @author  Marcus Boerger
 * @date    2007 - 2008
 *
 * Phar Command
 */
// {{{ class PharCommand extends CLICommand
/**
 * PharCommand class
 * 
 * This class handles the handling of the phar
 * commands. It will be used from command line/console
 * in order to retrieve and execute phar functions.
 * 
 * @ingroup Phar
 * @brief   Phar console command implementation
 * @author  Marcus Boerger
 * @version 1.0
 */
class PharCommand extends CLICommand
{
        // {{{ public function cli_get_SP2
        public function cli_get_SP2($l1, $arg_inf)
        {
                return str_repeat(' ', $l1 + 2 + 4 + 9);
        }
        // }}}
        // {{{ public function cli_get_SP3
        /**
         * Cli Get SP3
         *
         * @param string $l1      Eleven
         * @param string $l2      Twelve
         * @param string $arg_inf
         * @return string  The repeated string.
         */
        function cli_get_SP3($l1, $l2, $arg_inf)
        {
                return str_repeat(' ', $l1 + 2 + 4 + 9 + 2 + $l2 + 2);
        }
        // }}}
        // {{{ static function phar_args
        /**
         * Phar arguments
         * 
         * This function contains all the phar commands
         *
         * @param  string $which    Which argument is chosen.
         * @param  string $phartype The type of phar, specific file to work on
         * @return unknown
         */
        static function phar_args($which, $phartype)
        {
                $phar_args = array(
                        'a' => array(
                                'typ' => 'alias',
                                'val' => NULL,
                                'inf' => '<alias>  Provide an alias name for the phar file.'
                        ),
                        'b' => array(
                                'typ' => 'any',
                                'val' => NULL,
                                'inf' => '<bang>   Hash-bang line to start the archive (e.g. #!/usr/bin/php). The hash '
                                                 .'         mark itself \'#!\' and the newline character are optional.'
                        ),
                        'c' => array(
                                'typ' => 'compalg',
                                'val' => NULL,
                                'inf' => '<algo>   Compression algorithm.',
                                'select' => array(
                                        '0'    => 'No compression',
                                        'none' => 'No compression',
                                        'auto' => 'Automatically select compression algorithm'
                                )
                        ),
                        'e' => array(
                                'typ' => 'entry',
                                'val' => NULL,
                                'inf' => '<entry>  Name of entry to work on (must include PHAR internal directory name if any).'
                        ),
                        'f' => array(
                                'typ' => $phartype,
                                'val' => NULL,
                                'inf' => '<file>   Specifies the phar file to work on.'
                        ),
                        'h' => array(
                                'typ' => 'select',
                                'val' => NULL,
                                'inf' => '<method> Selects the hash algorithm.',
                                'select' => array('md5' => 'MD5','sha1' => 'SHA1')
                        ),
                        'i' => array(
                                'typ' => 'regex',
                                'val' => NULL,
                                'inf' => '<regex>  Specifies a regular expression for input files.'
                        ),
                        'k' => array(
                                'typ' => 'any',
                                'val' => NULL,
                                'inf' => '<index>  Subscription index to work on.',
                        ),
                        'l' => array(
                                'typ' => 'int',
                                'val' => 0,
                                'inf' => '<level>  Number of preceding subdirectories to strip from file entries',
                        ),
                        'm' => array(
                                'typ' => 'any',
                                'val' => NULL,
                                'inf' => '<meta>   Meta data to store with entry (serialized php data).'
                        ),
                        'p' => array(
                                'typ' => 'loader',
                                'val' => NULL,
                                'inf' => '<loader> Location of PHP_Archive class file (pear list-files PHP_Archive).'
                                                 .'You can use \'0\' or \'1\' to locate it automatically using the mentioned '
                                                 .'pear command. When using \'0\' the command does not error out when the '
                                                 .'class file cannot be located. This switch also adds some code around the '
                                                 .'stub so that class PHP_Archive gets registered as phar:// stream wrapper '
                                                 .'if necessary. And finally this switch will add the file phar.inc from '
                                                 .'this package and load it to ensure class Phar is present.'
                                                 ,
                        ),
                        's' => array(
                                'typ' => 'file',
                                'val' => NULL,
                                'inf' => '<stub>   Select the stub file.'
                        ),
                        'x' => array(
                                'typ' => 'regex',
                                'val' => NULL,
                                'inf' => '<regex>  Regular expression for input files to exclude.'
                        ),
                        'y' => array(
                                'typ' => 'privkey',
                                'val' => NULL,
                                'inf' => '<key>    Private key for OpenSSL signing.',
                        ),
                );

                if (extension_loaded('zlib')) {
                        $phar_args['c']['select']['gz']    = 'GZip compression';
                        $phar_args['c']['select']['gzip']  = 'GZip compression';
                }

                if (extension_loaded('bz2')) {
                        $phar_args['c']['select']['bz2']   = 'BZip2 compression';
                        $phar_args['c']['select']['bzip2'] = 'BZip2 compression';
                }

                $hash_avail = Phar::getSupportedSignatures();
                $hash_optional = array('SHA-256' => 'SHA256',
                                                           'SHA-512' => 'SHA512',
                                                           'OpenSSL' => 'OpenSSL');
                if (!in_array('OpenSSL', $hash_avail)) {
                        unset($phar_args['y']);
                }

                foreach($hash_optional as $key => $name) {
                        if (in_array($key, $hash_avail)) {
                                $phar_args['h']['select'][strtolower($name)] = $name;
                        }
                }

                $args = array();

                foreach($phar_args as $lkey => $cfg) {
                        $ukey     = strtoupper($lkey);
                        $required = strpos($which, $ukey) !== false;
                        $optional = strpos($which, $lkey) !== false;

                        if ($required || $optional) {
                                $args[$lkey] = $cfg;
                                $args[$lkey]['required'] = $required;
                        }
                }
                return $args;
        }
        // }}}
        // {{{ static function strEndsWith
        /**
         * String Ends With
         * 
         * Whether a string ends with another needle.
         *
         * @param string $haystack  The haystack
         * @param string $needle    The needle.
         * @return mixed false if doesn't end with anything, the string
         *               substr'ed if the string ends with the needle.
         */
        static function strEndsWith($haystack, $needle)
        {
                return substr($haystack, -strlen($needle)) == $needle;
        }
        // }}}
        // {{{ static function cli_arg_typ_loader
        /**
         * Argument type loader
         *
         * @param string $arg   Either 'auto', 'optional' or an filename that
         *                      contains class PHP_Archive
         * @param  string $cfg  Configuration to pass to a new file
         * @param  string $key  The key
         * @return string $arg  The argument.
         */
        static function cli_arg_typ_loader($arg, $cfg, $key)
        {
                if (($arg == '0' || $arg == '1') && !file_exists($arg) && substr(PHP_OS, 0, 3) != 'WIN') {
                        $found = NULL;
                        $apiver = false;
                        $path = explode(PATH_SEPARATOR, $_ENV['PATH']);
                        $pear = false;
                        foreach ($path as $component) {
                                if (file_exists($component . DIRECTORY_SEPARATOR . 'pear')
                                        && is_executable($component . DIRECTORY_SEPARATOR . 'pear')) {
                                        $pear = true;
                                        break;
                                }
                        }
                        if ($pear) {
                                $apiver = `pear -q info PHP_Archive 2>/dev/null|grep 'API Version'`;
                                $apiver = trim(substr($apiver, strlen('API Version')));
                        }
                        if ($apiver) {
                                self::notice("PEAR package PHP_Archive: API Version: $apiver.\n");
                                $files  = explode("\n", `pear list-files PHP_Archive`);
                                $phpdir = `pear config-get php_dir 2>/dev/null`;
                                $phpdir = trim($phpdir);
                                self::notice("PEAR package PHP_Archive: $phpdir.\n");
                                if (is_dir($phpdir)) {
                                        foreach($files as $ent) {
                                                $matches = NULL;
                                                if (preg_match(",^php[ \t]+([^ \t].*[\\\\/]PHP[\\\\/]Archive\.php)$,", $ent, $matches)) {
                                                        $sub = $matches[1];
                                                        if (strpos($sub, $phpdir) !== 0) {
                                                                $found = NULL;
                                                                break;
                                                        }
                                                        $found = $sub;
                                                        break;
                                                }
                                        }
                                } else {
                                        self::notice("PEAR package PHP_Archive: corrupt or inaccessible base dir: $php_dir.\n");
                                }
                        }
                        if (isset($found)) {
                                self::notice("PEAR package PHP_Archive: $found.\n");
                        } else {
                                $msg = "PEAR package PHP_Archive not installed: generated phar will require PHP's phar extension be enabled.\n";
                                if ($arg == '0') {
                                        self::notice($msg);
                                } else {
                                        self::error($msg);
                                }
                        }
                        $arg = $found;
                }
                return self::cli_arg_typ_file($arg);
        }
        // }}}
        // {{{ static function cli_arg_typ_pharnew
        /**
         * Argument type new phar
         *
         * @param  string $arg  The new phar component.
         * @param  string $cfg  Configuration to pass to a new file
         * @param  string $key  The key
         * @return string $arg  The new argument file.
         */
        static function cli_arg_typ_pharnew($arg, $cfg, $key)
        {
                $arg = self::cli_arg_typ_filenew($arg, $cfg, $key);
                if (!Phar::isValidPharFilename($arg)) {
                        self::error("Phar files must have file extension '.phar', '.phar.php', '.phar.bz2' or '.phar.gz'.\n");
                }
                return $arg;
        }
        // }}}
        // {{{ static function cli_arg_typ_pharfile
        /**
         * Argument type existing Phar file
         * 
         * Return filename of an existing Phar.
         *
         * @param  string $arg      The file in the phar to open.
         * @param  string $cfg      The configuration information
         * @param  string $key      The key information.
         * @return string $pharfile The name of the loaded Phar file.
         * @note The Phar will be loaded
         */
        static function cli_arg_typ_pharfile($arg, $cfg, $key)
        {
                try {
                        $pharfile = self::cli_arg_typ_file($arg, $cfg, $key);

                        if (!Phar::loadPhar($pharfile)) {
                                self::error("Unable to open phar '$arg'\n");
                        }

                        return $pharfile;
                } catch(Exception $e) {
                        self::error("Exception while opening phar '$arg':\n" . $e->getMessage() . "\n");
                }
        }
        // }}}
        // {{{ static function cli_arg_typ_pharurl
        /**
         * Argument type Phar url-like
         * 
         * Check the argument as cli_arg_Typ_phar and return its name prefixed
         * with phar://
         * 
         * Ex:
         * <code>
         *  $arg = 'pharchive.phar/file.php';
         *  cli_arg_typ_pharurl($arg)
         * </code>
         *
         * @param  string $arg The url-like phar archive to retrieve.
         * @return string The phar file-archive.
         */
        static function cli_arg_typ_pharurl($arg, $cfg, $key)
        {
                return 'phar://' . self::cli_arg_typ_pharfile($arg, $cfg, $key);
        }
        // }}}
        // {{{ static function cli_arg_typ_phar
        /**
         * Cli argument type phar
         *
         * @param  string $arg  The phar archive to use.
         * @return object new Phar of the passed argument.
         */
        static function cli_arg_typ_phar($arg, $cfg, $key)
        {
                try {
                        return new Phar(self::cli_arg_typ_pharfile($arg, $cfg, $key));
                } catch(Exception $e) {
                        self::error("Exception while opening phar '$argv':\n" . $e->getMessage() . "\n");
                }
        }
        // }}}
        // {{{ static function cli_arg_typ_entry
        /**
         * Argument type Entry name
         *
         * @param  string $arg The argument (the entry)
         * @return string $arg The entry itself.
         */
        static function cli_arg_typ_entry($arg, $cfg, $key)
        {
                // no further check atm, maybe check for no '/' at beginning
                return $arg;
        }
        // }}}
        // {{{ static function cli_arg_typ_compalg
        /**
         * Argument type compression algorithm
         *
         * @param  string $arg  The phar selection
         * @param  string $cfg  The config option.
         * @param  string $key  The key information.
         * @return string $arg  The selected algorithm
         */
        static function cli_arg_typ_compalg($arg, $cfg, $key)
        {
                $arg = self::cli_arg_typ_select($arg, $cfg, $key);

                switch($arg) {
                        case 'auto':
                                if (extension_loaded('zlib')) {
                                        $arg = 'gz';
                                } elseif (extension_loaded('bz2')) {
                                        $arg = 'bz2';
                                } else {
                                        $arg = '0';
                                }
                                break;
                }
                return $arg;
        }
        // }}}
        // {{{ static function cli_arg_typ_privkey
        /**
         * Argument type private key (for OpenSSL signing)
         *
         * @param  string $arg  The phar selection
         * @param  string $cfg  The config option.
         * @param  string $key  The key information.
         * @return string $arg  The private key.
         */
        static function cli_arg_typ_privkey($arg, $cfg, $key)
        {
                $arg = self::cli_arg_typ_string($arg, $cfg, $key);

                $hash_avail = Phar::getSupportedSignatures();
                if ($arg && !in_array('OpenSSL', $hash_avail))
                {
                        self::error("Cannot specifiy private key without OpenSSL support.\n");
                }
                return $arg;
        }
        // }}}
        // {{{ static function phar_check_hash
        /**
         * Check whether hash method is valid.
         *
         * @return Hash constant to be used.
         */
        function phar_check_hash($hash, $privkey)
        {
                switch($hash) {
                        case 'md5':
                                return Phar::MD5;
                        case 'sha1':
                                return Phar::SHA1;
                        case 'sha256':
                                return Phar::SHA256;
                        case 'sha512':
                                return Phar::SHA512;
                        case 'openssl':
                                if (!$privkey) {
                                        self::error("Cannot use OpenSSL signing without key.\n");
                                }
                                return Phar::OPENSSL;
                }
        }
        // }}}
        // {{{ static function cli_cmd_inf_pack
        /**
         * Information pack
         *
         * @return string A description about packing files into a Phar archive.
         */
        static function cli_cmd_inf_pack()
        {
                return "Pack files into a PHAR archive.\n" .
                           "When using -s <stub>, then the stub file is being " .
                           "excluded from the list of input files/dirs." .
                           "To create an archive that contains PEAR class PHP_Archive " .
                           "then point -p argument to PHP/Archive.php.\n";
        }
        // }}}
        // {{{ static function cli_cmd_arg_pack
        /**
         * Pack a new phar infos
         *
         * @return array  $args  The arguments for a new Phar archive.
         */
        static function cli_cmd_arg_pack()
        {
                $args = self::phar_args('abcFhilpsxy', 'pharnew');

                $args[''] = array(
                        'typ'     => 'any',
                        'val'      => NULL,
                        'required' => 1,
                        'inf'      => '         Any number of input files and directories. If -i is in use then ONLY files and matching the given regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
                );

                return $args;
        }
        // }}}
        // {{{ function phar_set_stub_begin
        /**
         * Set the stub
         */
        public function phar_set_stub_begin(Phar $phar, $stub, $loader = NULL, $hashbang = NULL)
        {
                if (isset($stub)) {
                        $c = file_get_contents($stub);

                        if (substr($c, 0, 2) == '#!') {
                                if (strpos($c, "\n") !== false) {
                                        if (!isset($hashbang)) {
                                                $hashbang = substr($c, 0, strpos($c, "\n") + 1);
                                        }
                                        $c = substr($c, strpos($c, "\n") + 1);
                                } else {
                                        if (!isset($hashbang)) {
                                                $hashbang = $c;
                                        }
                                        $c = NULL;
                                }
                        }

                        if (isset($hashbang)) {
                                if (substr($hashbang, 0, 2) != '#!') {
                                        $hashbang = '#!' . $hashbang;
                                }
                                if (substr($hashbang, -1) != "\n") {
                                        $hashbang .= "\n";
                                }
                        } else {
                                $hashbang = "";
                        }

                        if (isset($loader)) {
                                $s = "<?php if (!class_exists('PHP_Archive')) {\n?>";
                                if (is_file($loader)) {
                                        $s .= file_get_contents($loader);
                                }
                                $s .= "<?php\n";
                                $s .= "}\n";
                                $s .= "if (!in_array('phar', stream_get_wrappers())) {\n";
                                $s .= "\tstream_wrapper_register('phar', 'PHP_Archive');\n";
                                $s .= "}\n";
                                $s .= "if (!class_exists('Phar',0)) {\n";
                                $s .= "\tinclude 'phar://'.__FILE__.'/phar.inc';\n";
                                $s .= "}\n";
                                $s .= '?>';
                                $s .= $c;

                                $phar->setStub($hashbang . $s);
                        } else {
                                $phar->setStub($hashbang . $c);
                        }
                        return new SplFileInfo($stub);
                }
                return NULL;
        }
        // }}}
        // {{{ function phar_set_stub_end
        /**
         * Set stub end
         */
        public function phar_set_stub_end(Phar $phar, $stub, $loader = NULL)
        {
                if (isset($stub) && isset($loader)) {
                        if (substr(__FILE__, -15) == 'pharcommand.inc') {
                                self::phar_add_file($phar, 0, 'phar.inc', 'phar://'.__FILE__.'/phar.inc', NULL);
                        } else {
                                self::phar_add_file($phar, 0, 'phar.inc', dirname(__FILE__).'/phar/phar.inc', NULL);
                        }
                }
        }
        // }}}
        // {{{ function cli_cmd_run_pack
        /**
         * Pack a new Phar
         * 
         * This function will try to pack a new Phar archive.
         * 
         * @see Exit to make sure that we are done.
         */
        public function cli_cmd_run_pack()
        {
                if (ini_get('phar.readonly')) {
                        self::error("Creating phar files is disabled by ini setting 'phar.readonly'.\n");
                }

                if (!Phar::canWrite()) {
                        self::error("Creating phar files is disabled, Phar::canWrite() returned false.\n");
                }

                $alias    = $this->args['a']['val'];
                $hashbang = $this->args['b']['val'];
                $archive  = $this->args['f']['val'];
                $hash     = $this->args['h']['val'];
                $privkey  = $this->args['y']['val'];
                $regex    = $this->args['i']['val'];
                $level    = $this->args['l']['val'];
                $loader   = $this->args['p']['val'];
                $stub     = $this->args['s']['val'];
                $invregex = $this->args['x']['val'];
                $input    = $this->args['']['val'];

                $hash = self::phar_check_hash($hash, $privkey);

                $phar  = new Phar($archive, 0, $alias);

                $phar->startBuffering();

                $stub = $this->phar_set_stub_begin($phar, $stub, $loader, $hashbang);

                if (!is_array($input)) {
                        $this->phar_add($phar, $level, $input, $regex, $invregex, $stub, NULL, isset($loader));
                } else {
                        foreach($input as $i) {
                                $this->phar_add($phar, $level, $i, $regex, $invregex, $stub, NULL, isset($loader));
                        }
                }

                $this->phar_set_stub_end($phar, $stub, $loader);

                switch($this->args['c']['val']) {
                        case 'gz':
                        case 'gzip':
                                $phar->compressFiles(Phar::GZ);
                                break;
                        case 'bz2':
                        case 'bzip2':
                                $phar->compressFiles(Phar::BZ2);
                                break;
                        default:
                                $phar->decompressFiles();
                                break;
                }

                if ($hash) {
                        $phar->setSignatureAlgorithm($hash, $privkey);
                }

                $phar->stopBuffering();
                exit(0);
        }
        // }}}
        // {{{ static function phar_add
        /**
         * Add files to a phar archive.
         *
         * This function will take a directory and iterate through
         * it and get the files to insert into the Phar archive.
         * 
         * @param Phar        $phar      The phar object.
         * @param string      $input     The input directory
         * @param string      $regex     The regex used in RegexIterator.
         * @param string      $invregex  The InvertedRegexIterator expression.
         * @param SplFileInfo $stub Stub file object
         * @param mixed       $compress  Compression algorithm or NULL
         * @param boolean     $noloader  Whether to prevent adding the loader
         */
        static function phar_add(Phar $phar, $level, $input, $regex, $invregex, SplFileInfo $stub = NULL, $compress = NULL, $noloader = false)
        {
                if ($input && is_file($input) && !is_dir($input)) {
                        return self::phar_add_file($phar, $level, $input, $input, $compress);
                }
                $dir   = new RecursiveDirectoryIterator($input);
                $dir   = new RecursiveIteratorIterator($dir);

                if (isset($regex)) {
                        $dir = new RegexIterator($dir, $regex);
                }

                if (isset($invregex)) {
                        $dir = new InvertedRegexIterator($dir, $invregex);
                }

                try {
                        foreach($dir as $file) {
                                if ((empty($stub) || $file->getRealPath() != $stub->getRealPath()) && !is_dir($file)) {
                                        self::phar_add_file($phar, $level, $dir->getSubPathName(), $file, $compress, $noloader);
                                }
                        }
                } catch(Excpetion $e) {
                        self::error("Unable to complete operation on file '$file'\n" . $e->getMessage() . "\n");
                }
        }
        // }}}
        // {{{ static function phar_add_file
        /**
         * Add a phar file
         *
         * This function adds a file to a phar archive.
         *
         * @param Phar    $phar      The phar object
         * @param string  $level     The level of the file.
         * @param string  $entry     The entry point
         * @param string  $file      The file to add to the archive
         * @param string  $compress  The compression scheme for the file.
         * @param boolean $noloader  Whether to prevent adding the loader
         */
        static function phar_add_file(Phar $phar, $level, $entry, $file, $compress, $noloader = false)
        {
                $entry = str_replace('//', '/', $entry);
                while($level-- > 0 && ($p = strpos($entry, '/')) !== false) {
                        $entry = substr($entry, $p+1);
                }

        if ($noloader && $entry == 'phar.inc') {
                return;
        }

                echo "$entry\n";

                $phar[$entry] = file_get_contents($file);
                switch($compress) {
                        case 'gz':
                        case 'gzip':
                                $phar[$entry]->compress(Phar::GZ);
                                break;
                        case 'bz2':
                        case 'bzip2':
                                $phar[$entry]->compress(Phar::BZ2);
                                break;
                        case '0':
                                $phar[$entry]->decompress();
                                break;
                        default:
                                break;
                }
        }
        // }}}
        // {{{ public function phar_dir_echo
        /**
         * Echo directory
         *
         * @param string $pn
         * @param unknown_type $f
         */
        public function phar_dir_echo($pn, $f)
        {
                echo "$f\n";
        }
        // }}}
        // {{{ public function phar_dir_operation
        /**
         * Directory operations
         * 
         * Phar directory operations.
         *
         * @param RecursiveIteratorIterator $dir  The recursiveIteratorIterator object.
         * @param string                    $func Function to call on the iterations
         * @param array                     $args Function arguments.
         */
        public function phar_dir_operation(RecursiveIteratorIterator $dir, $func, array $args = array())
        {
                $regex   = $this->args['i']['val'];
                $invregex= $this->args['x']['val'];

                if (isset($regex)) {
                        $dir = new RegexIterator($dir, $regex);
                }

                if (isset($invregex)) {
                        $dir = new InvertedRegexIterator($dir, $invregex);
                }

                $any = false;
                foreach($dir as $pn => $f) {
                        $any = true;
                        call_user_func($func, $pn, $f, $args);
                }
                return $any;
        }
        // {{{ static function cli_cmd_inf_list
        /**
         * Cli Command Info List
         *
         * @return string What inf does
         */
        static function cli_cmd_inf_list()
        {
                return "List contents of a PHAR archive.";
        }
        // }}}
        // {{{ static function cli_cmd_arg_list
        /**
         * Cli Command Argument List
         *
         * @return arguments list
         */
        static function cli_cmd_arg_list()
        {
                return self::phar_args('Fix', 'pharurl');
        }
        // }}}
        // {{{ public function cli_cmd_run_list
        /**
         * Cli Command Run List
         *
         * @see $this->phar_dir_operation
         */
        public function cli_cmd_run_list()
        {
                $this->phar_dir_operation(
                        new DirectoryTreeIterator(
                                $this->args['f']['val']),
                                array($this, 'phar_dir_echo')
                        );
        }
        // }}}
        // {{{ static function cli_command_inf_tree
        /**
         * Cli Command Inf Tree
         *
         * @return string  The description of a directory tree for a Phar archive.
         */
        static function cli_cmd_inf_tree()
        {
                return "Get a directory tree for a PHAR archive.";
        }
        // }}}
        // {{{ static function cli_cmd_arg_tree
        /**
         * Cli Command Argument Tree
         *
         * @return string Arguments in URL format.
         */
        static function cli_cmd_arg_tree()
        {
                return self::phar_args('Fix', 'pharurl');
        }
        // }}}
        // {{{ public function cli_cmd_run_tree
        /**
         * Cli Command Run Tree
         * 
         * Set the phar_dir_operation with a directorygraphiterator.
         * 
         * @see DirectoryGraphIterator
         * @see $this->phar_dir_operation
         *
         */
        public function cli_cmd_run_tree()
        {
                $a = $this->phar_dir_operation(
                        new DirectoryGraphIterator(
                                $this->args['f']['val']),
                                array($this, 'phar_dir_echo')
                        );
                if (!$a) {
                        echo "|-<root directory>\n";
                }
        }
        // }}}
        // {{{ cli_cmd_inf_extract
        /**
         * Cli Command Inf Extract
         *
         * @return string The description of the command extra to a directory.
         */
        static function cli_cmd_inf_extract()
        {
                return "Extract a PHAR package to a directory.";
        }
        // }}}
        // {{{ static function cli_cmd_arg_extract
        /**
         * Cli Command Arguments Extract
         * 
         * The arguments for the extract function.
         *
         * @return array  The arguments for the extraction.
         */
        static function cli_cmd_arg_extract()
        {
                $args = self::phar_args('Fix', 'phar');

                $args[''] = array(
                        'type' => 'dir',
                        'val' => '.',
                        'inf' => '         Directory to extract to (defaults to \'.\').',
                );

                return $args;
        }
        // }}}
        // {{{ public function cli_cmd_run_extract
        /**
         * Run Extract
         * 
         * Run the extraction of a phar Archive.
         *
         * @see $this->phar_dir_operation
         */
        public function cli_cmd_run_extract()
        {
                $dir = $this->args['']['val'];

                if (is_array($dir)) {
                        if (count($dir) != 1) {
                                self::error("Only one target directory allowed.\n");
                        } else {
                                $dir = $dir[0];
                        }
                }

                $phar = $this->args['f']['val'];
                $base = $phar->getPathname();
                $bend = strpos($base, '.phar');
                $bend = strpos($base, '/', $bend);
                $base = substr($base, 0, $bend + 1);
                $blen = strlen($base);

                $this->phar_dir_operation(
                        new RecursiveIteratorIterator($phar),
                        array($this, 'phar_dir_extract'),
                        array($blen, $dir)
                );
        }
        // }}}
        // {{{ public function phar_dir_extract
        /**
         * Extract to a directory
         * 
         * This function will extract the content of a Phar
         * to a directory and create new files and directories
         * depending on the permissions on that folder.
         *
         * @param string $pn
         * @param string $f     The file name
         * @param array $args   The directory and Blen informations
         */
        public function phar_dir_extract($pn, $f, $args)
        {
                $blen   = $args[0];
                $dir    = $args[1];
                $sub    = substr($pn, $blen);
                $target = $dir . '/' . $sub;

                if (!file_exists(dirname($target))) {
                        @mkdir(dirname($target), 0777, true);
                }
                if (!file_exists(dirname($target))) {
                        self::error("Operation could not be completed\n");
                }

                echo "$sub";

                if (!@copy($f, $target)) {
                        echo " ...error\n";
                } else {
                        echo " ...ok\n";
                }
        }
        // }}}
        // {{{ static function cli_cmd_inf_delete
        /**
         * Delete an entry from a phar information.
         *
         * @return string The information
         */
        static function cli_cmd_inf_delete()
        {
                return 'Delete entry from a PHAR archive';
        }
        // }}}
        // {{{ static function cli_cmd_arg_delete
        /**
         * The cli command argument for deleting.
         *
         * @return array informations about the arguments to use.
         */
        static function cli_cmd_arg_delete()
        {
                return self::phar_args('FE', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_delete
        /**
         * Deleting execution
         *
         * Execute the deleting of the file from the phar archive.
         */
        public function cli_cmd_run_delete()
        {
                $phar  = $this->args['f']['val'];
                $entry = $this->args['e']['val'];

                $phar->startBuffering();
                unset($phar[$entry]);
                $phar->stopBuffering();
        }
        // }}}
        // {{{ static function cli_cmd_inf_add
        /**
         * Client comment add file information
         *
         * @return string The description of the feature
         */
        static function cli_cmd_inf_add()
        {
                return "Add entries to a PHAR package.";
        }
        // }}}
        // {{{ static function cli_cmd_arg_add
        /**
         * Add a file arguments
         */
        static function cli_cmd_arg_add()
        {
                $args = self::phar_args('acFilx', 'phar');
                $args[''] = array(
                        'type'     => 'any',
                        'val'      => NULL,
                        'required' => 1,
                        'inf'      => '         Any number of input files and directories. If -i is in use then ONLY files and matching the given regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
                );
                return $args;
        }
        // }}}
        // {{{ public functio cli_cmd_run_add
        /**
         * Add a file
         *
         * Run the action of adding a file to
         * a phar archive.
         */
        public function cli_cmd_run_add()
        {
                $compress= $this->args['c']['val'];
                $phar    = $this->args['f']['val'];
                $regex   = $this->args['i']['val'];
                $level   = $this->args['l']['val'];
                $invregex= $this->args['x']['val'];
                $input   = $this->args['']['val'];

                $phar->startBuffering();

                if (!is_array($input)) {
                        $this->phar_add($phar, $level, $input, $regex, $invregex, NULL, $compress);
                } else {
                        foreach($input as $i) {
                                $this->phar_add($phar, $level, $i, $regex, $invregex, NULL, $compress);
                        }
                }
                $phar->stopBuffering();
                exit(0);
        }
        // }}}
        // {{{ public function cli_cmd_inf_stub_set
        /**
         * Set the stup of a phar file.
         *
         * @return string The stub set description.
         */
        public function cli_cmd_inf_stub_set()
        {
                return "Set the stub of a PHAR file. " .
                           "If no input file is specified as stub then stdin is being used.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_stub_set
        /**
         * Set the argument stub
         *
         * @return string arguments for a stub
         */
        public function cli_cmd_arg_stub_set()
        {
                $args = self::phar_args('bFps', 'phar');
                $args['s']['val'] = 'php://stdin';
                return $args;
        }
        // }}}
        // {{{ public function cli_cmd_run_stub_set
        /**
         * Cli Command run stub set
         *
         * @see   $phar->setStub()
         */
        public function cli_cmd_run_stub_set()
        {
                $hashbang = $this->args['b']['val'];
                $phar     = $this->args['f']['val'];
                $stub     = $this->args['s']['val'];
                $loader   = $this->args['p']['val'];

                $this->phar_set_stub_begin($phar, $stub, $loader, $hashbang);
                $this->phar_set_stub_end($phar, $stub, $loader);
        }
        // }}}
        // {{{ public function cli_cmd_inf_stub_get
        /**
         * Get the command stub infos.
         *
         * @return string a description of the stub of a Phar file.
         */
        public function cli_cmd_inf_stub_get()
        {
                return "Get the stub of a PHAR file. " .
                           "If no output file is specified as stub then stdout is being used.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_stub_get
        /**
         * Get the argument stub
         *
         * @return array $args The arguments passed to the stub.
         */
        public function cli_cmd_arg_stub_get()
        {
                $args = self::phar_args('Fs', 'phar');
                $args['s']['val'] = 'php://stdin';
                return $args;
        }
        // }}}
        // {{{ public function cli_cmd_run_stub_get
        /**
         * Cli Command Run Stub
         * 
         * Get arguments and store them into a stub.
         *
         * @param arguments $args
         * @see   $this->args
         */
        public function cli_cmd_run_stub_get($args)
        {
                $phar = $this->args['f']['val'];
                $stub = $this->args['s']['val'];

                file_put_contents($stub, $phar->getStub());
        }
        // }}}
        // {{{ public function cli_cmd_inf_compress
        /**
         * Cli Command Inf Compress
         * 
         * Cli Command compress informations
         *
         * @return string A description of the command.
         */
        public function cli_cmd_inf_compress()
        {
                return "Compress or uncompress all files or a selected entry.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_cmpress
        /**
         * Cli Command Arg Compress
         *
         * @return array The arguments for compress
         */
        public function cli_cmd_arg_compress()
        {
                return self::phar_args('FCe', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_compress
        /**
         * Cli Command Run Compress
         *
         * @see $this->args
         */
        public function cli_cmd_run_compress()
        {
                $phar  = $this->args['f']['val'];
                $entry = $this->args['e']['val'];

                switch($this->args['c']['val']) {
                        case 'gz':
                        case 'gzip':
                                if (isset($entry)) {
                                        $phar[$entry]->compress(Phar::GZ);
                                } else {
                                        $phar->compressFiles(Phar::GZ);
                                }
                                break;
                        case 'bz2':
                        case 'bzip2':
                                if (isset($entry)) {
                                        $phar[$entry]->compress(Phar::BZ2);
                                } else {
                                        $phar->compressFiles(Phar::BZ2);
                                }
                                break;
                        default:
                                if (isset($entry)) {
                                        $phar[$entry]->decompress();
                                } else {
                                        $phar->decompressFiles();
                                }
                                break;
                }
        }
        // }}}
        // {{{ public function cli_cmd_inf_sign
        /**
         * Cli Command Info Signature
         *
         * @return string A description of the signature arguments.
         */
        public function cli_cmd_inf_sign()
        {
                return "Set signature hash algorithm.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_sign
        /**
         * Cli Command Argument Sign
         *
         * @return array Arguments for Signature
         */
        public function cli_cmd_arg_sign()
        {
                return self::phar_args('FHy', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_sign
        /**
         * Cli Command Run Signature
         *
         * @see $phar->setSignaturealgorithm
         */
        public function cli_cmd_run_sign()
        {
                $phar     = $this->args['f']['val'];
                $hash     = $this->args['h']['val'];
                $privkey  = $this->args['y']['val'];

                $hash = self::phar_check_hash($hash, $privkey);

                $phar->setSignatureAlgorithm($hash, $privkey);
        }
        // }}}
        // {{{ public function cli_cmd_inf_meta_set
        /**
         * Cli Command Inf Meta Set
         *
         * @return string A description
         */
        public function cli_cmd_inf_meta_set()
        {
                return "Set meta data of a PHAR entry or a PHAR package using serialized input. " .
                           "If no input file is specified for meta data then stdin is being used." .
                           "You can also specify a particular index using -k. In that case the metadata is " .
                           "expected to be an array and the value of the given index is being set. If " .
                           "the metadata is not present or empty a new array will be created. If the " .
                           "metadata is present and a flat value then the return value is 1. Also using -k " .
                           "the input is been taken directly rather then being serialized.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_meta_set
        /**
         * Cli Command Argument Meta Set
         *
         * @return array  The arguments for meta set
         */
        public function cli_cmd_arg_meta_set()
        {
                return self::phar_args('FekM', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_met_set
        /**
         * Cli Command Run Metaset
         *
         * @see $phar->startBuffering
         * @see $phar->setMetadata
         * @see $phar->stopBuffering
         */
        public function cli_cmd_run_meta_set()
        {
                $phar  = $this->args['f']['val'];
                $entry = $this->args['e']['val'];
                $index = $this->args['k']['val'];
                $meta  = $this->args['m']['val'];

                $phar->startBuffering();

                if (isset($index)) {
                        if (isset($entry)) {
                                if ($phar[$entry]->hasMetadata()) {
                                        $old = $phar[$entry]->getMetadata();
                                } else {
                                        $old = array();
                                }
                        } else {
                                if ($phar->hasMetadata()) {
                                        $old = $phar->getMetadata();
                                } else {
                                        $old = array();
                                }
                        }

                        if (!is_array($old)) {
                                self::error('Metadata is a flat value while an index operation was issued.');
                        }

                        $old[$index] = $meta;
                        $meta = $old;
                } else {
                        $meta = unserialize($meta);
                }

                if (isset($entry)) {
                        $phar[$entry]->setMetadata($meta);
                } else {
                        $phar->setMetadata($meta);
                }
                $phar->stopBuffering();
        }
        // }}}
        // {{{ public function cli_cmd_inf_met_get
        /**
         * Cli Command Inf Metaget
         *
         * @return string A description of the metaget arguments
         */
        public function cli_cmd_inf_meta_get()
        {
                return "Get meta information of a PHAR entry or a PHAR package in serialized from. " .
                           "If no output file is specified for meta data then stdout is being used.\n" .
                           "You can also specify a particular index using -k. In that case the metadata is " .
                           "expected to be an array and the value of the given index is returned using echo " .
                           "rather than using serialize. If that index does not exist or no meta data is " .
                           "present then the return value is 1.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_meta_get
        /**
         * Cli Command arg metaget
         *
         * @return array  The arguments for meta get.
         */
        public function cli_cmd_arg_meta_get()
        {
                return self::phar_args('Fek', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_meta_get
        /**
         * Cli Command Run Metaget
         *
         * @see $this->args
         * @see $phar[$x]->hasMetadata()
         * @see $phar->getMetadata()
         */
        public function cli_cmd_run_meta_get()
        {
                $phar  = $this->args['f']['val'];
                $entry = $this->args['e']['val'];
                $index = $this->args['k']['val'];

                if (isset($entry)) {
                        if (!$phar[$entry]->hasMetadata()) {
                                echo "No Metadata\n";
                                exit(1);
                        }
                        echo serialize($phar[$entry]->getMetadata());
                } else {
                        if (!$phar->hasMetadata()) {
                                echo "No Metadata\n";
                                exit(1);
                        }
                        $meta = $phar->getMetadata();
                }

                if (isset($index)) {
                        if (isset($index)) {
                                if (isset($meta[$index])) {
                                        echo $meta[$index];
                                        exit(0);
                                } else {
                                        echo "No Metadata\n";
                                        exit(1);
                                }
                        } else {
                                echo serialize($meta);
                        }
                }
        }
        // }}}
        // {{{ public function cli_cmd_inf_meta_del
        /**
         * Cli Command Inf Metadel
         *
         * @return string A description of the metadel function
         */
        public function cli_cmd_inf_meta_del()
        {
                return "Delete meta information of a PHAR entry or a PHAR package.\n" .
                           "If -k is given then the metadata is expected to be an array " .
                           "and the given index is being deleted.\n" .
                           "If something was deleted the return value is 0 otherwise it is 1.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_meta_del
        /**
         * CliC ommand Arg Metadelete
         *
         * @return array The arguments for metadel
         */
        public function cli_cmd_arg_meta_del()
        {
                return self::phar_args('Fek', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_meta_del
        /**
         * Cli Command Run MetaDel
         *
         * @see $phar[$x]->delMetadata()
         * @see $phar->delMetadata()
         */
        public function cli_cmd_run_meta_del()
        {
                $phar  = $this->args['f']['val'];
                $entry = $this->args['e']['val'];
                $index = $this->args['k']['val'];

                if (isset($entry)) {
                        if (isset($index)) {
                                if (!$phar[$entry]->hasMetadata()) {
                                        exit(1);
                                }
                                $meta = $phar[$entry]->getMetadata();

                                // @todo add error message here.
                                if (!is_array($meta)) {
                                        exit(1);
                                }

                                unset($meta[$index]);
                                $phar[$entry]->setMetadata($meta);
                        } else {
                                exit($phar[$entry]->delMetadata() ? 0 : 1);
                        }
                } else {
                        if (isset($index)) {
                                if (!$phar->hasMetadata()) {
                                        exit(1);
                                }

                                $meta = $phar->getMetadata();

                                // @todo Add error message
                                if (!is_array($meta)) {
                                        exit(1);
                                }

                                unset($meta[$index]);
                                $phar->setMetadata($meta);
                        } else {
                                exit($phar->delMetadata() ? 0 : 1);
                        }
                }
        }
        // }}}
        // {{{ public function cli_cmd_inf_info
        /**
         * CLi Command Inf Info
         *
         * @return string A description about the info commands.
         */
        public function cli_cmd_inf_info()
        {
                return "Get information about a PHAR package.\n" .
                           "By using -k it is possible to return a single value.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_info
        /**
         * Cli Command Arg Infos
         *
         * @return array The arguments for info command.
         */
        public function cli_cmd_arg_info()
        {
                return self::phar_args('Fk', 'phar');
        }
        // }}}
        // {{{ public function cli_cmd_run_info
        /**
         * Cli Command Run Info
         *
         * @param args $args
         */
        public function cli_cmd_run_info()
        {
                $phar  = $this->args['f']['val'];
                $index = $this->args['k']['val'];

                $hash  = $phar->getSignature();
                $infos = array();

                if ($phar->getAlias()) {
                        $infos['Alias'] = $phar->getAlias();
                }

                if (!$hash) {
                        $infos['Hash-type'] = 'NONE';
                } else {
                        $infos['Hash-type'] = $hash['hash_type'];
                        $infos['Hash'] = $hash['hash'];
                }

                $csize   = 0;
                $usize   = 0;
                $count   = 0;
                $ccount  = 0;
                $ucount  = 0;
                $mcount  = 0;
                $compalg = array('GZ'=>0, 'BZ2'=>0);

                foreach(new RecursiveIteratorIterator($phar) as $ent) {
                        $count++;
                        if ($ent->isCompressed()) {
                                $ccount++;
                                $csize += $ent->getCompressedSize();
                                if ($ent->isCompressed(Phar::GZ)) {
                                        $compalg['GZ']++;
                                } elseif ($ent->isCompressed(Phar::BZ2)) {
                                        $compalg['BZ2']++;
                                }
                        } else {
                                $ucount++;
                                $csize += $ent->getSize();
                        }

                        $usize += $ent->getSize();

                        if ($ent->hasMetadata()) {
                                $mcount++;
                        }
                }

                $infos['Entries']            = $count;
                $infos['Uncompressed-files'] = $ucount;
                $infos['Compressed-files']   = $ccount;
                $infos['Compressed-gz']      = $compalg['GZ'];
                $infos['Compressed-bz2']     = $compalg['BZ2'];
                $infos['Uncompressed-size']  = $usize;
                $infos['Compressed-size']    = $csize;
                $infos['Compression-ratio']  = sprintf('%.3g%%', $usize ? ($csize * 100) / $usize : 100);
                $infos['Metadata-global']    = $phar->hasMetadata() * 1;
                $infos['Metadata-files']     = $mcount;
                $infos['Stub-size']          = strlen($phar->getStub());

                if (isset($index)) {
                        if (!isset($infos[$index])) {
                                self::error("Requested value does not exist.\n");
                        }

                        echo $infos[$index];
                        exit(0);
                }

                $l = 0;
                foreach($infos as $which => $val) {
                        $l = max(strlen($which), $l);
                }

                foreach($infos as $which => $val) {
                        echo $which . ':' . str_repeat(' ', $l + 1 - strlen($which)) . $val . "\n";
                }
        }
        // }}}
        // {{{ public function cli_cmd_inf_version
        /**
         * CLi Command Inf Version
         *
         * @return string A description about the info commands.
         */
        public function cli_cmd_inf_version()
        {
                return "Get information about the PHAR environment and the tool version.";
        }
        // }}}
        // {{{ public function cli_cmd_arg_version
        /**
         * Cli Command Arg Version
         *
         * @return array The arguments for version command.
         */
        public function cli_cmd_arg_version()
        {
                return self::phar_args('', NULL);
        }
        // }}}
        // {{{ public function cli_cmd_run_info
        /**
         * Cli Command Run Info
         *
         * @param args $args
         */
        public function cli_cmd_run_version()
        {
                $use_ext = extension_loaded('phar');
                $version = array(
                        'PHP Version' => phpversion(),
                        'phar.phar version' => '$Id: cb343675b557b02dd09d0f1902d0ec50f5f482ee $',
                        'Phar EXT version' => $use_ext ? phpversion('phar') : 'Not available',
                        'Phar API version' => Phar::apiVersion(),
                        'Phar-based phar archives' => true,
                        'Tar-based phar archives' => $use_ext,
                        'ZIP-based phar archives' => $use_ext,
                        'gzip compression' => extension_loaded('zlib'),
                        'bzip2 compression' => extension_loaded('bz2'),
                        'supported signatures' => $use_ext ? join(', ', Phar::getSupportedSignatures()) : '',
                        );
                $klen = 0;
                foreach($version as $k => $v)
                {
                        $klen = max($klen, strlen($k));
                }
                ++$klen;
                foreach($version as $k => $v) {
                        if (is_bool($v)) {
                                $v = $v ? 'enabled' : 'disabled';
                        }
                        printf("%-${klen}s  %s\n", $k.':', $v);
                }
        }
        // }}}
}
// }}}

}

new PharCommand($argc, $argv);

/* [<][>][^][v][top][bottom][index][help] */