removed /etc and /opt

This commit is contained in:
cutemeli
2025-12-22 10:48:14 +00:00
parent 5ce7ca2c5d
commit 10d1afbb17
32559 changed files with 0 additions and 6756692 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,365 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PHP Version 5
*
* Copyright (c) 2001-2015, The PEAR developers
*
* This source file is subject to the BSD-2-Clause license,
* that is bundled with this package in the file LICENSE, and is
* available through the world-wide-web at the following url:
* http://opensource.org/licenses/bsd-license.php.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_Getopt
*/
require_once 'PEAR.php';
/**
* Command-line options parsing class.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @link http://pear.php.net/package/Console_Getopt
*/
class Console_Getopt
{
/**
* Parses the command-line options.
*
* The first parameter to this function should be the list of command-line
* arguments without the leading reference to the running program.
*
* The second parameter is a string of allowed short options. Each of the
* option letters can be followed by a colon ':' to specify that the option
* requires an argument, or a double colon '::' to specify that the option
* takes an optional argument.
*
* The third argument is an optional array of allowed long options. The
* leading '--' should not be included in the option name. Options that
* require an argument should be followed by '=', and options that take an
* option argument should be followed by '=='.
*
* The return value is an array of two elements: the list of parsed
* options and the list of non-option command-line arguments. Each entry in
* the list of parsed options is a pair of elements - the first one
* specifies the option, and the second one specifies the option argument,
* if there was one.
*
* Long and short options can be mixed.
*
* Most of the semantics of this function are based on GNU getopt_long().
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
}
/**
* This function expects $args to start with the script name (POSIX-style).
* Preserved for backwards compatibility.
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @see getopt2()
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
}
/**
* The actual implementation of the argument parsing code.
*
* @param int $version Version to use
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array
*/
public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
{
// in case you pass directly readPHPArgv() as the first arg
if (PEAR::isError($args)) {
return $args;
}
if (empty($args)) {
return array(array(), array());
}
$non_opts = $opts = array();
settype($args, 'array');
if ($long_options) {
sort($long_options);
}
/*
* Preserve backwards compatibility with callers that relied on
* erroneous POSIX fix.
*/
if ($version < 2) {
if (isset($args[0][0]) && $args[0][0] != '-') {
array_shift($args);
}
}
for ($i = 0; $i < count($args); $i++) {
$arg = $args[$i];
/* The special element '--' means explicit end of
options. Treat the rest of the arguments as non-options
and end the loop. */
if ($arg == '--') {
$non_opts = array_merge($non_opts, array_slice($args, $i + 1));
break;
}
if ($arg[0] != '-' || (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) {
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} elseif (strlen($arg) > 1 && $arg[1] == '-') {
$error = Console_Getopt::_parseLongOption(substr($arg, 2),
$long_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
} elseif ($arg == '-') {
// - is stdin
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} else {
$error = Console_Getopt::_parseShortOption(substr($arg, 1),
$short_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
}
}
return array($opts, $non_opts);
}
/**
* Parse short option
*
* @param string $arg Argument
* @param string[] $short_options Available short options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return void
*/
protected static function _parseShortOption($arg, $short_options, &$opts, &$argIdx, $args, $skip_unknown)
{
for ($i = 0; $i < strlen($arg); $i++) {
$opt = $arg[$i];
$opt_arg = null;
/* Try to find the short option in the specifier string. */
if (($spec = strstr($short_options, $opt)) === false || $arg[$i] == ':') {
if ($skip_unknown === true) {
break;
}
$msg = "Console_Getopt: unrecognized option -- $opt";
return PEAR::raiseError($msg);
}
if (strlen($spec) > 1 && $spec[1] == ':') {
if (strlen($spec) > 2 && $spec[2] == ':') {
if ($i + 1 < strlen($arg)) {
/* Option takes an optional argument. Use the remainder of
the arg string if there is anything left. */
$opts[] = array($opt, substr($arg, $i + 1));
break;
}
} else {
/* Option requires an argument. Use the remainder of the arg
string if there is anything left. */
if ($i + 1 < strlen($arg)) {
$opts[] = array($opt, substr($arg, $i + 1));
break;
} else if (isset($args[++$argIdx])) {
$opt_arg = $args[$argIdx];
/* Else use the next argument. */;
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
} else {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
}
}
$opts[] = array($opt, $opt_arg);
}
}
/**
* Checks if an argument is a short option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isShortOpt($arg)
{
return strlen($arg) == 2 && $arg[0] == '-'
&& preg_match('/[a-zA-Z]/', $arg[1]);
}
/**
* Checks if an argument is a long option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isLongOpt($arg)
{
return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
preg_match('/[a-zA-Z]+$/', substr($arg, 2));
}
/**
* Parse long option
*
* @param string $arg Argument
* @param string[] $long_options Available long options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
*
* @return void|PEAR_Error
*/
protected static function _parseLongOption($arg, $long_options, &$opts, &$argIdx, $args, $skip_unknown)
{
@list($opt, $opt_arg) = explode('=', $arg, 2);
$opt_len = strlen($opt);
for ($i = 0; $i < count($long_options); $i++) {
$long_opt = $long_options[$i];
$opt_start = substr($long_opt, 0, $opt_len);
$long_opt_name = str_replace('=', '', $long_opt);
/* Option doesn't match. Go on to the next one. */
if ($long_opt_name != $opt) {
continue;
}
$opt_rest = substr($long_opt, $opt_len);
/* Check that the options uniquely matches one of the allowed
options. */
if ($i + 1 < count($long_options)) {
$next_option_rest = substr($long_options[$i + 1], $opt_len);
} else {
$next_option_rest = '';
}
if ($opt_rest != '' && $opt[0] != '=' &&
$i + 1 < count($long_options) &&
$opt == substr($long_options[$i+1], 0, $opt_len) &&
$next_option_rest != '' &&
$next_option_rest[0] != '=') {
$msg = "Console_Getopt: option --$opt is ambiguous";
return PEAR::raiseError($msg);
}
if (substr($long_opt, -1) == '=') {
if (substr($long_opt, -2) != '==') {
/* Long option requires an argument.
Take the next argument if one wasn't specified. */;
if (!strlen($opt_arg)) {
if (!isset($args[++$argIdx])) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
$opt_arg = $args[$argIdx];
}
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
}
} else if ($opt_arg) {
$msg = "Console_Getopt: option --$opt doesn't allow an argument";
return PEAR::raiseError($msg);
}
$opts[] = array('--' . $opt, $opt_arg);
return;
}
if ($skip_unknown === true) {
return;
}
return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
}
/**
* Safely read the $argv PHP array across different PHP configurations.
* Will take care on register_globals and register_argc_argv ini directives
*
* @return mixed the $argv PHP array or PEAR error if not registered
*/
public static function readPHPArgv()
{
global $argv;
if (!is_array($argv)) {
if (!@is_array($_SERVER['argv'])) {
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
$msg = "Could not read cmd args (register_argc_argv=Off?)";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
}

View File

@@ -1,395 +0,0 @@
<?php
/**
* The OS_Guess class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since PEAR 0.1
*/
// {{{ uname examples
// php_uname() without args returns the same as 'uname -a', or a PHP-custom
// string for Windows.
// PHP versions prior to 4.3 return the uname of the host where PHP was built,
// as of 4.3 it returns the uname of the host running the PHP code.
//
// PC RedHat Linux 7.1:
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
//
// PC Debian Potato:
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
//
// PC FreeBSD 3.3:
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.3:
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5 w/uname from GNU shellutils:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown
//
// HP 9000/712 HP-UX 10:
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
//
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
// HP-UX host B.10.10 A 9000/712 unknown
//
// IBM RS6000/550 AIX 4.3:
// AIX host 3 4 000003531C00
//
// AIX 4.3 w/uname from GNU shellutils:
// AIX host 3 4 000003531C00 unknown
//
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
// IRIX64 host 6.5 01091820 IP19 mips
//
// SGI Onyx IRIX 6.5:
// IRIX64 host 6.5 01091820 IP19
//
// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
//
// SparcStation 20 Solaris 8:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
//
// Mac OS X (Darwin)
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh
//
// Mac OS X early versions
//
// }}}
/* TODO:
* - define endianness, to allow matchSignature("bigend") etc.
*/
/**
* Retrieves information about the current operating system
*
* This class uses php_uname() to grok information about the current OS
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2020 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class OS_Guess
{
var $sysname;
var $nodename;
var $cpu;
var $release;
var $extra;
function __construct($uname = null)
{
list($this->sysname,
$this->release,
$this->cpu,
$this->extra,
$this->nodename) = $this->parseSignature($uname);
}
function parseSignature($uname = null)
{
static $sysmap = array(
'HP-UX' => 'hpux',
'IRIX64' => 'irix',
);
static $cpumap = array(
'i586' => 'i386',
'i686' => 'i386',
'ppc' => 'powerpc',
);
if ($uname === null) {
$uname = php_uname();
}
$parts = preg_split('/\s+/', trim($uname));
$n = count($parts);
$release = $machine = $cpu = '';
$sysname = $parts[0];
$nodename = $parts[1];
$cpu = $parts[$n-1];
$extra = '';
if ($cpu == 'unknown') {
$cpu = $parts[$n - 2];
}
switch ($sysname) {
case 'AIX' :
$release = "$parts[3].$parts[2]";
break;
case 'Windows' :
$release = $parts[1];
if ($release == '95/98') {
$release = '9x';
}
$cpu = 'i386';
break;
case 'Linux' :
$extra = $this->_detectGlibcVersion();
// use only the first two digits from the kernel version
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
break;
case 'Mac' :
$sysname = 'darwin';
$nodename = $parts[2];
$release = $parts[3];
$cpu = $this->_determineIfPowerpc($cpu, $parts);
break;
case 'Darwin' :
$cpu = $this->_determineIfPowerpc($cpu, $parts);
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
break;
default:
$release = preg_replace('/-.*/', '', $parts[2]);
break;
}
if (isset($sysmap[$sysname])) {
$sysname = $sysmap[$sysname];
} else {
$sysname = strtolower($sysname);
}
if (isset($cpumap[$cpu])) {
$cpu = $cpumap[$cpu];
}
return array($sysname, $release, $cpu, $extra, $nodename);
}
function _determineIfPowerpc($cpu, $parts)
{
$n = count($parts);
if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') {
$cpu = 'powerpc';
}
return $cpu;
}
function _detectGlibcVersion()
{
static $glibc = false;
if ($glibc !== false) {
return $glibc; // no need to run this multiple times
}
$major = $minor = 0;
include_once "System.php";
// Let's try reading possible libc.so.6 symlinks
$libcs = array(
'/lib64/libc.so.6',
'/lib/libc.so.6',
'/lib/i386-linux-gnu/libc.so.6'
);
$versions = array();
foreach ($libcs as $file) {
$versions = $this->_readGlibCVersionFromSymlink($file);
if ($versions != []) {
list($major, $minor) = $versions;
break;
}
}
// Use glibc's <features.h> header file to
// get major and minor version number:
if (!($major && $minor)) {
$versions = $this->_readGlibCVersionFromFeaturesHeaderFile();
}
if (is_array($versions) && $versions != []) {
list($major, $minor) = $versions;
}
if (!($major && $minor)) {
return $glibc = '';
}
return $glibc = "glibc{$major}.{$minor}";
}
function _readGlibCVersionFromSymlink($file)
{
$versions = array();
if (@is_link($file)
&& (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches))
) {
$versions = explode('.', $matches[1]);
}
return $versions;
}
function _readGlibCVersionFromFeaturesHeaderFile()
{
$features_header_file = '/usr/include/features.h';
if (!(@file_exists($features_header_file)
&& @is_readable($features_header_file))
) {
return array();
}
if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
return $this-_parseFeaturesHeaderFile($features_header_file);
} // no cpp
return $this->_fromGlibCTest();
}
function _parseFeaturesHeaderFile($features_header_file)
{
$features_file = fopen($features_header_file, 'rb');
while (!feof($features_file)) {
$line = fgets($features_file, 8192);
if (!$this->_IsADefinition($line)) {
continue;
}
if (strpos($line, '__GLIBC__')) {
// major version number #define __GLIBC__ version
$line = preg_split('/\s+/', $line);
$glibc_major = trim($line[2]);
if (isset($glibc_minor)) {
break;
}
continue;
}
if (strpos($line, '__GLIBC_MINOR__')) {
// got the minor version number
// #define __GLIBC_MINOR__ version
$line = preg_split('/\s+/', $line);
$glibc_minor = trim($line[2]);
if (isset($glibc_major)) {
break;
}
}
}
fclose($features_file);
if (!isset($glibc_major) || !isset($glibc_minor)) {
return array();
}
return array(trim($glibc_major), trim($glibc_minor));
}
function _IsADefinition($line)
{
if ($line === false) {
return false;
}
return strpos(trim($line), '#define') !== false;
}
function _fromGlibCTest()
{
$major = null;
$minor = null;
$tmpfile = System::mktemp("glibctest");
$fp = fopen($tmpfile, "w");
fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
fclose($fp);
$cpp = popen("/usr/bin/cpp $tmpfile", "r");
while ($line = fgets($cpp, 1024)) {
if ($line[0] == '#' || trim($line) == '') {
continue;
}
if (list($major, $minor) = explode(' ', trim($line))) {
break;
}
}
pclose($cpp);
unlink($tmpfile);
if ($major !== null && $minor !== null) {
return [$major, $minor];
}
}
function getSignature()
{
if (empty($this->extra)) {
return "{$this->sysname}-{$this->release}-{$this->cpu}";
}
return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
}
function getSysname()
{
return $this->sysname;
}
function getNodename()
{
return $this->nodename;
}
function getCpu()
{
return $this->cpu;
}
function getRelease()
{
return $this->release;
}
function getExtra()
{
return $this->extra;
}
function matchSignature($match)
{
$fragments = is_array($match) ? $match : explode('-', $match);
$n = count($fragments);
$matches = 0;
if ($n > 0) {
$matches += $this->_matchFragment($fragments[0], $this->sysname);
}
if ($n > 1) {
$matches += $this->_matchFragment($fragments[1], $this->release);
}
if ($n > 2) {
$matches += $this->_matchFragment($fragments[2], $this->cpu);
}
if ($n > 3) {
$matches += $this->_matchFragment($fragments[3], $this->extra);
}
return ($matches == $n);
}
function _matchFragment($fragment, $value)
{
if (strcspn($fragment, '*?') < strlen($fragment)) {
$expression = str_replace(
array('*', '?', '/'),
array('.*', '.', '\\/'),
$fragment
);
$reg = '/^' . $expression . '\\z/';
return preg_match($reg, $value);
}
return ($fragment == '*' || !strcasecmp($fragment, $value));
}
}
/*
* Local Variables:
* indent-tabs-mode: nil
* c-basic-offset: 4
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,559 +0,0 @@
<?php
/**
* PEAR_Builder for building PHP extensions (PECL packages)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*
* TODO: log output parameters in PECL command line
* TODO: msdev path in configuration
*/
/**
* Needed for extending PEAR_Builder
*/
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
require_once 'System.php';
/**
* Class to handle building (compiling) extensions.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since PHP 4.0.2
* @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
*/
class PEAR_Builder extends PEAR_Common
{
var $php_api_version = 0;
var $zend_module_api_no = 0;
var $zend_extension_api_no = 0;
var $extensions_built = array();
/**
* @var string Used for reporting when it is not possible to pass function
* via extra parameter, e.g. log, msdevCallback
*/
var $current_callback = null;
// used for msdev builds
var $_lastline = null;
var $_firstline = null;
/**
* Parsed --configureoptions.
*
* @var mixed[]
*/
var $_parsed_configure_options;
/**
* PEAR_Builder constructor.
*
* @param mixed[] $configureoptions
* @param object $ui user interface object (instance of PEAR_Frontend_*)
*
* @access public
*/
function __construct($configureoptions, &$ui)
{
parent::__construct();
$this->setFrontendObject($ui);
$this->_parseConfigureOptions($configureoptions);
}
/**
* Parse --configureoptions string.
*
* @param string Options, in the form "X=1 Y=2 Z='there\'s always one'"
*/
function _parseConfigureOptions($options)
{
$data = '<XML><PROPERTIES ' . $options . ' /></XML>';
$parser = xml_parser_create('ISO-8859-1');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler(
$parser, array($this, '_parseConfigureOptionsStartElement'),
array($this, '_parseConfigureOptionsEndElement'));
xml_parse($parser, $data, true);
xml_parser_free($parser);
}
/**
* Handle element start.
*
* @see PEAR_Builder::_parseConfigureOptions()
*
* @param resource $parser
* @param string $tagName
* @param mixed[] $attribs
*/
function _parseConfigureOptionsStartElement($parser, $tagName, $attribs)
{
if ($tagName !== 'PROPERTIES') {
return;
}
$this->_parsed_configure_options = $attribs;
}
/**
* Handle element end.
*
* @see PEAR_Builder::_parseConfigureOptions()
*
* @param resource
* @param string $element
*/
function _parseConfigureOptionsEndElement($parser, $element)
{
}
/**
* Build an extension from source on windows.
* requires msdev
*/
function _build_win32($descfile, $callback = null)
{
if (is_object($descfile)) {
$pkg = $descfile;
$descfile = $pkg->getPackageFile();
} else {
$pf = new PEAR_PackageFile($this->config, $this->debug);
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($pkg)) {
return $pkg;
}
}
$dir = dirname($descfile);
$old_cwd = getcwd();
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
// packages that were in a .tar have the packagefile in this directory
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
if (file_exists($dir) && is_dir($vdir)) {
if (!chdir($vdir)) {
return $this->raiseError("could not chdir to " . realpath($vdir));
}
$dir = getcwd();
}
$this->log(2, "building in $dir");
$dsp = $pkg->getPackage().'.dsp';
if (!file_exists("$dir/$dsp")) {
return $this->raiseError("The DSP $dsp does not exist.");
}
// XXX TODO: make release build type configurable
$command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
$err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
if (PEAR::isError($err)) {
return $err;
}
// figure out the build platform and type
$platform = 'Win32';
$buildtype = 'Release';
if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
$platform = $matches[1];
$buildtype = $matches[2];
}
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
if ($matches[2]) {
// there were errors in the build
return $this->raiseError("There were errors during compilation.");
}
$out = $matches[1];
} else {
return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
}
// msdev doesn't tell us the output directory :/
// open the dsp, find /out and use that directory
$dsptext = join('', file($dsp));
// this regex depends on the build platform and type having been
// correctly identified above.
$regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
$pkg->getPackage().'\s-\s'.
$platform.'\s'.
$buildtype.'").*?'.
'\/out:"(.*?)"/is';
if ($dsptext && preg_match($regex, $dsptext, $matches)) {
// what we get back is a relative path to the output file itself.
$outfile = realpath($matches[2]);
} else {
return $this->raiseError("Could not retrieve output information from $dsp.");
}
// realpath returns false if the file doesn't exist
if ($outfile && copy($outfile, "$dir/$out")) {
$outfile = "$dir/$out";
}
$built_files[] = array(
'file' => "$outfile",
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
return $built_files;
}
// }}}
// {{{ msdevCallback()
function msdevCallback($what, $data)
{
if (!$this->_firstline)
$this->_firstline = $data;
$this->_lastline = $data;
call_user_func($this->current_callback, $what, $data);
}
/**
* @param string
* @param string
* @param array
* @access private
*/
function _harvestInstDir($dest_prefix, $dirname, &$built_files)
{
$d = opendir($dirname);
if (!$d)
return false;
$ret = true;
while (($ent = readdir($d)) !== false) {
if ($ent[0] == '.')
continue;
$full = $dirname . DIRECTORY_SEPARATOR . $ent;
if (is_dir($full)) {
if (!$this->_harvestInstDir(
$dest_prefix . DIRECTORY_SEPARATOR . $ent,
$full, $built_files)) {
$ret = false;
break;
}
} else {
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
$built_files[] = array(
'file' => $full,
'dest' => $dest,
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
}
}
closedir($d);
return $ret;
}
/**
* Build an extension from source. Runs "phpize" in the source
* directory, but compiles in a temporary directory
* (TMPDIR/pear-build-USER/PACKAGE-VERSION).
*
* @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
* a PEAR_PackageFile object
*
* @param mixed $callback callback function used to report output,
* see PEAR_Builder::_runCommand for details
*
* @return array an array of associative arrays with built files,
* format:
* array( array( 'file' => '/path/to/ext.so',
* 'php_api' => YYYYMMDD,
* 'zend_mod_api' => YYYYMMDD,
* 'zend_ext_api' => YYYYMMDD ),
* ... )
*
* @access public
*
* @see PEAR_Builder::_runCommand
*/
function build($descfile, $callback = null)
{
if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php([^\\/\\\\]+)?$/',
$this->config->get('php_bin'), $matches)) {
if (isset($matches[2]) && strlen($matches[2]) &&
trim($matches[2]) != trim($this->config->get('php_prefix'))) {
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
' appears to have a prefix ' . $matches[2] . ', but' .
' config variable php_prefix does not match');
}
if (isset($matches[3]) && strlen($matches[3]) &&
trim($matches[3]) != trim($this->config->get('php_suffix'))) {
$this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
' appears to have a suffix ' . $matches[3] . ', but' .
' config variable php_suffix does not match');
}
}
$this->current_callback = $callback;
if (PEAR_OS == "Windows") {
return $this->_build_win32($descfile, $callback);
}
if (PEAR_OS != 'Unix') {
return $this->raiseError("building extensions not supported on this platform");
}
if (is_object($descfile)) {
$pkg = $descfile;
$descfile = $pkg->getPackageFile();
if (is_a($pkg, 'PEAR_PackageFile_v1')) {
$dir = dirname($descfile);
} else {
$dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
// automatically delete at session end
self::addTempFile($dir);
}
} else {
$pf = new PEAR_PackageFile($this->config);
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($pkg)) {
return $pkg;
}
$dir = dirname($descfile);
}
// Find config. outside of normal path - e.g. config.m4
foreach (array_keys($pkg->getInstallationFileList()) as $item) {
if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
$dir .= DIRECTORY_SEPARATOR . dirname($item);
break;
}
}
$old_cwd = getcwd();
if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
if (is_dir($vdir)) {
chdir($vdir);
}
$dir = getcwd();
$this->log(2, "building in $dir");
$binDir = $this->config->get('bin_dir');
if (!preg_match('@(^|:)' . preg_quote($binDir, '@') . '(:|$)@', getenv('PATH'))) {
putenv('PATH=' . $binDir . ':' . getenv('PATH'));
}
$err = $this->_runCommand($this->config->get('php_prefix')
. "phpize" .
$this->config->get('php_suffix'),
array(&$this, 'phpizeCallback'));
if (PEAR::isError($err)) {
return $err;
}
if (!$err) {
return $this->raiseError("`phpize' failed");
}
// {{{ start of interactive part
$configure_command = "$dir/configure";
$phpConfigName = $this->config->get('php_prefix')
. 'php-config'
. $this->config->get('php_suffix');
$phpConfigPath = System::which($phpConfigName);
if ($phpConfigPath !== false) {
$configure_command .= ' --with-php-config='
. $phpConfigPath;
}
$configure_options = $pkg->getConfigureOptions();
if ($configure_options) {
foreach ($configure_options as $option) {
$default = array_key_exists('default', $option) ? $option['default'] : null;
if (array_key_exists($option['name'], $this->_parsed_configure_options)) {
$response = $this->_parsed_configure_options[$option['name']];
} else {
list($response) = $this->ui->userDialog(
'build', [$option['prompt']], ['text'], [$default]);
}
if (substr($option['name'], 0, 5) === 'with-' &&
($response === 'yes' || $response === 'autodetect')) {
$configure_command .= " --{$option['name']}";
} else {
$configure_command .= " --{$option['name']}=".trim($response);
}
}
}
// }}} end of interactive part
// FIXME make configurable
if (!$user=getenv('USER')) {
$user='defaultuser';
}
$tmpdir = $this->config->get('temp_dir');
$build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
$build_dir = "$build_basedir/$vdir";
$inst_dir = "$build_basedir/install-$vdir";
$this->log(1, "building in $build_dir");
if (is_dir($build_dir)) {
System::rm(array('-rf', $build_dir));
}
if (!System::mkDir(array('-p', $build_dir))) {
return $this->raiseError("could not create build dir: $build_dir");
}
self::addTempFile($build_dir);
if (!System::mkDir(array('-p', $inst_dir))) {
return $this->raiseError("could not create temporary install dir: $inst_dir");
}
self::addTempFile($inst_dir);
$make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
$to_run = array(
$configure_command,
$make_command,
"$make_command INSTALL_ROOT=\"$inst_dir\" install",
"find \"$inst_dir\" | xargs ls -dils"
);
if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
return $this->raiseError("could not chdir to $build_dir");
}
putenv('PHP_PEAR_VERSION=1.10.13');
foreach ($to_run as $cmd) {
$err = $this->_runCommand($cmd, $callback);
if (PEAR::isError($err)) {
chdir($old_cwd);
return $err;
}
if (!$err) {
chdir($old_cwd);
return $this->raiseError("`$cmd' failed");
}
}
if (!($dp = opendir("modules"))) {
chdir($old_cwd);
return $this->raiseError("no `modules' directory found");
}
$built_files = array();
$prefix = exec($this->config->get('php_prefix')
. "php-config" .
$this->config->get('php_suffix') . " --prefix");
$this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
chdir($old_cwd);
return $built_files;
}
/**
* Message callback function used when running the "phpize"
* program. Extracts the API numbers used. Ignores other message
* types than "cmdoutput".
*
* @param string $what the type of message
* @param mixed $data the message
*
* @return void
*
* @access public
*/
function phpizeCallback($what, $data)
{
if ($what != 'cmdoutput') {
return;
}
$this->log(1, rtrim($data));
if (preg_match('/You should update your .aclocal.m4/', $data)) {
return;
}
$matches = array();
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
$member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
$apino = (int)$matches[2];
if (isset($this->$member)) {
$this->$member = $apino;
//$msg = sprintf("%-22s : %d", $matches[1], $apino);
//$this->log(1, $msg);
}
}
}
/**
* Run an external command, using a message callback to report
* output. The command will be run through popen and output is
* reported for every line with a "cmdoutput" message with the
* line string, including newlines, as payload.
*
* @param string $command the command to run
*
* @param mixed $callback (optional) function to use as message
* callback
*
* @return bool whether the command was successful (exit code 0
* means success, any other means failure)
*
* @access private
*/
function _runCommand($command, $callback = null)
{
$this->log(1, "running: $command");
$pp = popen("$command 2>&1", "r");
if (!$pp) {
return $this->raiseError("failed to run `$command'");
}
if ($callback && $callback[0]->debug == 1) {
$olddbg = $callback[0]->debug;
$callback[0]->debug = 2;
}
while ($line = fgets($pp, 1024)) {
if ($callback) {
call_user_func($callback, 'cmdoutput', $line);
} else {
$this->log(2, rtrim($line));
}
}
if ($callback && isset($olddbg)) {
$callback[0]->debug = $olddbg;
}
$exitcode = is_resource($pp) ? pclose($pp) : -1;
return ($exitcode == 0);
}
function log($level, $msg, $append_crlf = true)
{
if ($this->current_callback) {
if ($this->debug >= $level) {
call_user_func($this->current_callback, 'output', $msg);
}
return;
}
return parent::log($level, $msg, $append_crlf);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +0,0 @@
<?php
/**
* PEAR_ChannelFile_Parser for parsing channel.xml
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base xml parser class
*/
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/ChannelFile.php';
/**
* Parser for channel.xml
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_ChannelFile_Parser extends PEAR_XMLParser
{
var $_config;
var $_logger;
var $_registry;
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
function parse($data, $file)
{
if (PEAR::isError($err = parent::parse($data, $file))) {
return $err;
}
$ret = new PEAR_ChannelFile;
$ret->setConfig($this->_config);
if (isset($this->_logger)) {
$ret->setLogger($this->_logger);
}
$ret->fromArray($this->_unserializedData);
// make sure the filelist is in the easy to read format needed
$ret->flattenFilelist();
$ret->setPackagefile($file, $archive);
return $ret;
}
}

View File

@@ -1,389 +0,0 @@
<?php
/**
* PEAR_Command, command pattern class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* Needed for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/XMLParser.php';
/**
* List of commands and what classes they are implemented in.
* @var array command => implementing class
*/
$GLOBALS['_PEAR_Command_commandlist'] = array();
/**
* List of commands and their descriptions
* @var array command => description
*/
$GLOBALS['_PEAR_Command_commanddesc'] = array();
/**
* List of shortcuts to common commands.
* @var array shortcut => command
*/
$GLOBALS['_PEAR_Command_shortcuts'] = array();
/**
* Array of command objects
* @var array class => object
*/
$GLOBALS['_PEAR_Command_objects'] = array();
/**
* PEAR command class, a simple factory class for administrative
* commands.
*
* How to implement command classes:
*
* - The class must be called PEAR_Command_Nnn, installed in the
* "PEAR/Common" subdir, with a method called getCommands() that
* returns an array of the commands implemented by the class (see
* PEAR/Command/Install.php for an example).
*
* - The class must implement a run() function that is called with three
* params:
*
* (string) command name
* (array) assoc array with options, freely defined by each
* command, for example:
* array('force' => true)
* (array) list of the other parameters
*
* The run() function returns a PEAR_CommandResponse object. Use
* these methods to get information:
*
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
* *_PARTIAL means that you need to issue at least
* one more command to complete the operation
* (used for example for validation steps).
*
* string getMessage() Returns a message for the user. Remember,
* no HTML or other interface-specific markup.
*
* If something unexpected happens, run() returns a PEAR error.
*
* - DON'T OUTPUT ANYTHING! Return text for output instead.
*
* - DON'T USE HTML! The text you return will be used from both Gtk,
* web and command-line interfaces, so for now, keep everything to
* plain text.
*
* - DON'T USE EXIT OR DIE! Always use pear errors. From static
* classes do PEAR::raiseError(), from other classes do
* $this->raiseError().
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command
{
// {{{ factory()
/**
* Get the right object for executing a command.
*
* @param string $command The name of the command
* @param object $config Instance of PEAR_Config object
*
* @return object the command object or a PEAR error
*/
public static function &factory($command, &$config)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$ui =& PEAR_Command::getFrontendObject();
$obj = new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getObject()
public static function &getObject($command)
{
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
return PEAR::raiseError("unknown command `$command'");
}
$ui =& PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton();
$obj = new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getFrontendObject()
/**
* Get instance of frontend object.
*
* @return object|PEAR_Error
*/
public static function &getFrontendObject()
{
$a = &PEAR_Frontend::singleton();
return $a;
}
// }}}
// {{{ & setFrontendClass()
/**
* Load current frontend class.
*
* @param string $uiclass Name of class implementing the frontend
*
* @return object the frontend object, or a PEAR error
*/
public static function &setFrontendClass($uiclass)
{
$a = &PEAR_Frontend::setFrontendClass($uiclass);
return $a;
}
// }}}
// {{{ setFrontendType()
/**
* Set current frontend.
*
* @param string $uitype Name of the frontend type (for example "CLI")
*
* @return object the frontend object, or a PEAR error
*/
public static function setFrontendType($uitype)
{
$uiclass = 'PEAR_Frontend_' . $uitype;
return PEAR_Command::setFrontendClass($uiclass);
}
// }}}
// {{{ registerCommands()
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
*
* @param bool (optional) if FALSE (default), the new list of
* commands should replace the current one. If TRUE,
* new entries will be merged with old.
*
* @param string (optional) where (what directory) to look for
* classes, defaults to the Command subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*/
public static function registerCommands($merge = false, $dir = null)
{
$parser = new PEAR_XMLParser;
if ($dir === null) {
$dir = dirname(__FILE__) . '/Command';
}
if (!is_dir($dir)) {
return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerCommands: opendir($dir) failed");
}
if (!$merge) {
$GLOBALS['_PEAR_Command_commandlist'] = array();
}
while ($file = readdir($dp)) {
if ($file[0] == '.' || substr($file, -4) != '.xml') {
continue;
}
$f = substr($file, 0, -4);
$class = "PEAR_Command_" . $f;
// List of commands
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
$GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
}
$parser->parse(file_get_contents("$dir/$file"));
$implements = $parser->getData();
foreach ($implements as $command => $desc) {
if ($command == 'attribs') {
continue;
}
if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return PEAR::raiseError('Command "' . $command . '" already registered in ' .
'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
if (isset($desc['shortcut'])) {
$shortcut = $desc['shortcut'];
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
'registered to command "' . $command . '" in class "' .
$GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
}
if (isset($desc['options']) && $desc['options']) {
foreach ($desc['options'] as $oname => $option) {
if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
return PEAR::raiseError('Option "' . $oname . '" short option "' .
$option['shortopt'] . '" must be ' .
'only 1 character in Command "' . $command . '" in class "' .
$class . '"');
}
}
}
}
}
ksort($GLOBALS['_PEAR_Command_shortcuts']);
ksort($GLOBALS['_PEAR_Command_commandlist']);
@closedir($dp);
return true;
}
// }}}
// {{{ getCommands()
/**
* Get the list of currently supported commands, and what
* classes implement them.
*
* @return array command => implementing class
*/
public static function getCommands()
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_commandlist'];
}
// }}}
// {{{ getShortcuts()
/**
* Get the list of command shortcuts.
*
* @return array shortcut => command
*/
public static function getShortcuts()
{
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_shortcuts'];
}
// }}}
// {{{ getGetoptArgs()
/**
* Compiles arguments for getopt.
*
* @param string $command command to get optstring for
* @param string $short_args (reference) short getopt format
* @param array $long_args (reference) long getopt format
*
* @return void
*/
public static function getGetoptArgs($command, &$short_args, &$long_args)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return null;
}
$obj = &PEAR_Command::getObject($command);
return $obj->getGetoptArgs($command, $short_args, $long_args);
}
// }}}
// {{{ getDescription()
/**
* Get description for a command.
*
* @param string $command Name of the command
*
* @return string command description
*/
public static function getDescription($command)
{
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
return null;
}
return $GLOBALS['_PEAR_Command_commanddesc'][$command];
}
// }}}
// {{{ getHelp()
/**
* Get help for command.
*
* @param string $command Name of the command to return help for
*/
public static function getHelp($command)
{
$cmds = PEAR_Command::getCommands();
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (isset($cmds[$command])) {
$obj = &PEAR_Command::getObject($command);
return $obj->getHelp($command);
}
return false;
}
// }}}
}

View File

@@ -1,80 +0,0 @@
<?php
/**
* PEAR_Command_Auth (login, logout commands)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
* @deprecated since 1.8.0alpha1
*/
/**
* base class
*/
require_once 'PEAR/Command/Channels.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @deprecated since 1.8.0alpha1
*/
class PEAR_Command_Auth extends PEAR_Command_Channels
{
var $commands = array(
'login' => array(
'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
'doc' => '<channel name>
WARNING: This function is deprecated in favor of using channel-login
Log in to a remote channel server. If <channel name> is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'logout' => array(
'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '
WARNING: This function is deprecated in favor of using channel-logout
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
)
);
/**
* PEAR_Command_Auth constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
}

View File

@@ -1,30 +0,0 @@
<commands version="1.0">
<login>
<summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
<function>doLogin</function>
<shortcut>li</shortcut>
<options />
<doc>&lt;channel name&gt;
WARNING: This function is deprecated in favor of using channel-login
Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.</doc>
</login>
<logout>
<summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
<function>doLogout</function>
<shortcut>lo</shortcut>
<options />
<doc>
WARNING: This function is deprecated in favor of using channel-logout
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.</doc>
</logout>
</commands>

View File

@@ -1,91 +0,0 @@
<?php
/**
* PEAR_Command_Auth (build command)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for building extensions.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Build extends PEAR_Command_Common
{
var $commands = array(
'build' => array(
'summary' => 'Build an Extension From C Source',
'function' => 'doBuild',
'shortcut' => 'b',
'options' => array(
'configureoptions' => array(
'shortopt' => 'D',
'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]',
'doc' => 'space-delimited list of configure options',
),
),
'doc' => '[package.xml]
Builds one or more extensions contained in a package.'
),
);
/**
* PEAR_Command_Build constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
function doBuild($command, $options, $params)
{
require_once 'PEAR/Builder.php';
if (sizeof($params) < 1) {
$params[0] = 'package.xml';
}
$configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions'];
$builder = new PEAR_Builder($configureoptions, $this->ui);
$this->debug = $this->config->get('verbose');
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
if (PEAR::isError($err)) {
return $err;
}
return true;
}
function buildCallback($what, $data)
{
if (($what == 'cmdoutput' && $this->debug > 1) ||
($what == 'output' && $this->debug > 0)) {
$this->ui->outputData(rtrim($data), 'build');
}
}
}

View File

@@ -1,15 +0,0 @@
<commands version="1.0">
<build>
<summary>Build an Extension From C Source</summary>
<function>doBuild</function>
<shortcut>b</shortcut>
<options>
<configureoptions>
<shortopt>D</shortopt>
<arg>OPTION1=VALUE[ OPTION2=VALUE]</arg>
</configureoptions>
</options>
<doc>[package.xml]
Builds one or more extensions contained in a package.</doc>
</build>
</commands>

View File

@@ -1,882 +0,0 @@
<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
* channel-update, channel-info, channel-alias, channel-discover commands)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
/**
* PEAR commands for managing channels.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Command_Channels extends PEAR_Command_Common
{
var $commands = array(
'list-channels' => array(
'summary' => 'List Available Channels',
'function' => 'doList',
'shortcut' => 'lc',
'options' => array(),
'doc' => '
List all available channels for installation.
',
),
'update-channels' => array(
'summary' => 'Update the Channel List',
'function' => 'doUpdateAll',
'shortcut' => 'uc',
'options' => array(),
'doc' => '
List all installed packages in all channels.
'
),
'channel-delete' => array(
'summary' => 'Remove a Channel From the List',
'function' => 'doDelete',
'shortcut' => 'cde',
'options' => array(),
'doc' => '<channel name>
Delete a channel from the registry. You may not
remove any channel that has installed packages.
'
),
'channel-add' => array(
'summary' => 'Add a Channel',
'function' => 'doAdd',
'shortcut' => 'ca',
'options' => array(),
'doc' => '<channel.xml>
Add a private channel to the channel list. Note that all
public channels should be synced using "update-channels".
Parameter may be either a local file or remote URL to a
channel.xml.
'
),
'channel-update' => array(
'summary' => 'Update an Existing Channel',
'function' => 'doUpdate',
'shortcut' => 'cu',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'will force download of new channel.xml if an existing channel name is used',
),
'channel' => array(
'shortopt' => 'c',
'arg' => 'CHANNEL',
'doc' => 'will force download of new channel.xml if an existing channel name is used',
),
),
'doc' => '[<channel.xml>|<channel name>]
Update a channel in the channel list directly. Note that all
public channels can be synced using "update-channels".
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
'
),
'channel-info' => array(
'summary' => 'Retrieve Information on a Channel',
'function' => 'doInfo',
'shortcut' => 'ci',
'options' => array(),
'doc' => '<package>
List the files in an installed package.
'
),
'channel-alias' => array(
'summary' => 'Specify an alias to a channel name',
'function' => 'doAlias',
'shortcut' => 'cha',
'options' => array(),
'doc' => '<channel> <alias>
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
'
),
'channel-discover' => array(
'summary' => 'Initialize a Channel from its server',
'function' => 'doDiscover',
'shortcut' => 'di',
'options' => array(),
'doc' => '[<channel.xml>|<channel name>]
Initialize a channel from its server and create a local channel.xml.
If <channel name> is in the format "<username>:<password>@<channel>" then
<username> and <password> will be set as the login username/password for
<channel>. Use caution when passing the username/password in this way, as
it may allow other users on your computer to briefly view your username/
password via the system\'s process list.
'
),
'channel-login' => array(
'summary' => 'Connects and authenticates to remote channel server',
'shortcut' => 'cli',
'function' => 'doLogin',
'options' => array(),
'doc' => '<channel name>
Log in to a remote channel server. If <channel name> is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'channel-logout' => array(
'summary' => 'Logs out from the remote channel server',
'shortcut' => 'clo',
'function' => 'doLogout',
'options' => array(),
'doc' => '<channel name>
Logs out from a remote channel server. If <channel name> is not supplied,
the default channel is used. This command does not actually connect to the
remote server, it only deletes the stored username and password from your user
configuration.',
),
);
/**
* PEAR_Command_Registry constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
function _sortChannels($a, $b)
{
return strnatcasecmp($a->getName(), $b->getName());
}
function doList($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$registered = $reg->getChannels();
usort($registered, array(&$this, '_sortchannels'));
$i = $j = 0;
$data = array(
'caption' => 'Registered Channels:',
'border' => true,
'headline' => array('Channel', 'Alias', 'Summary')
);
foreach ($registered as $channel) {
$data['data'][] = array($channel->getName(),
$channel->getAlias(),
$channel->getSummary());
}
if (count($registered) === 0) {
$data = '(no registered channels)';
}
$this->ui->outputData($data, $command);
return true;
}
function doUpdateAll($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$channels = $reg->getChannels();
$success = true;
foreach ($channels as $channel) {
if ($channel->getName() != '__uri') {
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$err = $this->doUpdate('channel-update',
$options,
array($channel->getName()));
if (PEAR::isError($err)) {
$this->ui->outputData($err->getMessage(), $command);
$success = false;
} else {
$success &= $err;
}
}
}
return $success;
}
function doInfo($command, $options, $params)
{
if (count($params) !== 1) {
return $this->raiseError("No channel specified");
}
$reg = &$this->config->getRegistry();
$channel = strtolower($params[0]);
if ($reg->channelExists($channel)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
} else {
if (strpos($channel, '://')) {
$downloader = &$this->getDownloader();
$tmpdir = $this->config->get('temp_dir');
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError('Cannot open "' . $channel .
'" (' . $loc->getMessage() . ')');
} else {
$contents = implode('', file($loc));
}
} else {
if (!file_exists($params[0])) {
return $this->raiseError('Unknown channel "' . $channel . '"');
}
$fp = fopen($params[0], 'r');
if (!$fp) {
return $this->raiseError('Cannot open "' . $params[0] . '"');
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$chan = new PEAR_ChannelFile;
$chan->fromXmlString($contents);
$chan->validate();
if ($errs = $chan->getErrors(true)) {
foreach ($errs as $err) {
$this->ui->outputData($err['level'] . ': ' . $err['message']);
}
return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
}
}
if (!$chan) {
return $this->raiseError('Serious error: Channel "' . $params[0] .
'" has a corrupted registry entry');
}
$channel = $chan->getName();
$caption = 'Channel ' . $channel . ' Information:';
$data1 = array(
'caption' => $caption,
'border' => true);
$data1['data']['server'] = array('Name and Server', $chan->getName());
if ($chan->getAlias() != $chan->getName()) {
$data1['data']['alias'] = array('Alias', $chan->getAlias());
}
$data1['data']['summary'] = array('Summary', $chan->getSummary());
$validate = $chan->getValidationPackage();
$data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
$data1['data']['vpackageversion'] =
array('Validation Package Version', $validate['attribs']['version']);
$d = array();
$d['main'] = $data1;
$data['data'] = array();
$data['caption'] = 'Server Capabilities';
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
if ($chan->supportsREST()) {
if ($chan->supportsREST()) {
$funcs = $chan->getFunctions('rest');
if (!isset($funcs[0])) {
$funcs = array($funcs);
}
foreach ($funcs as $protocol) {
$data['data'][] = array('rest', $protocol['attribs']['type'],
$protocol['_content']);
}
}
} else {
$data['data'][] = array('No supported protocols');
}
$d['protocols'] = $data;
$data['data'] = array();
$mirrors = $chan->getMirrors();
if ($mirrors) {
$data['caption'] = 'Channel ' . $channel . ' Mirrors:';
unset($data['headline']);
foreach ($mirrors as $mirror) {
$data['data'][] = array($mirror['attribs']['host']);
$d['mirrors'] = $data;
}
foreach ($mirrors as $i => $mirror) {
$data['data'] = array();
$data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
if ($chan->supportsREST($mirror['attribs']['host'])) {
if ($chan->supportsREST($mirror['attribs']['host'])) {
$funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
if (!isset($funcs[0])) {
$funcs = array($funcs);
}
foreach ($funcs as $protocol) {
$data['data'][] = array('rest', $protocol['attribs']['type'],
$protocol['_content']);
}
}
} else {
$data['data'][] = array('No supported protocols');
}
$d['mirrorprotocols' . $i] = $data;
}
}
$this->ui->outputData($d, 'channel-info');
}
// }}}
function doDelete($command, $options, $params)
{
if (count($params) !== 1) {
return $this->raiseError('channel-delete: no channel specified');
}
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($params[0])) {
return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
}
$channel = $reg->channelName($params[0]);
if ($channel == 'pear.php.net') {
return $this->raiseError('Cannot delete the pear.php.net channel');
}
if ($channel == 'pecl.php.net') {
return $this->raiseError('Cannot delete the pecl.php.net channel');
}
if ($channel == 'doc.php.net') {
return $this->raiseError('Cannot delete the doc.php.net channel');
}
if ($channel == '__uri') {
return $this->raiseError('Cannot delete the __uri pseudo-channel');
}
if (PEAR::isError($err = $reg->listPackages($channel))) {
return $err;
}
if (count($err)) {
return $this->raiseError('Channel "' . $channel .
'" has installed packages, cannot delete');
}
if (!$reg->deleteChannel($channel)) {
return $this->raiseError('Channel "' . $channel . '" deletion failed');
} else {
$this->config->deleteChannel($channel);
$this->ui->outputData('Channel "' . $channel . '" deleted', $command);
}
}
function doAdd($command, $options, $params)
{
if (count($params) !== 1) {
return $this->raiseError('channel-add: no channel file specified');
}
if (strpos($params[0], '://')) {
$downloader = &$this->getDownloader();
$tmpdir = $this->config->get('temp_dir');
if (!file_exists($tmpdir)) {
require_once 'System.php';
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$err = System::mkdir(array('-p', $tmpdir));
PEAR::staticPopErrorHandling();
if (PEAR::isError($err)) {
return $this->raiseError('channel-add: temp_dir does not exist: "' .
$tmpdir .
'" - You can change this location with "pear config-set temp_dir"');
}
}
if (!is_writable($tmpdir)) {
return $this->raiseError('channel-add: temp_dir is not writable: "' .
$tmpdir .
'" - You can change this location with "pear config-set temp_dir"');
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError('channel-add: Cannot open "' . $params[0] .
'" (' . $loc->getMessage() . ')');
}
list($loc, $lastmodified) = $loc;
$contents = implode('', file($loc));
} else {
$lastmodified = $fp = false;
if (file_exists($params[0])) {
$fp = fopen($params[0], 'r');
}
if (!$fp) {
return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$result = $channel->fromXmlString($contents);
PEAR::staticPopErrorHandling();
if (!$result) {
$exit = false;
if (count($errors = $channel->getErrors(true))) {
foreach ($errors as $error) {
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
if (!$exit) {
$exit = $error['level'] == 'error' ? true : false;
}
}
if ($exit) {
return $this->raiseError('channel-add: invalid channel.xml file');
}
}
}
$reg = &$this->config->getRegistry();
if ($reg->channelExists($channel->getName())) {
return $this->raiseError('channel-add: Channel "' . $channel->getName() .
'" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
}
$ret = $reg->addChannel($channel, $lastmodified);
if (PEAR::isError($ret)) {
return $ret;
}
if (!$ret) {
return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
'" to registry failed');
}
$this->config->setChannels($reg->listChannels());
$this->config->writeConfigFile();
$this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
}
function doUpdate($command, $options, $params)
{
if (count($params) !== 1) {
return $this->raiseError("No channel file specified");
}
$tmpdir = $this->config->get('temp_dir');
if (!file_exists($tmpdir)) {
require_once 'System.php';
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$err = System::mkdir(array('-p', $tmpdir));
PEAR::staticPopErrorHandling();
if (PEAR::isError($err)) {
return $this->raiseError('channel-add: temp_dir does not exist: "' .
$tmpdir .
'" - You can change this location with "pear config-set temp_dir"');
}
}
if (!is_writable($tmpdir)) {
return $this->raiseError('channel-add: temp_dir is not writable: "' .
$tmpdir .
'" - You can change this location with "pear config-set temp_dir"');
}
$reg = &$this->config->getRegistry();
$lastmodified = false;
if ((!file_exists($params[0]) || is_dir($params[0]))
&& $reg->channelExists(strtolower($params[0]))) {
$c = $reg->getChannel(strtolower($params[0]));
if (PEAR::isError($c)) {
return $this->raiseError($c);
}
$this->ui->outputData("Updating channel \"$params[0]\"", $command);
$dl = &$this->getDownloader(array());
// if force is specified, use a timestamp of "1" to force retrieval
$lastmodified = isset($options['force']) ? false : $c->lastModified();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($contents)) {
// Attempt to fall back to https
$this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
$this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($contents)) {
return $this->raiseError('Cannot retrieve channel.xml for channel "' .
$c->getName() . '" (' . $contents->getMessage() . ')');
}
}
list($contents, $lastmodified) = $contents;
if (!$contents) {
$this->ui->outputData("Channel \"$params[0]\" is up to date");
return;
}
$contents = implode('', file($contents));
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
$channel->fromXmlString($contents);
if (!$channel->getErrors()) {
// security check: is the downloaded file for the channel we got it from?
if (strtolower($channel->getName()) != strtolower($c->getName())) {
if (!isset($options['force'])) {
return $this->raiseError('ERROR: downloaded channel definition file' .
' for channel "' . $channel->getName() . '" from channel "' .
strtolower($c->getName()) . '"');
}
$this->ui->log(0, 'WARNING: downloaded channel definition file' .
' for channel "' . $channel->getName() . '" from channel "' .
strtolower($c->getName()) . '"');
}
}
} else {
if (strpos($params[0], '://')) {
$dl = &$this->getDownloader();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $dl->downloadHttp($params[0],
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError("Cannot open " . $params[0] .
' (' . $loc->getMessage() . ')');
}
list($loc, $lastmodified) = $loc;
$contents = implode('', file($loc));
} else {
$fp = false;
if (file_exists($params[0])) {
$fp = fopen($params[0], 'r');
}
if (!$fp) {
return $this->raiseError("Cannot open " . $params[0]);
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
$channel->fromXmlString($contents);
}
$exit = false;
if (count($errors = $channel->getErrors(true))) {
foreach ($errors as $error) {
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
if (!$exit) {
$exit = $error['level'] == 'error' ? true : false;
}
}
if ($exit) {
return $this->raiseError('Invalid channel.xml file');
}
}
if (!$reg->channelExists($channel->getName())) {
return $this->raiseError('Error: Channel "' . $channel->getName() .
'" does not exist, use channel-add to add an entry');
}
$ret = $reg->updateChannel($channel, $lastmodified);
if (PEAR::isError($ret)) {
return $ret;
}
if (!$ret) {
return $this->raiseError('Updating Channel "' . $channel->getName() .
'" in registry failed');
}
$this->config->setChannels($reg->listChannels());
$this->config->writeConfigFile();
$this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
}
function &getDownloader()
{
if (!class_exists('PEAR_Downloader')) {
require_once 'PEAR/Downloader.php';
}
$a = new PEAR_Downloader($this->ui, array(), $this->config);
return $a;
}
function doAlias($command, $options, $params)
{
if (count($params) === 1) {
return $this->raiseError('No channel alias specified');
}
if (count($params) !== 2 || (!empty($params[1]) && $params[1][0] == '-')) {
return $this->raiseError(
'Invalid format, correct is: channel-alias channel alias');
}
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($params[0], true)) {
$extra = '';
if ($reg->isAlias($params[0])) {
$extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
strtolower($params[1]) . '")';
}
return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
}
if ($reg->isAlias($params[1])) {
return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
}
$chan = $reg->getChannel($params[0]);
if (PEAR::isError($chan)) {
return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
'" information (' . $chan->getMessage() . ')');
}
// make it a local alias
if (!$chan->setAlias(strtolower($params[1]), true)) {
return $this->raiseError('Alias "' . strtolower($params[1]) .
'" is not a valid channel alias');
}
$reg->updateChannel($chan);
$this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
strtolower($params[1]) . '"');
}
/**
* The channel-discover command
*
* @param string $command command name
* @param array $options option_name => value
* @param array $params list of additional parameters.
* $params[0] should contain a string with either:
* - <channel name> or
* - <username>:<password>@<channel name>
* @return null|PEAR_Error
*/
function doDiscover($command, $options, $params)
{
if (count($params) !== 1) {
return $this->raiseError("No channel server specified");
}
// Look for the possible input format "<username>:<password>@<channel>"
if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
$username = $matches[1];
$password = $matches[2];
$channel = $matches[3];
} else {
$channel = $params[0];
}
$reg = &$this->config->getRegistry();
if ($reg->channelExists($channel)) {
if (!$reg->isAlias($channel)) {
return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
}
return $this->raiseError("A channel alias named \"$channel\" " .
'already exists, aliasing channel "' . $reg->channelName($channel)
. '"');
}
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
$this->popErrorHandling();
if (PEAR::isError($err)) {
if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
return $this->raiseError("Discovery of channel \"$channel\" failed (" .
$err->getMessage() . ')');
}
// Attempt fetch via https
$this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
$this->ui->outputData("Trying to discover channel $channel over https:// instead");
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
$this->popErrorHandling();
if (PEAR::isError($err)) {
return $this->raiseError("Discovery of channel \"$channel\" failed (" .
$err->getMessage() . ')');
}
}
// Store username/password if they were given
// Arguably we should do a logintest on the channel here, but since
// that's awkward on a REST-based channel (even "pear login" doesn't
// do it for those), and XML-RPC is deprecated, it's fairly pointless.
if (isset($username)) {
$this->config->set('username', $username, 'user', $channel);
$this->config->set('password', $password, 'user', $channel);
$this->config->store();
$this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
}
$this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
}
/**
* Execute the 'login' command.
*
* @param string $command command name
* @param array $options option_name => value
* @param array $params list of additional parameters
*
* @return bool TRUE on success or
* a PEAR error on failure
*
* @access public
*/
function doLogin($command, $options, $params)
{
$reg = &$this->config->getRegistry();
// If a parameter is supplied, use that as the channel to log in to
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
$server = $this->config->get('preferred_mirror', null, $channel);
$username = $this->config->get('username', null, $channel);
if (empty($username)) {
$username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
}
$this->ui->outputData("Logging in to $server.", $command);
list($username, $password) = $this->ui->userDialog(
$command,
array('Username', 'Password'),
array('text', 'password'),
array($username, '')
);
$username = trim($username);
$password = trim($password);
$ourfile = $this->config->getConfFile('user');
if (!$ourfile) {
$ourfile = $this->config->getConfFile('system');
}
$this->config->set('username', $username, 'user', $channel);
$this->config->set('password', $password, 'user', $channel);
if ($chan->supportsREST()) {
$ok = true;
}
if ($ok !== true) {
return $this->raiseError('Login failed!');
}
$this->ui->outputData("Logged in.", $command);
// avoid changing any temporary settings changed with -d
$ourconfig = new PEAR_Config($ourfile, $ourfile);
$ourconfig->set('username', $username, 'user', $channel);
$ourconfig->set('password', $password, 'user', $channel);
$ourconfig->store();
return true;
}
/**
* Execute the 'logout' command.
*
* @param string $command command name
* @param array $options option_name => value
* @param array $params list of additional parameters
*
* @return bool TRUE on success or
* a PEAR error on failure
*
* @access public
*/
function doLogout($command, $options, $params)
{
$reg = &$this->config->getRegistry();
// If a parameter is supplied, use that as the channel to log in to
$channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
$server = $this->config->get('preferred_mirror', null, $channel);
$this->ui->outputData("Logging out from $server.", $command);
$this->config->remove('username', 'user', $channel);
$this->config->remove('password', 'user', $channel);
$this->config->store();
return true;
}
}

View File

@@ -1,123 +0,0 @@
<commands version="1.0">
<list-channels>
<summary>List Available Channels</summary>
<function>doList</function>
<shortcut>lc</shortcut>
<options />
<doc>
List all available channels for installation.
</doc>
</list-channels>
<update-channels>
<summary>Update the Channel List</summary>
<function>doUpdateAll</function>
<shortcut>uc</shortcut>
<options />
<doc>
List all installed packages in all channels.
</doc>
</update-channels>
<channel-delete>
<summary>Remove a Channel From the List</summary>
<function>doDelete</function>
<shortcut>cde</shortcut>
<options />
<doc>&lt;channel name&gt;
Delete a channel from the registry. You may not
remove any channel that has installed packages.
</doc>
</channel-delete>
<channel-add>
<summary>Add a Channel</summary>
<function>doAdd</function>
<shortcut>ca</shortcut>
<options />
<doc>&lt;channel.xml&gt;
Add a private channel to the channel list. Note that all
public channels should be synced using &quot;update-channels&quot;.
Parameter may be either a local file or remote URL to a
channel.xml.
</doc>
</channel-add>
<channel-update>
<summary>Update an Existing Channel</summary>
<function>doUpdate</function>
<shortcut>cu</shortcut>
<options>
<force>
<shortopt>f</shortopt>
<doc>will force download of new channel.xml if an existing channel name is used</doc>
</force>
<channel>
<shortopt>c</shortopt>
<doc>will force download of new channel.xml if an existing channel name is used</doc>
<arg>CHANNEL</arg>
</channel>
</options>
<doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Update a channel in the channel list directly. Note that all
public channels can be synced using &quot;update-channels&quot;.
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
</doc>
</channel-update>
<channel-info>
<summary>Retrieve Information on a Channel</summary>
<function>doInfo</function>
<shortcut>ci</shortcut>
<options />
<doc>&lt;package&gt;
List the files in an installed package.
</doc>
</channel-info>
<channel-alias>
<summary>Specify an alias to a channel name</summary>
<function>doAlias</function>
<shortcut>cha</shortcut>
<options />
<doc>&lt;channel&gt; &lt;alias&gt;
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
</doc>
</channel-alias>
<channel-discover>
<summary>Initialize a Channel from its server</summary>
<function>doDiscover</function>
<shortcut>di</shortcut>
<options />
<doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Initialize a channel from its server and create a local channel.xml.
If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
&lt;username&gt; and &lt;password&gt; will be set as the login username/password for
&lt;channel&gt;. Use caution when passing the username/password in this way, as
it may allow other users on your computer to briefly view your username/
password via the system&#039;s process list.
</doc>
</channel-discover>
<channel-login>
<summary>Connects and authenticates to remote channel server</summary>
<function>doLogin</function>
<shortcut>cli</shortcut>
<options />
<doc>&lt;channel name&gt;
Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.</doc>
</channel-login>
<channel-logout>
<summary>Logs out from the remote channel server</summary>
<function>doLogout</function>
<shortcut>clo</shortcut>
<options />
<doc>&lt;channel name&gt;
Logs out from a remote channel server. If &lt;channel name&gt; is not supplied,
the default channel is used. This command does not actually connect to the
remote server, it only deletes the stored username and password from your user
configuration.</doc>
</channel-logout>
</commands>

View File

@@ -1,272 +0,0 @@
<?php
/**
* PEAR_Command_Common base class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR.php';
/**
* PEAR commands base class
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Common extends PEAR
{
/**
* PEAR_Config object used to pass user system and configuration
* on when executing commands
*
* @var PEAR_Config
*/
var $config;
/**
* @var PEAR_Registry
* @access protected
*/
var $_registry;
/**
* User Interface object, for all interaction with the user.
* @var object
*/
var $ui;
var $_deps_rel_trans = array(
'lt' => '<',
'le' => '<=',
'eq' => '=',
'ne' => '!=',
'gt' => '>',
'ge' => '>=',
'has' => '=='
);
var $_deps_type_trans = array(
'pkg' => 'package',
'ext' => 'extension',
'php' => 'PHP',
'prog' => 'external program',
'ldlib' => 'external library for linking',
'rtlib' => 'external runtime library',
'os' => 'operating system',
'websrv' => 'web server',
'sapi' => 'SAPI backend'
);
/**
* PEAR_Command_Common constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct();
$this->config = &$config;
$this->ui = &$ui;
}
/**
* Return a list of all the commands defined by this class.
* @return array list of commands
* @access public
*/
function getCommands()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
$ret[$command] = $this->commands[$command]['summary'];
}
return $ret;
}
/**
* Return a list of all the command shortcuts defined by this class.
* @return array shortcut => command
* @access public
*/
function getShortcuts()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
if (isset($this->commands[$command]['shortcut'])) {
$ret[$this->commands[$command]['shortcut']] = $command;
}
}
return $ret;
}
function getOptions($command)
{
$shortcuts = $this->getShortcuts();
if (isset($shortcuts[$command])) {
$command = $shortcuts[$command];
}
if (isset($this->commands[$command]) &&
isset($this->commands[$command]['options'])) {
return $this->commands[$command]['options'];
}
return null;
}
function getGetoptArgs($command, &$short_args, &$long_args)
{
$short_args = '';
$long_args = array();
if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
return;
}
reset($this->commands[$command]['options']);
foreach ($this->commands[$command]['options'] as $option => $info) {
$larg = $sarg = '';
if (isset($info['arg'])) {
if ($info['arg'][0] == '(') {
$larg = '==';
$sarg = '::';
$arg = substr($info['arg'], 1, -1);
} else {
$larg = '=';
$sarg = ':';
$arg = $info['arg'];
}
}
if (isset($info['shortopt'])) {
$short_args .= $info['shortopt'] . $sarg;
}
$long_args[] = $option . $larg;
}
}
/**
* Returns the help message for the given command
*
* @param string $command The command
* @return mixed A fail string if the command does not have help or
* a two elements array containing [0]=>help string,
* [1]=> help string for the accepted cmd args
*/
function getHelp($command)
{
$config = &PEAR_Config::singleton();
if (!isset($this->commands[$command])) {
return "No such command \"$command\"";
}
$help = null;
if (isset($this->commands[$command]['doc'])) {
$help = $this->commands[$command]['doc'];
}
if (empty($help)) {
// XXX (cox) Fallback to summary if there is no doc (show both?)
if (!isset($this->commands[$command]['summary'])) {
return "No help for command \"$command\"";
}
$help = $this->commands[$command]['summary'];
}
if (preg_match_all('/{config\s+([^\}]+)}/', $help, $matches)) {
foreach($matches[0] as $k => $v) {
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
}
}
return array($help, $this->getHelpArgs($command));
}
/**
* Returns the help for the accepted arguments of a command
*
* @param string $command
* @return string The help string
*/
function getHelpArgs($command)
{
if (isset($this->commands[$command]['options']) &&
count($this->commands[$command]['options']))
{
$help = "Options:\n";
foreach ($this->commands[$command]['options'] as $k => $v) {
if (isset($v['arg'])) {
if ($v['arg'][0] == '(') {
$arg = substr($v['arg'], 1, -1);
$sapp = " [$arg]";
$lapp = "[=$arg]";
} else {
$sapp = " $v[arg]";
$lapp = "=$v[arg]";
}
} else {
$sapp = $lapp = "";
}
if (isset($v['shortopt'])) {
$s = $v['shortopt'];
$help .= " -$s$sapp, --$k$lapp\n";
} else {
$help .= " --$k$lapp\n";
}
$p = " ";
$doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
$help .= " $doc\n";
}
return $help;
}
return null;
}
function run($command, $options, $params)
{
if (empty($this->commands[$command]['function'])) {
// look for shortcuts
foreach (array_keys($this->commands) as $cmd) {
if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
if (empty($this->commands[$cmd]['function'])) {
return $this->raiseError("unknown command `$command'");
} else {
$func = $this->commands[$cmd]['function'];
}
$command = $cmd;
//$command = $this->commands[$cmd]['function'];
break;
}
}
} else {
$func = $this->commands[$command]['function'];
}
return $this->$func($command, $options, $params);
}
}

View File

@@ -1,414 +0,0 @@
<?php
/**
* PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for managing configuration data.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Config extends PEAR_Command_Common
{
var $commands = array(
'config-show' => array(
'summary' => 'Show All Settings',
'function' => 'doConfigShow',
'shortcut' => 'csh',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are "user", "system" and "default". To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
',
),
'config-get' => array(
'summary' => 'Show One Setting',
'function' => 'doConfigGet',
'shortcut' => 'cg',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '<parameter> [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are "user", "system" and "default". If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified. The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
',
),
'config-set' => array(
'summary' => 'Change Setting',
'function' => 'doConfigSet',
'shortcut' => 'cs',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '<parameter> <value> [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is "user". The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
',
),
'config-help' => array(
'summary' => 'Show Information About Setting',
'function' => 'doConfigHelp',
'shortcut' => 'ch',
'options' => array(),
'doc' => '[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
',
),
'config-create' => array(
'summary' => 'Create a Default configuration file',
'function' => 'doConfigCreate',
'shortcut' => 'coc',
'options' => array(
'windows' => array(
'shortopt' => 'w',
'doc' => 'create a config file for a windows install',
),
),
'doc' => '<root path> <filename>
Create a default configuration file with all directory configuration
variables set to subdirectories of <root path>, and save it as <filename>.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
',
),
);
/**
* PEAR_Command_Config constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
function doConfigShow($command, $options, $params)
{
$layer = null;
if (is_array($params)) {
$layer = isset($params[0]) ? $params[0] : null;
}
// $params[0] -> the layer
if ($error = $this->_checkLayer($layer)) {
return $this->raiseError("config-show:$error");
}
$keys = $this->config->getKeys();
sort($keys);
$channel = isset($options['channel']) ? $options['channel'] :
$this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$channel = $reg->channelName($channel);
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
foreach ($keys as $key) {
$type = $this->config->getType($key);
$value = $this->config->get($key, $layer, $channel);
if ($type == 'password' && $value) {
$value = '********';
}
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
}
foreach ($this->config->getLayers() as $layer) {
$data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
}
$this->ui->outputData($data, $command);
return true;
}
function doConfigGet($command, $options, $params)
{
$args_cnt = is_array($params) ? count($params) : 0;
switch ($args_cnt) {
case 1:
$config_key = $params[0];
$layer = null;
break;
case 2:
$config_key = $params[0];
$layer = $params[1];
if ($error = $this->_checkLayer($layer)) {
return $this->raiseError("config-get:$error");
}
break;
case 0:
default:
return $this->raiseError("config-get expects 1 or 2 parameters");
}
$reg = &$this->config->getRegistry();
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$channel = $reg->channelName($channel);
$this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
return true;
}
function doConfigSet($command, $options, $params)
{
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
if (count($params) < 2 || count($params) > 3) {
$failmsg .= "config-set expects 2 or 3 parameters";
return PEAR::raiseError($failmsg);
}
if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
$failmsg .= $error;
return PEAR::raiseError("config-set:$failmsg");
}
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$channel = $reg->channelName($channel);
if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
return $this->raiseError('Channel "' . $params[1] . '" does not exist');
}
if ($params[0] == 'preferred_mirror'
&& (
!$reg->mirrorExists($channel, $params[1]) &&
(!$reg->channelExists($params[1]) || $channel != $params[1])
)
) {
$msg = 'Channel Mirror "' . $params[1] . '" does not exist';
$msg .= ' in your registry for channel "' . $channel . '".';
$msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
$msg .= ' if you believe this mirror should exist as you may';
$msg .= ' have outdated channel information.';
return $this->raiseError($msg);
}
if (count($params) == 2) {
array_push($params, 'user');
$layer = 'user';
} else {
$layer = $params[2];
}
array_push($params, $channel);
if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
array_pop($params);
$failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
} else {
$this->config->store($layer);
}
if ($failmsg) {
return $this->raiseError($failmsg);
}
$this->ui->outputData('config-set succeeded', $command);
return true;
}
function doConfigHelp($command, $options, $params)
{
if (empty($params)) {
$params = $this->config->getKeys();
}
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
$data['headline'] = array('Name', 'Type', 'Description');
$data['border'] = true;
foreach ($params as $name) {
$type = $this->config->getType($name);
$docs = $this->config->getDocs($name);
if ($type == 'set') {
$docs = rtrim($docs) . "\nValid set: " .
implode(' ', $this->config->getSetValues($name));
}
$data['data'][] = array($name, $type, $docs);
}
$this->ui->outputData($data, $command);
}
function doConfigCreate($command, $options, $params)
{
if (count($params) != 2) {
return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
'filename to save as');
}
$root = $params[0];
// Clean up the DIRECTORY_SEPARATOR mess
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
$root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
array('/', '/', '/'),
$root);
if ($root[0] != '/') {
if (!isset($options['windows'])) {
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
'with "/", was: "' . $root . '"');
}
if (!preg_match('/^[A-Za-z]:/', $root)) {
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
'with "\\" or "C:\\", was: "' . $root . '"');
}
}
$windows = isset($options['windows']);
if ($windows) {
$root = str_replace('/', '\\', $root);
}
if (!file_exists($params[1]) && !@touch($params[1])) {
return PEAR::raiseError('Could not create "' . $params[1] . '"');
}
$params[1] = realpath($params[1]);
$config = new PEAR_Config($params[1], '#no#system#config#', false, false);
if ($root[strlen($root) - 1] == '/') {
$root = substr($root, 0, strlen($root) - 1);
}
$config->noRegistry();
$config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
$config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
$config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
$config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
$config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
$config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
$config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
$config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
$config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
$config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
$config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
$config->set('man_dir', $windows ? "$root\\pear\\man" : "$root/pear/man");
$config->writeConfigFile();
$this->_showConfig($config);
$this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
$command);
}
function _showConfig(&$config)
{
$params = array('user');
$keys = $config->getKeys();
sort($keys);
$channel = 'pear.php.net';
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
foreach ($keys as $key) {
$type = $config->getType($key);
$value = $config->get($key, 'user', $channel);
if ($type == 'password' && $value) {
$value = '********';
}
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$data['data'][$config->getGroup($key)][] =
array($config->getPrompt($key) , $key, $value);
}
foreach ($config->getLayers() as $layer) {
$data['data']['Config Files'][] =
array(ucfirst($layer) . ' Configuration File', 'Filename' ,
$config->getConfFile($layer));
}
$this->ui->outputData($data, 'config-show');
return true;
}
/**
* Checks if a layer is defined or not
*
* @param string $layer The layer to search for
* @return mixed False on no error or the error message
*/
function _checkLayer($layer = null)
{
if (!empty($layer) && $layer != 'default') {
$layers = $this->config->getLayers();
if (!in_array($layer, $layers)) {
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
}
}
return false;
}
}

View File

@@ -1,92 +0,0 @@
<commands version="1.0">
<config-show>
<summary>Show All Settings</summary>
<function>doConfigShow</function>
<shortcut>csh</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
</doc>
</config-show>
<config-get>
<summary>Show One Setting</summary>
<function>doConfigGet</function>
<shortcut>cg</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>&lt;parameter&gt; [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified. The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
</doc>
</config-get>
<config-set>
<summary>Change Setting</summary>
<function>doConfigSet</function>
<shortcut>cs</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>&lt;parameter&gt; &lt;value&gt; [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is &quot;user&quot;. The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
</doc>
</config-set>
<config-help>
<summary>Show Information About Setting</summary>
<function>doConfigHelp</function>
<shortcut>ch</shortcut>
<options />
<doc>[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
</doc>
</config-help>
<config-create>
<summary>Create a Default configuration file</summary>
<function>doConfigCreate</function>
<shortcut>coc</shortcut>
<options>
<windows>
<shortopt>w</shortopt>
<doc>create a config file for a windows install</doc>
</windows>
</options>
<doc>&lt;root path&gt; &lt;filename&gt;
Create a default configuration file with all directory configuration
variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
</doc>
</config-create>
</commands>

File diff suppressed because it is too large Load Diff

View File

@@ -1,280 +0,0 @@
<commands version="1.0">
<install>
<summary>Install Package</summary>
<function>doInstall</function>
<shortcut>i</shortcut>
<options>
<force>
<shortopt>f</shortopt>
<doc>will overwrite newer installed packages</doc>
</force>
<loose>
<shortopt>l</shortopt>
<doc>do not check for recommended dependency version</doc>
</loose>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, install anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as installed</doc>
</register-only>
<soft>
<shortopt>s</shortopt>
<doc>soft install, fail silently, or upgrade if already installed</doc>
</soft>
<nobuild>
<shortopt>B</shortopt>
<doc>don&#039;t build C extensions</doc>
</nobuild>
<configureoptions>
<shortopt>D</shortopt>
<arg>OPTION1=VALUE[ OPTION2=VALUE]</arg>
</configureoptions>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
<arg>DIR</arg>
</installroot>
<packagingroot>
<shortopt>P</shortopt>
<doc>root directory used when packaging files, like RPM packaging</doc>
<arg>DIR</arg>
</packagingroot>
<ignore-errors>
<shortopt></shortopt>
<doc>force install even if there were errors</doc>
</ignore-errors>
<alldeps>
<shortopt>a</shortopt>
<doc>install all required and optional dependencies</doc>
</alldeps>
<onlyreqdeps>
<shortopt>o</shortopt>
<doc>install all required dependencies</doc>
</onlyreqdeps>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to download any urls or contact channels</doc>
</offline>
<pretend>
<shortopt>p</shortopt>
<doc>Only list the packages that would be downloaded</doc>
</pretend>
</options>
<doc>[channel/]&lt;package&gt; ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
&quot;Package-1.0.tgz&quot; : installs from a local file
&quot;http://example.com/Package-1.0.tgz&quot; : installs from
anywhere on the net.
&quot;package.xml&quot; : installs the package described in
package.xml. Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.
&quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).
To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
Package state beta, use &quot;Package-beta.&quot; To retrieve an uncompressed
file, append .tar (make sure there is no file by the same name first)
To download a package from another channel, prefix with the channel name like
&quot;channel/Package&quot;
More than one package may be specified at once. It is ok to mix these
four ways of specifying packages.
</doc>
</install>
<upgrade>
<summary>Upgrade Package</summary>
<function>doInstall</function>
<shortcut>up</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>upgrade packages from a specific channel</doc>
<arg>CHAN</arg>
</channel>
<force>
<shortopt>f</shortopt>
<doc>overwrite newer installed packages</doc>
</force>
<loose>
<shortopt>l</shortopt>
<doc>do not check for recommended dependency version</doc>
</loose>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, upgrade anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as upgraded</doc>
</register-only>
<nobuild>
<shortopt>B</shortopt>
<doc>don&#039;t build C extensions</doc>
</nobuild>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
<arg>DIR</arg>
</installroot>
<ignore-errors>
<shortopt></shortopt>
<doc>force install even if there were errors</doc>
</ignore-errors>
<alldeps>
<shortopt>a</shortopt>
<doc>install all required and optional dependencies</doc>
</alldeps>
<onlyreqdeps>
<shortopt>o</shortopt>
<doc>install all required dependencies</doc>
</onlyreqdeps>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to download any urls or contact channels</doc>
</offline>
<pretend>
<shortopt>p</shortopt>
<doc>Only list the packages that would be downloaded</doc>
</pretend>
</options>
<doc>&lt;package&gt; ...
Upgrades one or more PEAR packages. See documentation for the
&quot;install&quot; command for ways to specify a package.
When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).
More than one package may be specified at once.
</doc>
</upgrade>
<upgrade-all>
<summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
<function>doUpgradeAll</function>
<shortcut>ua</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>upgrade packages from a specific channel</doc>
<arg>CHAN</arg>
</channel>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, upgrade anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as upgraded</doc>
</register-only>
<nobuild>
<shortopt>B</shortopt>
<doc>don&#039;t build C extensions</doc>
</nobuild>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
<arg>DIR</arg>
</installroot>
<ignore-errors>
<shortopt></shortopt>
<doc>force install even if there were errors</doc>
</ignore-errors>
<loose>
<shortopt></shortopt>
<doc>do not check for recommended dependency version</doc>
</loose>
</options>
<doc>
WARNING: This function is deprecated in favor of using the upgrade command with no params
Upgrades all packages that have a newer release available. Upgrades are
done only if there is a release available of the state specified in
&quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
more stable.
</doc>
</upgrade-all>
<uninstall>
<summary>Un-install Package</summary>
<function>doUninstall</function>
<shortcut>un</shortcut>
<options>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, uninstall anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not remove files, only register the packages as not installed</doc>
</register-only>
<installroot>
<shortopt>R</shortopt>
<doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
<arg>DIR</arg>
</installroot>
<ignore-errors>
<shortopt></shortopt>
<doc>force install even if there were errors</doc>
</ignore-errors>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to uninstall remotely</doc>
</offline>
</options>
<doc>[channel/]&lt;package&gt; ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once. Prefix with channel name to uninstall from a
channel not in your default channel ({config default_channel})
</doc>
</uninstall>
<bundle>
<summary>Unpacks a Pecl Package</summary>
<function>doBundle</function>
<shortcut>bun</shortcut>
<options>
<destination>
<shortopt>d</shortopt>
<doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
<arg>DIR</arg>
</destination>
<force>
<shortopt>f</shortopt>
<doc>Force the unpacking even if there were errors in the package</doc>
</force>
</options>
<doc>&lt;package&gt;
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
</doc>
</bundle>
<run-scripts>
<summary>Run Post-Install Scripts bundled with a package</summary>
<function>doRunScripts</function>
<shortcut>rs</shortcut>
<options />
<doc>&lt;package&gt;
Run post-installation scripts in package &lt;package&gt;, if any exist.
</doc>
</run-scripts>
</commands>

View File

@@ -1,138 +0,0 @@
<?php
/**
* PEAR_Command_Mirror (download-all command)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Alexander Merz <alexmerz@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.2.0
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for providing file mirrors
*
* @category pear
* @package PEAR
* @author Alexander Merz <alexmerz@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.2.0
*/
class PEAR_Command_Mirror extends PEAR_Command_Common
{
var $commands = array(
'download-all' => array(
'summary' => 'Downloads each available package from the default channel',
'function' => 'doDownloadAll',
'shortcut' => 'da',
'options' => array(
'channel' =>
array(
'shortopt' => 'c',
'doc' => 'specify a channel other than the default channel',
'arg' => 'CHAN',
),
),
'doc' => '
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory. Note: only
packages within preferred_state ({config preferred_state}) will be downloaded'
),
);
/**
* PEAR_Command_Mirror constructor.
*
* @access public
* @param object PEAR_Frontend a reference to an frontend
* @param object PEAR_Config a reference to the configuration data
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
/**
* For unit-testing
*/
function &factory($a)
{
$a = &PEAR_Command::factory($a, $this->config);
return $a;
}
/**
* retrieves a list of avaible Packages from master server
* and downloads them
*
* @access public
* @param string $command the command
* @param array $options the command options before the command
* @param array $params the stuff after the command name
* @return bool true if successful
* @throw PEAR_Error
*/
function doDownloadAll($command, $options, $params)
{
$savechannel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
$channel = isset($options['channel']) ? $options['channel'] :
$this->config->get('default_channel');
if (!$reg->channelExists($channel)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$this->config->set('default_channel', $channel);
$this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$rest = &$this->config->getREST('1.0', array());
$remoteInfo = array_flip($rest->listPackages($base, $channel));
}
if (PEAR::isError($remoteInfo)) {
return $remoteInfo;
}
$cmd = &$this->factory("download");
if (PEAR::isError($cmd)) {
return $cmd;
}
$this->ui->outputData('Using Preferred State of ' .
$this->config->get('preferred_state'));
$this->ui->outputData('Gathering release information, please wait...');
/**
* Error handling not necessary, because already done by
* the download command
*/
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
PEAR::staticPopErrorHandling();
$this->config->set('default_channel', $savechannel);
if (PEAR::isError($err)) {
$this->ui->outputData($err->getMessage());
}
return true;
}
}

View File

@@ -1,18 +0,0 @@
<commands version="1.0">
<download-all>
<summary>Downloads each available package from the default channel</summary>
<function>doDownloadAll</function>
<shortcut>da</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>specify a channel other than the default channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory. Note: only
packages within preferred_state ({config preferred_state}) will be downloaded</doc>
</download-all>
</commands>

File diff suppressed because it is too large Load Diff

View File

@@ -1,237 +0,0 @@
<commands version="1.0">
<package>
<summary>Build Package</summary>
<function>doPackage</function>
<shortcut>p</shortcut>
<options>
<nocompress>
<shortopt>Z</shortopt>
<doc>Do not gzip the package file</doc>
</nocompress>
<showname>
<shortopt>n</shortopt>
<doc>Print the name of the packaged file.</doc>
</showname>
</options>
<doc>[descfile] [descfile2]
Creates a PEAR package from its description file (usually called
package.xml). If a second packagefile is passed in, then
the packager will check to make sure that one is a package.xml
version 1.0, and the other is a package.xml version 2.0. The
package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
and the other as &quot;package2.xml&quot; in the archive&quot;
</doc>
</package>
<package-validate>
<summary>Validate Package Consistency</summary>
<function>doPackageValidate</function>
<shortcut>pv</shortcut>
<options />
<doc>
</doc>
</package-validate>
<cvsdiff>
<summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
<function>doCvsDiff</function>
<shortcut>cd</shortcut>
<options>
<quiet>
<shortopt>q</shortopt>
<doc>Be quiet</doc>
</quiet>
<reallyquiet>
<shortopt>Q</shortopt>
<doc>Be really quiet</doc>
</reallyquiet>
<date>
<shortopt>D</shortopt>
<doc>Diff against revision of DATE</doc>
<arg>DATE</arg>
</date>
<release>
<shortopt>R</shortopt>
<doc>Diff against tag for package release REL</doc>
<arg>REL</arg>
</release>
<revision>
<shortopt>r</shortopt>
<doc>Diff against revision REV</doc>
<arg>REV</arg>
</revision>
<context>
<shortopt>c</shortopt>
<doc>Generate context diff</doc>
</context>
<unified>
<shortopt>u</shortopt>
<doc>Generate unified diff</doc>
</unified>
<ignore-case>
<shortopt>i</shortopt>
<doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
</ignore-case>
<ignore-whitespace>
<shortopt>b</shortopt>
<doc>Ignore changes in amount of white space</doc>
</ignore-whitespace>
<ignore-blank-lines>
<shortopt>B</shortopt>
<doc>Ignore changes that insert or delete blank lines</doc>
</ignore-blank-lines>
<brief>
<shortopt></shortopt>
<doc>Report only whether the files differ, no details</doc>
</brief>
<dry-run>
<shortopt>n</shortopt>
<doc>Don&#039;t do anything, just pretend</doc>
</dry-run>
</options>
<doc>&lt;package.xml&gt;
Compares all the files in a package. Without any options, this
command will compare the current code with the last checked-in code.
Using the -r or -R option you may compare the current code with that
of a specific release.
</doc>
</cvsdiff>
<svntag>
<summary>Set SVN Release Tag</summary>
<function>doSvnTag</function>
<shortcut>sv</shortcut>
<options>
<quiet>
<shortopt>q</shortopt>
<doc>Be quiet</doc>
</quiet>
<slide>
<shortopt>F</shortopt>
<doc>Move (slide) tag if it exists</doc>
</slide>
<delete>
<shortopt>d</shortopt>
<doc>Remove tag</doc>
</delete>
<dry-run>
<shortopt>n</shortopt>
<doc>Don&#039;t do anything, just pretend</doc>
</dry-run>
</options>
<doc>&lt;package.xml&gt; [files...]
Sets a SVN tag on all files in a package. Use this command after you have
packaged a distribution tarball with the &quot;package&quot; command to tag what
revisions of what files were in that release. If need to fix something
after running svntag once, but before the tarball is released to the public,
use the &quot;slide&quot; option to move the release tag.
to include files (such as a second package.xml, or tests not included in the
release), pass them as additional parameters.
</doc>
</svntag>
<cvstag>
<summary>Set CVS Release Tag</summary>
<function>doCvsTag</function>
<shortcut>ct</shortcut>
<options>
<quiet>
<shortopt>q</shortopt>
<doc>Be quiet</doc>
</quiet>
<reallyquiet>
<shortopt>Q</shortopt>
<doc>Be really quiet</doc>
</reallyquiet>
<slide>
<shortopt>F</shortopt>
<doc>Move (slide) tag if it exists</doc>
</slide>
<delete>
<shortopt>d</shortopt>
<doc>Remove tag</doc>
</delete>
<dry-run>
<shortopt>n</shortopt>
<doc>Don&#039;t do anything, just pretend</doc>
</dry-run>
</options>
<doc>&lt;package.xml&gt; [files...]
Sets a CVS tag on all files in a package. Use this command after you have
packaged a distribution tarball with the &quot;package&quot; command to tag what
revisions of what files were in that release. If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the &quot;slide&quot; option to move the release tag.
to include files (such as a second package.xml, or tests not included in the
release), pass them as additional parameters.
</doc>
</cvstag>
<package-dependencies>
<summary>Show package dependencies</summary>
<function>doPackageDependencies</function>
<shortcut>pd</shortcut>
<options />
<doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
List all dependencies the package has.
Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
</package-dependencies>
<sign>
<summary>Sign a package distribution file</summary>
<function>doSign</function>
<shortcut>si</shortcut>
<options>
<verbose>
<shortopt>v</shortopt>
<doc>Display GnuPG output</doc>
</verbose>
</options>
<doc>&lt;package-file&gt;
Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
</sign>
<makerpm>
<summary>Builds an RPM spec file from a PEAR package</summary>
<function>doMakeRPM</function>
<shortcut>rpm</shortcut>
<options>
<spec-template>
<shortopt>t</shortopt>
<doc>Use FILE as RPM spec file template</doc>
<arg>FILE</arg>
</spec-template>
<rpm-pkgname>
<shortopt>p</shortopt>
<doc>Use FORMAT as format string for RPM package name, %s is replaced
by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
<arg>FORMAT</arg>
</rpm-pkgname>
</options>
<doc>&lt;package-file&gt;
Creates an RPM .spec file for wrapping a PEAR package inside an RPM
package. Intended to be used from the SPECS directory, with the PEAR
package tarball in the SOURCES directory:
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
$ rpm -bb PEAR::Net_Socket-1.0.spec
...
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
</doc>
</makerpm>
<convert>
<summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
<function>doConvert</function>
<shortcut>c2</shortcut>
<options>
<flat>
<shortopt>f</shortopt>
<doc>do not beautify the filelist.</doc>
</flat>
</options>
<doc>[descfile] [descfile2]
Converts a package.xml in 1.0 format into a package.xml
in 2.0 format. The new file will be named package2.xml by default,
and package.xml will be used as the old file by default.
This is not the most intelligent conversion, and should only be
used for automated conversion or learning the format.
</doc>
</convert>
</commands>

View File

@@ -1,420 +0,0 @@
<?php
/**
* PEAR_Command_Pickle (pickle command)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2005-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2005-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.1
*/
class PEAR_Command_Pickle extends PEAR_Command_Common
{
var $commands = array(
'pickle' => array(
'summary' => 'Build PECL Package',
'function' => 'doPackage',
'shortcut' => 'pi',
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'Do not gzip the package file'
),
'showname' => array(
'shortopt' => 'n',
'doc' => 'Print the name of the packaged file.',
),
),
'doc' => '[descfile]
Creates a PECL package from its package2.xml file.
An automatic conversion will be made to a package.xml 1.0 and written out to
disk in the current directory as "package.xml". Note that
only simple package.xml 2.0 will be converted. package.xml 2.0 with:
- dependency types other than required/optional PECL package/ext/php/pearinstaller
- more than one extsrcrelease or zendextsrcrelease
- zendextbinrelease, extbinrelease, phprelease, or bundle release type
- dependency groups
- ignore tags in release filelist
- tasks other than replace
- custom roles
will cause pickle to fail, and output an error message. If your package2.xml
uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
'
),
);
/**
* PEAR_Command_Package constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
/**
* For unit-testing ease
*
* @return PEAR_Packager
*/
function &getPackager()
{
if (!class_exists('PEAR_Packager')) {
require_once 'PEAR/Packager.php';
}
$a = new PEAR_Packager;
return $a;
}
/**
* For unit-testing ease
*
* @param PEAR_Config $config
* @param bool $debug
* @param string|null $tmpdir
* @return PEAR_PackageFile
*/
function &getPackageFile($config, $debug = false)
{
if (!class_exists('PEAR_Common')) {
require_once 'PEAR/Common.php';
}
if (!class_exists('PEAR_PackageFile')) {
require_once 'PEAR/PackageFile.php';
}
$a = new PEAR_PackageFile($config, $debug);
$common = new PEAR_Common;
$common->ui = $this->ui;
$a->setLogger($common);
return $a;
}
function doPackage($command, $options, $params)
{
$this->output = '';
$pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
$packager = &$this->getPackager();
if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
return $err;
}
$compress = empty($options['nocompress']) ? true : false;
$result = $packager->package($pkginfofile, $compress, 'package.xml');
if (PEAR::isError($result)) {
return $this->raiseError($result);
}
// Don't want output, only the package file name just created
if (isset($options['showname'])) {
$this->ui->outputData($result, $command);
}
return true;
}
function _convertPackage($packagexml)
{
$pkg = &$this->getPackageFile($this->config);
$pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
return $this->raiseError('Cannot process "' .
$packagexml . '", is not a package.xml 2.0');
}
require_once 'PEAR/PackageFile/v1.php';
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->config);
if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
'script is an option');
}
if (is_array($pf2->getUsesRole())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
'the convert command is an option');
}
if (is_array($pf2->getUsesTask())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
'the convert command is an option');
}
$deps = $pf2->getDependencies();
if (isset($deps['group'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if (isset($deps['required']['subpackage']) ||
isset($deps['optional']['subpackage'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
if (isset($deps['required']['os'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains os dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
if (isset($deps['required']['arch'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
$pf->setPackage($pf2->getPackage());
$pf->setSummary($pf2->getSummary());
$pf->setDescription($pf2->getDescription());
foreach ($pf2->getMaintainers() as $maintainer) {
$pf->addMaintainer($maintainer['role'], $maintainer['handle'],
$maintainer['name'], $maintainer['email']);
}
$pf->setVersion($pf2->getVersion());
$pf->setDate($pf2->getDate());
$pf->setLicense($pf2->getLicense());
$pf->setState($pf2->getState());
$pf->setNotes($pf2->getNotes());
$pf->addPhpDep($deps['required']['php']['min'], 'ge');
if (isset($deps['required']['php']['max'])) {
$pf->addPhpDep($deps['required']['php']['max'], 'le');
}
if (isset($deps['required']['package'])) {
if (!isset($deps['required']['package'][0])) {
$deps['required']['package'] = array($deps['required']['package']);
}
foreach ($deps['required']['package'] as $dep) {
if (!isset($dep['channel'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains uri-based dependency on a package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if ($dep['channel'] != 'pear.php.net'
&& $dep['channel'] != 'pecl.php.net'
&& $dep['channel'] != 'doc.php.net') {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains dependency on a non-standard channel package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['conflicts'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains conflicts dependency. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addPackageDep($dep['name'], $dep['min'], 'ge');
}
if (isset($dep['max'])) {
$pf->addPackageDep($dep['name'], $dep['max'], 'le');
}
}
}
if (isset($deps['required']['extension'])) {
if (!isset($deps['required']['extension'][0])) {
$deps['required']['extension'] = array($deps['required']['extension']);
}
foreach ($deps['required']['extension'] as $dep) {
if (isset($dep['conflicts'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains conflicts dependency. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
}
if (isset($dep['max'])) {
$pf->addExtensionDep($dep['name'], $dep['max'], 'le');
}
}
}
if (isset($deps['optional']['package'])) {
if (!isset($deps['optional']['package'][0])) {
$deps['optional']['package'] = array($deps['optional']['package']);
}
foreach ($deps['optional']['package'] as $dep) {
if (!isset($dep['channel'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains uri-based dependency on a package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if ($dep['channel'] != 'pear.php.net'
&& $dep['channel'] != 'pecl.php.net'
&& $dep['channel'] != 'doc.php.net') {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains dependency on a non-standard channel package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
}
if (isset($dep['max'])) {
$pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
}
}
}
if (isset($deps['optional']['extension'])) {
if (!isset($deps['optional']['extension'][0])) {
$deps['optional']['extension'] = array($deps['optional']['extension']);
}
foreach ($deps['optional']['extension'] as $dep) {
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
}
if (isset($dep['max'])) {
$pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
}
}
}
$contents = $pf2->getContents();
$release = $pf2->getReleases();
if (isset($releases[0])) {
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
. 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if ($configoptions = $pf2->getConfigureOptions()) {
foreach ($configoptions as $option) {
$default = isset($option['default']) ? $option['default'] : false;
$pf->addConfigureOption($option['name'], $option['prompt'], $default);
}
}
if (isset($release['filelist']['ignore'])) {
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
. 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
' command is an option');
}
if (isset($release['filelist']['install']) &&
!isset($release['filelist']['install'][0])) {
$release['filelist']['install'] = array($release['filelist']['install']);
}
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
$baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
} else {
$baseinstalldir = false;
}
if (!isset($contents['dir']['file'][0])) {
$contents['dir']['file'] = array($contents['dir']['file']);
}
foreach ($contents['dir']['file'] as $file) {
if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
$file['attribs']['baseinstalldir'] = $baseinstalldir;
}
$processFile = $file;
unset($processFile['attribs']);
if (count($processFile)) {
foreach ($processFile as $name => $task) {
if ($name != $pf2->getTasksNs() . ':replace') {
return $this->raiseError('Cannot safely process "' . $packagexml .
'" contains tasks other than replace. Using a ' .
'PEAR_PackageFileManager-based script is an option.');
}
$file['attribs']['replace'][] = $task;
}
}
if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if (isset($release['filelist']['install'])) {
foreach ($release['filelist']['install'] as $installas) {
if ($installas['attribs']['name'] == $file['attribs']['name']) {
$file['attribs']['install-as'] = $installas['attribs']['as'];
}
}
}
$pf->addFile('/', $file['attribs']['name'], $file['attribs']);
}
if ($pf2->getChangeLog()) {
$this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
'1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
'translation for package.xml 1.0');
}
$gen = &$pf->getDefaultGenerator();
$gen->toPackageFile('.');
}
}

View File

@@ -1,36 +0,0 @@
<commands version="1.0">
<pickle>
<summary>Build PECL Package</summary>
<function>doPackage</function>
<shortcut>pi</shortcut>
<options>
<nocompress>
<shortopt>Z</shortopt>
<doc>Do not gzip the package file</doc>
</nocompress>
<showname>
<shortopt>n</shortopt>
<doc>Print the name of the packaged file.</doc>
</showname>
</options>
<doc>[descfile]
Creates a PECL package from its package2.xml file.
An automatic conversion will be made to a package.xml 1.0 and written out to
disk in the current directory as &quot;package.xml&quot;. Note that
only simple package.xml 2.0 will be converted. package.xml 2.0 with:
- dependency types other than required/optional PECL package/ext/php/pearinstaller
- more than one extsrcrelease or zendextsrcrelease
- zendextbinrelease, extbinrelease, phprelease, or bundle release type
- dependency groups
- ignore tags in release filelist
- tasks other than replace
- custom roles
will cause pickle to fail, and output an error message. If your package2.xml
uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
</doc>
</pickle>
</commands>

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +0,0 @@
<commands version="1.0">
<list>
<summary>List Installed Packages In The Default Channel</summary>
<function>doList</function>
<shortcut>l</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>list installed packages from this channel</doc>
<arg>CHAN</arg>
</channel>
<allchannels>
<shortopt>a</shortopt>
<doc>list installed packages from all channels</doc>
</allchannels>
<channelinfo>
<shortopt>i</shortopt>
<doc>output fully channel-aware data, even on failure</doc>
</channelinfo>
</options>
<doc>&lt;package&gt;
If invoked without parameters, this command lists the PEAR packages
installed in your php_dir ({config php_dir}). With a parameter, it
lists the files in a package.
</doc>
</list>
<list-files>
<summary>List Files In Installed Package</summary>
<function>doFileList</function>
<shortcut>fl</shortcut>
<options />
<doc>&lt;package&gt;
List the files in an installed package.
</doc>
</list-files>
<shell-test>
<summary>Shell Script Test</summary>
<function>doShellTest</function>
<shortcut>st</shortcut>
<options />
<doc>&lt;package&gt; [[relation] version]
Tests if a package is installed in the system. Will exit(1) if it is not.
&lt;relation&gt; The version comparison operator. One of:
&lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
&lt;version&gt; The version to compare with
</doc>
</shell-test>
<info>
<summary>Display information about a package</summary>
<function>doInfo</function>
<shortcut>in</shortcut>
<options />
<doc>&lt;package&gt;
Displays information about a package. The package argument may be a
local package file, an URL to a package file, or the name of an
installed package.</doc>
</info>
</commands>

View File

@@ -1,809 +0,0 @@
<?php
/**
* PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
* clear-cache commands)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/REST.php';
/**
* PEAR commands for remote server querying
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Remote extends PEAR_Command_Common
{
var $commands = array(
'remote-info' => array(
'summary' => 'Information About Remote Packages',
'function' => 'doRemoteInfo',
'shortcut' => 'ri',
'options' => array(),
'doc' => '<package>
Get details on a package from the server.',
),
'list-upgrades' => array(
'summary' => 'List Available Upgrades',
'function' => 'doListUpgrades',
'shortcut' => 'lu',
'options' => array(
'channelinfo' => array(
'shortopt' => 'i',
'doc' => 'output fully channel-aware data, even on failure',
),
),
'doc' => '[preferred_state]
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.)
or the state passed as the second parameter.'
),
'remote-list' => array(
'summary' => 'List Remote Packages',
'function' => 'doRemoteList',
'shortcut' => 'rl',
'options' => array(
'channel' =>
array(
'shortopt' => 'c',
'doc' => 'specify a channel other than the default channel',
'arg' => 'CHAN',
)
),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
),
'search' => array(
'summary' => 'Search remote package database',
'function' => 'doSearch',
'shortcut' => 'sp',
'options' => array(
'channel' =>
array(
'shortopt' => 'c',
'doc' => 'specify a channel other than the default channel',
'arg' => 'CHAN',
),
'allchannels' => array(
'shortopt' => 'a',
'doc' => 'search packages from all known channels',
),
'channelinfo' => array(
'shortopt' => 'i',
'doc' => 'output fully channel-aware data, even on failure',
),
),
'doc' => '[packagename] [packageinfo]
Lists all packages which match the search parameters. The first
parameter is a fragment of a packagename. The default channel
will be used unless explicitly overridden. The second parameter
will be used to match any portion of the summary/description',
),
'list-all' => array(
'summary' => 'List All Packages',
'function' => 'doListAll',
'shortcut' => 'la',
'options' => array(
'channel' =>
array(
'shortopt' => 'c',
'doc' => 'specify a channel other than the default channel',
'arg' => 'CHAN',
),
'channelinfo' => array(
'shortopt' => 'i',
'doc' => 'output fully channel-aware data, even on failure',
),
),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
),
'download' => array(
'summary' => 'Download Package',
'function' => 'doDownload',
'shortcut' => 'd',
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'download an uncompressed (.tar) file',
),
),
'doc' => '<package>...
Download package tarballs. The files will be named as suggested by the
server, for example if you download the DB package and the latest stable
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
),
'clear-cache' => array(
'summary' => 'Clear Web Services Cache',
'function' => 'doClearCache',
'shortcut' => 'cc',
'options' => array(),
'doc' => '
Clear the REST cache. See also the cache_ttl configuration
parameter.
',
),
);
/**
* PEAR_Command_Remote constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
function _checkChannelForStatus($channel, $chan)
{
if (PEAR::isError($chan)) {
$this->raiseError($chan);
}
if (!is_a($chan, 'PEAR_ChannelFile')) {
return $this->raiseError('Internal corruption error: invalid channel "' .
$channel . '"');
}
$rest = new PEAR_REST($this->config);
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$mirror = $this->config->get('preferred_mirror', null,
$channel);
$a = $rest->downloadHttp('http://' . $channel .
'/channel.xml', $chan->lastModified());
PEAR::staticPopErrorHandling();
if (!PEAR::isError($a) && $a) {
$this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
'" to update');
}
}
function doRemoteInfo($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError("$command expects one param: the remote package name");
}
$savechannel = $channel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
$package = $params[0];
$parsed = $reg->parsePackageName($package, $channel);
if (PEAR::isError($parsed)) {
return $this->raiseError('Invalid package name "' . $package . '"');
}
$channel = $parsed['channel'];
$this->config->set('default_channel', $channel);
$chan = $reg->getChannel($channel);
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
return $e;
}
$mirror = $this->config->get('preferred_mirror');
if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
$rest = &$this->config->getREST('1.0', array());
$info = $rest->packageInfo($base, $parsed['package'], $channel);
}
if (!isset($info)) {
return $this->raiseError('No supported protocol was found');
}
if (PEAR::isError($info)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError($info);
}
if (!isset($info['name'])) {
return $this->raiseError('No remote package "' . $package . '" was found');
}
$installed = $reg->packageInfo($info['name'], null, $channel);
$info['installed'] = $installed ? $installed['version'] : '- no -';
if (is_array($info['installed'])) {
$info['installed'] = $info['installed']['release'];
}
$this->ui->outputData($info, $command);
$this->config->set('default_channel', $savechannel);
return true;
}
function doRemoteList($command, $options, $params)
{
$savechannel = $channel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (isset($options['channel'])) {
$channel = $options['channel'];
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$this->config->set('default_channel', $channel);
}
$chan = $reg->getChannel($channel);
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
return $e;
}
$list_options = false;
if ($this->config->get('preferred_state') == 'stable') {
$list_options = true;
}
$available = array();
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
) {
// use faster list-all if available
$rest = &$this->config->getREST('1.1', array());
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$rest = &$this->config->getREST('1.0', array());
$available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
}
if (PEAR::isError($available)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError($available);
}
$i = $j = 0;
$data = array(
'caption' => 'Channel ' . $channel . ' Available packages:',
'border' => true,
'headline' => array('Package', 'Version'),
'channel' => $channel
);
if (count($available) == 0) {
$data = '(no packages available yet)';
} else {
foreach ($available as $name => $info) {
$version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
$data['data'][] = array($name, $version);
}
}
$this->ui->outputData($data, $command);
$this->config->set('default_channel', $savechannel);
return true;
}
function doListAll($command, $options, $params)
{
$savechannel = $channel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (isset($options['channel'])) {
$channel = $options['channel'];
if (!$reg->channelExists($channel)) {
return $this->raiseError("Channel \"$channel\" does not exist");
}
$this->config->set('default_channel', $channel);
}
$list_options = false;
if ($this->config->get('preferred_state') == 'stable') {
$list_options = true;
}
$chan = $reg->getChannel($channel);
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
return $e;
}
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
// use faster list-all if available
$rest = &$this->config->getREST('1.1', array());
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
} elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$rest = &$this->config->getREST('1.0', array());
$available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
}
if (PEAR::isError($available)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
}
$data = array(
'caption' => 'All packages [Channel ' . $channel . ']:',
'border' => true,
'headline' => array('Package', 'Latest', 'Local'),
'channel' => $channel,
);
if (isset($options['channelinfo'])) {
// add full channelinfo
$data['caption'] = 'Channel ' . $channel . ' All packages:';
$data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
'Description', 'Dependencies');
}
$local_pkgs = $reg->listPackages($channel);
foreach ($available as $name => $info) {
$installed = $reg->packageInfo($name, null, $channel);
if ($installed && is_array($installed['version'])) {
$installed['version'] = $installed['version']['release'];
}
$desc = $info['summary'];
if (isset($params[$name])) {
$desc .= "\n\n".$info['description'];
}
if (isset($options['mode']))
{
if ($options['mode'] == 'installed' && !isset($installed['version'])) {
continue;
}
if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
continue;
}
if ($options['mode'] == 'upgrades'
&& (!isset($installed['version']) || version_compare($installed['version'],
$info['stable'], '>='))) {
continue;
}
}
$pos = array_search(strtolower($name), $local_pkgs);
if ($pos !== false) {
unset($local_pkgs[$pos]);
}
if (isset($info['stable']) && !$info['stable']) {
$info['stable'] = null;
}
if (isset($options['channelinfo'])) {
// add full channelinfo
if ($info['stable'] === $info['unstable']) {
$state = $info['state'];
} else {
$state = 'stable';
}
$latest = $info['stable'].' ('.$state.')';
$local = '';
if (isset($installed['version'])) {
$inst_state = $reg->packageInfo($name, 'release_state', $channel);
$local = $installed['version'].' ('.$inst_state.')';
}
$packageinfo = array(
$channel,
$name,
$latest,
$local,
isset($desc) ? $desc : null,
isset($info['deps']) ? $info['deps'] : null,
);
} else {
$packageinfo = array(
$reg->channelAlias($channel) . '/' . $name,
isset($info['stable']) ? $info['stable'] : null,
isset($installed['version']) ? $installed['version'] : null,
isset($desc) ? $desc : null,
isset($info['deps']) ? $info['deps'] : null,
);
}
$data['data'][$info['category']][] = $packageinfo;
}
if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
$this->config->set('default_channel', $savechannel);
$this->ui->outputData($data, $command);
return true;
}
foreach ($local_pkgs as $name) {
$info = &$reg->getPackage($name, $channel);
$data['data']['Local'][] = array(
$reg->channelAlias($channel) . '/' . $info->getPackage(),
'',
$info->getVersion(),
$info->getSummary(),
$info->getDeps()
);
}
$this->config->set('default_channel', $savechannel);
$this->ui->outputData($data, $command);
return true;
}
function doSearch($command, $options, $params)
{
if ((!isset($params[0]) || empty($params[0]))
&& (!isset($params[1]) || empty($params[1])))
{
return $this->raiseError('no valid search string supplied');
}
$channelinfo = isset($options['channelinfo']);
$reg = &$this->config->getRegistry();
if (isset($options['allchannels'])) {
// search all channels
unset($options['allchannels']);
$channels = $reg->getChannels();
$errors = array();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
foreach ($channels as $channel) {
if ($channel->getName() != '__uri') {
$options['channel'] = $channel->getName();
$ret = $this->doSearch($command, $options, $params);
if (PEAR::isError($ret)) {
$errors[] = $ret;
}
}
}
PEAR::staticPopErrorHandling();
if (count($errors) !== 0) {
// for now, only give first error
return PEAR::raiseError($errors[0]);
}
return true;
}
$savechannel = $channel = $this->config->get('default_channel');
$package = strtolower($params[0]);
$summary = isset($params[1]) ? $params[1] : false;
if (isset($options['channel'])) {
$reg = &$this->config->getRegistry();
$channel = $options['channel'];
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$this->config->set('default_channel', $channel);
}
$chan = $reg->getChannel($channel);
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
return $e;
}
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$rest = &$this->config->getREST('1.0', array());
$available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
}
if (PEAR::isError($available)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError($available);
}
if (!$available && !$channelinfo) {
// clean exit when not found, no error !
$data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
$this->ui->outputData($data);
$this->config->set('default_channel', $channel);
return true;
}
if ($channelinfo) {
$data = array(
'caption' => 'Matched packages, channel ' . $channel . ':',
'border' => true,
'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
'channel' => $channel
);
} else {
$data = array(
'caption' => 'Matched packages, channel ' . $channel . ':',
'border' => true,
'headline' => array('Package', 'Stable/(Latest)', 'Local'),
'channel' => $channel
);
}
if (!$available && $channelinfo) {
unset($data['headline']);
$data['data'] = 'No packages found that match pattern "' . $package . '".';
$available = array();
}
foreach ($available as $name => $info) {
$installed = $reg->packageInfo($name, null, $channel);
$desc = $info['summary'];
if (isset($params[$name]))
$desc .= "\n\n".$info['description'];
if (!isset($info['stable']) || !$info['stable']) {
$version_remote = 'none';
} else {
if ($info['unstable']) {
$version_remote = $info['unstable'];
} else {
$version_remote = $info['stable'];
}
$version_remote .= ' ('.$info['state'].')';
}
$version = is_array($installed['version']) ? $installed['version']['release'] :
$installed['version'];
if ($channelinfo) {
$packageinfo = array(
$channel,
$name,
$version_remote,
$version,
$desc,
);
} else {
$packageinfo = array(
$name,
$version_remote,
$version,
$desc,
);
}
$data['data'][$info['category']][] = $packageinfo;
}
$this->ui->outputData($data, $command);
$this->config->set('default_channel', $channel);
return true;
}
function &getDownloader($options)
{
if (!class_exists('PEAR_Downloader')) {
require_once 'PEAR/Downloader.php';
}
$a = new PEAR_Downloader($this->ui, $options, $this->config);
return $a;
}
function doDownload($command, $options, $params)
{
// make certain that dependencies are ignored
$options['downloadonly'] = 1;
// eliminate error messages for preferred_state-related errors
/* TODO: Should be an option, but until now download does respect
preferred state */
/* $options['ignorepreferred_state'] = 1; */
// eliminate error messages for preferred_state-related errors
$downloader = &$this->getDownloader($options);
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$e = $downloader->setDownloadDir(getcwd());
PEAR::staticPopErrorHandling();
if (PEAR::isError($e)) {
return $this->raiseError('Current directory is not writeable, cannot download');
}
$errors = array();
$downloaded = array();
$err = $downloader->download($params);
if (PEAR::isError($err)) {
return $err;
}
$errors = $downloader->getErrorMsgs();
if (count($errors)) {
foreach ($errors as $error) {
if ($error !== null) {
$this->ui->outputData($error);
}
}
return $this->raiseError("$command failed");
}
$downloaded = $downloader->getDownloadedPackages();
foreach ($downloaded as $pkg) {
$this->ui->outputData("File $pkg[file] downloaded", $command);
}
return true;
}
function downloadCallback($msg, $params = null)
{
if ($msg == 'done') {
$this->bytes_downloaded = $params;
}
}
function doListUpgrades($command, $options, $params)
{
require_once 'PEAR/Common.php';
if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
}
$savechannel = $channel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
foreach ($reg->listChannels() as $channel) {
$inst = array_flip($reg->listPackages($channel));
if (!count($inst)) {
continue;
}
if ($channel == '__uri') {
continue;
}
$this->config->set('default_channel', $channel);
$state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
$caption = $channel . ' Available Upgrades';
$chan = $reg->getChannel($channel);
if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
return $e;
}
$latest = array();
$base2 = false;
$preferred_mirror = $this->config->get('preferred_mirror');
if ($chan->supportsREST($preferred_mirror) &&
(
($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
|| ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
)
) {
if ($base2) {
$rest = &$this->config->getREST('1.3', array());
$base = $base2;
} else {
$rest = &$this->config->getREST('1.0', array());
}
if (empty($state) || $state == 'any') {
$state = false;
} else {
$caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
PEAR::staticPopErrorHandling();
}
if (PEAR::isError($latest)) {
$this->ui->outputData($latest->getMessage());
continue;
}
$caption .= ':';
if (PEAR::isError($latest)) {
$this->config->set('default_channel', $savechannel);
return $latest;
}
$data = array(
'caption' => $caption,
'border' => 1,
'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
'channel' => $channel
);
foreach ((array)$latest as $pkg => $info) {
$package = strtolower($pkg);
if (!isset($inst[$package])) {
// skip packages we don't have installed
continue;
}
extract($info);
$inst_version = $reg->packageInfo($package, 'version', $channel);
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
if (version_compare("$version", "$inst_version", "le")) {
// installed version is up-to-date
continue;
}
if ($filesize >= 20480) {
$filesize += 1024 - ($filesize % 1024);
$fs = sprintf("%dkB", $filesize / 1024);
} elseif ($filesize > 0) {
$filesize += 103 - ($filesize % 103);
$fs = sprintf("%.1fkB", $filesize / 1024.0);
} else {
$fs = " -"; // XXX center instead
}
$data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
}
if (isset($options['channelinfo'])) {
if (empty($data['data'])) {
unset($data['headline']);
if (count($inst) == 0) {
$data['data'] = '(no packages installed)';
} else {
$data['data'] = '(no upgrades available)';
}
}
$this->ui->outputData($data, $command);
} else {
if (empty($data['data'])) {
$this->ui->outputData('Channel ' . $channel . ': No upgrades available');
} else {
$this->ui->outputData($data, $command);
}
}
}
$this->config->set('default_channel', $savechannel);
return true;
}
function doClearCache($command, $options, $params)
{
$cache_dir = $this->config->get('cache_dir');
$verbose = $this->config->get('verbose');
$output = '';
if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
return $this->raiseError("$cache_dir does not exist or is not a directory");
}
if (!($dp = @opendir($cache_dir))) {
return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
}
if ($verbose >= 1) {
$output .= "reading directory $cache_dir\n";
}
$num = 0;
while ($ent = readdir($dp)) {
if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
$path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
if (file_exists($path)) {
$ok = @unlink($path);
} else {
$ok = false;
$php_errormsg = '';
}
if ($ok) {
if ($verbose >= 2) {
$output .= "deleted $path\n";
}
$num++;
} elseif ($verbose >= 1) {
$output .= "failed to delete $path $php_errormsg\n";
}
}
}
closedir($dp);
if ($verbose >= 1) {
$output .= "$num cache entries cleared\n";
}
$this->ui->outputData(rtrim($output), $command);
return $num;
}
}

View File

@@ -1,109 +0,0 @@
<commands version="1.0">
<remote-info>
<summary>Information About Remote Packages</summary>
<function>doRemoteInfo</function>
<shortcut>ri</shortcut>
<options />
<doc>&lt;package&gt;
Get details on a package from the server.</doc>
</remote-info>
<list-upgrades>
<summary>List Available Upgrades</summary>
<function>doListUpgrades</function>
<shortcut>lu</shortcut>
<options>
<channelinfo>
<shortopt>i</shortopt>
<doc>output fully channel-aware data, even on failure</doc>
</channelinfo>
</options>
<doc>[preferred_state]
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.)
or the state passed as the second parameter.</doc>
</list-upgrades>
<remote-list>
<summary>List Remote Packages</summary>
<function>doRemoteList</function>
<shortcut>rl</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>specify a channel other than the default channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>
Lists the packages available on the configured server along with the
latest stable release of each package.</doc>
</remote-list>
<search>
<summary>Search remote package database</summary>
<function>doSearch</function>
<shortcut>sp</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>specify a channel other than the default channel</doc>
<arg>CHAN</arg>
</channel>
<allchannels>
<shortopt>a</shortopt>
<doc>search packages from all known channels</doc>
</allchannels>
<channelinfo>
<shortopt>i</shortopt>
<doc>output fully channel-aware data, even on failure</doc>
</channelinfo>
</options>
<doc>[packagename] [packageinfo]
Lists all packages which match the search parameters. The first
parameter is a fragment of a packagename. The default channel
will be used unless explicitly overridden. The second parameter
will be used to match any portion of the summary/description</doc>
</search>
<list-all>
<summary>List All Packages</summary>
<function>doListAll</function>
<shortcut>la</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>specify a channel other than the default channel</doc>
<arg>CHAN</arg>
</channel>
<channelinfo>
<shortopt>i</shortopt>
<doc>output fully channel-aware data, even on failure</doc>
</channelinfo>
</options>
<doc>
Lists the packages available on the configured server along with the
latest stable release of each package.</doc>
</list-all>
<download>
<summary>Download Package</summary>
<function>doDownload</function>
<shortcut>d</shortcut>
<options>
<nocompress>
<shortopt>Z</shortopt>
<doc>download an uncompressed (.tar) file</doc>
</nocompress>
</options>
<doc>&lt;package&gt;...
Download package tarballs. The files will be named as suggested by the
server, for example if you download the DB package and the latest stable
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
</download>
<clear-cache>
<summary>Clear Web Services Cache</summary>
<function>doClearCache</function>
<shortcut>cc</shortcut>
<options />
<doc>
Clear the XML-RPC/REST cache. See also the cache_ttl configuration
parameter.
</doc>
</clear-cache>
</commands>

View File

@@ -1,343 +0,0 @@
<?php
/**
* PEAR_Command_Test (run-tests)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Martin Jansen <mj@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Martin Jansen <mj@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Test extends PEAR_Command_Common
{
var $commands = array(
'run-tests' => array(
'summary' => 'Run Regression Tests',
'function' => 'doRunTests',
'shortcut' => 'rt',
'options' => array(
'recur' => array(
'shortopt' => 'r',
'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
),
'ini' => array(
'shortopt' => 'i',
'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
'arg' => 'SETTINGS'
),
'realtimelog' => array(
'shortopt' => 'l',
'doc' => 'Log test runs/results as they are run',
),
'quiet' => array(
'shortopt' => 'q',
'doc' => 'Only display detail for failed tests',
),
'simple' => array(
'shortopt' => 's',
'doc' => 'Display simple output for all tests',
),
'package' => array(
'shortopt' => 'p',
'doc' => 'Treat parameters as installed packages from which to run tests',
),
'phpunit' => array(
'shortopt' => 'u',
'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
If none is found, all .phpt tests will be tried instead.',
),
'tapoutput' => array(
'shortopt' => 't',
'doc' => 'Output run-tests.log in TAP-compliant format',
),
'cgi' => array(
'shortopt' => 'c',
'doc' => 'CGI php executable (needed for tests with POST/GET section)',
'arg' => 'PHPCGI',
),
'coverage' => array(
'shortopt' => 'x',
'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
),
'showdiff' => array(
'shortopt' => 'd',
'doc' => 'Output diff on test failure',
),
),
'doc' => '[testfile|dir ...]
Run regression tests with PHP\'s regression testing script (run-tests.php).',
),
);
var $output;
/**
* PEAR_Command_Test constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
function doRunTests($command, $options, $params)
{
if (isset($options['phpunit']) && isset($options['tapoutput'])) {
return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
}
require_once 'PEAR/Common.php';
require_once 'System.php';
$log = new PEAR_Common;
$log->ui = &$this->ui; // slightly hacky, but it will work
$tests = array();
$depth = isset($options['recur']) ? 14 : 1;
if (!count($params)) {
$params[] = '.';
}
if (isset($options['package'])) {
$oldparams = $params;
$params = array();
$reg = &$this->config->getRegistry();
foreach ($oldparams as $param) {
$pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
if (PEAR::isError($pname)) {
return $this->raiseError($pname);
}
$package = &$reg->getPackage($pname['package'], $pname['channel']);
if (!$package) {
return PEAR::raiseError('Unknown package "' .
$reg->parsedPackageNameToString($pname) . '"');
}
$filelist = $package->getFilelist();
foreach ($filelist as $name => $atts) {
if (isset($atts['role']) && $atts['role'] != 'test') {
continue;
}
if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
$params[] = $atts['installed_as'];
continue;
} elseif (!preg_match('/\.phpt\\z/', $name)) {
continue;
}
$params[] = $atts['installed_as'];
}
}
}
foreach ($params as $p) {
if (is_dir($p)) {
if (isset($options['phpunit'])) {
$dir = System::find(array($p, '-type', 'f',
'-maxdepth', $depth,
'-name', 'AllTests.php'));
if (count($dir)) {
foreach ($dir as $p) {
$p = realpath($p);
if (!count($tests) ||
(count($tests) && strlen($p) < strlen($tests[0]))) {
// this is in a higher-level directory, use this one instead.
$tests = array($p);
}
}
}
continue;
}
$args = array($p, '-type', 'f', '-name', '*.phpt');
} else {
if (isset($options['phpunit'])) {
if (preg_match('/AllTests\.php\\z/i', $p)) {
$p = realpath($p);
if (!count($tests) ||
(count($tests) && strlen($p) < strlen($tests[0]))) {
// this is in a higher-level directory, use this one instead.
$tests = array($p);
}
}
continue;
}
if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
$tests[] = $p;
continue;
}
if (!preg_match('/\.phpt\\z/', $p)) {
$p .= '.phpt';
}
$args = array(dirname($p), '-type', 'f', '-name', $p);
}
if (!isset($options['recur'])) {
$args[] = '-maxdepth';
$args[] = 1;
}
$dir = System::find($args);
$tests = array_merge($tests, $dir);
}
$ini_settings = '';
if (isset($options['ini'])) {
$ini_settings .= $options['ini'];
}
if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
$ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
}
if ($ini_settings) {
$this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
}
$skipped = $passed = $failed = array();
$tests_count = count($tests);
$this->ui->outputData('Running ' . $tests_count . ' tests', $command);
$start = time();
if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
unlink('run-tests.log');
}
if (isset($options['tapoutput'])) {
$tap = '1..' . $tests_count . "\n";
}
require_once 'PEAR/RunTest.php';
$run = new PEAR_RunTest($log, $options);
$run->tests_count = $tests_count;
if (isset($options['coverage']) && extension_loaded('xdebug')){
$run->xdebug_loaded = true;
} else {
$run->xdebug_loaded = false;
}
$j = $i = 1;
foreach ($tests as $t) {
if (isset($options['realtimelog'])) {
$fp = @fopen('run-tests.log', 'a');
if ($fp) {
fwrite($fp, "Running test [$i / $tests_count] $t...");
fclose($fp);
}
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
if (isset($options['phpunit'])) {
$result = $run->runPHPUnit($t, $ini_settings);
} else {
$result = $run->run($t, $ini_settings, $j);
}
PEAR::staticPopErrorHandling();
if (PEAR::isError($result)) {
$this->ui->log($result->getMessage());
continue;
}
if (isset($options['tapoutput'])) {
$tap .= $result[0] . ' ' . $i . $result[1] . "\n";
continue;
}
if (isset($options['realtimelog'])) {
$fp = @fopen('run-tests.log', 'a');
if ($fp) {
fwrite($fp, "$result\n");
fclose($fp);
}
}
if ($result == 'FAILED') {
$failed[] = $t;
}
if ($result == 'PASSED') {
$passed[] = $t;
}
if ($result == 'SKIPPED') {
$skipped[] = $t;
}
$j++;
}
$total = date('i:s', time() - $start);
if (isset($options['tapoutput'])) {
$fp = @fopen('run-tests.log', 'w');
if ($fp) {
fwrite($fp, $tap, strlen($tap));
fclose($fp);
$this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
'"', $command);
}
} else {
if (count($failed)) {
$output = "TOTAL TIME: $total\n";
$output .= count($passed) . " PASSED TESTS\n";
$output .= count($skipped) . " SKIPPED TESTS\n";
$output .= count($failed) . " FAILED TESTS:\n";
foreach ($failed as $failure) {
$output .= $failure . "\n";
}
$mode = isset($options['realtimelog']) ? 'a' : 'w';
$fp = @fopen('run-tests.log', $mode);
if ($fp) {
fwrite($fp, $output, strlen($output));
fclose($fp);
$this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
}
} elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
@unlink('run-tests.log');
}
}
$this->ui->outputData('TOTAL TIME: ' . $total);
$this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
$this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
if (count($failed)) {
$this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
foreach ($failed as $failure) {
$this->ui->outputData($failure, $command);
}
}
if (count($failed) == 0) {
return true;
}
return $this->raiseError('Some tests failed');
}
}

View File

@@ -1,54 +0,0 @@
<commands version="1.0">
<run-tests>
<summary>Run Regression Tests</summary>
<function>doRunTests</function>
<shortcut>rt</shortcut>
<options>
<recur>
<shortopt>r</shortopt>
<doc>Run tests in child directories, recursively. 4 dirs deep maximum</doc>
</recur>
<ini>
<shortopt>i</shortopt>
<doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
<arg>SETTINGS</arg>
</ini>
<realtimelog>
<shortopt>l</shortopt>
<doc>Log test runs/results as they are run</doc>
</realtimelog>
<quiet>
<shortopt>q</shortopt>
<doc>Only display detail for failed tests</doc>
</quiet>
<simple>
<shortopt>s</shortopt>
<doc>Display simple output for all tests</doc>
</simple>
<package>
<shortopt>p</shortopt>
<doc>Treat parameters as installed packages from which to run tests</doc>
</package>
<phpunit>
<shortopt>u</shortopt>
<doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
If none is found, all .phpt tests will be tried instead.</doc>
</phpunit>
<tapoutput>
<shortopt>t</shortopt>
<doc>Output run-tests.log in TAP-compliant format</doc>
</tapoutput>
<cgi>
<shortopt>c</shortopt>
<doc>CGI php executable (needed for tests with POST/GET section)</doc>
<arg>PHPCGI</arg>
</cgi>
<coverage>
<shortopt>x</shortopt>
<doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
</coverage>
</options>
<doc>[testfile|dir ...]
Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
</run-tests>
</commands>

View File

@@ -1,838 +0,0 @@
<?php
/**
* PEAR_Common, the base class for the PEAR Installer
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1.0
* @deprecated File deprecated since Release 1.4.0a1
*/
/**
* Include error handling
*/
require_once 'PEAR.php';
/**
* PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
*/
define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
// XXX far from perfect :-)
define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
')(-([.0-9a-zA-Z]+))?');
define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
'\\z/');
define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
. _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
/**
* List of temporary files and directories registered by
* PEAR_Common::addTempFile().
* @var array
*/
$GLOBALS['_PEAR_Common_tempfiles'] = array();
/**
* Valid maintainer roles
* @var array
*/
$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
/**
* Valid release states
* @var array
*/
$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
/**
* Valid dependency types
* @var array
*/
$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
/**
* Valid dependency relations
* @var array
*/
$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
/**
* Valid file roles
* @var array
*/
$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
/**
* Valid replacement types
* @var array
*/
$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
/**
* Valid "provide" types
* @var array
*/
$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
/**
* Valid "provide" types
* @var array
*/
$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');
/**
* Class providing common functionality for PEAR administration classes.
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
* @deprecated This class will disappear, and its components will be spread
* into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
*/
class PEAR_Common extends PEAR
{
/**
* User Interface object (PEAR_Frontend_* class). If null,
* the log() method uses print.
* @var object
*/
var $ui = null;
/**
* Configuration object (PEAR_Config).
* @var PEAR_Config
*/
var $config = null;
/** stack of elements, gives some sort of XML context */
var $element_stack = array();
/** name of currently parsed XML element */
var $current_element;
/** array of attributes of the currently parsed XML element */
var $current_attributes = array();
/** assoc with information about a package */
var $pkginfo = array();
var $current_path = null;
/**
* Flag variable used to mark a valid package file
* @var boolean
* @access private
*/
var $_validPackageFile;
/**
* PEAR_Common constructor
*
* @access public
*/
function __construct()
{
parent::__construct();
$this->config = &PEAR_Config::singleton();
$this->debug = $this->config->get('verbose');
}
/**
* PEAR_Common destructor
*
* @access private
*/
function _PEAR_Common()
{
// doesn't work due to bug #14744
//$tempfiles = $this->_tempfiles;
$tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
while ($file = array_shift($tempfiles)) {
if (@is_dir($file)) {
if (!class_exists('System')) {
require_once 'System.php';
}
System::rm(array('-rf', $file));
} elseif (file_exists($file)) {
unlink($file);
}
}
}
/**
* Register a temporary file or directory. When the destructor is
* executed, all registered temporary files and directories are
* removed.
*
* @param string $file name of file or directory
*
* @return void
*
* @access public
*/
static function addTempFile($file)
{
if (!class_exists('PEAR_Frontend')) {
require_once 'PEAR/Frontend.php';
}
PEAR_Frontend::addTempFile($file);
}
/**
* Wrapper to System::mkDir(), creates a directory as well as
* any necessary parent directories.
*
* @param string $dir directory name
*
* @return bool TRUE on success, or a PEAR error
*
* @access public
*/
function mkDirHier($dir)
{
// Only used in Installer - move it there ?
$this->log(2, "+ create dir $dir");
if (!class_exists('System')) {
require_once 'System.php';
}
return System::mkDir(array('-p', $dir));
}
/**
* Logging method.
*
* @param int $level log level (0 is quiet, higher is noisier)
* @param string $msg message to write to the log
*
* @return void
*/
public function log($level, $msg, $append_crlf = true)
{
if ($this->debug >= $level) {
if (!class_exists('PEAR_Frontend')) {
require_once 'PEAR/Frontend.php';
}
$ui = &PEAR_Frontend::singleton();
if (is_a($ui, 'PEAR_Frontend')) {
$ui->log($msg, $append_crlf);
} else {
print "$msg\n";
}
}
}
/**
* Create and register a temporary directory.
*
* @param string $tmpdir (optional) Directory to use as tmpdir.
* Will use system defaults (for example
* /tmp or c:\windows\temp) if not specified
*
* @return string name of created directory
*
* @access public
*/
function mkTempDir($tmpdir = '')
{
$topt = $tmpdir ? array('-t', $tmpdir) : array();
$topt = array_merge($topt, array('-d', 'pear'));
if (!class_exists('System')) {
require_once 'System.php';
}
if (!$tmpdir = System::mktemp($topt)) {
return false;
}
self::addTempFile($tmpdir);
return $tmpdir;
}
/**
* Set object that represents the frontend to be used.
*
* @param object Reference of the frontend object
* @return void
* @access public
*/
function setFrontendObject(&$ui)
{
$this->ui = &$ui;
}
/**
* Return an array containing all of the states that are more stable than
* or equal to the passed in state
*
* @param string Release state
* @param boolean Determines whether to include $state in the list
* @return false|array False if $state is not a valid release state
*/
static function betterStates($state, $include = false)
{
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
$i = array_search($state, $states);
if ($i === false) {
return false;
}
if ($include) {
$i--;
}
return array_slice($states, $i + 1);
}
/**
* Get the valid roles for a PEAR package maintainer
*
* @return array
*/
public static function getUserRoles()
{
return $GLOBALS['_PEAR_Common_maintainer_roles'];
}
/**
* Get the valid package release states of packages
*
* @return array
*/
public static function getReleaseStates()
{
return $GLOBALS['_PEAR_Common_release_states'];
}
/**
* Get the implemented dependency types (php, ext, pkg etc.)
*
* @return array
*/
public static function getDependencyTypes()
{
return $GLOBALS['_PEAR_Common_dependency_types'];
}
/**
* Get the implemented dependency relations (has, lt, ge etc.)
*
* @return array
*/
public static function getDependencyRelations()
{
return $GLOBALS['_PEAR_Common_dependency_relations'];
}
/**
* Get the implemented file roles
*
* @return array
*/
public static function getFileRoles()
{
return $GLOBALS['_PEAR_Common_file_roles'];
}
/**
* Get the implemented file replacement types in
*
* @return array
*/
public static function getReplacementTypes()
{
return $GLOBALS['_PEAR_Common_replacement_types'];
}
/**
* Get the implemented file replacement types in
*
* @return array
*/
public static function getProvideTypes()
{
return $GLOBALS['_PEAR_Common_provide_types'];
}
/**
* Get the implemented file replacement types in
*
* @return array
*/
public static function getScriptPhases()
{
return $GLOBALS['_PEAR_Common_script_phases'];
}
/**
* Test whether a string contains a valid package name.
*
* @param string $name the package name to test
*
* @return bool
*
* @access public
*/
function validPackageName($name)
{
return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
}
/**
* Test whether a string contains a valid package version.
*
* @param string $ver the package version to test
*
* @return bool
*
* @access public
*/
function validPackageVersion($ver)
{
return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
}
/**
* @param string $path relative or absolute include path
* @return boolean
*/
public static function isIncludeable($path)
{
if (file_exists($path) && is_readable($path)) {
return true;
}
$ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($ipath as $include) {
$test = realpath($include . DIRECTORY_SEPARATOR . $path);
if (file_exists($test) && is_readable($test)) {
return true;
}
}
return false;
}
function _postProcessChecks($pf)
{
if (!PEAR::isError($pf)) {
return $this->_postProcessValidPackagexml($pf);
}
$errs = $pf->getUserinfo();
if (is_array($errs)) {
foreach ($errs as $error) {
$e = $this->raiseError($error['message'], $error['code'], null, null, $error);
}
}
return $pf;
}
/**
* Returns information about a package file. Expects the name of
* a gzipped tar file as input.
*
* @param string $file name of .tgz file
*
* @return array array with package information
*
* @access public
* @deprecated use PEAR_PackageFile->fromTgzFile() instead
*
*/
function infoFromTgzFile($file)
{
$packagefile = new PEAR_PackageFile($this->config);
$pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
return $this->_postProcessChecks($pf);
}
/**
* Returns information about a package file. Expects the name of
* a package xml file as input.
*
* @param string $descfile name of package xml file
*
* @return array array with package information
*
* @access public
* @deprecated use PEAR_PackageFile->fromPackageFile() instead
*
*/
function infoFromDescriptionFile($descfile)
{
$packagefile = new PEAR_PackageFile($this->config);
$pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
return $this->_postProcessChecks($pf);
}
/**
* Returns information about a package file. Expects the contents
* of a package xml file as input.
*
* @param string $data contents of package.xml file
*
* @return array array with package information
*
* @access public
* @deprecated use PEAR_PackageFile->fromXmlstring() instead
*
*/
function infoFromString($data)
{
$packagefile = new PEAR_PackageFile($this->config);
$pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
return $this->_postProcessChecks($pf);
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @return array
*/
function _postProcessValidPackagexml(&$pf)
{
if (!is_a($pf, 'PEAR_PackageFile_v2')) {
$this->pkginfo = $pf->toArray();
return $this->pkginfo;
}
// sort of make this into a package.xml 1.0-style array
// changelog is not converted to old format.
$arr = $pf->toArray(true);
$arr = array_merge($arr, $arr['old']);
unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
$arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
$arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
$arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
$arr['helper'], $arr['contributor']);
$arr['filelist'] = $pf->getFilelist();
$this->pkginfo = $arr;
return $arr;
}
/**
* Returns package information from different sources
*
* This method is able to extract information about a package
* from a .tgz archive or from a XML package definition file.
*
* @access public
* @param string Filename of the source ('package.xml', '<package>.tgz')
* @return string
* @deprecated use PEAR_PackageFile->fromAnyFile() instead
*/
function infoFromAny($info)
{
if (is_string($info) && file_exists($info)) {
$packagefile = new PEAR_PackageFile($this->config);
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($pf)) {
$errs = $pf->getUserinfo();
if (is_array($errs)) {
foreach ($errs as $error) {
$e = $this->raiseError($error['message'], $error['code'], null, null, $error);
}
}
return $pf;
}
return $this->_postProcessValidPackagexml($pf);
}
return $info;
}
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @param array $pkginfo package info
*
* @return string XML data
*
* @access public
* @deprecated use a PEAR_PackageFile_v* object's generator instead
*/
function xmlFromInfo($pkginfo)
{
$config = &PEAR_Config::singleton();
$packagefile = new PEAR_PackageFile($config);
$pf = &$packagefile->fromArray($pkginfo);
$gen = &$pf->getDefaultGenerator();
return $gen->toXml(PEAR_VALIDATE_PACKAGING);
}
/**
* Validate XML package definition file.
*
* @param string $info Filename of the package archive or of the
* package definition file
* @param array $errors Array that will contain the errors
* @param array $warnings Array that will contain the warnings
* @param string $dir_prefix (optional) directory where source files
* may be found, or empty if they are not available
* @access public
* @return boolean
* @deprecated use the validation of PEAR_PackageFile objects
*/
function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
{
$config = &PEAR_Config::singleton();
$packagefile = new PEAR_PackageFile($config);
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
if (strpos($info, '<?xml') !== false) {
$pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
} else {
$pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
}
PEAR::staticPopErrorHandling();
if (PEAR::isError($pf)) {
$errs = $pf->getUserinfo();
if (is_array($errs)) {
foreach ($errs as $error) {
if ($error['level'] == 'error') {
$errors[] = $error['message'];
} else {
$warnings[] = $error['message'];
}
}
}
return false;
}
return true;
}
/**
* Build a "provides" array from data returned by
* analyzeSourceCode(). The format of the built array is like
* this:
*
* array(
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
* ...
* )
*
*
* @param array $srcinfo array with information about a source file
* as returned by the analyzeSourceCode() method.
*
* @return void
*
* @access public
*
*/
function buildProvidesArray($srcinfo)
{
$file = basename($srcinfo['source_file']);
$pn = '';
if (isset($this->_packageName)) {
$pn = $this->_packageName;
}
$pnl = strlen($pn);
foreach ($srcinfo['declared_classes'] as $class) {
$key = "class;$class";
if (isset($this->pkginfo['provides'][$key])) {
continue;
}
$this->pkginfo['provides'][$key] =
array('file'=> $file, 'type' => 'class', 'name' => $class);
if (isset($srcinfo['inheritance'][$class])) {
$this->pkginfo['provides'][$key]['extends'] =
$srcinfo['inheritance'][$class];
}
}
foreach ($srcinfo['declared_methods'] as $class => $methods) {
foreach ($methods as $method) {
$function = "$class::$method";
$key = "function;$function";
if ($method[0] == '_' || !strcasecmp($method, $class) ||
isset($this->pkginfo['provides'][$key])) {
continue;
}
$this->pkginfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
foreach ($srcinfo['declared_functions'] as $function) {
$key = "function;$function";
if ($function[0] == '_' || isset($this->pkginfo['provides'][$key])) {
continue;
}
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
}
$this->pkginfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
/**
* Analyze the source code of the given PHP file
*
* @param string Filename of the PHP file
* @return mixed
* @access public
*/
static function analyzeSourceCode($file)
{
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
require_once 'PEAR/PackageFile/v2/Validator.php';
}
$a = new PEAR_PackageFile_v2_Validator;
return $a->analyzeSourceCode($file);
}
function detectDependencies($any, $status_callback = null)
{
if (!function_exists("token_get_all")) {
return false;
}
if (PEAR::isError($info = $this->infoFromAny($any))) {
return $this->raiseError($info);
}
if (!is_array($info)) {
return false;
}
$deps = array();
$used_c = $decl_c = $decl_f = $decl_m = array();
foreach ($info['filelist'] as $file => $fa) {
$tmp = $this->analyzeSourceCode($file);
$used_c = @array_merge($used_c, $tmp['used_classes']);
$decl_c = @array_merge($decl_c, $tmp['declared_classes']);
$decl_f = @array_merge($decl_f, $tmp['declared_functions']);
$decl_m = @array_merge($decl_m, $tmp['declared_methods']);
$inheri = @array_merge($inheri, $tmp['inheritance']);
}
$used_c = array_unique($used_c);
$decl_c = array_unique($decl_c);
$undecl_c = array_diff($used_c, $decl_c);
return array('used_classes' => $used_c,
'declared_classes' => $decl_c,
'declared_methods' => $decl_m,
'declared_functions' => $decl_f,
'undeclared_classes' => $undecl_c,
'inheritance' => $inheri,
);
}
/**
* Download a file through HTTP. Considers suggested file name in
* Content-disposition: header and can run a callback function for
* different events. The callback will be called with two
* parameters: the callback type, and parameters. The implemented
* callback types are:
*
* 'setup' called at the very beginning, parameter is a UI object
* that should be used for all output
* 'message' the parameter is a string with an informational message
* 'saveas' may be used to save with a different file name, the
* parameter is the filename that is about to be used.
* If a 'saveas' callback returns a non-empty string,
* that file name will be used as the filename instead.
* Note that $save_dir will not be affected by this, only
* the basename of the file.
* 'start' download is starting, parameter is number of bytes
* that are expected, or -1 if unknown
* 'bytesread' parameter is the number of bytes read so far
* 'done' download is complete, parameter is the total number
* of bytes read
* 'connfailed' if the TCP connection fails, this callback is called
* with array(host,port,errno,errmsg)
* 'writefailed' if writing to disk fails, this callback is called
* with array(destfile,errmsg)
*
* If an HTTP proxy has been configured (http_proxy PEAR_Config
* setting), the proxy will be used.
*
* @param string $url the URL to download
* @param object $ui PEAR_Frontend_* instance
* @param object $config PEAR_Config instance
* @param string $save_dir (optional) directory to save file in
* @param mixed $callback (optional) function/method to call for status
* updates
* @param false|string|array $lastmodified header values to check against
* for caching
* use false to return the header
* values from this download
* @param false|array $accept Accept headers to send
* @param false|string $channel Channel to use for retrieving
* authentication
*
* @return mixed Returns the full path of the downloaded file or a PEAR
* error on failure. If the error is caused by
* socket-related errors, the error object will
* have the fsockopen error code available through
* getCode(). If caching is requested, then return the header
* values.
* If $lastmodified was given and the there are no changes,
* boolean false is returned.
*
* @access public
*/
function downloadHttp(
$url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
$accept = false, $channel = false
) {
if (!class_exists('PEAR_Downloader')) {
require_once 'PEAR/Downloader.php';
}
return PEAR_Downloader::_downloadHttp(
$this, $url, $ui, $save_dir, $callback, $lastmodified,
$accept, $channel
);
}
}
require_once 'PEAR/Config.php';
require_once 'PEAR/PackageFile.php';

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,767 +0,0 @@
<?php
/**
* PEAR_DependencyDB, advanced installed packages dependency database
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Needed for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
/**
* Track dependency relationships between installed packages
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Tomas V.V.Cox <cox@idec.net.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_DependencyDB
{
// {{{ properties
/**
* This is initialized by {@link setConfig()}
* @var PEAR_Config
* @access private
*/
var $_config;
/**
* This is initialized by {@link setConfig()}
* @var PEAR_Registry
* @access private
*/
var $_registry;
/**
* Filename of the dependency DB (usually .depdb)
* @var string
* @access private
*/
var $_depdb = false;
/**
* File name of the lockfile (usually .depdblock)
* @var string
* @access private
*/
var $_lockfile = false;
/**
* Open file resource for locking the lockfile
* @var resource|false
* @access private
*/
var $_lockFp = false;
/**
* API version of this class, used to validate a file on-disk
* @var string
* @access private
*/
var $_version = '1.0';
/**
* Cached dependency database file
* @var array|null
* @access private
*/
var $_cache;
// }}}
// {{{ & singleton()
/**
* Get a raw dependency database. Calls setConfig() and assertDepsDB()
* @param PEAR_Config
* @param string|false full path to the dependency database, or false to use default
* @return PEAR_DependencyDB|PEAR_Error
*/
public static function &singleton(&$config, $depdb = false)
{
$phpdir = $config->get('php_dir', null, 'pear.php.net');
if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
$a = new PEAR_DependencyDB;
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
$a->setConfig($config, $depdb);
$e = $a->assertDepsDB();
if (PEAR::isError($e)) {
return $e;
}
}
return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
}
/**
* Set up the registry/location of dependency DB
* @param PEAR_Config|false
* @param string|false full path to the dependency database, or false to use default
*/
function setConfig(&$config, $depdb = false)
{
if (!$config) {
$this->_config = &PEAR_Config::singleton();
} else {
$this->_config = &$config;
}
$this->_registry = &$this->_config->getRegistry();
if (!$depdb) {
$dir = $this->_config->get('metadata_dir', null, 'pear.php.net');
if (!$dir) {
$dir = $this->_config->get('php_dir', null, 'pear.php.net');
}
$this->_depdb = $dir . DIRECTORY_SEPARATOR . '.depdb';
} else {
$this->_depdb = $depdb;
}
$this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
}
// }}}
function hasWriteAccess()
{
if (!file_exists($this->_depdb)) {
$dir = $this->_depdb;
while ($dir && $dir != '.') {
$dir = dirname($dir); // cd ..
if ($dir != '.' && file_exists($dir)) {
if (is_writeable($dir)) {
return true;
}
return false;
}
}
return false;
}
return is_writeable($this->_depdb);
}
// {{{ assertDepsDB()
/**
* Create the dependency database, if it doesn't exist. Error if the database is
* newer than the code reading it.
* @return void|PEAR_Error
*/
function assertDepsDB()
{
if (!is_file($this->_depdb)) {
$this->rebuildDB();
return;
}
$depdb = $this->_getDepDB();
// Datatype format has been changed, rebuild the Deps DB
if ($depdb['_version'] < $this->_version) {
$this->rebuildDB();
}
if ($depdb['_version'][0] > $this->_version[0]) {
return PEAR::raiseError('Dependency database is version ' .
$depdb['_version'] . ', and we are version ' .
$this->_version . ', cannot continue');
}
}
/**
* Get a list of installed packages that depend on this package
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependentPackages(&$pkg)
{
$data = $this->_getDepDB();
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
if (isset($data['packages'][$channel][$package])) {
return $data['packages'][$channel][$package];
}
return false;
}
/**
* Get a list of the actual dependencies of installed packages that depend on
* a package.
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependentPackageDependencies(&$pkg)
{
$data = $this->_getDepDB();
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else if (is_array($pkg)) {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
} else {
return false;
}
$depend = $this->getDependentPackages($pkg);
if (!$depend) {
return false;
}
$dependencies = array();
foreach ($depend as $info) {
$temp = $this->getDependencies($info);
foreach ($temp as $dep) {
if (
isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
strtolower($dep['dep']['channel']) == $channel &&
strtolower($dep['dep']['name']) == $package
) {
if (!isset($dependencies[$info['channel']])) {
$dependencies[$info['channel']] = array();
}
if (!isset($dependencies[$info['channel']][$info['package']])) {
$dependencies[$info['channel']][$info['package']] = array();
}
$dependencies[$info['channel']][$info['package']][] = $dep;
}
}
}
return $dependencies;
}
/**
* Get a list of dependencies of this installed package
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependencies(&$pkg)
{
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
$data = $this->_getDepDB();
if (isset($data['dependencies'][$channel][$package])) {
return $data['dependencies'][$channel][$package];
}
return false;
}
/**
* Determine whether $parent depends on $child, near or deep
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
*/
function dependsOn($parent, $child)
{
$c = array();
$this->_getDepDB();
return $this->_dependsOn($parent, $child, $c);
}
function _dependsOn($parent, $child, &$checked)
{
if (is_object($parent)) {
$channel = strtolower($parent->getChannel());
$package = strtolower($parent->getPackage());
} else {
$channel = strtolower($parent['channel']);
$package = strtolower($parent['package']);
}
if (is_object($child)) {
$depchannel = strtolower($child->getChannel());
$deppackage = strtolower($child->getPackage());
} else {
$depchannel = strtolower($child['channel']);
$deppackage = strtolower($child['package']);
}
if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
return false; // avoid endless recursion
}
$checked[$channel][$package][$depchannel][$deppackage] = true;
if (!isset($this->_cache['dependencies'][$channel][$package])) {
return false;
}
foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
if (isset($info['dep']['uri'])) {
if (is_object($child)) {
if ($info['dep']['uri'] == $child->getURI()) {
return true;
}
} elseif (isset($child['uri'])) {
if ($info['dep']['uri'] == $child['uri']) {
return true;
}
}
return false;
}
if (strtolower($info['dep']['channel']) == $depchannel &&
strtolower($info['dep']['name']) == $deppackage) {
return true;
}
}
foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
if (isset($info['dep']['uri'])) {
if ($this->_dependsOn(array(
'uri' => $info['dep']['uri'],
'package' => $info['dep']['name']), $child, $checked)) {
return true;
}
} else {
if ($this->_dependsOn(array(
'channel' => $info['dep']['channel'],
'package' => $info['dep']['name']), $child, $checked)) {
return true;
}
}
}
return false;
}
/**
* Register dependencies of a package that is being installed or upgraded
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
*/
function installPackage(&$package)
{
$data = $this->_getDepDB();
unset($this->_cache);
$this->_setPackageDeps($data, $package);
$this->_writeDepDB($data);
}
/**
* Remove dependencies of a package that is being uninstalled, or upgraded.
*
* Upgraded packages first uninstall, then install
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
* indices 'channel' and 'package'
*/
function uninstallPackage(&$pkg)
{
$data = $this->_getDepDB();
unset($this->_cache);
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
if (!isset($data['dependencies'][$channel][$package])) {
return true;
}
foreach ($data['dependencies'][$channel][$package] as $dep) {
$found = false;
$depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
$depname = strtolower($dep['dep']['name']);
if (isset($data['packages'][$depchannel][$depname])) {
foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
if ($info['channel'] == $channel && $info['package'] == $package) {
$found = true;
break;
}
}
}
if ($found) {
unset($data['packages'][$depchannel][$depname][$i]);
if (!count($data['packages'][$depchannel][$depname])) {
unset($data['packages'][$depchannel][$depname]);
if (!count($data['packages'][$depchannel])) {
unset($data['packages'][$depchannel]);
}
} else {
$data['packages'][$depchannel][$depname] =
array_values($data['packages'][$depchannel][$depname]);
}
}
}
unset($data['dependencies'][$channel][$package]);
if (!count($data['dependencies'][$channel])) {
unset($data['dependencies'][$channel]);
}
if (!count($data['dependencies'])) {
unset($data['dependencies']);
}
if (!count($data['packages'])) {
unset($data['packages']);
}
$this->_writeDepDB($data);
}
/**
* Rebuild the dependency DB by reading registry entries.
* @return true|PEAR_Error
*/
function rebuildDB()
{
$depdb = array('_version' => $this->_version);
if (!$this->hasWriteAccess()) {
// allow startup for read-only with older Registry
return $depdb;
}
$packages = $this->_registry->listAllPackages();
if (PEAR::isError($packages)) {
return $packages;
}
foreach ($packages as $channel => $ps) {
foreach ($ps as $package) {
$package = $this->_registry->getPackage($package, $channel);
if (PEAR::isError($package)) {
return $package;
}
$this->_setPackageDeps($depdb, $package);
}
}
$error = $this->_writeDepDB($depdb);
if (PEAR::isError($error)) {
return $error;
}
$this->_cache = $depdb;
return true;
}
/**
* Register usage of the dependency DB to prevent race conditions
* @param int one of the LOCK_* constants
* @return true|PEAR_Error
* @access private
*/
function _lock($mode = LOCK_EX)
{
if (stristr(php_uname(), 'Windows 9')) {
return true;
}
if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
return true;
}
$open_mode = 'w';
// XXX People reported problems with LOCK_SH and 'w'
if ($mode === LOCK_SH) {
if (!file_exists($this->_lockfile)) {
touch($this->_lockfile);
} elseif (!is_file($this->_lockfile)) {
return PEAR::raiseError('could not create Dependency lock file, ' .
'it exists and is not a regular file');
}
$open_mode = 'r';
}
if (!is_resource($this->_lockFp)) {
$this->_lockFp = @fopen($this->_lockfile, $open_mode);
}
if (!is_resource($this->_lockFp)) {
$last_errormsg = error_get_last();
return PEAR::raiseError("could not create Dependency lock file" .
(isset($last_errormsg) ? ": " . $last_errormsg : ""));
}
if (!(int)flock($this->_lockFp, $mode)) {
switch ($mode) {
case LOCK_SH: $str = 'shared'; break;
case LOCK_EX: $str = 'exclusive'; break;
case LOCK_UN: $str = 'unlock'; break;
default: $str = 'unknown'; break;
}
return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
}
return true;
}
/**
* Release usage of dependency DB
* @return true|PEAR_Error
* @access private
*/
function _unlock()
{
$ret = $this->_lock(LOCK_UN);
if (is_resource($this->_lockFp)) {
fclose($this->_lockFp);
}
$this->_lockFp = null;
return $ret;
}
/**
* Load the dependency database from disk, or return the cache
* @return array|PEAR_Error
*/
function _getDepDB()
{
if (!$this->hasWriteAccess()) {
return array('_version' => $this->_version);
}
if (isset($this->_cache)) {
return $this->_cache;
}
if (!$fp = fopen($this->_depdb, 'r')) {
$err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
return $err;
}
clearstatcache();
fclose($fp);
$data = unserialize(file_get_contents($this->_depdb));
$this->_cache = $data;
return $data;
}
/**
* Write out the dependency database to disk
* @param array the database
* @return true|PEAR_Error
* @access private
*/
function _writeDepDB(&$deps)
{
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
if (!$fp = fopen($this->_depdb, 'wb')) {
$this->_unlock();
return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
}
fwrite($fp, serialize($deps));
fclose($fp);
$this->_unlock();
$this->_cache = $deps;
return true;
}
/**
* Register all dependencies from a package in the dependencies database, in essence
* "installing" the package's dependency information
* @param array the database
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @access private
*/
function _setPackageDeps(&$data, &$pkg)
{
$pkg->setConfig($this->_config);
if ($pkg->getPackagexmlVersion() == '1.0') {
$gen = &$pkg->getDefaultGenerator();
$deps = $gen->dependenciesToV2();
} else {
$deps = $pkg->getDeps(true);
}
if (!$deps) {
return;
}
if (!is_array($data)) {
$data = array();
}
if (!isset($data['dependencies'])) {
$data['dependencies'] = array();
}
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
if (!isset($data['dependencies'][$channel])) {
$data['dependencies'][$channel] = array();
}
$data['dependencies'][$channel][$package] = array();
if (isset($deps['required']['package'])) {
if (!isset($deps['required']['package'][0])) {
$deps['required']['package'] = array($deps['required']['package']);
}
foreach ($deps['required']['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'required');
}
}
if (isset($deps['optional']['package'])) {
if (!isset($deps['optional']['package'][0])) {
$deps['optional']['package'] = array($deps['optional']['package']);
}
foreach ($deps['optional']['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional');
}
}
if (isset($deps['required']['subpackage'])) {
if (!isset($deps['required']['subpackage'][0])) {
$deps['required']['subpackage'] = array($deps['required']['subpackage']);
}
foreach ($deps['required']['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'required');
}
}
if (isset($deps['optional']['subpackage'])) {
if (!isset($deps['optional']['subpackage'][0])) {
$deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
}
foreach ($deps['optional']['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional');
}
}
if (isset($deps['group'])) {
if (!isset($deps['group'][0])) {
$deps['group'] = array($deps['group']);
}
foreach ($deps['group'] as $group) {
if (isset($group['package'])) {
if (!isset($group['package'][0])) {
$group['package'] = array($group['package']);
}
foreach ($group['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional',
$group['attribs']['name']);
}
}
if (isset($group['subpackage'])) {
if (!isset($group['subpackage'][0])) {
$group['subpackage'] = array($group['subpackage']);
}
foreach ($group['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional',
$group['attribs']['name']);
}
}
}
}
if ($data['dependencies'][$channel][$package] == array()) {
unset($data['dependencies'][$channel][$package]);
if (!count($data['dependencies'][$channel])) {
unset($data['dependencies'][$channel]);
}
}
}
/**
* @param array the database
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param array the specific dependency
* @param required|optional whether this is a required or an optional dep
* @param string|false dependency group this dependency is from, or false for ordinary dep
*/
function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
{
$info = array(
'dep' => $dep,
'type' => $type,
'group' => $group
);
$dep = array_map('strtolower', $dep);
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (!isset($data['dependencies'])) {
$data['dependencies'] = array();
}
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
if (!isset($data['dependencies'][$channel])) {
$data['dependencies'][$channel] = array();
}
if (!isset($data['dependencies'][$channel][$package])) {
$data['dependencies'][$channel][$package] = array();
}
$data['dependencies'][$channel][$package][] = $info;
if (isset($data['packages'][$depchannel][$dep['name']])) {
$found = false;
foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
if ($p['channel'] == $channel && $p['package'] == $package) {
$found = true;
break;
}
}
} else {
if (!isset($data['packages'])) {
$data['packages'] = array();
}
if (!isset($data['packages'][$depchannel])) {
$data['packages'][$depchannel] = array();
}
if (!isset($data['packages'][$depchannel][$dep['name']])) {
$data['packages'][$depchannel][$dep['name']] = array();
}
$found = false;
}
if (!$found) {
$data['packages'][$depchannel][$dep['name']][] = array(
'channel' => $channel,
'package' => $package
);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,979 +0,0 @@
<?php
/**
* Error Stack Implementation
*
* This is an incredibly simple implementation of a very complex error handling
* facility. It contains the ability
* to track multiple errors from multiple packages simultaneously. In addition,
* it can track errors of many levels, save data along with the error, context
* information such as the exact file, line number, class and function that
* generated the error, and if necessary, it can raise a traditional PEAR_Error.
* It has built-in support for PEAR::Log, to log errors as they occur
*
* Since version 0.2alpha, it is also possible to selectively ignore errors,
* through the use of an error callback, see {@link pushCallback()}
*
* Since version 0.3alpha, it is possible to specify the exception class
* returned from {@link push()}
*
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can
* still be done quite handily in an error callback or by manipulating the returned array
* @category Debugging
* @package PEAR_ErrorStack
* @author Greg Beaver <cellog@php.net>
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
/**
* Singleton storage
*
* Format:
* <pre>
* array(
* 'package1' => PEAR_ErrorStack object,
* 'package2' => PEAR_ErrorStack object,
* ...
* )
* </pre>
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
*/
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
/**
* Global error callback (default)
*
* This is only used if set to non-false. * is the default callback for
* all packages, whereas specific packages may set a default callback
* for all instances, regardless of whether they are a singleton or not.
*
* To exclude non-singletons, only set the local callback for the singleton
* @see PEAR_ErrorStack::setDefaultCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
'*' => false,
);
/**
* Global Log object (default)
*
* This is only used if set to non-false. Use to set a default log object for
* all stacks, regardless of instantiation order or location
* @see PEAR_ErrorStack::setDefaultLogger()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
/**
* Global Overriding Callback
*
* This callback will override any error callbacks that specific loggers have set.
* Use with EXTREME caution
* @see PEAR_ErrorStack::staticPushCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
/**#@+
* One of four possible return values from the error Callback
* @see PEAR_ErrorStack::_errorCallback()
*/
/**
* If this is returned, then the error will be both pushed onto the stack
* and logged.
*/
define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
/**
* If this is returned, then the error will only be pushed onto the stack,
* and not logged.
*/
define('PEAR_ERRORSTACK_PUSH', 2);
/**
* If this is returned, then the error will only be logged, but not pushed
* onto the error stack.
*/
define('PEAR_ERRORSTACK_LOG', 3);
/**
* If this is returned, then the error is completely ignored.
*/
define('PEAR_ERRORSTACK_IGNORE', 4);
/**
* If this is returned, then the error is logged and die() is called.
*/
define('PEAR_ERRORSTACK_DIE', 5);
/**#@-*/
/**
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
* the singleton method.
*/
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
/**
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
* that has no __toString() method
*/
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
/**
* Error Stack Implementation
*
* Usage:
* <code>
* // global error stack
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
* // local error stack
* $local_stack = new PEAR_ErrorStack('MyPackage');
* </code>
* @author Greg Beaver <cellog@php.net>
* @version 1.10.13
* @package PEAR_ErrorStack
* @category Debugging
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
class PEAR_ErrorStack {
/**
* Errors are stored in the order that they are pushed on the stack.
* @since 0.4alpha Errors are no longer organized by error level.
* This renders pop() nearly unusable, and levels could be more easily
* handled in a callback anyway
* @var array
* @access private
*/
var $_errors = array();
/**
* Storage of errors by level.
*
* Allows easy retrieval and deletion of only errors from a particular level
* @since PEAR 1.4.0dev
* @var array
* @access private
*/
var $_errorsByLevel = array();
/**
* Package name this error stack represents
* @var string
* @access protected
*/
var $_package;
/**
* Determines whether a PEAR_Error is thrown upon every error addition
* @var boolean
* @access private
*/
var $_compat = false;
/**
* If set to a valid callback, this will be used to generate the error
* message from the error code, otherwise the message passed in will be
* used
* @var false|string|array
* @access private
*/
var $_msgCallback = false;
/**
* If set to a valid callback, this will be used to generate the error
* context for an error. For PHP-related errors, this will be a file
* and line number as retrieved from debug_backtrace(), but can be
* customized for other purposes. The error might actually be in a separate
* configuration file, or in a database query.
* @var false|string|array
* @access protected
*/
var $_contextCallback = false;
/**
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one an PEAR_ERRORSTACK_* constant
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @var false|string|array
* @access protected
*/
var $_errorCallback = array();
/**
* PEAR::Log object for logging errors
* @var false|Log
* @access protected
*/
var $_logger = false;
/**
* Error messages - designed to be overridden
* @var array
* @abstract
*/
var $_errorMsgs = array();
/**
* Set up a new error stack
*
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
*/
function __construct($package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false)
{
$this->_package = $package;
$this->setMessageCallback($msgCallback);
$this->setContextCallback($contextCallback);
$this->_compat = $throwPEAR_Error;
}
/**
* Return a single error stack for this package.
*
* Note that all parameters are ignored if the stack for package $package
* has already been instantiated
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
* @param string $stackClass class to instantiate
*
* @return PEAR_ErrorStack
*/
public static function &singleton(
$package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
) {
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
if (!class_exists($stackClass)) {
if (function_exists('debug_backtrace')) {
$trace = debug_backtrace();
}
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
'exception', array('stackclass' => $stackClass),
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
false, $trace);
}
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
/**
* Internal error handler for PEAR_ErrorStack class
*
* Dies if the error is an exception (and would have died anyway)
* @access private
*/
function _handleError($err)
{
if ($err['level'] == 'exception') {
$message = $err['message'];
if (isset($_SERVER['REQUEST_URI'])) {
echo '<br />';
} else {
echo "\n";
}
var_dump($err['context']);
die($message);
}
}
/**
* Set up a PEAR::Log object for all error stacks that don't have one
* @param Log $log
*/
public static function setDefaultLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
} elseif (is_callable($log)) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
}
}
/**
* Set up a PEAR::Log object for this error stack
* @param Log $log
*/
function setLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$this->_logger = &$log;
} elseif (is_callable($log)) {
$this->_logger = &$log;
}
}
/**
* Set an error code => error message mapping callback
*
* This method sets the callback that can be used to generate error
* messages for any instance
* @param array|string Callback function/method
*/
function setMessageCallback($msgCallback)
{
if (!$msgCallback) {
$this->_msgCallback = array(&$this, 'getErrorMessage');
} else {
if (is_callable($msgCallback)) {
$this->_msgCallback = $msgCallback;
}
}
}
/**
* Get an error code => error message mapping callback
*
* This method returns the current callback that can be used to generate error
* messages
* @return array|string|false Callback function/method or false if none
*/
function getMessageCallback()
{
return $this->_msgCallback;
}
/**
* Sets a default callback to be used by all error stacks
*
* This method sets the callback that can be used to generate error
* messages for a singleton
* @param array|string Callback function/method
* @param string Package name, or false for all packages
*/
public static function setDefaultCallback($callback = false, $package = false)
{
if (!is_callable($callback)) {
$callback = false;
}
$package = $package ? $package : '*';
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
}
/**
* Set a callback that generates context information (location of error) for an error stack
*
* This method sets the callback that can be used to generate context
* information for an error. Passing in NULL will disable context generation
* and remove the expensive call to debug_backtrace()
* @param array|string|null Callback function/method
*/
function setContextCallback($contextCallback)
{
if ($contextCallback === null) {
return $this->_contextCallback = false;
}
if (!$contextCallback) {
$this->_contextCallback = array(&$this, 'getFileLine');
} else {
if (is_callable($contextCallback)) {
$this->_contextCallback = $contextCallback;
}
}
}
/**
* Set an error Callback
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one of the ERRORSTACK_* constants.
*
* This functionality can be used to emulate PEAR's pushErrorHandling, and
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
* the error stack or logging
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see popCallback()
* @param string|array $cb
*/
function pushCallback($cb)
{
array_push($this->_errorCallback, $cb);
}
/**
* Remove a callback from the error callback stack
* @see pushCallback()
* @return array|string|false
*/
function popCallback()
{
if (!count($this->_errorCallback)) {
return false;
}
return array_pop($this->_errorCallback);
}
/**
* Set a temporary overriding error callback for every package error stack
*
* Use this to temporarily disable all existing callbacks (can be used
* to emulate the @ operator, for instance)
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see staticPopCallback(), pushCallback()
* @param string|array $cb
*/
public static function staticPushCallback($cb)
{
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
}
/**
* Remove a temporary overriding error callback
* @see staticPushCallback()
* @return array|string|false
*/
public static function staticPopCallback()
{
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
}
return $ret;
}
/**
* Add an error to the stack
*
* If the message generator exists, it is called with 2 parameters.
* - the current Error Stack object
* - an array that is in the same format as an error. Available indices
* are 'code', 'package', 'time', 'params', 'level', and 'context'
*
* Next, if the error should contain context information, this is
* handled by the context grabbing method.
* Finally, the error is pushed onto the proper error stack
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. If a PEAR_Error is returned, the userinfo
* property is set to the following array:
*
* <code>
* array(
* 'code' => $code,
* 'params' => $params,
* 'package' => $this->_package,
* 'level' => $level,
* 'time' => time(),
* 'context' => $context,
* 'message' => $msg,
* //['repackage' => $err] repackaged error array/Exception class
* );
* </code>
*
* Normally, the previous array is returned.
*/
function push($code, $level = 'error', $params = array(), $msg = false,
$repackage = false, $backtrace = false)
{
$context = false;
// grab error context
if ($this->_contextCallback) {
if (!$backtrace) {
$backtrace = debug_backtrace();
}
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
}
// save error
$time = explode(' ', microtime());
$time = $time[1] + $time[0];
$err = array(
'code' => $code,
'params' => $params,
'package' => $this->_package,
'level' => $level,
'time' => $time,
'context' => $context,
'message' => $msg,
);
if ($repackage) {
$err['repackage'] = $repackage;
}
// set up the error message, if necessary
if ($this->_msgCallback) {
$msg = call_user_func_array($this->_msgCallback,
array(&$this, $err));
$err['message'] = $msg;
}
$push = $log = true;
$die = false;
// try the overriding callback first
$callback = $this->staticPopCallback();
if ($callback) {
$this->staticPushCallback($callback);
}
if (!is_callable($callback)) {
// try the local callback next
$callback = $this->popCallback();
if (is_callable($callback)) {
$this->pushCallback($callback);
} else {
// try the default callback
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
}
}
if (is_callable($callback)) {
switch(call_user_func($callback, $err)){
case PEAR_ERRORSTACK_IGNORE:
return $err;
break;
case PEAR_ERRORSTACK_PUSH:
$log = false;
break;
case PEAR_ERRORSTACK_LOG:
$push = false;
break;
case PEAR_ERRORSTACK_DIE:
$die = true;
break;
// anything else returned has the same effect as pushandlog
}
}
if ($push) {
array_unshift($this->_errors, $err);
if (!isset($this->_errorsByLevel[$err['level']])) {
$this->_errorsByLevel[$err['level']] = array();
}
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
}
if ($log) {
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
$this->_log($err);
}
}
if ($die) {
die();
}
if ($this->_compat && $push) {
return $this->raiseError($msg, $code, null, null, $err);
}
return $err;
}
/**
* Static version of {@link push()}
*
* @param string $package Package name this error belongs to
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. see docs for {@link push()}
*/
public static function staticPush(
$package, $code, $level = 'error', $params = array(),
$msg = false, $repackage = false, $backtrace = false
) {
$s = &PEAR_ErrorStack::singleton($package);
if ($s->_contextCallback) {
if (!$backtrace) {
if (function_exists('debug_backtrace')) {
$backtrace = debug_backtrace();
}
}
}
return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
}
/**
* Log an error using PEAR::Log
* @param array $err Error array
* @param array $levels Error level => Log constant map
* @access protected
*/
function _log($err)
{
if ($this->_logger) {
$logger = &$this->_logger;
} else {
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
}
if (is_a($logger, 'Log')) {
$levels = array(
'exception' => PEAR_LOG_CRIT,
'alert' => PEAR_LOG_ALERT,
'critical' => PEAR_LOG_CRIT,
'error' => PEAR_LOG_ERR,
'warning' => PEAR_LOG_WARNING,
'notice' => PEAR_LOG_NOTICE,
'info' => PEAR_LOG_INFO,
'debug' => PEAR_LOG_DEBUG);
if (isset($levels[$err['level']])) {
$level = $levels[$err['level']];
} else {
$level = PEAR_LOG_INFO;
}
$logger->log($err['message'], $level, $err);
} else { // support non-standard logs
call_user_func($logger, $err);
}
}
/**
* Pop an error off of the error stack
*
* @return false|array
* @since 0.4alpha it is no longer possible to specify a specific error
* level to return - the last error pushed will be returned, instead
*/
function pop()
{
$err = @array_shift($this->_errors);
if (!is_null($err)) {
@array_pop($this->_errorsByLevel[$err['level']]);
if (!count($this->_errorsByLevel[$err['level']])) {
unset($this->_errorsByLevel[$err['level']]);
}
}
return $err;
}
/**
* Pop an error off of the error stack, static method
*
* @param string package name
* @return boolean
* @since PEAR1.5.0a1
*/
static function staticPop($package)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
}
}
/**
* Determine whether there are any errors on the stack
* @param string|array Level name. Use to determine if any errors
* of level (string), or levels (array) have been pushed
* @return boolean
*/
function hasErrors($level = false)
{
if ($level) {
return isset($this->_errorsByLevel[$level]);
}
return count($this->_errors);
}
/**
* Retrieve all errors since last purge
*
* @param boolean set in order to empty the error stack
* @param string level name, to return only errors of a particular severity
* @return array
*/
function getErrors($purge = false, $level = false)
{
if (!$purge) {
if ($level) {
if (!isset($this->_errorsByLevel[$level])) {
return array();
} else {
return $this->_errorsByLevel[$level];
}
} else {
return $this->_errors;
}
}
if ($level) {
$ret = $this->_errorsByLevel[$level];
foreach ($this->_errorsByLevel[$level] as $i => $unused) {
// entries are references to the $_errors array
$this->_errorsByLevel[$level][$i] = false;
}
// array_filter removes all entries === false
$this->_errors = array_filter($this->_errors);
unset($this->_errorsByLevel[$level]);
return $ret;
}
$ret = $this->_errors;
$this->_errors = array();
$this->_errorsByLevel = array();
return $ret;
}
/**
* Determine whether there are any errors on a single error stack, or on any error stack
*
* The optional parameter can be used to test the existence of any errors without the need of
* singleton instantiation
* @param string|false Package name to check for errors
* @param string Level name to check for a particular severity
* @return boolean
*/
public static function staticHasErrors($package = false, $level = false)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
if ($obj->hasErrors($level)) {
return true;
}
}
return false;
}
/**
* Get a list of all errors since last purge, organized by package
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
* @param boolean $purge Set to purge the error stack of existing errors
* @param string $level Set to a level name in order to retrieve only errors of a particular level
* @param boolean $merge Set to return a flat array, not organized by package
* @param array $sortfunc Function used to sort a merged array - default
* sorts by time, and should be good for most cases
*
* @return array
*/
public static function staticGetErrors(
$purge = false, $level = false, $merge = false,
$sortfunc = array('PEAR_ErrorStack', '_sortErrors')
) {
$ret = array();
if (!is_callable($sortfunc)) {
$sortfunc = array('PEAR_ErrorStack', '_sortErrors');
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
if ($test) {
if ($merge) {
$ret = array_merge($ret, $test);
} else {
$ret[$package] = $test;
}
}
}
if ($merge) {
usort($ret, $sortfunc);
}
return $ret;
}
/**
* Error sorting function, sorts by time
* @access private
*/
public static function _sortErrors($a, $b)
{
if ($a['time'] == $b['time']) {
return 0;
}
if ($a['time'] < $b['time']) {
return 1;
}
return -1;
}
/**
* Standard file/line number/function/class context callback
*
* This function uses a backtrace generated from {@link debug_backtrace()}
* and so will not work at all in PHP < 4.3.0. The frame should
* reference the frame that contains the source of the error.
* @return array|false either array('file' => file, 'line' => line,
* 'function' => function name, 'class' => class name) or
* if this doesn't work, then false
* @param unused
* @param integer backtrace frame.
* @param array Results of debug_backtrace()
*/
public static function getFileLine($code, $params, $backtrace = null)
{
if ($backtrace === null) {
return false;
}
$frame = 0;
$functionframe = 1;
if (!isset($backtrace[1])) {
$functionframe = 0;
} else {
while (isset($backtrace[$functionframe]['function']) &&
$backtrace[$functionframe]['function'] == 'eval' &&
isset($backtrace[$functionframe + 1])) {
$functionframe++;
}
}
if (isset($backtrace[$frame])) {
if (!isset($backtrace[$frame]['file'])) {
$frame++;
}
$funcbacktrace = $backtrace[$functionframe];
$filebacktrace = $backtrace[$frame];
$ret = array('file' => $filebacktrace['file'],
'line' => $filebacktrace['line']);
// rearrange for eval'd code or create function errors
if (strpos($filebacktrace['file'], '(') &&
preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
$matches)) {
$ret['file'] = $matches[1];
$ret['line'] = $matches[2] + 0;
}
if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
if ($funcbacktrace['function'] != 'eval') {
if ($funcbacktrace['function'] == '__lambda_func') {
$ret['function'] = 'create_function() code';
} else {
$ret['function'] = $funcbacktrace['function'];
}
}
}
if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
$ret['class'] = $funcbacktrace['class'];
}
return $ret;
}
return false;
}
/**
* Standard error message generation callback
*
* This method may also be called by a custom error message generator
* to fill in template values from the params array, simply
* set the third parameter to the error message template string to use
*
* The special variable %__msg% is reserved: use it only to specify
* where a message passed in by the user should be placed in the template,
* like so:
*
* Error message: %msg% - internal error
*
* If the message passed like so:
*
* <code>
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
* </code>
*
* The returned error message will be "Error message: server error 500 -
* internal error"
* @param PEAR_ErrorStack
* @param array
* @param string|false Pre-generated error message template
*
* @return string
*/
public static function getErrorMessage(&$stack, $err, $template = false)
{
if ($template) {
$mainmsg = $template;
} else {
$mainmsg = $stack->getErrorMessageTemplate($err['code']);
}
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
if (is_array($err['params']) && count($err['params'])) {
foreach ($err['params'] as $name => $val) {
if (is_array($val)) {
// @ is needed in case $val is a multi-dimensional array
$val = @implode(', ', $val);
}
if (is_object($val)) {
if (method_exists($val, '__toString')) {
$val = $val->__toString();
} else {
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
'warning', array('obj' => get_class($val)),
'object %obj% passed into getErrorMessage, but has no __toString() method');
$val = 'Object';
}
}
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
}
}
return $mainmsg;
}
/**
* Standard Error Message Template generator from code
* @return string
*/
function getErrorMessageTemplate($code)
{
if (!isset($this->_errorMsgs[$code])) {
return '%__msg%';
}
return $this->_errorMsgs[$code];
}
/**
* Set the Error Message Template array
*
* The array format must be:
* <pre>
* array(error code => 'message template',...)
* </pre>
*
* Error message parameters passed into {@link push()} will be used as input
* for the error message. If the template is 'message %foo% was %bar%', and the
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
* be 'message one was six'
* @return string
*/
function setErrorMessageTemplate($template)
{
$this->_errorMsgs = $template;
}
/**
* emulate PEAR::raiseError()
*
* @return PEAR_Error
*/
function raiseError()
{
require_once 'PEAR.php';
$args = func_get_args();
return call_user_func_array(array('PEAR', 'raiseError'), $args);
}
}
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>

View File

@@ -1,388 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
/**
* PEAR_Exception
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.3.3
*/
/**
* Base PEAR_Exception Class
*
* 1) Features:
*
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
* - Definable triggers, shot when exceptions occur
* - Pretty and informative error messages
* - Added more context info available (like class, method or cause)
* - cause can be a PEAR_Exception or an array of mixed
* PEAR_Exceptions/PEAR_ErrorStack warnings
* - callbacks for specific exception classes and their children
*
* 2) Ideas:
*
* - Maybe a way to define a 'template' for the output
*
* 3) Inherited properties from PHP Exception Class:
*
* protected $message
* protected $code
* protected $line
* protected $file
* private $trace
*
* 4) Inherited methods from PHP Exception Class:
*
* __clone
* __construct
* getMessage
* getCode
* getFile
* getLine
* getTraceSafe
* getTraceSafeAsString
* __toString
*
* 5) Usage example
*
* <code>
* require_once 'PEAR/Exception.php';
*
* class Test {
* function foo() {
* throw new PEAR_Exception('Error Message', ERROR_CODE);
* }
* }
*
* function myLogger($pear_exception) {
* echo $pear_exception->getMessage();
* }
* // each time a exception is thrown the 'myLogger' will be called
* // (its use is completely optional)
* PEAR_Exception::addObserver('myLogger');
* $test = new Test;
* try {
* $test->foo();
* } catch (PEAR_Exception $e) {
* print $e;
* }
* </code>
*
* @category pear
* @package PEAR
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.3.3
*
*/
class PEAR_Exception extends Exception
{
const OBSERVER_PRINT = -2;
const OBSERVER_TRIGGER = -4;
const OBSERVER_DIE = -8;
protected $cause;
private static $_observers = array();
private static $_uniqueid = 0;
private $_trace;
/**
* Supported signatures:
* - PEAR_Exception(string $message);
* - PEAR_Exception(string $message, int $code);
* - PEAR_Exception(string $message, Exception $cause);
* - PEAR_Exception(string $message, Exception $cause, int $code);
* - PEAR_Exception(string $message, PEAR_Error $cause);
* - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
* - PEAR_Exception(string $message, array $causes);
* - PEAR_Exception(string $message, array $causes, int $code);
* @param string exception message
* @param int|Exception|PEAR_Error|array|null exception cause
* @param int|null exception code or null
*/
public function __construct($message, $p2 = null, $p3 = null)
{
if (is_int($p2)) {
$code = $p2;
$this->cause = null;
} elseif (is_object($p2) || is_array($p2)) {
// using is_object allows both Exception and PEAR_Error
if (is_object($p2) && !($p2 instanceof Exception)) {
if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
throw new PEAR_Exception('exception cause must be Exception, ' .
'array, or PEAR_Error');
}
}
$code = $p3;
if (is_array($p2) && isset($p2['message'])) {
// fix potential problem of passing in a single warning
$p2 = array($p2);
}
$this->cause = $p2;
} else {
$code = null;
$this->cause = null;
}
parent::__construct($message, $code);
$this->signal();
}
/**
* @param mixed $callback - A valid php callback, see php func is_callable()
* - A PEAR_Exception::OBSERVER_* constant
* - An array(const PEAR_Exception::OBSERVER_*,
* mixed $options)
* @param string $label The name of the observer. Use this if you want
* to remove it later with removeObserver()
*/
public static function addObserver($callback, $label = 'default')
{
self::$_observers[$label] = $callback;
}
public static function removeObserver($label = 'default')
{
unset(self::$_observers[$label]);
}
/**
* @return int unique identifier for an observer
*/
public static function getUniqueId()
{
return self::$_uniqueid++;
}
private function signal()
{
foreach (self::$_observers as $func) {
if (is_callable($func)) {
call_user_func($func, $this);
continue;
}
settype($func, 'array');
switch ($func[0]) {
case self::OBSERVER_PRINT :
$f = (isset($func[1])) ? $func[1] : '%s';
printf($f, $this->getMessage());
break;
case self::OBSERVER_TRIGGER :
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
trigger_error($this->getMessage(), $f);
break;
case self::OBSERVER_DIE :
$f = (isset($func[1])) ? $func[1] : '%s';
die(printf($f, $this->getMessage()));
break;
default:
trigger_error('invalid observer type', E_USER_WARNING);
}
}
}
/**
* Return specific error information that can be used for more detailed
* error messages or translation.
*
* This method may be overridden in child exception classes in order
* to add functionality not present in PEAR_Exception and is a placeholder
* to define API
*
* The returned array must be an associative array of parameter => value like so:
* <pre>
* array('name' => $name, 'context' => array(...))
* </pre>
* @return array
*/
public function getErrorData()
{
return array();
}
/**
* Returns the exception that caused this exception to be thrown
* @access public
* @return Exception|array The context of the exception
*/
public function getCause()
{
return $this->cause;
}
/**
* Function must be public to call on caused exceptions
* @param array
*/
public function getCauseMessage(&$causes)
{
$trace = $this->getTraceSafe();
$cause = array('class' => get_class($this),
'message' => $this->message,
'file' => 'unknown',
'line' => 'unknown');
if (isset($trace[0])) {
if (isset($trace[0]['file'])) {
$cause['file'] = $trace[0]['file'];
$cause['line'] = $trace[0]['line'];
}
}
$causes[] = $cause;
if ($this->cause instanceof PEAR_Exception) {
$this->cause->getCauseMessage($causes);
} elseif ($this->cause instanceof Exception) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => $this->cause->getFile(),
'line' => $this->cause->getLine());
} elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($this->cause)) {
foreach ($this->cause as $cause) {
if ($cause instanceof PEAR_Exception) {
$cause->getCauseMessage($causes);
} elseif ($cause instanceof Exception) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => $cause->getFile(),
'line' => $cause->getLine());
} elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($cause) && isset($cause['message'])) {
// PEAR_ErrorStack warning
$causes[] = array(
'class' => $cause['package'],
'message' => $cause['message'],
'file' => isset($cause['context']['file']) ?
$cause['context']['file'] :
'unknown',
'line' => isset($cause['context']['line']) ?
$cause['context']['line'] :
'unknown',
);
}
}
}
}
public function getTraceSafe()
{
if (!isset($this->_trace)) {
$this->_trace = $this->getTrace();
if (empty($this->_trace)) {
$backtrace = debug_backtrace();
$this->_trace = array($backtrace[count($backtrace)-1]);
}
}
return $this->_trace;
}
public function getErrorClass()
{
$trace = $this->getTraceSafe();
return $trace[0]['class'];
}
public function getErrorMethod()
{
$trace = $this->getTraceSafe();
return $trace[0]['function'];
}
public function __toString()
{
if (isset($_SERVER['REQUEST_URI'])) {
return $this->toHtml();
}
return $this->toText();
}
public function toHtml()
{
$trace = $this->getTraceSafe();
$causes = array();
$this->getCauseMessage($causes);
$html = '<table style="border: 1px" cellspacing="0">' . "\n";
foreach ($causes as $i => $cause) {
$html .= '<tr><td colspan="3" style="background: #ff9999">'
. str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
. htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
. 'on line <b>' . $cause['line'] . '</b>'
. "</td></tr>\n";
}
$html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
. '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
foreach ($trace as $k => $v) {
$html .= '<tr><td style="text-align: center;">' . $k . '</td>'
. '<td>';
if (!empty($v['class'])) {
$html .= $v['class'] . $v['type'];
}
$html .= $v['function'];
$args = array();
if (!empty($v['args'])) {
foreach ($v['args'] as $arg) {
if (is_null($arg)) $args[] = 'null';
elseif (is_array($arg)) $args[] = 'Array';
elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
else {
$arg = (string)$arg;
$str = htmlspecialchars(substr($arg, 0, 16));
if (strlen($arg) > 16) $str .= '&hellip;';
$args[] = "'" . $str . "'";
}
}
}
$html .= '(' . implode(', ',$args) . ')'
. '</td>'
. '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
. ':' . (isset($v['line']) ? $v['line'] : 'unknown')
. '</td></tr>' . "\n";
}
$html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
. '<td>{main}</td>'
. '<td>&nbsp;</td></tr>' . "\n"
. '</table>';
return $html;
}
public function toText()
{
$causes = array();
$this->getCauseMessage($causes);
$causeMsg = '';
foreach ($causes as $i => $cause) {
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
. $cause['message'] . ' in ' . $cause['file']
. ' on line ' . $cause['line'] . "\n";
}
return $causeMsg . $this->getTraceAsString();
}
}

View File

@@ -1,223 +0,0 @@
<?php
/**
* PEAR_Frontend, the singleton-based frontend for user input/output
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Include error handling
*/
//require_once 'PEAR.php';
/**
* Which user interface class is being used.
* @var string class name
*/
$GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
/**
* Instance of $_PEAR_Command_uiclass.
* @var object
*/
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
/**
* Singleton-based frontend for PEAR user input/output
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Frontend extends PEAR
{
/**
* Retrieve the frontend object
* @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
*/
public static function &singleton($type = null)
{
if ($type === null) {
if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
$a = false;
return $a;
}
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
$a = PEAR_Frontend::setFrontendClass($type);
return $a;
}
/**
* Set the frontend class that will be used by calls to {@link singleton()}
*
* Frontends are expected to conform to the PEAR naming standard of
* _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
* @param string $uiclass full class name
* @return PEAR_Frontend
*/
public static function &setFrontendClass($uiclass)
{
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
if (!class_exists($uiclass)) {
$file = str_replace('_', '/', $uiclass) . '.php';
if (PEAR_Frontend::isIncludeable($file)) {
include_once $file;
}
}
if (class_exists($uiclass)) {
$obj = new $uiclass;
// quick test to see if this class implements a few of the most
// important frontend methods
if (is_a($obj, 'PEAR_Frontend')) {
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
$GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
return $obj;
}
$err = PEAR::raiseError("not a frontend class: $uiclass");
return $err;
}
$err = PEAR::raiseError("no such class: $uiclass");
return $err;
}
/**
* Set the frontend class that will be used by calls to {@link singleton()}
*
* Frontends are expected to be a descendant of PEAR_Frontend
* @param PEAR_Frontend
* @return PEAR_Frontend
*/
public static function &setFrontendObject($uiobject)
{
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
if (!is_a($uiobject, 'PEAR_Frontend')) {
$err = PEAR::raiseError('not a valid frontend class: (' .
get_class($uiobject) . ')');
return $err;
}
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
$GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
return $uiobject;
}
/**
* @param string $path relative or absolute include path
* @return boolean
*/
public static function isIncludeable($path)
{
if (file_exists($path) && is_readable($path)) {
return true;
}
$fp = @fopen($path, 'r', true);
if ($fp) {
fclose($fp);
return true;
}
return false;
}
/**
* @param PEAR_Config
*/
function setConfig(&$config)
{
}
/**
* This can be overridden to allow session-based temporary file management
*
* By default, all files are deleted at the end of a session. The web installer
* needs to be able to sustain a list over many sessions in order to support
* user interaction with install scripts
*/
static function addTempFile($file)
{
$GLOBALS['_PEAR_Common_tempfiles'][] = $file;
}
/**
* Log an action
*
* @param string $msg the message to log
* @param boolean $append_crlf
* @return boolean true
* @abstract
*/
function log($msg, $append_crlf = true)
{
}
/**
* Run a post-installation script
*
* @param array $scripts array of post-install scripts
* @abstract
*/
function runPostinstallScripts(&$scripts)
{
}
/**
* Display human-friendly output formatted depending on the
* $command parameter.
*
* This should be able to handle basic output data with no command
* @param mixed $data data structure containing the information to display
* @param string $command command from which this method was called
* @abstract
*/
function outputData($data, $command = '_default')
{
}
/**
* Display a modal form dialog and return the given input
*
* A frontend that requires multiple requests to retrieve and process
* data must take these needs into account, and implement the request
* handling code.
* @param string $command command from which this method was called
* @param array $prompts associative array. keys are the input field names
* and values are the description
* @param array $types array of input field types (text, password,
* etc.) keys have to be the same like in $prompts
* @param array $defaults array of default values. again keys have
* to be the same like in $prompts. Do not depend
* on a default value being set.
* @return array input sent by the user
* @abstract
*/
function userDialog($command, $prompts, $types = array(), $defaults = array())
{
}
}

View File

@@ -1,750 +0,0 @@
<?php
/**
* PEAR_Frontend_CLI
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Frontend.php';
/**
* Command-line Frontend for the PEAR Installer
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Frontend_CLI extends PEAR_Frontend
{
/**
* What type of user interface this frontend is for.
* @var string
* @access public
*/
var $type = 'CLI';
var $lp = ''; // line prefix
var $params = array();
var $term = array(
'bold' => '',
'normal' => '',
);
function __construct()
{
parent::__construct();
$term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
if (function_exists('posix_isatty') && !posix_isatty(1)) {
// output is being redirected to a file or through a pipe
} elseif ($term) {
if (preg_match('/^(xterm|vt220|linux)/', $term)) {
$this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109);
$this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
} elseif (preg_match('/^vt100/', $term)) {
$this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
$this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
}
} elseif (OS_WINDOWS) {
// XXX add ANSI codes here
}
}
/**
* @param object PEAR_Error object
*/
function displayError($e)
{
return $this->_displayLine($e->getMessage());
}
/**
* @param object PEAR_Error object
*/
function displayFatalError($eobj)
{
$this->displayError($eobj);
if (class_exists('PEAR_Config')) {
$config = &PEAR_Config::singleton();
if ($config->get('verbose') > 5) {
if (function_exists('debug_print_backtrace')) {
debug_print_backtrace();
exit(1);
}
$raised = false;
foreach (debug_backtrace() as $i => $frame) {
if (!$raised) {
if (isset($frame['class'])
&& strtolower($frame['class']) == 'pear'
&& strtolower($frame['function']) == 'raiseerror'
) {
$raised = true;
} else {
continue;
}
}
$frame['class'] = !isset($frame['class']) ? '' : $frame['class'];
$frame['type'] = !isset($frame['type']) ? '' : $frame['type'];
$frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
$frame['line'] = !isset($frame['line']) ? '' : $frame['line'];
$this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
}
}
}
exit(1);
}
/**
* Instruct the runInstallScript method to skip a paramgroup that matches the
* id value passed in.
*
* This method is useful for dynamically configuring which sections of a post-install script
* will be run based on the user's setup, which is very useful for making flexible
* post-install scripts without losing the cross-Frontend ability to retrieve user input
* @param string
*/
function skipParamgroup($id)
{
$this->_skipSections[$id] = true;
}
function runPostinstallScripts(&$scripts)
{
foreach ($scripts as $i => $script) {
$this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
}
}
/**
* @param array $xml contents of postinstallscript tag
* @param object $script post-installation script
* @param string install|upgrade
*/
function runInstallScript($xml, &$script)
{
$this->_skipSections = array();
if (!is_array($xml) || !isset($xml['paramgroup'])) {
$script->run(array(), '_default');
return;
}
$completedPhases = array();
if (!isset($xml['paramgroup'][0])) {
$xml['paramgroup'] = array($xml['paramgroup']);
}
foreach ($xml['paramgroup'] as $group) {
if (isset($this->_skipSections[$group['id']])) {
// the post-install script chose to skip this section dynamically
continue;
}
if (isset($group['name'])) {
$paramname = explode('::', $group['name']);
if ($lastgroup['id'] != $paramname[0]) {
continue;
}
$group['name'] = $paramname[1];
if (!isset($answers)) {
return;
}
if (isset($answers[$group['name']])) {
switch ($group['conditiontype']) {
case '=' :
if ($answers[$group['name']] != $group['value']) {
continue 2;
}
break;
case '!=' :
if ($answers[$group['name']] == $group['value']) {
continue 2;
}
break;
case 'preg_match' :
if (!@preg_match('/' . $group['value'] . '/',
$answers[$group['name']])) {
continue 2;
}
break;
default :
return;
}
}
}
$lastgroup = $group;
if (isset($group['instructions'])) {
$this->_display($group['instructions']);
}
if (!isset($group['param'][0])) {
$group['param'] = array($group['param']);
}
if (isset($group['param'])) {
if (method_exists($script, 'postProcessPrompts')) {
$prompts = $script->postProcessPrompts($group['param'], $group['id']);
if (!is_array($prompts) || count($prompts) != count($group['param'])) {
$this->outputData('postinstall', 'Error: post-install script did not ' .
'return proper post-processed prompts');
$prompts = $group['param'];
} else {
foreach ($prompts as $i => $var) {
if (!is_array($var) || !isset($var['prompt']) ||
!isset($var['name']) ||
($var['name'] != $group['param'][$i]['name']) ||
($var['type'] != $group['param'][$i]['type'])
) {
$this->outputData('postinstall', 'Error: post-install script ' .
'modified the variables or prompts, severe security risk. ' .
'Will instead use the defaults from the package.xml');
$prompts = $group['param'];
}
}
}
$answers = $this->confirmDialog($prompts);
} else {
$answers = $this->confirmDialog($group['param']);
}
}
if ((isset($answers) && $answers) || !isset($group['param'])) {
if (!isset($answers)) {
$answers = array();
}
array_unshift($completedPhases, $group['id']);
if (!$script->run($answers, $group['id'])) {
$script->run($completedPhases, '_undoOnError');
return;
}
} else {
$script->run($completedPhases, '_undoOnError');
return;
}
}
}
/**
* Ask for user input, confirm the answers and continue until the user is satisfied
* @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
* 'text to display', 'type' => 'string'[, default => 'default value'])
* @return array
*/
function confirmDialog($params)
{
$answers = $prompts = $types = array();
foreach ($params as $param) {
$prompts[$param['name']] = $param['prompt'];
$types[$param['name']] = $param['type'];
$answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
}
$tried = false;
do {
if ($tried) {
$i = 1;
foreach ($answers as $var => $value) {
if (!strlen($value)) {
echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
}
$i++;
}
}
$answers = $this->userDialog('', $prompts, $types, $answers);
$tried = true;
} while (is_array($answers) && count(array_filter($answers)) != count($prompts));
return $answers;
}
function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
{
if (!is_array($prompts)) {
return array();
}
$testprompts = array_keys($prompts);
$result = $defaults;
reset($prompts);
if (count($prompts) === 1) {
foreach ($prompts as $key => $prompt) {
$type = $types[$key];
$default = @$defaults[$key];
print "$prompt ";
if ($default) {
print "[$default] ";
}
print ": ";
$line = fgets(STDIN, 2048);
$result[$key] = ($default && trim($line) == '') ? $default : trim($line);
}
return $result;
}
$first_run = true;
while (true) {
$descLength = max(array_map('strlen', $prompts));
$descFormat = "%-{$descLength}s";
$last = count($prompts);
$i = 0;
foreach ($prompts as $n => $var) {
$res = isset($result[$n]) ? $result[$n] : null;
printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
}
print "\n1-$last, 'all', 'abort', or Enter to continue: ";
$tmp = trim(fgets(STDIN, 1024));
if (empty($tmp)) {
break;
}
if ($tmp == 'abort') {
return false;
}
if (isset($testprompts[(int)$tmp - 1])) {
$var = $testprompts[(int)$tmp - 1];
$desc = $prompts[$var];
$current = @$result[$var];
print "$desc [$current] : ";
$tmp = trim(fgets(STDIN, 1024));
if ($tmp !== '') {
$result[$var] = $tmp;
}
} elseif ($tmp == 'all') {
foreach ($prompts as $var => $desc) {
$current = $result[$var];
print "$desc [$current] : ";
$tmp = trim(fgets(STDIN, 1024));
if (trim($tmp) !== '') {
$result[$var] = trim($tmp);
}
}
}
$first_run = false;
}
return $result;
}
function userConfirm($prompt, $default = 'yes')
{
trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
static $positives = array('y', 'yes', 'on', '1');
static $negatives = array('n', 'no', 'off', '0');
print "$this->lp$prompt [$default] : ";
$fp = fopen("php://stdin", "r");
$line = fgets($fp, 2048);
fclose($fp);
$answer = strtolower(trim($line));
if (empty($answer)) {
$answer = $default;
}
if (in_array($answer, $positives)) {
return true;
}
if (in_array($answer, $negatives)) {
return false;
}
if (in_array($default, $positives)) {
return true;
}
return false;
}
function outputData($data, $command = '_default')
{
switch ($command) {
case 'channel-info':
foreach ($data as $type => $section) {
if ($type == 'main') {
$section['data'] = array_values($section['data']);
}
$this->outputData($section);
}
break;
case 'install':
case 'upgrade':
case 'upgrade-all':
if (is_array($data) && isset($data['release_warnings'])) {
$this->_displayLine('');
$this->_startTable(array(
'border' => false,
'caption' => 'Release Warnings'
));
$this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
$this->_endTable();
$this->_displayLine('');
}
$this->_displayLine(is_array($data) ? $data['data'] : $data);
break;
case 'search':
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
}
$packages = array();
foreach($data['data'] as $category) {
foreach($category as $name => $pkg) {
$packages[$pkg[0]] = $pkg;
}
}
$p = array_keys($packages);
natcasesort($p);
foreach ($p as $name) {
$this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
}
$this->_endTable();
break;
case 'list-all':
if (!isset($data['data'])) {
$this->_displayLine('No packages in channel');
break;
}
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
}
$packages = array();
foreach($data['data'] as $category) {
foreach($category as $name => $pkg) {
$packages[$pkg[0]] = $pkg;
}
}
$p = array_keys($packages);
natcasesort($p);
foreach ($p as $name) {
$pkg = $packages[$name];
unset($pkg[4], $pkg[5]);
$this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
}
$this->_endTable();
break;
case 'config-show':
$data['border'] = false;
$opts = array(
0 => array('wrap' => 30),
1 => array('wrap' => 20),
2 => array('wrap' => 35)
);
$this->_startTable($data);
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'], array('bold' => true), $opts);
}
foreach ($data['data'] as $group) {
foreach ($group as $value) {
if ($value[2] == '') {
$value[2] = "<not set>";
}
$this->_tableRow($value, null, $opts);
}
}
$this->_endTable();
break;
case 'remote-info':
$d = $data;
$data = array(
'caption' => 'Package details:',
'border' => false,
'data' => array(
array("Latest", $data['stable']),
array("Installed", $data['installed']),
array("Package", $data['name']),
array("License", $data['license']),
array("Category", $data['category']),
array("Summary", $data['summary']),
array("Description", $data['description']),
),
);
if (isset($d['deprecated']) && $d['deprecated']) {
$conf = &PEAR_Config::singleton();
$reg = $conf->getRegistry();
$name = $reg->parsedPackageNameToString($d['deprecated'], true);
$data['data'][] = array('Deprecated! use', $name);
}
default: {
if (is_array($data)) {
$this->_startTable($data);
$count = count($data['data'][0]);
if ($count == 2) {
$opts = array(0 => array('wrap' => 25),
1 => array('wrap' => 48)
);
} elseif ($count == 3) {
$opts = array(0 => array('wrap' => 30),
1 => array('wrap' => 20),
2 => array('wrap' => 35)
);
} else {
$opts = null;
}
if (isset($data['headline']) && is_array($data['headline'])) {
$this->_tableRow($data['headline'],
array('bold' => true),
$opts);
}
if (is_array($data['data'])) {
foreach($data['data'] as $row) {
$this->_tableRow($row, null, $opts);
}
} else {
$this->_tableRow(array($data['data']), null, $opts);
}
$this->_endTable();
} else {
$this->_displayLine($data);
}
}
}
}
function log($text, $append_crlf = true)
{
if ($append_crlf) {
return $this->_displayLine($text);
}
return $this->_display($text);
}
function bold($text)
{
if (empty($this->term['bold'])) {
return strtoupper($text);
}
return $this->term['bold'] . $text . $this->term['normal'];
}
function _displayHeading($title)
{
print $this->lp.$this->bold($title)."\n";
print $this->lp.str_repeat("=", strlen($title))."\n";
}
function _startTable($params = array())
{
$params['table_data'] = array();
$params['widest'] = array(); // indexed by column
$params['highest'] = array(); // indexed by row
$params['ncols'] = 0;
$this->params = $params;
}
function _tableRow($columns, $rowparams = array(), $colparams = array())
{
$highest = 1;
for ($i = 0; $i < count($columns); $i++) {
$col = &$columns[$i];
if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
$col = wordwrap($col, $colparams[$i]['wrap']);
}
if (strpos($col, "\n") !== false) {
$multiline = explode("\n", $col);
$w = 0;
foreach ($multiline as $n => $line) {
$len = strlen($line);
if ($len > $w) {
$w = $len;
}
}
$lines = count($multiline);
} else {
$w = strlen($col);
}
if (isset($this->params['widest'][$i])) {
if ($w > $this->params['widest'][$i]) {
$this->params['widest'][$i] = $w;
}
} else {
$this->params['widest'][$i] = $w;
}
$tmp = count_chars($columns[$i], 1);
// handle unix, mac and windows formats
$lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
if ($lines > $highest) {
$highest = $lines;
}
}
if (count($columns) > $this->params['ncols']) {
$this->params['ncols'] = count($columns);
}
$new_row = array(
'data' => $columns,
'height' => $highest,
'rowparams' => $rowparams,
'colparams' => $colparams,
);
$this->params['table_data'][] = $new_row;
}
function _endTable()
{
extract($this->params);
if (!empty($caption)) {
$this->_displayHeading($caption);
}
if (count($table_data) === 0) {
return;
}
if (!isset($width)) {
$width = $widest;
} else {
for ($i = 0; $i < $ncols; $i++) {
if (!isset($width[$i])) {
$width[$i] = $widest[$i];
}
}
}
$border = false;
if (empty($border)) {
$cellstart = '';
$cellend = ' ';
$rowend = '';
$padrowend = false;
$borderline = '';
} else {
$cellstart = '| ';
$cellend = ' ';
$rowend = '|';
$padrowend = true;
$borderline = '+';
foreach ($width as $w) {
$borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
$borderline .= '+';
}
}
if ($borderline) {
$this->_displayLine($borderline);
}
for ($i = 0; $i < count($table_data); $i++) {
extract($table_data[$i]);
if (!is_array($rowparams)) {
$rowparams = array();
}
if (!is_array($colparams)) {
$colparams = array();
}
$rowlines = array();
if ($height > 1) {
for ($c = 0; $c < count($data); $c++) {
$rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
if (count($rowlines[$c]) < $height) {
$rowlines[$c] = array_pad($rowlines[$c], $height, '');
}
}
} else {
for ($c = 0; $c < count($data); $c++) {
$rowlines[$c] = array($data[$c]);
}
}
for ($r = 0; $r < $height; $r++) {
$rowtext = '';
for ($c = 0; $c < count($data); $c++) {
if (isset($colparams[$c])) {
$attribs = array_merge($rowparams, $colparams);
} else {
$attribs = $rowparams;
}
$w = isset($width[$c]) ? $width[$c] : 0;
//$cell = $data[$c];
$cell = $rowlines[$c][$r];
$l = strlen($cell);
if ($l > $w) {
$cell = substr($cell, 0, $w);
}
if (isset($attribs['bold'])) {
$cell = $this->bold($cell);
}
if ($l < $w) {
// not using str_pad here because we may
// add bold escape characters to $cell
$cell .= str_repeat(' ', $w - $l);
}
$rowtext .= $cellstart . $cell . $cellend;
}
if (!$border) {
$rowtext = rtrim($rowtext);
}
$rowtext .= $rowend;
$this->_displayLine($rowtext);
}
}
if ($borderline) {
$this->_displayLine($borderline);
}
}
function _displayLine($text)
{
print "$this->lp$text\n";
}
function _display($text)
{
print $text;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,266 +0,0 @@
<?php
/**
* PEAR_Installer_Role
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base class for installer roles
*/
require_once 'PEAR/Installer/Role/Common.php';
require_once 'PEAR/XMLParser.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role
{
/**
* Set up any additional configuration variables that file roles require
*
* Never call this directly, it is called by the PEAR_Config constructor
* @param PEAR_Config
*/
public static function initializeConfig(&$config)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
if (!$info['config_vars']) {
continue;
}
$config->_addConfigVars($class, $info['config_vars']);
}
}
/**
* @param PEAR_PackageFile_v2
* @param string role name
* @param PEAR_Config
* @return PEAR_Installer_Role_Common
*/
public static function &factory($pkg, $role, &$config)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
$a = false;
return $a;
}
$a = 'PEAR_Installer_Role_' . ucfirst($role);
if (!class_exists($a)) {
require_once str_replace('_', '/', $a) . '.php';
}
$b = new $a($config);
return $b;
}
/**
* Get a list of file roles that are valid for the particular release type.
*
* For instance, src files serve no purpose in regular php releases.
* @param string
* @param bool clear cache
* @return array
*/
public static function getValidRoles($release, $clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret = array();
if ($clear) {
$ret = array();
}
if (isset($ret[$release])) {
return $ret[$release];
}
$ret[$release] = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if (in_array($release, $okreleases['releasetypes'])) {
$ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret[$release];
}
/**
* Get a list of roles that require their files to be installed
*
* Most roles must be installed, but src and package roles, for instance
* are pseudo-roles. src files are compiled into a new extension. Package
* roles are actually fully bundled releases of a package
* @param bool clear cache
* @return array
*/
public static function getInstallableRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['installable']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Return an array of roles that are affected by the baseinstalldir attribute
*
* Most roles ignore this attribute, and instead install directly into:
* PackageName/filepath
* so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
* @param bool clear cache
* @return array
*/
public static function getBaseinstallRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['honorsbaseinstall']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Return an array of file roles that should be analyzed for PHP content at package time,
* like the "php" role.
* @param bool clear cache
* @return array
*/
public static function getPhpRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['phpfile']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
* @param string which directory to look for classes, defaults to
* the Installer/Roles subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*/
public static function registerRoles($dir = null)
{
$GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
$parser = new PEAR_XMLParser;
if ($dir === null) {
$dir = dirname(__FILE__) . '/Role';
}
if (!file_exists($dir) || !is_dir($dir)) {
return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
}
while ($entry = readdir($dp)) {
if ($entry[0] == '.' || substr($entry, -4) != '.xml') {
continue;
}
$class = "PEAR_Installer_Role_".substr($entry, 0, -4);
// List of roles
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
$file = "$dir/$entry";
$parser->parse(file_get_contents($file));
$data = $parser->getData();
if (!is_array($data['releasetypes'])) {
$data['releasetypes'] = array($data['releasetypes']);
}
$GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
}
}
closedir($dp);
ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
PEAR_Installer_Role::getBaseinstallRoles(true);
PEAR_Installer_Role::getInstallableRoles(true);
PEAR_Installer_Role::getPhpRoles(true);
PEAR_Installer_Role::getValidRoles('****', true);
return true;
}
}

View File

@@ -1,105 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Cfg
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.7.0
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.7.0
*/
class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
{
/**
* @var PEAR_Installer
*/
var $installer;
/**
* the md5 of the original file
*
* @var unknown_type
*/
var $md5 = null;
/**
* Do any unusual setup here
* @param PEAR_Installer
* @param PEAR_PackageFile_v2
* @param array file attributes
* @param string file name
*/
function setup(&$installer, $pkg, $atts, $file)
{
$this->installer = &$installer;
$reg = &$this->installer->config->getRegistry();
$package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
if ($package) {
$filelist = $package->getFilelist();
if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
$this->md5 = $filelist[$file]['md5sum'];
}
}
}
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
{
$test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
if (@file_exists($test[2]) && @file_exists($test[3])) {
$md5 = md5_file($test[2]);
// configuration has already been installed, check for mods
if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
// configuration has been modified, so save our version as
// configfile-version
$old = $test[2];
$test[2] .= '.new-' . $pkg->getVersion();
// backup original and re-install it
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$tmpcfg = $this->config->get('temp_dir');
$newloc = System::mkdir(array('-p', $tmpcfg));
if (!$newloc) {
// try temp_dir
$newloc = System::mktemp(array('-d'));
if (!$newloc || PEAR::isError($newloc)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Could not save existing configuration file '.
$old . ', unable to install. Please set temp_dir ' .
'configuration variable to a writeable location and try again');
}
} else {
$newloc = $tmpcfg;
}
$temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
if (!@copy($old, $temp_file)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Could not save existing configuration file '.
$old . ', unable to install. Please set temp_dir ' .
'configuration variable to a writeable location and try again');
}
PEAR::popErrorHandling();
$this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
$this->installer->addFileOperation('rename', array($temp_file, $old, false));
$this->installer->addFileOperation('delete', array($temp_file));
}
}
return $test;
}
}

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>cfg_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall>1</unusualbaseinstall>
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,173 +0,0 @@
<?php
/**
* Base class for all installation roles.
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class for all installation roles.
*
* This class allows extensibility of file roles. Packages with complex
* customization can now provide custom file roles along with the possibility of
* adding configuration values to match.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Common
{
/**
* @var PEAR_Config
* @access protected
*/
var $config;
/**
* @param PEAR_Config
*/
function __construct(&$config)
{
$this->config = $config;
}
/**
* Retrieve configuration information about a file role from its XML info
*
* @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
* @return array
*/
function getInfo($role)
{
if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
return PEAR::raiseError('Unknown Role class: "' . $role . '"');
}
return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
}
/**
* This is called for each file to set up the directories and files
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param array attributes from the <file> tag
* @param string file name
* @return array an array consisting of:
*
* 1 the original, pre-baseinstalldir installation directory
* 2 the final installation directory
* 3 the full path to the final location of the file
* 4 the location of the pre-installation file
*/
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
if (!$roleInfo['locationconfig']) {
return false;
}
if ($roleInfo['honorsbaseinstall']) {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
$pkg->getChannel());
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
} elseif ($roleInfo['unusualbaseinstall']) {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
} else {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
}
if (dirname($file) != '.' && empty($atts['install-as'])) {
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
}
if (empty($atts['install-as'])) {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
} else {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
}
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
// Clean up the DIRECTORY_SEPARATOR mess
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR),
array($dest_dir, $dest_file, $orig_file));
return array($save_destdir, $dest_dir, $dest_file, $orig_file);
}
/**
* Get the name of the configuration variable that specifies the location of this file
* @return string|false
*/
function getLocationConfig()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['locationconfig'];
}
/**
* Do any unusual setup here
* @param PEAR_Installer
* @param PEAR_PackageFile_v2
* @param array file attributes
* @param string file name
*/
function setup(&$installer, $pkg, $atts, $file)
{
}
function isExecutable()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['executable'];
}
function isInstallable()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['installable'];
}
function isExtension()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['phpextension'];
}
}
?>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Data
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>data_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Doc
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>doc_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Ext
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,12 +0,0 @@
<role version="1.0">
<releasetypes>extbin</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>ext_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension>1</phpextension>
<config_vars />
</role>

View File

@@ -1,28 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Man
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Hannes Magnusson <bjori@php.net>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version SVN: $Id: $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.10.0
*/
/**
* @category pear
* @package PEAR
* @author Hannes Magnusson <bjori@php.net>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.10.0
*/
class PEAR_Installer_Role_Man extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>man_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Php
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>php_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile>1</phpfile>
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Script
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>bin_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable>1</executable>
<phpextension />
<config_vars />
</role>

View File

@@ -1,33 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Src
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
{
function setup(&$installer, $pkg, $atts, $file)
{
$installer->source_files++;
}
}
?>

View File

@@ -1,12 +0,0 @@
<role version="1.0">
<releasetypes>extsrc</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<installable>1</installable>
<locationconfig>temp_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Test
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>test_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,27 +0,0 @@
<?php
/**
* PEAR_Installer_Role_Www
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.7.0
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.7.0
*/
class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
?>

View File

@@ -1,15 +0,0 @@
<role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>www_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>

View File

@@ -1,491 +0,0 @@
<?php
/**
* PEAR_PackageFile, package.xml parsing utility class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* needed for PEAR_VALIDATE_* constants
*/
require_once 'PEAR/Validate.php';
/**
* Error code if the package.xml <package> tag does not contain a valid version
*/
define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
/**
* Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
* currently
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
/**
* Abstraction for the package.xml package description file
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile
{
/**
* @var PEAR_Config
*/
var $_config;
var $_debug;
var $_logger = false;
/**
* @var boolean
*/
var $_rawReturn = false;
/**
* helper for extracting Archive_Tar errors
* @var array
* @access private
*/
var $_extractErrors = array();
/**
*
* @param PEAR_Config $config
* @param ? $debug
* @param string @tmpdir Optional temporary directory for uncompressing
* files
*/
function __construct(&$config, $debug = false)
{
$this->_config = $config;
$this->_debug = $debug;
}
/**
* Turn off validation - return a parsed package.xml without checking it
*
* This is used by the package-validate command
*/
function rawReturn()
{
$this->_rawReturn = true;
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* Create a PEAR_PackageFile_Parser_v* of a given version.
* @param int $version
* @return PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
*/
function &parserFactory($version)
{
if (!in_array($version[0], array('1', '2'))) {
$a = false;
return $a;
}
include_once 'PEAR/PackageFile/Parser/v' . $version[0] . '.php';
$version = $version[0];
$class = "PEAR_PackageFile_Parser_v$version";
$a = new $class;
return $a;
}
/**
* For simpler unit-testing
* @return string
*/
function getClassPrefix()
{
return 'PEAR_PackageFile_v';
}
/**
* Create a PEAR_PackageFile_v* of a given version.
* @param int $version
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v1
*/
function &factory($version)
{
if (!in_array($version[0], array('1', '2'))) {
$a = false;
return $a;
}
include_once 'PEAR/PackageFile/v' . $version[0] . '.php';
$version = $version[0];
$class = $this->getClassPrefix() . $version;
$a = new $class;
return $a;
}
/**
* Create a PEAR_PackageFile_v* from its toArray() method
*
* WARNING: no validation is performed, the array is assumed to be valid,
* always parse from xml if you want validation.
* @param array $arr
* @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
* @uses factory() to construct the returned object.
*/
function &fromArray($arr)
{
if (isset($arr['xsdversion'])) {
$obj = &$this->factory($arr['xsdversion']);
if ($this->_logger) {
$obj->setLogger($this->_logger);
}
$obj->setConfig($this->_config);
$obj->fromArray($arr);
return $obj;
}
if (isset($arr['package']['attribs']['version'])) {
$obj = &$this->factory($arr['package']['attribs']['version']);
} else {
$obj = &$this->factory('1.0');
}
if ($this->_logger) {
$obj->setLogger($this->_logger);
}
$obj->setConfig($this->_config);
$obj->fromArray($arr);
return $obj;
}
/**
* Create a PEAR_PackageFile_v* from an XML string.
* @access public
* @param string $data contents of package.xml file
* @param int $state package state (one of PEAR_VALIDATE_* constants)
* @param string $file full path to the package.xml file (and the files
* it references)
* @param string $archive optional name of the archive that the XML was
* extracted from, if any
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @uses parserFactory() to construct a parser to load the package.
*/
function &fromXmlString($data, $state, $file, $archive = false)
{
if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
return PEAR::raiseError('package.xml version "' . $packageversion[1] .
'" is not supported, only 1.0, 2.0, and 2.1 are supported.');
}
$object = &$this->parserFactory($packageversion[1]);
if ($this->_logger) {
$object->setLogger($this->_logger);
}
$object->setConfig($this->_config);
$pf = $object->parse($data, $file, $archive);
if (PEAR::isError($pf)) {
return $pf;
}
if ($this->_rawReturn) {
return $pf;
}
if (!$pf->validate($state)) {;
if ($this->_config->get('verbose') > 0
&& $this->_logger && $pf->getValidationWarnings(false)
) {
foreach ($pf->getValidationWarnings(false) as $warning) {
$this->_logger->log(0, 'ERROR: ' . $warning['message']);
}
}
$a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
2, null, null, $pf->getValidationWarnings());
return $a;
}
if ($this->_logger && $pf->getValidationWarnings(false)) {
foreach ($pf->getValidationWarnings() as $warning) {
$this->_logger->log(0, 'WARNING: ' . $warning['message']);
}
}
if (method_exists($pf, 'flattenFilelist')) {
$pf->flattenFilelist(); // for v2
}
return $pf;
} elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
$a = PEAR::raiseError('package.xml file "' . $file .
'" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
return $a;
} else {
if (!class_exists('PEAR_ErrorStack')) {
require_once 'PEAR/ErrorStack.php';
}
PEAR_ErrorStack::staticPush('PEAR_PackageFile',
PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
'warning', array('xml' => $data), 'package.xml "' . $file .
'" has no package.xml <package> version');
$object = &$this->parserFactory('1.0');
$object->setConfig($this->_config);
$pf = $object->parse($data, $file, $archive);
if (PEAR::isError($pf)) {
return $pf;
}
if ($this->_rawReturn) {
return $pf;
}
if (!$pf->validate($state)) {
$a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
2, null, null, $pf->getValidationWarnings());
return $a;
}
if ($this->_logger && $pf->getValidationWarnings(false)) {
foreach ($pf->getValidationWarnings() as $warning) {
$this->_logger->log(0, 'WARNING: ' . $warning['message']);
}
}
if (method_exists($pf, 'flattenFilelist')) {
$pf->flattenFilelist(); // for v2
}
return $pf;
}
}
/**
* Register a temporary file or directory. When the destructor is
* executed, all registered temporary files and directories are
* removed.
*
* @param string $file name of file or directory
* @return void
*/
static function addTempFile($file)
{
$GLOBALS['_PEAR_Common_tempfiles'][] = $file;
}
/**
* Create a PEAR_PackageFile_v* from a compressed Tar or Tgz file.
* @access public
* @param string contents of package.xml file
* @param int package state (one of PEAR_VALIDATE_* constants)
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @using Archive_Tar to extract the files
* @using fromPackageFile() to load the package after the package.xml
* file is extracted.
*/
function &fromTgzFile($file, $state)
{
if (!class_exists('Archive_Tar')) {
require_once 'Archive/Tar.php';
}
$tar = new Archive_Tar($file);
if ($this->_debug <= 1) {
$tar->pushErrorHandling(PEAR_ERROR_RETURN);
}
$content = $tar->listContent();
if ($this->_debug <= 1) {
$tar->popErrorHandling();
}
if (!is_array($content)) {
if (is_string($file) && strlen($file) < 255 &&
(!file_exists($file) || !@is_file($file))) {
$ret = PEAR::raiseError("could not open file \"$file\"");
return $ret;
}
$file = realpath($file);
$ret = PEAR::raiseError("Could not get contents of package \"$file\"".
'. Invalid tgz file.');
return $ret;
}
if (!count($content) && !@is_file($file)) {
$ret = PEAR::raiseError("could not open file \"$file\"");
return $ret;
}
$xml = null;
$origfile = $file;
foreach ($content as $file) {
$name = $file['filename'];
if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
$xml = $name;
break;
}
if ($name == 'package.xml') {
$xml = $name;
break;
} elseif (preg_match('/package.xml$/', $name, $match)) {
$xml = $name;
break;
}
}
$tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
if ($tmpdir === false) {
$ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
return $ret;
}
PEAR_PackageFile::addTempFile($tmpdir);
$this->_extractErrors();
PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
$extra = implode("\n", $this->_extractErrors());
if ($extra) {
$extra = ' ' . $extra;
}
PEAR::staticPopErrorHandling();
$ret = PEAR::raiseError('could not extract the package.xml file from "' .
$origfile . '"' . $extra);
return $ret;
}
PEAR::staticPopErrorHandling();
$ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
return $ret;
}
/**
* helper callback for extracting Archive_Tar errors
*
* @param PEAR_Error|null $err
* @return array
* @access private
*/
function _extractErrors($err = null)
{
static $errors = array();
if ($err === null) {
$e = $errors;
$errors = array();
return $e;
}
$errors[] = $err->getMessage();
}
/**
* Create a PEAR_PackageFile_v* from a package.xml file.
*
* @access public
* @param string $descfile name of package xml file
* @param int $state package state (one of PEAR_VALIDATE_* constants)
* @param string|false $archive name of the archive this package.xml came
* from, if any
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @uses PEAR_PackageFile::fromXmlString to create the oject after the
* XML is loaded from the package.xml file.
*/
function &fromPackageFile($descfile, $state, $archive = false)
{
$fp = false;
if (is_string($descfile) && strlen($descfile) < 255 &&
(
!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
|| (!$fp = @fopen($descfile, 'r'))
)
) {
$a = PEAR::raiseError("Unable to open $descfile");
return $a;
}
// read the whole thing so we only get one cdata callback
// for each block of cdata
fclose($fp);
$data = file_get_contents($descfile);
$ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
return $ret;
}
/**
* Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
*
* This method is able to extract information about a package from a .tgz
* archive or from a XML package definition file.
*
* @access public
* @param string $info file name
* @param int $state package state (one of PEAR_VALIDATE_* constants)
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @uses fromPackageFile() if the file appears to be XML
* @uses fromTgzFile() to load all non-XML files
*/
function &fromAnyFile($info, $state)
{
if (is_dir($info)) {
$dir_name = realpath($info);
if (file_exists($dir_name . '/package.xml')) {
$info = PEAR_PackageFile::fromPackageFile($dir_name . '/package.xml', $state);
} elseif (file_exists($dir_name . '/package2.xml')) {
$info = PEAR_PackageFile::fromPackageFile($dir_name . '/package2.xml', $state);
} else {
$info = PEAR::raiseError("No package definition found in '$info' directory");
}
return $info;
}
$fp = false;
if (is_string($info) && strlen($info) < 255 &&
(file_exists($info) || ($fp = @fopen($info, 'r')))
) {
if ($fp) {
fclose($fp);
}
$tmp = substr($info, -4);
if ($tmp == '.xml') {
$info = &PEAR_PackageFile::fromPackageFile($info, $state);
} elseif ($tmp == '.tar' || $tmp == '.tgz') {
$info = &PEAR_PackageFile::fromTgzFile($info, $state);
} else {
$fp = fopen($info, 'r');
$test = fread($fp, 5);
fclose($fp);
if ($test == '<?xml') {
$info = &PEAR_PackageFile::fromPackageFile($info, $state);
} else {
$info = &PEAR_PackageFile::fromTgzFile($info, $state);
}
}
return $info;
}
$info = PEAR::raiseError("Cannot open '$info' for parsing");
return $info;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,886 +0,0 @@
<?php
/**
* package.xml generation class, package.xml version 2.0
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* file/dir manipulation routines
*/
require_once 'System.php';
require_once 'XML/Util.php';
/**
* This class converts a PEAR_PackageFile_v2 object into any output format.
*
* Supported output formats include array, XML string (using S. Schmidt's
* XML_Serializer, slightly customized)
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Generator_v2
{
/**
* default options for the serialization
* @access private
* @var array $_defaultOptions
*/
var $_defaultOptions = array(
'indent' => ' ', // string used for indentation
'linebreak' => "\n", // string used for newlines
'typeHints' => false, // automatically add type hin attributes
'addDecl' => true, // add an XML declaration
'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names
'classAsTagName' => false, // use classname for objects in indexed arrays
'keyAttribute' => '_originalKey', // attribute where original key is stored
'typeAttribute' => '_type', // attribute for type (only if typeHints => true)
'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true)
'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute
'prependAttributes' => '', // prepend string for attributes
'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array
'addDoctype' => false, // add a doctype declaration
'doctype' => null, // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
'rootName' => 'package', // name of the root tag
'rootAttributes' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
), // attributes of the root tag
'attributesArray' => 'attribs', // all values in this key will be treated as attributes
'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjunction with attributesArray
'beautifyFilelist' => false,
'encoding' => 'UTF-8',
);
/**
* options for the serialization
* @access private
* @var array $options
*/
var $options = array();
/**
* current tag depth
* @var integer $_tagDepth
*/
var $_tagDepth = 0;
/**
* serilialized representation of the data
* @var string $_serializedData
*/
var $_serializedData = null;
/**
* @var PEAR_PackageFile_v2
*/
var $_packagefile;
/**
* @param PEAR_PackageFile_v2
*/
function __construct(&$packagefile)
{
$this->_packagefile = &$packagefile;
if (isset($this->_packagefile->encoding)) {
$this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
}
}
/**
* @return string
*/
function getPackagerVersion()
{
return '1.10.13';
}
/**
* @param PEAR_Packager
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz(&$packager, $compress = true, $where = null)
{
$a = null;
return $this->toTgz2($packager, $a, $compress, $where);
}
/**
* Package up both a package.xml and package2.xml for the same release
* @param PEAR_Packager
* @param PEAR_PackageFile_v1
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
{
require_once 'Archive/Tar.php';
if (!$this->_packagefile->isEquivalent($pf1)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
basename($pf1->getPackageFile()) .
'" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
. '"');
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
' not be created');
}
$file = $where . DIRECTORY_SEPARATOR . 'package.xml';
if (file_exists($file) && !is_file($file)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
' "' . $file .'"');
}
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
}
$ext = $compress ? '.tgz' : '.tar';
$pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
if (file_exists($dest_package) && !is_file($dest_package)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
$dest_package . '"');
}
$pkgfile = $this->_packagefile->getPackageFile();
if (!$pkgfile) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
'be created from a real file');
}
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
// {{{ Create the package file list
$filelist = array();
$i = 0;
$this->_packagefile->flattenFilelist();
$contents = $this->_packagefile->getContents();
if (isset($contents['bundledpackage'])) { // bundles of packages
$contents = $contents['bundledpackage'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $package) {
$fname = $package;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
}
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
$filelist[$i++] = $tfile;
$packager->log(2, "Adding package $fname");
}
} else { // normal packages
$contents = $contents['dir']['file'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $file) {
$fname = $file['attribs']['name'];
$atts = $file['attribs'];
$orig = $file;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
}
$origperms = fileperms($file);
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
unset($orig['attribs']);
if (count($orig)) { // file with tasks
// run any package-time tasks
$contents = file_get_contents($file);
foreach ($orig as $tag => $raw) {
$tag = str_replace(
array($this->_packagefile->getTasksNs() . ':', '-'),
array('', '_'), $tag);
$task = "PEAR_Task_$tag";
$task = new $task($this->_packagefile->_config,
$this->_packagefile->_logger,
PEAR_TASK_PACKAGE);
$task->init($raw, $atts, null);
$res = $task->startSession($this->_packagefile, $contents, $tfile);
if (!$res) {
continue; // skip this task
}
if (PEAR::isError($res)) {
return $res;
}
$contents = $res; // save changes
System::mkdir(array('-p', dirname($tfile)));
$wp = fopen($tfile, "wb");
fwrite($wp, $contents);
fclose($wp);
}
}
if (!file_exists($tfile)) {
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
}
chmod($tfile, $origperms);
$filelist[$i++] = $tfile;
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
$packager->log(2, "Adding file $fname");
}
}
// }}}
$name = $pf1 !== null ? 'package2.xml' : 'package.xml';
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
if ($packagexml) {
$tar = new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($packagexml), '', $where);
if (PEAR::isError($ok)) {
return $packager->raiseError($ok);
} elseif (!$ok) {
return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
' failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
}
// add the package.xml version 1.0
if ($pf1 !== null) {
$pfgen = &$pf1->getDefaultGenerator();
$packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
if (!$tar->addModify(array($packagexml1), '', $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
}
}
return $dest_package;
}
}
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
{
if (!$this->_packagefile->validate($state)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
null, null, null, $this->_packagefile->getValidationWarnings());
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
' not be created');
}
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
"$name as $newpkgfile");
}
fwrite($np, $this->toXml($state));
fclose($np);
return $newpkgfile;
}
function &toV2()
{
return $this->_packagefile;
}
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @return string XML data
*/
function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
{
$this->_packagefile->setDate(date('Y-m-d'));
$this->_packagefile->setTime(date('H:i:s'));
if (!$this->_packagefile->validate($state)) {
return false;
}
if (is_array($options)) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = $this->_defaultOptions;
}
$arr = $this->_packagefile->getArray();
if (isset($arr['filelist'])) {
unset($arr['filelist']);
}
if (isset($arr['_lastversion'])) {
unset($arr['_lastversion']);
}
// Fix the notes a little bit
if (isset($arr['notes'])) {
// This trims out the indenting, needs fixing
$arr['notes'] = "\n" . trim($arr['notes']) . "\n";
}
if (isset($arr['changelog']) && !empty($arr['changelog'])) {
// Fix for inconsistency how the array is filled depending on the changelog release amount
if (!isset($arr['changelog']['release'][0])) {
$release = $arr['changelog']['release'];
unset($arr['changelog']['release']);
$arr['changelog']['release'] = array();
$arr['changelog']['release'][0] = $release;
}
foreach (array_keys($arr['changelog']['release']) as $key) {
$c =& $arr['changelog']['release'][$key];
if (isset($c['notes'])) {
// This trims out the indenting, needs fixing
$c['notes'] = "\n" . trim($c['notes']) . "\n";
}
}
}
if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
$use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
unset($arr['contents']['dir']['file']);
if (isset($use['dir'])) {
$arr['contents']['dir']['dir'] = $use['dir'];
}
if (isset($use['file'])) {
$arr['contents']['dir']['file'] = $use['file'];
}
$this->options['beautifyFilelist'] = true;
}
$arr['attribs']['packagerversion'] = '1.10.13';
if ($this->serialize($arr, $options)) {
return $this->_serializedData . "\n";
}
return false;
}
function _recursiveXmlFilelist($list)
{
$dirs = array();
if (isset($list['attribs'])) {
$file = $list['attribs']['name'];
unset($list['attribs']['name']);
$attributes = $list['attribs'];
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
} else {
foreach ($list as $a) {
$file = $a['attribs']['name'];
$attributes = $a['attribs'];
unset($a['attribs']);
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
}
}
$this->_formatDir($dirs);
$this->_deFormat($dirs);
return $dirs;
}
function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
{
if (!$tasks) {
$tasks = array();
}
if ($dir == array() || $dir == array('.')) {
$dirs['file'][basename($file)] = $tasks;
$attributes['name'] = basename($file);
$dirs['file'][basename($file)]['attribs'] = $attributes;
return;
}
$curdir = array_shift($dir);
if (!isset($dirs['dir'][$curdir])) {
$dirs['dir'][$curdir] = array();
}
$this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
}
function _formatDir(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
$newdirs['dir'] = $dirs['dir'];
}
if (isset($dirs['file'])) {
$newdirs['file'] = $dirs['file'];
}
$dirs = $newdirs;
if (isset($dirs['dir'])) {
uksort($dirs['dir'], 'strnatcasecmp');
foreach ($dirs['dir'] as $dir => $contents) {
$this->_formatDir($dirs['dir'][$dir]);
}
}
if (isset($dirs['file'])) {
uksort($dirs['file'], 'strnatcasecmp');
};
}
function _deFormat(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
foreach ($dirs['dir'] as $dir => $contents) {
$newdir = array();
$newdir['attribs']['name'] = $dir;
$this->_deFormat($contents);
foreach ($contents as $tag => $val) {
$newdir[$tag] = $val;
}
$newdirs['dir'][] = $newdir;
}
if (count($newdirs['dir']) == 1) {
$newdirs['dir'] = $newdirs['dir'][0];
}
}
if (isset($dirs['file'])) {
foreach ($dirs['file'] as $name => $file) {
$newdirs['file'][] = $file;
}
if (count($newdirs['file']) == 1) {
$newdirs['file'] = $newdirs['file'][0];
}
}
$dirs = $newdirs;
}
/**
* reset all options to default options
*
* @access public
* @see setOption(), XML_Unserializer()
*/
function resetOptions()
{
$this->options = $this->_defaultOptions;
}
/**
* set an option
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Serializer()
*/
function setOption($name, $value)
{
$this->options[$name] = $value;
}
/**
* sets several options at once
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Unserializer(), setOption()
*/
function setOptions($options)
{
$this->options = array_merge($this->options, $options);
}
/**
* serialize data
*
* @access public
* @param mixed $data data to serialize
* @return boolean true on success, pear error on failure
*/
function serialize($data, $options = null)
{
// if options have been specified, use them instead
// of the previously defined ones
if (is_array($options)) {
$optionsBak = $this->options;
if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = array_merge($this->options, $options);
}
} else {
$optionsBak = null;
}
// start depth is zero
$this->_tagDepth = 0;
$this->_serializedData = '';
// serialize an array
if (is_array($data)) {
$tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
$this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
}
// add doctype declaration
if ($this->options['addDoctype'] === true) {
$this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
. $this->options['linebreak']
. $this->_serializedData;
}
// build xml declaration
if ($this->options['addDecl']) {
$atts = array();
$encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
$this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
. $this->options['linebreak']
. $this->_serializedData;
}
if ($optionsBak !== null) {
$this->options = $optionsBak;
}
return true;
}
/**
* get the result of the serialization
*
* @access public
* @return string serialized XML
*/
function getSerializedData()
{
if ($this->_serializedData === null) {
return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
}
return $this->_serializedData;
}
/**
* serialize any value
*
* This method checks for the type of the value and calls the appropriate method
*
* @access private
* @param mixed $value
* @param string $tagName
* @param array $attributes
* @return string
*/
function _serializeValue($value, $tagName = null, $attributes = array())
{
if (is_array($value)) {
$xml = $this->_serializeArray($value, $tagName, $attributes);
} elseif (is_object($value)) {
$xml = $this->_serializeObject($value, $tagName);
} else {
$tag = array(
'qname' => $tagName,
'attributes' => $attributes,
'content' => $value
);
$xml = $this->_createXMLTag($tag);
}
return $xml;
}
/**
* serialize an array
*
* @access private
* @param array $array array to serialize
* @param string $tagName name of the root tag
* @param array $attributes attributes for the root tag
* @return string $string serialized data
* @uses XML_Util::isValidName() to check, whether key has to be substituted
*/
function _serializeArray(&$array, $tagName = null, $attributes = array())
{
$_content = null;
/**
* check for special attributes
*/
if ($this->options['attributesArray'] !== null) {
if (isset($array[$this->options['attributesArray']])) {
$attributes = $array[$this->options['attributesArray']];
unset($array[$this->options['attributesArray']]);
}
/**
* check for special content
*/
if ($this->options['contentName'] !== null) {
if (isset($array[$this->options['contentName']])) {
$_content = $array[$this->options['contentName']];
unset($array[$this->options['contentName']]);
}
}
}
/*
* if mode is set to simpleXML, check whether
* the array is associative or indexed
*/
if (is_array($array) && $this->options['mode'] == 'simplexml') {
$indexed = true;
if (!count($array)) {
$indexed = false;
}
foreach ($array as $key => $val) {
if (!is_int($key)) {
$indexed = false;
break;
}
}
if ($indexed && $this->options['mode'] == 'simplexml') {
$string = '';
foreach ($array as $key => $val) {
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($val['attribs'])) {
if ($val['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
if ($this->_curdir == '/') {
$this->_curdir = '';
}
$this->_curdir .= '/' . $val['attribs']['name'];
}
}
}
$string .= $this->_serializeValue( $val, $tagName, $attributes);
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
$string .= ' <!-- ' . $this->_curdir . ' -->';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
$string .= $this->options['linebreak'];
// do indentation
if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
$string .= str_repeat($this->options['indent'], $this->_tagDepth);
}
}
return rtrim($string);
}
}
if ($this->options['scalarAsAttributes'] === true) {
foreach ($array as $key => $value) {
if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
unset($array[$key]);
$attributes[$this->options['prependAttributes'].$key] = $value;
}
}
}
// check for empty array => create empty tag
if (empty($array)) {
$tag = array(
'qname' => $tagName,
'content' => $_content,
'attributes' => $attributes
);
} else {
$this->_tagDepth++;
$tmp = $this->options['linebreak'];
foreach ($array as $key => $value) {
// do indentation
if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
// copy key
$origKey = $key;
// key cannot be used as tagname => use default tag
$valid = XML_Util::isValidName($key);
if (PEAR::isError($valid)) {
if ($this->options['classAsTagName'] && is_object($value)) {
$key = get_class($value);
} else {
$key = $this->options['defaultTagName'];
}
}
$atts = array();
if ($this->options['typeHints'] === true) {
$atts[$this->options['typeAttribute']] = gettype($value);
if ($key !== $origKey) {
$atts[$this->options['keyAttribute']] = (string)$origKey;
}
}
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($value['attribs'])) {
if ($value['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
$this->_curdir .= '/' . $value['attribs']['name'];
}
}
}
if (is_string($value) && $value && ($value[strlen($value) - 1] == "\n")) {
$value .= str_repeat($this->options['indent'], $this->_tagDepth);
}
$tmp .= $this->_createXMLTag(array(
'qname' => $key,
'attributes' => $atts,
'content' => $value )
);
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (isset($value['attribs'])) {
$tmp .= ' <!-- ' . $this->_curdir . ' -->';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
}
$tmp .= $this->options['linebreak'];
}
$this->_tagDepth--;
if ($this->options['indent']!==null && $this->_tagDepth>0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
if (trim($tmp) === '') {
$tmp = null;
}
$tag = array(
'qname' => $tagName,
'content' => $tmp,
'attributes' => $attributes
);
}
if ($this->options['typeHints'] === true) {
if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
$tag['attributes'][$this->options['typeAttribute']] = 'array';
}
}
$string = $this->_createXMLTag($tag, false);
return $string;
}
/**
* create a tag from an array
* this method awaits an array in the following format
* array(
* 'qname' => $tagName,
* 'attributes' => array(),
* 'content' => $content, // optional
* 'namespace' => $namespace // optional
* 'namespaceUri' => $namespaceUri // optional
* )
*
* @access private
* @param array $tag tag definition
* @param boolean $replaceEntities whether to replace XML entities in content or not
* @return string $string XML tag
*/
function _createXMLTag($tag, $replaceEntities = true)
{
if ($this->options['indentAttributes'] !== false) {
$multiline = true;
$indent = str_repeat($this->options['indent'], $this->_tagDepth);
if ($this->options['indentAttributes'] == '_auto') {
$indent .= str_repeat(' ', (strlen($tag['qname'])+2));
} else {
$indent .= $this->options['indentAttributes'];
}
} else {
$indent = $multiline = false;
}
if (is_array($tag['content'])) {
if (empty($tag['content'])) {
$tag['content'] = '';
}
} elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
$tag['content'] = '';
}
if (is_scalar($tag['content']) || is_null($tag['content'])) {
if ($replaceEntities === true) {
$replaceEntities = XML_UTIL_ENTITIES_XML;
}
$tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
} elseif (is_array($tag['content'])) {
$tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_object($tag['content'])) {
$tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_resource($tag['content'])) {
settype($tag['content'], 'string');
$tag = XML_Util::createTagFromArray($tag, $replaceEntities);
}
return $tag;
}
}

View File

@@ -1,458 +0,0 @@
<?php
/**
* package.xml parsing class, package.xml version 1.0
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* package.xml abstraction class
*/
require_once 'PEAR/PackageFile/v1.php';
/**
* Parser for package.xml version 1.0
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v1
{
var $_registry;
var $_config;
var $_logger;
/**
* BC hack to allow PEAR_Common::infoFromString() to sort of
* work with the version 2.0 format - there's no filelist though
* @param PEAR_PackageFile_v2
*/
function fromV2($packagefile)
{
$info = $packagefile->getArray(true);
$ret = new PEAR_PackageFile_v1;
$ret->fromArray($info['old']);
}
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* @param string contents of package.xml file, version 1.0
* @return bool success of parsing
*/
function &parse($data, $file, $archive = false)
{
if (!extension_loaded('xml')) {
return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
}
$xp = xml_parser_create();
if (!$xp) {
$a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
return $a;
}
xml_set_object($xp, $this);
xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
$this->element_stack = array();
$this->_packageInfo = array('provides' => array());
$this->current_element = false;
unset($this->dir_install);
$this->_packageInfo['filelist'] = array();
$this->filelist =& $this->_packageInfo['filelist'];
$this->dir_names = array();
$this->in_changelog = false;
$this->d_i = 0;
$this->cdata = '';
$this->_isValid = true;
if (!xml_parse($xp, $data, 1)) {
$code = xml_get_error_code($xp);
$line = xml_get_current_line_number($xp);
xml_parser_free($xp);
$a = PEAR::raiseError(sprintf("XML error: %s at line %d",
$str = xml_error_string($code), $line), 2);
return $a;
}
xml_parser_free($xp);
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->_config);
if (isset($this->_logger)) {
$pf->setLogger($this->_logger);
}
$pf->setPackagefile($file, $archive);
$pf->fromArray($this->_packageInfo);
return $pf;
}
// {{{ _unIndent()
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
} elseif (trim(substr($line, 0, $indent_len))) {
$data .= ltrim($line);
}
}
return $data;
}
// Support for package DTD v1.0:
// {{{ _element_start_1_0()
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_start_1_0($xp, $name, $attribs)
{
array_push($this->element_stack, $name);
$this->current_element = $name;
$spos = sizeof($this->element_stack) - 2;
$this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
$this->current_attributes = $attribs;
$this->cdata = '';
switch ($name) {
case 'dir':
if ($this->in_changelog) {
break;
}
if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
$attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
$attribs['name'] = substr($attribs['name'], 0,
strlen($attribs['name']) - 1);
}
if (strpos($attribs['name'], '/') === 0) {
$attribs['name'] = substr($attribs['name'], 1);
}
$this->dir_names[] = $attribs['name'];
}
if (isset($attribs['baseinstalldir'])) {
$this->dir_install = $attribs['baseinstalldir'];
}
if (isset($attribs['role'])) {
$this->dir_role = $attribs['role'];
}
break;
case 'file':
if ($this->in_changelog) {
break;
}
if (isset($attribs['name'])) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
unset($attribs['name']);
$this->current_path = $path;
$this->filelist[$path] = $attribs;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'replace':
if (!$this->in_changelog) {
$this->filelist[$this->current_path]['replacements'][] = $attribs;
}
break;
case 'maintainers':
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0; // maintainers array index
break;
case 'maintainer':
// compatibility check
if (!isset($this->_packageInfo['maintainers'])) {
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0;
}
$this->_packageInfo['maintainers'][$this->m_i] = array();
$this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
break;
case 'changelog':
$this->_packageInfo['changelog'] = array();
$this->c_i = 0; // changelog array index
$this->in_changelog = true;
break;
case 'release':
if ($this->in_changelog) {
$this->_packageInfo['changelog'][$this->c_i] = array();
$this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
} else {
$this->current_release = &$this->_packageInfo;
}
break;
case 'deps':
if (!$this->in_changelog) {
$this->_packageInfo['release_deps'] = array();
}
break;
case 'dep':
// dependencies array index
if (!$this->in_changelog) {
$this->d_i++;
isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
$this->_packageInfo['release_deps'][$this->d_i] = $attribs;
}
break;
case 'configureoptions':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'] = array();
}
break;
case 'configureoption':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'][] = $attribs;
}
break;
case 'provides':
if (empty($attribs['type']) || empty($attribs['name'])) {
break;
}
$attribs['explicit'] = true;
$this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
break;
case 'package' :
if (isset($attribs['version'])) {
$this->_packageInfo['xsdversion'] = trim($attribs['version']);
} else {
$this->_packageInfo['xsdversion'] = '1.0';
}
if (isset($attribs['packagerversion'])) {
$this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
}
break;
}
}
// }}}
// {{{ _element_end_1_0()
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_end_1_0($xp, $name)
{
$data = trim($this->cdata);
switch ($name) {
case 'name':
switch ($this->prev_element) {
case 'package':
$this->_packageInfo['package'] = $data;
break;
case 'maintainer':
$this->current_maintainer['name'] = $data;
break;
}
break;
case 'extends' :
$this->_packageInfo['extends'] = $data;
break;
case 'summary':
$this->_packageInfo['summary'] = $data;
break;
case 'description':
$data = $this->_unIndent($this->cdata);
$this->_packageInfo['description'] = $data;
break;
case 'user':
$this->current_maintainer['handle'] = $data;
break;
case 'email':
$this->current_maintainer['email'] = $data;
break;
case 'role':
$this->current_maintainer['role'] = $data;
break;
case 'version':
if ($this->in_changelog) {
$this->current_release['version'] = $data;
} else {
$this->_packageInfo['version'] = $data;
}
break;
case 'date':
if ($this->in_changelog) {
$this->current_release['release_date'] = $data;
} else {
$this->_packageInfo['release_date'] = $data;
}
break;
case 'notes':
// try to "de-indent" release notes in case someone
// has been over-indenting their xml ;-)
// Trim only on the right side
$data = rtrim($this->_unIndent($this->cdata));
if ($this->in_changelog) {
$this->current_release['release_notes'] = $data;
} else {
$this->_packageInfo['release_notes'] = $data;
}
break;
case 'warnings':
if ($this->in_changelog) {
$this->current_release['release_warnings'] = $data;
} else {
$this->_packageInfo['release_warnings'] = $data;
}
break;
case 'state':
if ($this->in_changelog) {
$this->current_release['release_state'] = $data;
} else {
$this->_packageInfo['release_state'] = $data;
}
break;
case 'license':
if ($this->in_changelog) {
$this->current_release['release_license'] = $data;
} else {
$this->_packageInfo['release_license'] = $data;
}
break;
case 'dep':
if ($data && !$this->in_changelog) {
$this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
}
break;
case 'dir':
if ($this->in_changelog) {
break;
}
array_pop($this->dir_names);
break;
case 'file':
if ($this->in_changelog) {
break;
}
if ($data) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= $data;
$this->filelist[$path] = $this->current_attributes;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'maintainer':
if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
$this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
}
$this->m_i++;
break;
case 'release':
if ($this->in_changelog) {
$this->c_i++;
}
break;
case 'changelog':
$this->in_changelog = false;
break;
}
array_pop($this->element_stack);
$spos = sizeof($this->element_stack) - 1;
$this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
$this->cdata = '';
}
// }}}
// {{{ _pkginfo_cdata_1_0()
/**
* XML parser callback for character data. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name character data
*
* @return void
*
* @access private
*/
function _pkginfo_cdata_1_0($xp, $data)
{
if (isset($this->cdata)) {
$this->cdata .= $data;
}
}
// }}}
}
?>

View File

@@ -1,112 +0,0 @@
<?php
/**
* package.xml parsing class, package.xml version 2.0
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base xml parser class
*/
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/PackageFile/v2.php';
/**
* Parser for package.xml version 2.0
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
{
var $_config;
var $_logger;
var $_registry;
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
} else {
$data .= $line . "\n";
}
}
return $data;
}
/**
* post-process data
*
* @param string $data
* @param string $element element name
*/
function postProcess($data, $element)
{
if ($element == 'notes') {
return trim($this->_unIndent($data));
}
return trim($data);
}
/**
* @param string
* @param string file name of the package.xml
* @param string|false name of the archive this package.xml came from, if any
* @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or
* a subclass
* @return PEAR_PackageFile_v2
*/
function parse($data, $file = null, $archive = false, $class = 'PEAR_PackageFile_v2')
{
if (PEAR::isError($err = parent::parse($data))) {
return $err;
}
$ret = new $class;
$ret->encoding = $this->encoding;
$ret->setConfig($this->_config);
if (isset($this->_logger)) {
$ret->setLogger($this->_logger);
}
$ret->fromArray($this->_unserializedData);
$ret->setPackagefile($file, $archive);
return $ret;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,200 +0,0 @@
<?php
/**
* PEAR_Packager for generating releases
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
require_once 'System.php';
/**
* Administration class used to make a PEAR release tarball.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Packager extends PEAR_Common
{
/**
* @var PEAR_Registry
*/
var $_registry;
function package($pkgfile = null, $compress = true, $pkg2 = null)
{
// {{{ validate supplied package.xml file
if (empty($pkgfile)) {
$pkgfile = 'package.xml';
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$pkg = new PEAR_PackageFile($this->config, $this->debug);
$pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
$main = &$pf;
PEAR::staticPopErrorHandling();
if (PEAR::isError($pf)) {
if (is_array($pf->getUserInfo())) {
foreach ($pf->getUserInfo() as $error) {
$this->log(0, 'Error: ' . $error['message']);
}
}
$this->log(0, $pf->getMessage());
return $this->raiseError("Cannot package, errors in package file");
}
foreach ($pf->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
// }}}
if ($pkg2) {
$this->log(0, 'Attempting to process the second package file');
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
PEAR::staticPopErrorHandling();
if (PEAR::isError($pf2)) {
if (is_array($pf2->getUserInfo())) {
foreach ($pf2->getUserInfo() as $error) {
$this->log(0, 'Error: ' . $error['message']);
}
}
$this->log(0, $pf2->getMessage());
return $this->raiseError("Cannot package, errors in second package file");
}
foreach ($pf2->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
if ($pf2->getPackagexmlVersion() == '2.0' ||
$pf2->getPackagexmlVersion() == '2.1'
) {
$main = &$pf2;
$other = &$pf;
} else {
$main = &$pf;
$other = &$pf2;
}
if ($main->getPackagexmlVersion() != '2.0' &&
$main->getPackagexmlVersion() != '2.1') {
return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
'only package together a package.xml 1.0 and package.xml 2.0');
}
if ($other->getPackagexmlVersion() != '1.0') {
return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
'only package together a package.xml 1.0 and package.xml 2.0');
}
}
$main->setLogger($this);
if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
foreach ($main->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
return $this->raiseError("Cannot package, errors in package");
}
foreach ($main->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
if ($pkg2) {
$other->setLogger($this);
$a = false;
if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
foreach ($other->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
foreach ($main->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
if ($a) {
return $this->raiseError('The two package.xml files are not equivalent!');
}
return $this->raiseError("Cannot package, errors in package");
}
foreach ($other->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
$gen = &$main->getDefaultGenerator();
$tgzfile = $gen->toTgz2($this, $other, $compress);
if (PEAR::isError($tgzfile)) {
return $tgzfile;
}
$dest_package = basename($tgzfile);
$pkgdir = dirname($pkgfile);
// TAR the Package -------------------------------------------
$this->log(1, "Package $dest_package done");
if (file_exists("$pkgdir/CVS/Root")) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
$cvstag = "RELEASE_$cvsversion";
$this->log(1, 'Tag the released code with "pear cvstag ' .
$main->getPackageFile() . '"');
$this->log(1, "(or set the CVS tag $cvstag by hand)");
} elseif (file_exists("$pkgdir/.svn")) {
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
$svntag = $pf->getName() . "-$svnversion";
$this->log(1, 'Tag the released code with "pear svntag ' .
$main->getPackageFile() . '"');
$this->log(1, "(or set the SVN tag $svntag by hand)");
}
} else { // this branch is executed for single packagefile packaging
$gen = &$pf->getDefaultGenerator();
$tgzfile = $gen->toTgz($this, $compress);
if (PEAR::isError($tgzfile)) {
$this->log(0, $tgzfile->getMessage());
return $this->raiseError("Cannot package, errors in package");
}
$dest_package = basename($tgzfile);
$pkgdir = dirname($pkgfile);
// TAR the Package -------------------------------------------
$this->log(1, "Package $dest_package done");
if (file_exists("$pkgdir/CVS/Root")) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
$cvstag = "RELEASE_$cvsversion";
$this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
$this->log(1, "(or set the CVS tag $cvstag by hand)");
} elseif (file_exists("$pkgdir/.svn")) {
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
$svntag = $pf->getName() . "-$svnversion";
$this->log(1, "Tag the released code with `pear svntag $pkgfile'");
$this->log(1, "(or set the SVN tag $svntag by hand)");
}
}
return $dest_package;
}
}

View File

@@ -1,191 +0,0 @@
<?php
/**
* PEAR_Proxy
*
* HTTP Proxy handling
*
* @category pear
* @package PEAR
* @author Nico Boehr
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
*/
class PEAR_Proxy
{
var $config = null;
/**
* @access private
*/
var $proxy_host;
/**
* @access private
*/
var $proxy_port;
/**
* @access private
*/
var $proxy_user;
/**
* @access private
*/
var $proxy_pass;
/**
* @access private
*/
var $proxy_schema;
function __construct($config = null)
{
$this->config = $config;
$this->_parseProxyInfo();
}
/**
* @access private
*/
function _parseProxyInfo()
{
$this->proxy_host = $this->proxy_port = $this->proxy_user = $this->proxy_pass = '';
if ($this->config->get('http_proxy')&&
$proxy = parse_url($this->config->get('http_proxy'))
) {
$this->proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
$this->proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
$this->proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
$this->proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
$this->proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
}
}
/**
* @access private
*/
function _httpConnect($fp, $host, $port)
{
fwrite($fp, "CONNECT $host:$port HTTP/1.1\r\n");
fwrite($fp, "Host: $host:$port\r\n");
if ($this->getProxyAuth()) {
fwrite($fp, 'Proxy-Authorization: Basic ' . $this->getProxyAuth() . "\r\n");
}
fwrite($fp, "\r\n");
while ($line = trim(fgets($fp, 1024))) {
if (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
$code = (int)$matches[1];
/* as per RFC 2817 */
if ($code < 200 || $code >= 300) {
return PEAR::raiseError("Establishing a CONNECT tunnel through proxy failed with response code $code");
}
}
}
// connection was successful -- establish SSL through
// the tunnel
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
// set the correct hostname for working hostname
// verification
stream_context_set_option($fp, 'ssl', 'peer_name', $host);
// blocking socket needed for
// stream_socket_enable_crypto()
// see
// <http://php.net/manual/en/function.stream-socket-enable-crypto.php>
stream_set_blocking ($fp, true);
$crypto_res = stream_socket_enable_crypto($fp, true, $crypto_method);
if (!$crypto_res) {
return PEAR::raiseError("Could not establish SSL connection through proxy $proxy_host:$proxy_port: $crypto_res");
}
return true;
}
/**
* get the authorization information for the proxy, encoded to be
* passed in the Proxy-Authentication HTTP header.
* @return null|string the encoded authentication information if a
* proxy and authentication is configured, null
* otherwise.
*/
function getProxyAuth()
{
if ($this->isProxyConfigured() && $this->proxy_user != '') {
return base64_encode($this->proxy_user . ':' . $this->proxy_pass);
}
return null;
}
function getProxyUser()
{
return $this->proxy_user;
}
/**
* Check if we are configured to use a proxy.
*
* @return boolean true if we are configured to use a proxy, false
* otherwise.
* @access public
*/
function isProxyConfigured()
{
return $this->proxy_host != '';
}
/**
* Open a socket to a remote server, possibly involving a HTTP
* proxy.
*
* If an HTTP proxy has been configured (http_proxy PEAR_Config
* setting), the proxy will be used.
*
* @param string $host the host to connect to
* @param string $port the port to connect to
* @param boolean $secure if true, establish a secure connection
* using TLS.
* @access public
*/
function openSocket($host, $port, $secure = false)
{
if ($this->isProxyConfigured()) {
$fp = @fsockopen(
$this->proxy_host, $this->proxy_port,
$errno, $errstr, 15
);
if (!$fp) {
return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276);
}
/* HTTPS is to be used and we have a proxy, use CONNECT verb */
if ($secure) {
$res = $this->_httpConnect($fp, $host, $port);
if (PEAR::isError($res)) {
return $res;
}
}
} else {
if ($secure) {
$host = 'ssl://' . $host;
}
$fp = @fsockopen($host, $port, $errno, $errstr);
if (!$fp) {
return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
}
}
return $fp;
}
}

View File

@@ -1,474 +0,0 @@
<?php
/**
* PEAR_REST
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* For downloading xml files
*/
require_once 'PEAR.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Proxy.php';
/**
* Intelligently retrieve data, following hyperlinks if necessary, and re-directing
* as well
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_REST
{
var $config;
var $_options;
function __construct(&$config, $options = array())
{
$this->config = &$config;
$this->_options = $options;
}
/**
* Retrieve REST data, but always retrieve the local cache if it is available.
*
* This is useful for elements that should never change, such as information on a particular
* release
* @param string full URL to this resource
* @param array|false contents of the accept-encoding header
* @param boolean if true, xml will be returned as a string, otherwise, xml will be
* parsed using PEAR_XMLParser
* @return string|array
*/
function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
{
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cachefile';
if (file_exists($cachefile)) {
return unserialize(implode('', file($cachefile)));
}
return $this->retrieveData($url, $accept, $forcestring, $channel);
}
/**
* Retrieve a remote REST resource
* @param string full URL to this resource
* @param array|false contents of the accept-encoding header
* @param boolean if true, xml will be returned as a string, otherwise, xml will be
* parsed using PEAR_XMLParser
* @return string|array
*/
function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
{
$cacheId = $this->getCacheId($url);
if ($ret = $this->useLocalCache($url, $cacheId)) {
return $ret;
}
$file = $trieddownload = false;
if (!isset($this->_options['offline'])) {
$trieddownload = true;
$file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
}
if (PEAR::isError($file)) {
if ($file->getCode() !== -9276) {
return $file;
}
$trieddownload = false;
$file = false; // use local copy if available on socket connect error
}
if (!$file) {
$ret = $this->getCache($url);
if (!PEAR::isError($ret) && $trieddownload) {
// reset the age of the cache if the server says it was unmodified
$result = $this->saveCache($url, $ret, null, true, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
}
return $ret;
}
if (is_array($file)) {
$headers = $file[2];
$lastmodified = $file[1];
$content = $file[0];
} else {
$headers = array();
$lastmodified = false;
$content = $file;
}
if ($forcestring) {
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
return $content;
}
if (isset($headers['content-type'])) {
$content_type = explode(";", $headers['content-type']);
$content_type = $content_type[0];
switch ($content_type) {
case 'text/xml' :
case 'application/xml' :
case 'text/plain' :
if ($content_type === 'text/plain') {
$check = substr($content, 0, 5);
if ($check !== '<?xml') {
break;
}
}
$parser = new PEAR_XMLParser;
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$err = $parser->parse($content);
PEAR::popErrorHandling();
if (PEAR::isError($err)) {
return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
$err->getMessage());
}
$content = $parser->getData();
case 'text/html' :
default :
// use it as a string
}
} else {
// assume XML
$parser = new PEAR_XMLParser;
$parser->parse($content);
$content = $parser->getData();
}
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
return $content;
}
function useLocalCache($url, $cacheid = null)
{
if (!is_array($cacheid)) {
$cacheid = $this->getCacheId($url);
}
$cachettl = $this->config->get('cache_ttl');
// If cache is newer than $cachettl seconds, we use the cache!
if (is_array($cacheid) && time() - $cacheid['age'] < $cachettl) {
return $this->getCache($url);
}
return false;
}
/**
* @param string $url
*
* @return bool|mixed
*/
function getCacheId($url)
{
$cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cacheid';
if (!file_exists($cacheidfile)) {
return false;
}
$ret = unserialize(implode('', file($cacheidfile)));
return $ret;
}
function getCache($url)
{
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cachefile';
if (!file_exists($cachefile)) {
return PEAR::raiseError('No cached content available for "' . $url . '"');
}
return unserialize(implode('', file($cachefile)));
}
/**
* @param string full URL to REST resource
* @param string original contents of the REST resource
* @param array HTTP Last-Modified and ETag headers
* @param bool if true, then the cache id file should be regenerated to
* trigger a new time-to-live value
*/
function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
{
$cache_dir = $this->config->get('cache_dir');
$d = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
$cacheidfile = $d . 'rest.cacheid';
$cachefile = $d . 'rest.cachefile';
if (!is_dir($cache_dir)) {
if (System::mkdir(array('-p', $cache_dir)) === false) {
return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
}
}
if (!is_writeable($cache_dir)) {
// If writing to the cache dir is not going to work, silently do nothing.
// An ugly hack, but retains compat with PEAR 1.9.1 where many commands
// work fine as non-root user (w/out write access to default cache dir).
return true;
}
if ($cacheid === null && $nochange) {
$cacheid = unserialize(implode('', file($cacheidfile)));
}
$idData = serialize(array(
'age' => time(),
'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
));
$result = $this->saveCacheFile($cacheidfile, $idData);
if (PEAR::isError($result)) {
return $result;
} elseif ($nochange) {
return true;
}
$result = $this->saveCacheFile($cachefile, serialize($contents));
if (PEAR::isError($result)) {
if (file_exists($cacheidfile)) {
@unlink($cacheidfile);
}
return $result;
}
return true;
}
function saveCacheFile($file, $contents)
{
$len = strlen($contents);
$cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
if ($cachefile_fp !== false) { // create file
if (fwrite($cachefile_fp, $contents, $len) < $len) {
fclose($cachefile_fp);
return PEAR::raiseError("Could not write $file.");
}
} else { // update file
$cachefile_fp = @fopen($file, 'r+b'); // do not truncate file
if (!$cachefile_fp) {
return PEAR::raiseError("Could not open $file for writing.");
}
if (OS_WINDOWS) {
$not_symlink = !is_link($file); // see bug #18834
} else {
$cachefile_lstat = lstat($file);
$cachefile_fstat = fstat($cachefile_fp);
$not_symlink = $cachefile_lstat['mode'] == $cachefile_fstat['mode']
&& $cachefile_lstat['ino'] == $cachefile_fstat['ino']
&& $cachefile_lstat['dev'] == $cachefile_fstat['dev']
&& $cachefile_fstat['nlink'] === 1;
}
if ($not_symlink) {
ftruncate($cachefile_fp, 0); // NOW truncate
if (fwrite($cachefile_fp, $contents, $len) < $len) {
fclose($cachefile_fp);
return PEAR::raiseError("Could not write $file.");
}
} else {
fclose($cachefile_fp);
$link = function_exists('readlink') ? readlink($file) : $file;
return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
}
}
fclose($cachefile_fp);
return true;
}
/**
* Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory
* This is best used for small files
*
* If an HTTP proxy has been configured (http_proxy PEAR_Config
* setting), the proxy will be used.
*
* @param string $url the URL to download
* @param string $save_dir directory to save file in
* @param false|string|array $lastmodified header values to check against for caching
* use false to return the header values from this download
* @param false|array $accept Accept headers to send
* @return string|array Returns the contents of the downloaded file or a PEAR
* error on failure. If the error is caused by
* socket-related errors, the error object will
* have the fsockopen error code available through
* getCode(). If caching is requested, then return the header
* values.
*
* @access public
*/
function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
{
static $redirect = 0;
// always reset , so we are clean case of error
$wasredirect = $redirect;
$redirect = 0;
$info = parse_url($url);
if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
}
if (!isset($info['host'])) {
return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
}
$host = isset($info['host']) ? $info['host'] : null;
$port = isset($info['port']) ? $info['port'] : null;
$path = isset($info['path']) ? $info['path'] : null;
$schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
$proxy = new PEAR_Proxy($this->config);
if (empty($port)) {
$port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
}
if ($proxy->isProxyConfigured() && $schema === 'http') {
$request = "GET $url HTTP/1.1\r\n";
} else {
$request = "GET $path HTTP/1.1\r\n";
}
$request .= "Host: $host\r\n";
$ifmodifiedsince = '';
if (is_array($lastmodified)) {
if (isset($lastmodified['Last-Modified'])) {
$ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
}
if (isset($lastmodified['ETag'])) {
$ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
}
} else {
$ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
}
$request .= $ifmodifiedsince .
"User-Agent: PEAR/1.10.13/PHP/" . PHP_VERSION . "\r\n";
$username = $this->config->get('username', null, $channel);
$password = $this->config->get('password', null, $channel);
if ($username && $password) {
$tmp = base64_encode("$username:$password");
$request .= "Authorization: Basic $tmp\r\n";
}
$proxyAuth = $proxy->getProxyAuth();
if ($proxyAuth) {
$request .= 'Proxy-Authorization: Basic ' .
$proxyAuth . "\r\n";
}
if ($accept) {
$request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
}
$request .= "Accept-Encoding:\r\n";
$request .= "Connection: close\r\n";
$request .= "\r\n";
$secure = ($schema == 'https');
$fp = $proxy->openSocket($host, $port, $secure);
if (PEAR::isError($fp)) {
return $fp;
}
fwrite($fp, $request);
$headers = array();
$reply = 0;
while ($line = trim(fgets($fp, 1024))) {
if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
$headers[strtolower($matches[1])] = trim($matches[2]);
} elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
$reply = (int)$matches[1];
if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
return false;
}
if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
}
}
}
if ($reply != 200) {
if (!isset($headers['location'])) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
}
if ($wasredirect > 4) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
}
$redirect = $wasredirect + 1;
return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
}
$length = isset($headers['content-length']) ? $headers['content-length'] : -1;
$data = '';
while ($chunk = @fread($fp, 8192)) {
$data .= $chunk;
}
fclose($fp);
if ($lastmodified === false || $lastmodified) {
if (isset($headers['etag'])) {
$lastmodified = array('ETag' => $headers['etag']);
}
if (isset($headers['last-modified'])) {
if (is_array($lastmodified)) {
$lastmodified['Last-Modified'] = $headers['last-modified'];
} else {
$lastmodified = $headers['last-modified'];
}
}
return array($data, $lastmodified, $headers);
}
return $data;
}
}

View File

@@ -1,870 +0,0 @@
<?php
/**
* PEAR_REST_10
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a12
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
/**
* Implement REST 1.0
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a12
*/
class PEAR_REST_10
{
/**
* @var PEAR_REST
*/
var $_rest;
function __construct($config, $options = array())
{
$this->_rest = new PEAR_REST($config, $options);
}
/**
* Retrieve information about a remote package to be downloaded from a REST server
*
* @param string $base The uri to prepend to all REST calls
* @param array $packageinfo an array of format:
* <pre>
* array(
* 'package' => 'packagename',
* 'channel' => 'channelname',
* ['state' => 'alpha' (or valid state),]
* -or-
* ['version' => '1.whatever']
* </pre>
* @param string $prefstate Current preferred_state config variable value
* @param bool $installed the installed version of this package to compare against
* @return array|false|PEAR_Error see {@link _returnDownloadURL()}
*/
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $packageinfo['channel'];
$package = $packageinfo['package'];
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null;
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('No releases available for package "' .
$channel . '/' . $package . '"');
}
if (!isset($info['r'])) {
return false;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (isset($state)) {
// try our preferred state first
if ($release['s'] == $state) {
$found = true;
break;
}
// see if there is something newer and more stable
// bug #7221
if (in_array($release['s'], $this->betterStates($state), true)) {
$found = true;
break;
}
} elseif (isset($version)) {
if ($release['v'] == $version) {
$found = true;
break;
}
} else {
if (in_array($release['s'], $states)) {
$found = true;
break;
}
}
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
}
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
$prefstate = 'stable', $installed = false, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $dependency['channel'];
$package = $dependency['name'];
$state = isset($dependency['state']) ? $dependency['state'] : null;
$version = isset($dependency['version']) ? $dependency['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
. '" dependency "' . $channel . '/' . $package . '" has no releases');
}
if (!is_array($info) || !isset($info['r'])) {
return false;
}
$exclude = array();
$min = $max = $recommended = false;
if ($xsdversion == '1.0') {
switch ($dependency['rel']) {
case 'ge' :
$min = $dependency['version'];
break;
case 'gt' :
$min = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'eq' :
$recommended = $dependency['version'];
break;
case 'lt' :
$max = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'le' :
$max = $dependency['version'];
break;
case 'ne' :
$exclude = array($dependency['version']);
break;
}
} else {
$min = isset($dependency['min']) ? $dependency['min'] : false;
$max = isset($dependency['max']) ? $dependency['max'] : false;
$recommended = isset($dependency['recommended']) ?
$dependency['recommended'] : false;
if (isset($dependency['exclude'])) {
if (!isset($dependency['exclude'][0])) {
$exclude = array($dependency['exclude']);
}
}
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (in_array($release['v'], $exclude)) { // skip excluded versions
continue;
}
// allow newer releases to say "I'm OK with the dependent package"
if ($xsdversion == '2.0' && isset($release['co'])) {
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
if (isset($entry['x']) && !is_array($entry['x'])) {
$entry['x'] = array($entry['x']);
} elseif (!isset($entry['x'])) {
$entry['x'] = array();
}
if ($entry['c'] == $deppackage['channel'] &&
strtolower($entry['p']) == strtolower($deppackage['package']) &&
version_compare($deppackage['version'], $entry['min'], '>=') &&
version_compare($deppackage['version'], $entry['max'], '<=') &&
!in_array($release['v'], $entry['x'])) {
$recommended = $release['v'];
break;
}
}
}
if ($recommended) {
if ($release['v'] != $recommended) { // if we want a specific
// version, then skip all others
continue;
} else {
if (!in_array($release['s'], $states)) {
// the stability is too low, but we must return the
// recommended version if possible
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
}
}
}
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
continue;
}
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
continue;
}
if ($installed && version_compare($release['v'], $installed, '<')) {
continue;
}
if (in_array($release['s'], $states)) { // if in the preferred state...
$found = true; // ... then use it
break;
}
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
}
/**
* Take raw data and return the array needed for processing a download URL
*
* @param string $base REST base uri
* @param string $package Package name
* @param array $release an array of format array('v' => version, 's' => state)
* describing the release to download
* @param array $info list of all releases as defined by allreleases.xml
* @param bool|null $found determines whether the release was found or this is the next
* best alternative. If null, then versions were skipped because
* of PHP dependency
* @return array|PEAR_Error
* @access private
*/
function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
{
if (!$found) {
$release = $info['r'][0];
}
$packageLower = strtolower($package);
$pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
'info.xml', false, false, $channel);
if (PEAR::isError($pinfo)) {
return PEAR::raiseError('Package "' . $package .
'" does not have REST info xml available');
}
$releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($releaseinfo)) {
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
'" does not have REST xml available');
}
$packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
'deps.' . $release['v'] . '.txt', false, true, $channel);
if (PEAR::isError($packagexml)) {
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
'" does not have REST dependency information available');
}
$packagexml = unserialize($packagexml);
if (!$packagexml) {
$packagexml = array();
}
$allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
'/allreleases.xml', false, false, $channel);
if (PEAR::isError($allinfo)) {
return $allinfo;
}
if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
$allinfo['r'] = array($allinfo['r']);
}
$compatible = false;
foreach ($allinfo['r'] as $release) {
if ($release['v'] != $releaseinfo['v']) {
continue;
}
if (!isset($release['co'])) {
break;
}
$compatible = array();
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
$comp = array();
$comp['name'] = $entry['p'];
$comp['channel'] = $entry['c'];
$comp['min'] = $entry['min'];
$comp['max'] = $entry['max'];
if (isset($entry['x']) && !is_array($entry['x'])) {
$comp['exclude'] = $entry['x'];
}
$compatible[] = $comp;
}
if (count($compatible) == 1) {
$compatible = $compatible[0];
}
break;
}
$deprecated = false;
if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
if (is_array($pinfo['dp'])) {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']['_content']));
} else {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']));
}
}
$return = array(
'version' => $releaseinfo['v'],
'info' => $packagexml,
'package' => $releaseinfo['p']['_content'],
'stability' => $releaseinfo['st'],
'compatible' => $compatible,
'deprecated' => $deprecated,
);
if ($found) {
$return['url'] = $releaseinfo['g'];
return $return;
}
$return['php'] = $phpversion;
return $return;
}
function listPackages($base, $channel = false)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
return $packagelist['p'];
}
/**
* List all categories of a REST server
*
* @param string $base base URL of the server
* @return array of categorynames
*/
function listCategories($base, $channel = false)
{
$categories = array();
// c/categories.xml does not exist;
// check for every package its category manually
// This is SLOOOWWWW : ///
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
$ret = array();
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($packagelist['p'] as $package) {
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($inf)) {
PEAR::popErrorHandling();
return $inf;
}
$cat = $inf['ca']['_content'];
if (!isset($categories[$cat])) {
$categories[$cat] = $inf['ca'];
}
}
return array_values($categories);
}
/**
* List a category of a REST server
*
* @param string $base base URL of the server
* @param string $category name of the category
* @param boolean $info also download full package info
* @return array of packagenames
*/
function listCategory($base, $category, $info = false, $channel = false)
{
// gives '404 Not Found' error when category doesn't exist
$packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p']) ||
!isset($packagelist['p'][0])) { // only 1 pkg
$packagelist = array($packagelist['p']);
} else {
$packagelist = $packagelist['p'];
}
if ($info == true) {
// get individual package info
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($packagelist as $i => $packageitem) {
$url = sprintf('%s'.'r/%s/latest.txt',
$base,
strtolower($packageitem['_content']));
$version = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($version)) {
break; // skipit
}
$url = sprintf('%s'.'r/%s/%s.xml',
$base,
strtolower($packageitem['_content']),
$version);
$info = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($info)) {
break; // skipit
}
$packagelist[$i]['info'] = $info;
}
PEAR::popErrorHandling();
}
return $packagelist;
}
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if ($this->_rest->config->get('verbose') > 0) {
$ui = &PEAR_Frontend::singleton();
$ui->log('Retrieving data...0%', true);
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
// only search-packagename = quicksearch !
if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
$newpackagelist = array();
foreach ($packagelist['p'] as $package) {
if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
$newpackagelist[] = $package;
}
}
$packagelist['p'] = $newpackagelist;
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$next = .1;
foreach ($packagelist['p'] as $progress => $package) {
if ($this->_rest->config->get('verbose') > 0) {
if ($progress / count($packagelist['p']) >= $next) {
if ($next == .5) {
$ui->log('50%', false);
} else {
$ui->log('.', false);
}
$next += .1;
}
}
if ($basic) { // remote-list command
if ($dostable) {
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/stable.txt', false, false, $channel);
} else {
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/latest.txt', false, false, $channel);
}
if (PEAR::isError($latest)) {
$latest = false;
}
$info = array('stable' => $latest);
} else { // list-all command
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($inf)) {
PEAR::popErrorHandling();
return $inf;
}
if ($searchpackage) {
$found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
if (!$found && !(isset($searchsummary) && !empty($searchsummary)
&& (stristr($inf['s'], $searchsummary) !== false
|| stristr($inf['d'], $searchsummary) !== false)))
{
continue;
};
}
$releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
if (PEAR::isError($releases)) {
continue;
}
if (!isset($releases['r'][0])) {
$releases['r'] = array($releases['r']);
}
unset($latest);
unset($unstable);
unset($stable);
unset($state);
foreach ($releases['r'] as $release) {
if (!isset($latest)) {
if ($dostable && $release['s'] == 'stable') {
$latest = $release['v'];
$state = 'stable';
}
if (!$dostable) {
$latest = $release['v'];
$state = $release['s'];
}
}
if (!isset($stable) && $release['s'] == 'stable') {
$stable = $release['v'];
if (!isset($unstable)) {
$unstable = $stable;
}
}
if (!isset($unstable) && $release['s'] != 'stable') {
$latest = $unstable = $release['v'];
$state = $release['s'];
}
if (isset($latest) && !isset($state)) {
$state = $release['s'];
}
if (isset($latest) && isset($stable) && isset($unstable)) {
break;
}
}
$deps = array();
if (!isset($unstable)) {
$unstable = false;
$state = 'stable';
if (isset($stable)) {
$latest = $unstable = $stable;
}
} else {
$latest = $unstable;
}
if (!isset($latest)) {
$latest = false;
}
if ($latest) {
$d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
$latest . '.txt', false, false, $channel);
if (!PEAR::isError($d)) {
$d = unserialize($d);
if ($d) {
if (isset($d['required'])) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!isset($pf)) {
$pf = new PEAR_PackageFile_v2;
}
$pf->setDeps($d);
$tdeps = $pf->getDeps();
} else {
$tdeps = $d;
}
foreach ($tdeps as $dep) {
if ($dep['type'] !== 'pkg') {
continue;
}
$deps[] = $dep;
}
}
}
}
if (!isset($stable)) {
$stable = '-n/a-';
}
if (!$searchpackage) {
$info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
'unstable' => $unstable, 'state' => $state);
} else {
$info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
'unstable' => $unstable, 'state' => $state);
}
}
$ret[$package] = $info;
}
PEAR::popErrorHandling();
return $ret;
}
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
foreach ($packagelist['p'] as $package) {
if (!isset($installed[strtolower($package)])) {
continue;
}
$inst_version = $reg->packageInfo($package, 'version', $channel);
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
PEAR::popErrorHandling();
if (PEAR::isError($info)) {
continue; // no remote releases
}
if (!isset($info['r'])) {
continue;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
// $info['r'] is sorted by version number
usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
foreach ($info['r'] as $release) {
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
// not newer than the one installed
break;
}
// new version > installed version
if (!$pref_state) {
// every state is a good state
$found = true;
break;
} else {
$new_state = $release['s'];
// if new state >= installed state: go
if (in_array($new_state, $this->betterStates($inst_state, true))) {
$found = true;
break;
} else {
// only allow to lower the state of package,
// if new state >= preferred state: go
if (in_array($new_state, $this->betterStates($pref_state, true))) {
$found = true;
break;
}
}
}
}
if (!$found) {
continue;
}
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($relinfo)) {
return $relinfo;
}
$ret[$package] = array(
'version' => $release['v'],
'state' => $release['s'],
'filesize' => $relinfo['f'],
);
}
return $ret;
}
function packageInfo($base, $package, $channel = false)
{
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($pinfo)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
$pinfo->getMessage());
}
$releases = array();
$allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
if (!PEAR::isError($allreleases)) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
$allreleases['r'] = array($allreleases['r']);
}
$pf = new PEAR_PackageFile_v2;
foreach ($allreleases['r'] as $release) {
$ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
$release['v'] . '.txt', false, false, $channel);
if (PEAR::isError($ds)) {
continue;
}
if (!isset($latest)) {
$latest = $release['v'];
}
$pf->setDeps(unserialize($ds));
$ds = $pf->getDeps();
$info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
. '/' . $release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($info)) {
continue;
}
$releases[$release['v']] = array(
'doneby' => $info['m'],
'license' => $info['l'],
'summary' => $info['s'],
'description' => $info['d'],
'releasedate' => $info['da'],
'releasenotes' => $info['n'],
'state' => $release['s'],
'deps' => $ds ? $ds : array(),
);
}
} else {
$latest = '';
}
PEAR::popErrorHandling();
if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
if (is_array($pinfo['dp'])) {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']['_content']));
} else {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']));
}
} else {
$deprecated = false;
}
if (!isset($latest)) {
$latest = '';
}
return array(
'name' => $pinfo['n'],
'channel' => $pinfo['c'],
'category' => $pinfo['ca']['_content'],
'stable' => $latest,
'license' => $pinfo['l'],
'summary' => $pinfo['s'],
'description' => $pinfo['d'],
'releases' => $releases,
'deprecated' => $deprecated,
);
}
/**
* Return an array containing all of the states that are more stable than
* or equal to the passed in state
*
* @param string Release state
* @param boolean Determines whether to include $state in the list
* @return false|array False if $state is not a valid release state
*/
function betterStates($state, $include = false)
{
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
$i = array_search($state, $states);
if ($i === false) {
return false;
}
if ($include) {
$i--;
}
return array_slice($states, $i + 1);
}
/**
* Sort releases by version number
*
* @access private
*/
function _sortReleasesByVersionNumber($a, $b)
{
if (version_compare($a['v'], $b['v'], '=')) {
return 0;
}
if (version_compare($a['v'], $b['v'], '>')) {
return -1;
}
if (version_compare($a['v'], $b['v'], '<')) {
return 1;
}
}
}

View File

@@ -1,340 +0,0 @@
<?php
/**
* PEAR_REST_11 - implement faster list-all/remote-list command
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.3
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
/**
* Implement REST 1.1
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.3
*/
class PEAR_REST_11
{
/**
* @var PEAR_REST
*/
var $_rest;
function __construct($config, $options = array())
{
$this->_rest = new PEAR_REST($config, $options);
}
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
{
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
if (PEAR::isError($categorylist)) {
return $categorylist;
}
$ret = array();
if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
$categorylist['c'] = array($categorylist['c']);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($categorylist['c'] as $progress => $category) {
$category = $category['_content'];
$packagesinfo = $this->_rest->retrieveData($base .
'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
if (PEAR::isError($packagesinfo)) {
continue;
}
if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
continue;
}
if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
$packagesinfo['pi'] = array($packagesinfo['pi']);
}
foreach ($packagesinfo['pi'] as $packageinfo) {
if (empty($packageinfo)) {
continue;
}
$info = $packageinfo['p'];
$package = $info['n'];
$releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
unset($latest);
unset($unstable);
unset($stable);
unset($state);
if ($releases) {
if (!isset($releases['r'][0])) {
$releases['r'] = array($releases['r']);
}
foreach ($releases['r'] as $release) {
if (!isset($latest)) {
if ($dostable && $release['s'] == 'stable') {
$latest = $release['v'];
$state = 'stable';
}
if (!$dostable) {
$latest = $release['v'];
$state = $release['s'];
}
}
if (!isset($stable) && $release['s'] == 'stable') {
$stable = $release['v'];
if (!isset($unstable)) {
$unstable = $stable;
}
}
if (!isset($unstable) && $release['s'] != 'stable') {
$unstable = $release['v'];
$state = $release['s'];
}
if (isset($latest) && !isset($state)) {
$state = $release['s'];
}
if (isset($latest) && isset($stable) && isset($unstable)) {
break;
}
}
}
if ($basic) { // remote-list command
if (!isset($latest)) {
$latest = false;
}
if ($dostable) {
// $state is not set if there are no releases
if (isset($state) && $state == 'stable') {
$ret[$package] = array('stable' => $latest);
} else {
$ret[$package] = array('stable' => '-n/a-');
}
} else {
$ret[$package] = array('stable' => $latest);
}
continue;
}
// list-all command
if (!isset($unstable)) {
$unstable = false;
$state = 'stable';
if (isset($stable)) {
$latest = $unstable = $stable;
}
} else {
$latest = $unstable;
}
if (!isset($latest)) {
$latest = false;
}
$deps = array();
if ($latest && isset($packageinfo['deps'])) {
if (!is_array($packageinfo['deps']) ||
!isset($packageinfo['deps'][0])
) {
$packageinfo['deps'] = array($packageinfo['deps']);
}
$d = false;
foreach ($packageinfo['deps'] as $dep) {
if ($dep['v'] == $latest) {
$d = unserialize($dep['d']);
}
}
if ($d) {
if (isset($d['required'])) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!isset($pf)) {
$pf = new PEAR_PackageFile_v2;
}
$pf->setDeps($d);
$tdeps = $pf->getDeps();
} else {
$tdeps = $d;
}
foreach ($tdeps as $dep) {
if ($dep['type'] !== 'pkg') {
continue;
}
$deps[] = $dep;
}
}
}
$info = array(
'stable' => $latest,
'summary' => $info['s'],
'description' => $info['d'],
'deps' => $deps,
'category' => $info['ca']['_content'],
'unstable' => $unstable,
'state' => $state
);
$ret[$package] = $info;
}
}
PEAR::popErrorHandling();
return $ret;
}
/**
* List all categories of a REST server
*
* @param string $base base URL of the server
* @return array of categorynames
*/
function listCategories($base, $channel = false)
{
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
if (PEAR::isError($categorylist)) {
return $categorylist;
}
if (!is_array($categorylist) || !isset($categorylist['c'])) {
return array();
}
if (isset($categorylist['c']['_content'])) {
// only 1 category
$categorylist['c'] = array($categorylist['c']);
}
return $categorylist['c'];
}
/**
* List packages in a category of a REST server
*
* @param string $base base URL of the server
* @param string $category name of the category
* @param boolean $info also download full package info
* @return array of packagenames
*/
function listCategory($base, $category, $info = false, $channel = false)
{
if ($info == false) {
$url = '%s'.'c/%s/packages.xml';
} else {
$url = '%s'.'c/%s/packagesinfo.xml';
}
$url = sprintf($url,
$base,
urlencode($category));
// gives '404 Not Found' error when category doesn't exist
$packagelist = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist)) {
return array();
}
if ($info == false) {
if (!isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p']) ||
!isset($packagelist['p'][0])) { // only 1 pkg
$packagelist = array($packagelist['p']);
} else {
$packagelist = $packagelist['p'];
}
return $packagelist;
}
// info == true
if (!isset($packagelist['pi'])) {
return array();
}
if (!is_array($packagelist['pi']) ||
!isset($packagelist['pi'][0])) { // only 1 pkg
$packagelist_pre = array($packagelist['pi']);
} else {
$packagelist_pre = $packagelist['pi'];
}
$packagelist = array();
foreach ($packagelist_pre as $i => $item) {
// compatibility with r/<latest.txt>.xml
if (isset($item['a']['r'][0])) {
// multiple releases
$item['p']['v'] = $item['a']['r'][0]['v'];
$item['p']['st'] = $item['a']['r'][0]['s'];
} elseif (isset($item['a'])) {
// first and only release
$item['p']['v'] = $item['a']['r']['v'];
$item['p']['st'] = $item['a']['r']['s'];
}
$packagelist[$i] = array('attribs' => $item['p']['r'],
'_content' => $item['p']['n'],
'info' => $item['p']);
}
return $packagelist;
}
/**
* Return an array containing all of the states that are more stable than
* or equal to the passed in state
*
* @param string Release state
* @param boolean Determines whether to include $state in the list
* @return false|array False if $state is not a valid release state
*/
function betterStates($state, $include = false)
{
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
$i = array_search($state, $states);
if ($i === false) {
return false;
}
if ($include) {
$i--;
}
return array_slice($states, $i + 1);
}
}
?>

View File

@@ -1,396 +0,0 @@
<?php
/**
* PEAR_REST_13
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a12
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
require_once 'PEAR/REST/10.php';
/**
* Implement REST 1.3
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a12
*/
class PEAR_REST_13 extends PEAR_REST_10
{
/**
* Retrieve information about a remote package to be downloaded from a REST server
*
* This is smart enough to resolve the minimum PHP version dependency prior to download
* @param string $base The uri to prepend to all REST calls
* @param array $packageinfo an array of format:
* <pre>
* array(
* 'package' => 'packagename',
* 'channel' => 'channelname',
* ['state' => 'alpha' (or valid state),]
* -or-
* ['version' => '1.whatever']
* </pre>
* @param string $prefstate Current preferred_state config variable value
* @param bool $installed the installed version of this package to compare against
* @return array|false|PEAR_Error see {@link _returnDownloadURL()}
*/
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $packageinfo['channel'];
$package = $packageinfo['package'];
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null;
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('No releases available for package "' .
$channel . '/' . $package . '"');
}
if (!isset($info['r'])) {
return false;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
$skippedphp = false;
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (isset($state)) {
// try our preferred state first
if ($release['s'] == $state) {
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
// see if there is something newer and more stable
// bug #7221
if (in_array($release['s'], $this->betterStates($state), true)) {
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
} elseif (isset($version)) {
if ($release['v'] == $version) {
if (!isset($this->_rest->_options['force']) &&
!isset($version) &&
version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
} else {
if (in_array($release['s'], $states)) {
if (version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
}
}
if (!$found && $skippedphp) {
$found = null;
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
}
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
$prefstate = 'stable', $installed = false, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $dependency['channel'];
$package = $dependency['name'];
$state = isset($dependency['state']) ? $dependency['state'] : null;
$version = isset($dependency['version']) ? $dependency['version'] : null;
$restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
. '" dependency "' . $channel . '/' . $package . '" has no releases');
}
if (!is_array($info) || !isset($info['r'])) {
return false;
}
$exclude = array();
$min = $max = $recommended = false;
if ($xsdversion == '1.0') {
$pinfo['package'] = $dependency['name'];
$pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
switch ($dependency['rel']) {
case 'ge' :
$min = $dependency['version'];
break;
case 'gt' :
$min = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'eq' :
$recommended = $dependency['version'];
break;
case 'lt' :
$max = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'le' :
$max = $dependency['version'];
break;
case 'ne' :
$exclude = array($dependency['version']);
break;
}
} else {
$pinfo['package'] = $dependency['name'];
$min = isset($dependency['min']) ? $dependency['min'] : false;
$max = isset($dependency['max']) ? $dependency['max'] : false;
$recommended = isset($dependency['recommended']) ?
$dependency['recommended'] : false;
if (isset($dependency['exclude'])) {
if (!isset($dependency['exclude'][0])) {
$exclude = array($dependency['exclude']);
}
}
}
$skippedphp = $found = $release = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (in_array($release['v'], $exclude)) { // skip excluded versions
continue;
}
// allow newer releases to say "I'm OK with the dependent package"
if ($xsdversion == '2.0' && isset($release['co'])) {
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
if (isset($entry['x']) && !is_array($entry['x'])) {
$entry['x'] = array($entry['x']);
} elseif (!isset($entry['x'])) {
$entry['x'] = array();
}
if ($entry['c'] == $deppackage['channel'] &&
strtolower($entry['p']) == strtolower($deppackage['package']) &&
version_compare($deppackage['version'], $entry['min'], '>=') &&
version_compare($deppackage['version'], $entry['max'], '<=') &&
!in_array($release['v'], $entry['x'])) {
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
$skippedphp = $release;
continue;
}
$recommended = $release['v'];
break;
}
}
}
if ($recommended) {
if ($release['v'] != $recommended) { // if we want a specific
// version, then skip all others
continue;
}
if (!in_array($release['s'], $states)) {
// the stability is too low, but we must return the
// recommended version if possible
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
}
}
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
continue;
}
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
continue;
}
if ($installed && version_compare($release['v'], $installed, '<')) {
continue;
}
if (in_array($release['s'], $states)) { // if in the preferred state...
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true; // ... then use it
break;
}
}
if (!$found && $skippedphp) {
$found = null;
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
}
/**
* List package upgrades but take the PHP version into account.
*/
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
foreach ($packagelist['p'] as $package) {
if (!isset($installed[strtolower($package)])) {
continue;
}
$inst_version = $reg->packageInfo($package, 'version', $channel);
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases2.xml', false, false, $channel);
PEAR::popErrorHandling();
if (PEAR::isError($info)) {
continue; // no remote releases
}
if (!isset($info['r'])) {
continue;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
// $info['r'] is sorted by version number
usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
foreach ($info['r'] as $release) {
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
// not newer than the one installed
break;
}
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
continue;
}
// new version > installed version
if (!$pref_state) {
// every state is a good state
$found = true;
break;
} else {
$new_state = $release['s'];
// if new state >= installed state: go
if (in_array($new_state, $this->betterStates($inst_state, true))) {
$found = true;
break;
} else {
// only allow to lower the state of package,
// if new state >= preferred state: go
if (in_array($new_state, $this->betterStates($pref_state, true))) {
$found = true;
break;
}
}
}
}
if (!$found) {
continue;
}
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($relinfo)) {
return $relinfo;
}
$ret[$package] = array(
'version' => $release['v'],
'state' => $release['s'],
'filesize' => $relinfo['f'],
);
}
return $ret;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,972 +0,0 @@
<?php
/**
* PEAR_RunTest
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.3.3
*/
/**
* for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
define('DETAILED', 1);
putenv("PHP_PEAR_RUNTESTS=1");
/**
* Simplified version of PHP's test suite
*
* Try it with:
*
* $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
*
*
* @category pear
* @package PEAR
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.3.3
*/
class PEAR_RunTest
{
var $_headers = array();
var $_logger;
var $_options;
var $_php;
var $tests_count;
var $xdebug_loaded;
/**
* Saved value of php executable, used to reset $_php when we
* have a test that uses cgi
*
* @var unknown_type
*/
var $_savephp;
var $ini_overwrites = array(
'output_handler=',
'open_basedir=',
'disable_functions=',
'output_buffering=Off',
'display_errors=1',
'log_errors=0',
'html_errors=0',
'report_memleaks=0',
'report_zend_debug=0',
'docref_root=',
'docref_ext=.html',
'error_prepend_string=',
'error_append_string=',
'auto_prepend_file=',
'auto_append_file=',
'xdebug.default_enable=0',
'allow_url_fopen=1',
);
/**
* An object that supports the PEAR_Common->log() signature, or null
* @param PEAR_Common|null
*/
function __construct($logger = null, $options = array())
{
if (!defined('E_DEPRECATED')) {
define('E_DEPRECATED', 0);
}
if (!defined('E_STRICT')) {
define('E_STRICT', 0);
}
$this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
if (is_null($logger)) {
require_once 'PEAR/Common.php';
$logger = new PEAR_Common;
}
$this->_logger = $logger;
$this->_options = $options;
$conf = &PEAR_Config::singleton();
$this->_php = $conf->get('php_bin');
}
/**
* Taken from php-src/run-tests.php
*
* @param string $commandline command name
* @param array $env
* @param string $stdin standard input to pass to the command
* @return unknown
*/
function system_with_timeout($commandline, $env = null, $stdin = null)
{
$data = '';
$proc = proc_open($commandline, array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
), $pipes, null, $env, array('suppress_errors' => true));
if (!$proc) {
return false;
}
if (is_string($stdin)) {
fwrite($pipes[0], $stdin);
}
fclose($pipes[0]);
while (true) {
/* hide errors from interrupted syscalls */
$r = $pipes;
unset($r[0]);
$e = $w = [];
$n = @stream_select($r, $w, $e, 60);
if ($n === 0) {
/* timed out */
$data .= "\n ** ERROR: process timed out **\n";
proc_terminate($proc);
return array(1234567890, $data);
} else if ($n > 0) {
$line = fread($pipes[1], 8192);
if (strlen($line) == 0) {
/* EOF */
break;
}
$data .= $line;
}
}
if (function_exists('proc_get_status')) {
$stat = proc_get_status($proc);
if ($stat['signaled']) {
$data .= "\nTermsig=".$stat['stopsig'];
}
}
$code = proc_close($proc);
if (function_exists('proc_get_status')) {
$code = $stat['exitcode'];
}
return array($code, $data);
}
/**
* Turns a PHP INI string into an array
*
* Turns -d "include_path=/foo/bar" into this:
* array(
* 'include_path' => array(
* 'operator' => '-d',
* 'value' => '/foo/bar',
* )
* )
* Works both with quotes and without
*
* @param string an PHP INI string, -d "include_path=/foo/bar"
* @return array
*/
function iniString2array($ini_string)
{
if (!$ini_string) {
return array();
}
$split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
$key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1];
$value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
// FIXME review if this is really the struct to go with
$array = array($key => array('operator' => $split[0], 'value' => $value));
return $array;
}
function settings2array($settings, $ini_settings)
{
foreach ($settings as $setting) {
if (strpos($setting, '=') !== false) {
$setting = explode('=', $setting, 2);
$name = trim(strtolower($setting[0]));
$value = trim($setting[1]);
$ini_settings[$name] = $value;
}
}
return $ini_settings;
}
function settings2params($ini_settings)
{
$settings = '';
foreach ($ini_settings as $name => $value) {
if (is_array($value)) {
$operator = $value['operator'];
$value = $value['value'];
} else {
$operator = '-d';
}
$value = addslashes($value);
$settings .= " $operator \"$name=$value\"";
}
return $settings;
}
function _preparePhpBin($php, $file, $ini_settings)
{
$file = escapeshellarg($file);
$cmd = $php . $ini_settings . ' -f ' . $file;
return $cmd;
}
function runPHPUnit($file, $ini_settings = '')
{
if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
$file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
} elseif (file_exists($file)) {
$file = realpath($file);
}
$cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
if (isset($this->_logger)) {
$this->_logger->log(2, 'Running command "' . $cmd . '"');
}
$savedir = getcwd(); // in case the test moves us around
chdir(dirname($file));
echo `$cmd`;
chdir($savedir);
return 'PASSED'; // we have no way of knowing this information so assume passing
}
/**
* Runs an individual test case.
*
* @param string The filename of the test
* @param array|string INI settings to be applied to the test run
* @param integer Number what the current running test is of the
* whole test suite being runned.
*
* @return string|object Returns PASSED, WARNED, FAILED depending on how the
* test came out.
* PEAR Error when the tester it self fails
*/
function run($file, $ini_settings = array(), $test_number = 1)
{
$this->_restorePHPBinary();
if (empty($this->_options['cgi'])) {
// try to see if php-cgi is in the path
$res = $this->system_with_timeout('php-cgi -v');
if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
$this->_options['cgi'] = 'php-cgi';
}
}
if (1 < $len = strlen($this->tests_count)) {
$test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
$test_nr = "[$test_number/$this->tests_count] ";
} else {
$test_nr = '';
}
$file = realpath($file);
$section_text = $this->_readFile($file);
if (PEAR::isError($section_text)) {
return $section_text;
}
if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
}
$cwd = getcwd();
$pass_options = '';
if (!empty($this->_options['ini'])) {
$pass_options = $this->_options['ini'];
}
if (is_string($ini_settings)) {
$ini_settings = $this->iniString2array($ini_settings);
}
$ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
if ($section_text['INI']) {
if (strpos($section_text['INI'], '{PWD}') !== false) {
$section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
}
$ini = preg_split( "/[\n\r]+/", $section_text['INI']);
$ini_settings = $this->settings2array($ini, $ini_settings);
}
$ini_settings = $this->settings2params($ini_settings);
$shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
$tested = trim($section_text['TEST']);
$tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
!empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
!empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
if (empty($this->_options['cgi'])) {
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
}
return 'SKIPPED';
}
$this->_savePHPBinary();
$this->_php = $this->_options['cgi'];
}
$temp_dir = realpath(dirname($file));
$main_file_name = basename($file, 'phpt');
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
// unlink old test results
$this->_cleanupOldFiles($file);
// Check if test should be skipped.
$res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
if ($res == 'SKIPPED' || count($res) != 2) {
return $res;
}
$info = $res['info'];
$warn = $res['warn'];
// We've satisfied the preconditions - run the test!
if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
$xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
$text = "\n" . 'function coverage_shutdown() {' .
"\n" . ' $xdebug = var_export(xdebug_get_code_coverage(), true);';
if (!function_exists('file_put_contents')) {
$text .= "\n" . ' $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
"\n" . ' if ($fh !== false) {' .
"\n" . ' fwrite($fh, $xdebug);' .
"\n" . ' fclose($fh);' .
"\n" . ' }';
} else {
$text .= "\n" . ' file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
}
// Workaround for http://pear.php.net/bugs/bug.php?id=17292
$lines = explode("\n", $section_text['FILE']);
$numLines = count($lines);
$namespace = '';
$coverage_shutdown = 'coverage_shutdown';
if (
substr($lines[0], 0, 2) == '<?' ||
substr($lines[0], 0, 5) == '<?php'
) {
unset($lines[0]);
}
for ($i = 0; $i < $numLines; $i++) {
if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
$namespace = substr($lines[$i], 10, -1);
$coverage_shutdown = $namespace . '\\coverage_shutdown';
$namespace = "namespace " . $namespace . ";\n";
unset($lines[$i]);
break;
}
}
$text .= "\n xdebug_stop_code_coverage();" .
"\n" . '} // end coverage_shutdown()' .
"\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
$text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
$this->save_text($temp_file, "<?php\n" . $namespace . $text . "\n" . implode("\n", $lines));
} else {
$this->save_text($temp_file, $section_text['FILE']);
}
$args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
$cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
$cmd.= "$args 2>&1";
if (isset($this->_logger)) {
$this->_logger->log(2, 'Running command "' . $cmd . '"');
}
// Reset environment from any previous test.
$env = $this->_resetEnv($section_text, $temp_file);
$section_text = $this->_processUpload($section_text, $file);
if (PEAR::isError($section_text)) {
return $section_text;
}
if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
$post = trim($section_text['POST_RAW']);
$raw_lines = explode("\n", $post);
$request = '';
$started = false;
foreach ($raw_lines as $i => $line) {
if (empty($env['CONTENT_TYPE']) &&
preg_match('/^Content-Type:(.*)/i', $line, $res)) {
$env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
continue;
}
if ($started) {
$request .= "\n";
}
$started = true;
$request .= $line;
}
$env['CONTENT_LENGTH'] = strlen($request);
$env['REQUEST_METHOD'] = 'POST';
$this->save_text($tmp_post, $request);
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
} elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
$post = trim($section_text['POST']);
$this->save_text($tmp_post, $post);
$content_length = strlen($post);
$env['REQUEST_METHOD'] = 'POST';
$env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
$env['CONTENT_LENGTH'] = $content_length;
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
} else {
$env['REQUEST_METHOD'] = 'GET';
$env['CONTENT_TYPE'] = '';
$env['CONTENT_LENGTH'] = '';
}
if (OS_WINDOWS && isset($section_text['RETURNS'])) {
ob_start();
system($cmd, $return_value);
$out = ob_get_contents();
ob_end_clean();
$section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
$returnfail = ($return_value != $section_text['RETURNS']);
} else {
$returnfail = false;
$stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
$out = $this->system_with_timeout($cmd, $env, $stdin);
$return_value = $out[0];
$out = $out[1];
}
$output = preg_replace('/\r\n/', "\n", trim($out));
if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
@unlink(realpath($tmp_post));
}
chdir($cwd); // in case the test moves us around
/* when using CGI, strip the headers from the output */
$output = $this->_stripHeadersCGI($output);
if (isset($section_text['EXPECTHEADERS'])) {
$testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
$missing = array_diff_assoc($testheaders, $this->_headers);
$changed = '';
foreach ($missing as $header => $value) {
if (isset($this->_headers[$header])) {
$changed .= "-$header: $value\n+$header: ";
$changed .= $this->_headers[$header];
} else {
$changed .= "-$header: $value\n";
}
}
if ($missing) {
// tack on failed headers to output:
$output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
}
}
$this->_testCleanup($section_text, $temp_clean);
// Does the output match what is expected?
do {
if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
if (isset($section_text['EXPECTF'])) {
$wanted = trim($section_text['EXPECTF']);
} else {
$wanted = trim($section_text['EXPECTREGEX']);
}
$wanted_re = preg_replace('/\r\n/', "\n", $wanted);
if (isset($section_text['EXPECTF'])) {
$wanted_re = preg_quote($wanted_re, '/');
// Stick to basics
$wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
$wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
$wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
$wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
$wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
$wanted_re = str_replace("%c", ".", $wanted_re);
// %f allows two points "-.0.0" but that is the best *simple* expression
}
/* DEBUG YOUR REGEX HERE
var_dump($wanted_re);
print(str_repeat('=', 80) . "\n");
var_dump($output);
*/
if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
if (file_exists($temp_file)) {
unlink($temp_file);
}
if (array_key_exists('FAIL', $section_text)) {
break;
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
} else {
if (isset($section_text['EXPECTFILE'])) {
$f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
if (!($fp = @fopen($f, 'rb'))) {
return PEAR::raiseError('--EXPECTFILE-- section file ' .
$f . ' not found');
}
fclose($fp);
$section_text['EXPECT'] = file_get_contents($f);
}
if (isset($section_text['EXPECT'])) {
$wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
} else {
$wanted = '';
}
// compare and leave on success
if (!$returnfail && 0 == strcmp($output, $wanted)) {
if (file_exists($temp_file)) {
unlink($temp_file);
}
if (array_key_exists('FAIL', $section_text)) {
break;
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
}
} while (false);
if (array_key_exists('FAIL', $section_text)) {
// we expect a particular failure
// this is only used for testing PEAR_RunTest
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
$faildiff = $this->generate_diff($wanted, $output, null, $expectf);
$faildiff = preg_replace('/\r/', '', $faildiff);
$wanted = preg_replace('/\r/', '', trim($section_text['FAIL']));
if ($faildiff == $wanted) {
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
unset($section_text['EXPECTF']);
$output = $faildiff;
if (isset($section_text['RETURNS'])) {
return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
$file);
}
}
// Test failed so we need to report details.
$txt = $warn ? 'WARN ' : 'FAIL ';
$this->_logger->log(0, $txt . $test_nr . $tested . $info);
// write .exp
$res = $this->_writeLog($exp_filename, $wanted);
if (PEAR::isError($res)) {
return $res;
}
// write .out
$res = $this->_writeLog($output_filename, $output);
if (PEAR::isError($res)) {
return $res;
}
// write .diff
$returns = isset($section_text['RETURNS']) ?
array(trim($section_text['RETURNS']), $return_value) : null;
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
$data = $this->generate_diff($wanted, $output, $returns, $expectf);
$res = $this->_writeLog($diff_filename, $data);
if (isset($this->_options['showdiff'])) {
$this->_logger->log(0, "========DIFF========");
$this->_logger->log(0, $data);
$this->_logger->log(0, "========DONE========");
}
if (PEAR::isError($res)) {
return $res;
}
// write .log
$data = "
---- EXPECTED OUTPUT
$wanted
---- ACTUAL OUTPUT
$output
---- FAILED
";
if ($returnfail) {
$data .= "
---- EXPECTED RETURN
$section_text[RETURNS]
---- ACTUAL RETURN
$return_value
";
}
$res = $this->_writeLog($log_filename, $data);
if (PEAR::isError($res)) {
return $res;
}
if (isset($this->_options['tapoutput'])) {
$wanted = explode("\n", $wanted);
$wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
$output = explode("\n", $output);
$output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
return array($wanted . $output . 'not ok', ' - ' . $tested);
}
return $warn ? 'WARNED' : 'FAILED';
}
function generate_diff($wanted, $output, $rvalue, $wanted_re)
{
$w = explode("\n", $wanted);
$o = explode("\n", $output);
$wr = explode("\n", $wanted_re);
$w1 = array_diff_assoc($w, $o);
$o1 = array_diff_assoc($o, $w);
$o2 = $w2 = array();
foreach ($w1 as $idx => $val) {
if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
!preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
$w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
}
}
foreach ($o1 as $idx => $val) {
if (!$wanted_re || !isset($wr[$idx]) ||
!preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
$o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
}
}
$diff = array_merge($w2, $o2);
ksort($diff);
$extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
return implode("\r\n", $diff) . $extra;
}
// Write the given text to a temporary file, and return the filename.
function save_text($filename, $text)
{
if (!$fp = fopen($filename, 'w')) {
return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
}
fwrite($fp, $text);
fclose($fp);
if (1 < DETAILED) echo "
FILE $filename {{{
$text
}}}
";
}
function _cleanupOldFiles($file)
{
$temp_dir = realpath(dirname($file));
$mainFileName = basename($file, 'phpt');
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
// unlink old test results
@unlink($diff_filename);
@unlink($log_filename);
@unlink($exp_filename);
@unlink($output_filename);
@unlink($memcheck_filename);
@unlink($temp_file);
@unlink($temp_skipif);
@unlink($tmp_post);
@unlink($temp_clean);
}
function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
{
$info = '';
$warn = false;
if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
$this->save_text($temp_skipif, $section_text['SKIPIF']);
$output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
$output = $output[1];
$loutput = ltrim($output);
unlink($temp_skipif);
if (!strncasecmp('skip', $loutput, 4)) {
$skipreason = "SKIP $tested";
if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
$skipreason .= '(reason: ' . $m[1] . ')';
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, $skipreason);
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' # skip ' . $reason);
}
return 'SKIPPED';
}
if (!strncasecmp('info', $loutput, 4)
&& preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
$info = " (info: $m[1])";
}
if (!strncasecmp('warn', $loutput, 4)
&& preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
$warn = true; /* only if there is a reason */
$info = " (warn: $m[1])";
}
}
return array('warn' => $warn, 'info' => $info);
}
function _stripHeadersCGI($output)
{
$this->headers = array();
if (!empty($this->_options['cgi']) &&
$this->_php == $this->_options['cgi'] &&
preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
$output = isset($match[2]) ? trim($match[2]) : '';
$this->_headers = $this->_processHeaders($match[1]);
}
return $output;
}
/**
* Return an array that can be used with array_diff() to compare headers
*
* @param string $text
*/
function _processHeaders($text)
{
$headers = array();
$rh = preg_split("/[\n\r]+/", $text);
foreach ($rh as $line) {
if (strpos($line, ':')!== false) {
$line = explode(':', $line, 2);
$headers[trim($line[0])] = trim($line[1]);
}
}
return $headers;
}
function _readFile($file)
{
// Load the sections of the test file.
$section_text = array(
'TEST' => '(unnamed test)',
'SKIPIF' => '',
'GET' => '',
'COOKIE' => '',
'POST' => '',
'ARGS' => '',
'INI' => '',
'CLEAN' => '',
);
if (!is_file($file) || !$fp = fopen($file, "r")) {
return PEAR::raiseError("Cannot open test file: $file");
}
$section = '';
while (!feof($fp)) {
$line = fgets($fp);
// Match the beginning of a section.
if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
$section = $r[1];
$section_text[$section] = '';
continue;
} elseif (empty($section)) {
fclose($fp);
return PEAR::raiseError("Invalid sections formats in test file: $file");
}
// Add to the section text.
$section_text[$section] .= $line;
}
fclose($fp);
return $section_text;
}
function _writeLog($logname, $data)
{
if (!$log = fopen($logname, 'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log, $data);
fclose($log);
}
function _resetEnv($section_text, $temp_file)
{
$env = $_ENV;
$env['REDIRECT_STATUS'] = '';
$env['QUERY_STRING'] = '';
$env['PATH_TRANSLATED'] = '';
$env['SCRIPT_FILENAME'] = '';
$env['REQUEST_METHOD'] = '';
$env['CONTENT_TYPE'] = '';
$env['CONTENT_LENGTH'] = '';
if (!empty($section_text['ENV'])) {
if (strpos($section_text['ENV'], '{PWD}') !== false) {
$section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
}
foreach (explode("\n", trim($section_text['ENV'])) as $e) {
$e = explode('=', trim($e), 2);
if (!empty($e[0]) && isset($e[1])) {
$env[$e[0]] = $e[1];
}
}
}
if (array_key_exists('GET', $section_text)) {
$env['QUERY_STRING'] = trim($section_text['GET']);
} else {
$env['QUERY_STRING'] = '';
}
if (array_key_exists('COOKIE', $section_text)) {
$env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
} else {
$env['HTTP_COOKIE'] = '';
}
$env['REDIRECT_STATUS'] = '1';
$env['PATH_TRANSLATED'] = $temp_file;
$env['SCRIPT_FILENAME'] = $temp_file;
return $env;
}
function _processUpload($section_text, $file)
{
if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
$upload_files = trim($section_text['UPLOAD']);
$upload_files = explode("\n", $upload_files);
$request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
"-----------------------------20896060251896012921717172737\n";
foreach ($upload_files as $fileinfo) {
$fileinfo = explode('=', $fileinfo);
if (count($fileinfo) != 2) {
return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
}
if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
"in test file: $file");
}
$file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
$fileinfo[1] = basename($fileinfo[1]);
$request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
$request .= "Content-Type: text/plain\n\n";
$request .= $file_contents . "\n" .
"-----------------------------20896060251896012921717172737\n";
}
if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
// encode POST raw
$post = trim($section_text['POST']);
$post = explode('&', $post);
foreach ($post as $i => $post_info) {
$post_info = explode('=', $post_info);
if (count($post_info) != 2) {
return PEAR::raiseError("Invalid POST data in test file: $file");
}
$post_info[0] = rawurldecode($post_info[0]);
$post_info[1] = rawurldecode($post_info[1]);
$post[$i] = $post_info;
}
foreach ($post as $post_info) {
$request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
$request .= $post_info[1] . "\n" .
"-----------------------------20896060251896012921717172737\n";
}
unset($section_text['POST']);
}
$section_text['POST_RAW'] = $request;
}
return $section_text;
}
function _testCleanup($section_text, $temp_clean)
{
if ($section_text['CLEAN']) {
$this->_restorePHPBinary();
// perform test cleanup
$this->save_text($temp_clean, $section_text['CLEAN']);
$output = $this->system_with_timeout("$this->_php $temp_clean 2>&1");
if (strlen($output[1])) {
echo "BORKED --CLEAN-- section! output:\n", $output[1];
}
if (file_exists($temp_clean)) {
unlink($temp_clean);
}
}
}
function _savePHPBinary()
{
$this->_savephp = $this->_php;
}
function _restorePHPBinary()
{
if (isset($this->_savephp))
{
$this->_php = $this->_savephp;
unset($this->_savephp);
}
}
}

View File

@@ -1,207 +0,0 @@
<?php
/**
* PEAR_Task_Common, base class for installer tasks
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**#@+
* Error codes for task validation routines
*/
define('PEAR_TASK_ERROR_NOATTRIBS', 1);
define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
define('PEAR_TASK_ERROR_INVALID', 4);
/**#@-*/
define('PEAR_TASK_PACKAGE', 1);
define('PEAR_TASK_INSTALL', 2);
define('PEAR_TASK_PACKAGEANDINSTALL', 3);
/**
* A task is an operation that manipulates the contents of a file.
*
* Simple tasks operate on 1 file. Multiple tasks are executed after all files have been
* processed and installed, and are designed to operate on all files containing the task.
* The Post-install script task simply takes advantage of the fact that it will be run
* after installation, replace is a simple task.
*
* Combining tasks is possible, but ordering is significant.
*
* <file name="test.php" role="php">
* <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
* <tasks:postinstallscript/>
* </file>
*
* This will first replace any instance of @data-dir@ in the test.php file
* with the path to the current data directory. Then, it will include the
* test.php file and run the script it contains to configure the package post-installation.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
* @abstract
*/
class PEAR_Task_Common
{
/**
* Valid types for this version are 'simple' and 'multiple'
*
* - simple tasks operate on the contents of a file and write out changes to disk
* - multiple tasks operate on the contents of many files and write out the
* changes directly to disk
*
* Child task classes must override this property.
*
* @access protected
*/
protected $type = 'simple';
/**
* Determines which install phase this task is executed under
*/
public $phase = PEAR_TASK_INSTALL;
/**
* @access protected
*/
protected $config;
/**
* @access protected
*/
protected $registry;
/**
* @access protected
*/
public $logger;
/**
* @access protected
*/
protected $installphase;
/**
* @param PEAR_Config
* @param PEAR_Common
*/
function __construct(&$config, &$logger, $phase)
{
$this->config = &$config;
$this->registry = &$config->getRegistry();
$this->logger = &$logger;
$this->installphase = $phase;
if ($this->type == 'multiple') {
$GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
}
}
/**
* Validate the basic contents of a task tag.
*
* @param PEAR_PackageFile_v2
* @param array
* @param PEAR_Config
* @param array the entire parsed <file> tag
*
* @return true|array On error, return an array in format:
* array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
*
* For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
* For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and
* an array of legal values in
*
* @abstract
*/
public static function validateXml($pkg, $xml, $config, $fileXml)
{
}
/**
* Initialize a task instance with the parameters
*
* @param array raw, parsed xml
* @param array attributes from the <file> tag containing this task
* @param string|null last installed version of this package
* @abstract
*/
public function init($xml, $fileAttributes, $lastVersion)
{
}
/**
* Begin a task processing session. All multiple tasks will be processed
* after each file has been successfully installed, all simple tasks should
* perform their task here and return any errors using the custom
* throwError() method to allow forward compatibility
*
* This method MUST NOT write out any changes to disk
*
* @param PEAR_PackageFile_v2
* @param string file contents
* @param string the eventual final file location (informational only)
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
* (use $this->throwError), otherwise return the new contents
* @abstract
*/
public function startSession($pkg, $contents, $dest)
{
}
/**
* This method is used to process each of the tasks for a particular
* multiple class type. Simple tasks need not implement this method.
*
* @param array an array of tasks
* @access protected
*/
public static function run($tasks)
{
}
/**
* @final
*/
public static function hasPostinstallTasks()
{
return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
}
/**
* @final
*/
public static function runPostinstallTasks()
{
foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
$err = call_user_func(
array($class, 'run'),
$GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]
);
if ($err) {
return PEAR_Task_Common::throwError($err);
}
}
unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
}
/**
* Determines whether a role is a script
* @return bool
*/
public function isScript()
{
return $this->type == 'script';
}
public function throwError($msg, $code = -1)
{
include_once 'PEAR.php';
return PEAR::raiseError($msg, $code);
}
}

View File

@@ -1,350 +0,0 @@
<?php
/**
* <tasks:postinstallscript>
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class
*/
require_once 'PEAR/Task/Common.php';
/**
* Implements the postinstallscript file task.
*
* Note that post-install scripts are handled separately from installation, by the
* "pear run-scripts" command
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Task_Postinstallscript extends PEAR_Task_Common
{
public $type = 'script';
public $_class;
public $_params;
public $_obj;
/**
*
* @var PEAR_PackageFile_v2
*/
public $_pkg;
public $_contents;
public $phase = PEAR_TASK_INSTALL;
/**
* Validate the raw xml at parsing-time.
*
* This also attempts to validate the script to make sure it meets the criteria
* for a post-install script
*
* @param PEAR_PackageFile_v2
* @param array The XML contents of the <postinstallscript> tag
* @param PEAR_Config
* @param array the entire parsed <file> tag
*/
public static function validateXml($pkg, $xml, $config, $fileXml)
{
if ($fileXml['role'] != 'php') {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" must be role="php"', );
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$file = $pkg->getFileContents($fileXml['name']);
if (PEAR::isError($file)) {
PEAR::popErrorHandling();
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" is not valid: '.
$file->getMessage(), );
} elseif ($file === null) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" could not be retrieved for processing!', );
} else {
$analysis = $pkg->analyzeSourceCode($file, true);
if (!$analysis) {
PEAR::popErrorHandling();
$warnings = '';
foreach ($pkg->getValidationWarnings() as $warn) {
$warnings .= $warn['message']."\n";
}
return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "'.
$fileXml['name'].'" failed: '.$warnings, );
}
if (count($analysis['declared_classes']) != 1) {
PEAR::popErrorHandling();
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" must declare exactly 1 class', );
}
$class = $analysis['declared_classes'][0];
if ($class != str_replace(
array('/', '.php'), array('_', ''),
$fileXml['name']
).'_postinstall') {
PEAR::popErrorHandling();
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" class "'.$class.'" must be named "'.
str_replace(
array('/', '.php'), array('_', ''),
$fileXml['name']
).'_postinstall"', );
}
if (!isset($analysis['declared_methods'][$class])) {
PEAR::popErrorHandling();
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" must declare methods init() and run()', );
}
$methods = array('init' => 0, 'run' => 1);
foreach ($analysis['declared_methods'][$class] as $method) {
if (isset($methods[$method])) {
unset($methods[$method]);
}
}
if (count($methods)) {
PEAR::popErrorHandling();
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" must declare methods init() and run()', );
}
}
PEAR::popErrorHandling();
$definedparams = array();
$tasksNamespace = $pkg->getTasksNs().':';
if (!isset($xml[$tasksNamespace.'paramgroup']) && isset($xml['paramgroup'])) {
// in order to support the older betas, which did not expect internal tags
// to also use the namespace
$tasksNamespace = '';
}
if (isset($xml[$tasksNamespace.'paramgroup'])) {
$params = $xml[$tasksNamespace.'paramgroup'];
if (!is_array($params) || !isset($params[0])) {
$params = array($params);
}
foreach ($params as $param) {
if (!isset($param[$tasksNamespace.'id'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" <paramgroup> must have '.
'an '.$tasksNamespace.'id> tag', );
}
if (isset($param[$tasksNamespace.'name'])) {
if (!in_array($param[$tasksNamespace.'name'], $definedparams)) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" '.$tasksNamespace.
'paramgroup> id "'.$param[$tasksNamespace.'id'].
'" parameter "'.$param[$tasksNamespace.'name'].
'" has not been previously defined', );
}
if (!isset($param[$tasksNamespace.'conditiontype'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" '.$tasksNamespace.
'paramgroup> id "'.$param[$tasksNamespace.'id'].
'" must have a '.$tasksNamespace.
'conditiontype> tag containing either "=", '.
'"!=", or "preg_match"', );
}
if (!in_array(
$param[$tasksNamespace.'conditiontype'],
array('=', '!=', 'preg_match')
)) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" '.$tasksNamespace.
'paramgroup> id "'.$param[$tasksNamespace.'id'].
'" must have a '.$tasksNamespace.
'conditiontype> tag containing either "=", '.
'"!=", or "preg_match"', );
}
if (!isset($param[$tasksNamespace.'value'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" '.$tasksNamespace.
'paramgroup> id "'.$param[$tasksNamespace.'id'].
'" must have a '.$tasksNamespace.
'value> tag containing expected parameter value', );
}
}
if (isset($param[$tasksNamespace.'instructions'])) {
if (!is_string($param[$tasksNamespace.'instructions'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" '.$tasksNamespace.
'paramgroup> id "'.$param[$tasksNamespace.'id'].
'" '.$tasksNamespace.'instructions> must be simple text', );
}
}
if (!isset($param[$tasksNamespace.'param'])) {
continue; // <param> is no longer required
}
$subparams = $param[$tasksNamespace.'param'];
if (!is_array($subparams) || !isset($subparams[0])) {
$subparams = array($subparams);
}
foreach ($subparams as $subparam) {
if (!isset($subparam[$tasksNamespace.'name'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" parameter for '.
$tasksNamespace.'paramgroup> id "'.
$param[$tasksNamespace.'id'].'" must have '.
'a '.$tasksNamespace.'name> tag', );
}
if (!preg_match(
'/[a-zA-Z0-9]+/',
$subparam[$tasksNamespace.'name']
)) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" parameter "'.
$subparam[$tasksNamespace.'name'].
'" for '.$tasksNamespace.'paramgroup> id "'.
$param[$tasksNamespace.'id'].
'" is not a valid name. Must contain only alphanumeric characters', );
}
if (!isset($subparam[$tasksNamespace.'prompt'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" parameter "'.
$subparam[$tasksNamespace.'name'].
'" for '.$tasksNamespace.'paramgroup> id "'.
$param[$tasksNamespace.'id'].
'" must have a '.$tasksNamespace.'prompt> tag', );
}
if (!isset($subparam[$tasksNamespace.'type'])) {
return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'.
$fileXml['name'].'" parameter "'.
$subparam[$tasksNamespace.'name'].
'" for '.$tasksNamespace.'paramgroup> id "'.
$param[$tasksNamespace.'id'].
'" must have a '.$tasksNamespace.'type> tag', );
}
$definedparams[] = $param[$tasksNamespace.'id'].'::'.
$subparam[$tasksNamespace.'name'];
}
}
}
return true;
}
/**
* Initialize a task instance with the parameters
* @param array $xml raw, parsed xml
* @param array $fileattribs attributes from the <file> tag containing
* this task
* @param string|null $lastversion last installed version of this package,
* if any (useful for upgrades)
*/
public function init($xml, $fileattribs, $lastversion)
{
$this->_class = str_replace('/', '_', $fileattribs['name']);
$this->_filename = $fileattribs['name'];
$this->_class = str_replace('.php', '', $this->_class).'_postinstall';
$this->_params = $xml;
$this->_lastversion = $lastversion;
}
/**
* Strip the tasks: namespace from internal params
*
* @access private
*/
public function _stripNamespace($params = null)
{
if ($params === null) {
$params = array();
if (!is_array($this->_params)) {
return;
}
foreach ($this->_params as $i => $param) {
if (is_array($param)) {
$param = $this->_stripNamespace($param);
}
$params[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param;
}
$this->_params = $params;
} else {
$newparams = array();
foreach ($params as $i => $param) {
if (is_array($param)) {
$param = $this->_stripNamespace($param);
}
$newparams[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param;
}
return $newparams;
}
}
/**
* Unlike other tasks, the installed file name is passed in instead of the
* file contents, because this task is handled post-installation
*
* @param mixed $pkg PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param string $contents file name
* @param string $dest the eventual final file location (informational only)
*
* @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
* (use $this->throwError)
*/
public function startSession($pkg, $contents, $dest)
{
if ($this->installphase != PEAR_TASK_INSTALL) {
return false;
}
// remove the tasks: namespace if present
$this->_pkg = $pkg;
$this->_stripNamespace();
$this->logger->log(
0, 'Including external post-installation script "'.
$contents.'" - any errors are in this script'
);
include_once $contents;
if (class_exists($this->_class)) {
$this->logger->log(0, 'Inclusion succeeded');
} else {
return $this->throwError(
'init of post-install script class "'.$this->_class
.'" failed'
);
}
$this->_obj = new $this->_class();
$this->logger->log(1, 'running post-install script "'.$this->_class.'->init()"');
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
PEAR::popErrorHandling();
if ($res) {
$this->logger->log(0, 'init succeeded');
} else {
return $this->throwError(
'init of post-install script "'.$this->_class.
'->init()" failed'
);
}
$this->_contents = $contents;
return true;
}
/**
* No longer used
*
* @see PEAR_PackageFile_v2::runPostinstallScripts()
* @param array an array of tasks
* @param string install or upgrade
* @access protected
*/
public static function run($tasks)
{
}
}

View File

@@ -1,182 +0,0 @@
<?php
/**
* <tasks:postinstallscript> - read/write version
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
/**
* Base class
*/
require_once 'PEAR/Task/Postinstallscript.php';
/**
* Abstracts the postinstallscript file task xml.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
{
/**
* parent package file object
*
* @var PEAR_PackageFile_v2_rw
*/
public $_pkg;
/**
* Enter description here...
*
* @param PEAR_PackageFile_v2_rw $pkg Package
* @param PEAR_Config $config Config
* @param PEAR_Frontend $logger Logger
* @param array $fileXml XML
*
* @return PEAR_Task_Postinstallscript_rw
*/
function __construct(&$pkg, &$config, &$logger, $fileXml)
{
parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
$this->_contents = $fileXml;
$this->_pkg = &$pkg;
$this->_params = array();
}
public function validate()
{
return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
}
public function getName()
{
return 'postinstallscript';
}
/**
* add a simple <paramgroup> to the post-install script
*
* Order is significant, so call this method in the same
* sequence the users should see the paramgroups. The $params
* parameter should either be the result of a call to {@link getParam()}
* or an array of calls to getParam().
*
* Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
* a <conditiontype> tag
*
* @param string $id <paramgroup> id as seen by the script
* @param array|false $params array of getParam() calls, or false for no params
* @param string|false $instructions
*/
public function addParamGroup($id, $params = false, $instructions = false)
{
if ($params && isset($params[0]) && !isset($params[1])) {
$params = $params[0];
}
$stuff =
array(
$this->_pkg->getTasksNs().':id' => $id,
);
if ($instructions) {
$stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions;
}
if ($params) {
$stuff[$this->_pkg->getTasksNs().':param'] = $params;
}
$this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff;
}
/**
* Add a complex <paramgroup> to the post-install script with conditions
*
* This inserts a <paramgroup> with
*
* Order is significant, so call this method in the same
* sequence the users should see the paramgroups. The $params
* parameter should either be the result of a call to {@link getParam()}
* or an array of calls to getParam().
*
* Use {@link addParamGroup()} to add a simple <paramgroup>
*
* @param string $id <paramgroup> id as seen by the script
* @param string $oldgroup <paramgroup> id of the section referenced by
* <conditiontype>
* @param string $param name of the <param> from the older section referenced
* by <contitiontype>
* @param string $value value to match of the parameter
* @param string $conditiontype one of '=', '!=', 'preg_match'
* @param array|false $params array of getParam() calls, or false for no params
* @param string|false $instructions
*/
public function addConditionTypeGroup($id,
$oldgroup,
$param,
$value,
$conditiontype = '=',
$params = false,
$instructions = false
) {
if ($params && isset($params[0]) && !isset($params[1])) {
$params = $params[0];
}
$stuff = array(
$this->_pkg->getTasksNs().':id' => $id,
);
if ($instructions) {
$stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions;
}
$stuff[$this->_pkg->getTasksNs().':name'] = $oldgroup.'::'.$param;
$stuff[$this->_pkg->getTasksNs().':conditiontype'] = $conditiontype;
$stuff[$this->_pkg->getTasksNs().':value'] = $value;
if ($params) {
$stuff[$this->_pkg->getTasksNs().':param'] = $params;
}
$this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff;
}
public function getXml()
{
return $this->_params;
}
/**
* Use to set up a param tag for use in creating a paramgroup
*
* @param mixed $name Name of parameter
* @param mixed $prompt Prompt
* @param string $type Type, defaults to 'string'
* @param mixed $default Default value
*
* @return array
*/
public function getParam(
$name, $prompt, $type = 'string', $default = null
) {
if ($default !== null) {
return
array(
$this->_pkg->getTasksNs().':name' => $name,
$this->_pkg->getTasksNs().':prompt' => $prompt,
$this->_pkg->getTasksNs().':type' => $type,
$this->_pkg->getTasksNs().':default' => $default,
);
}
return
array(
$this->_pkg->getTasksNs().':name' => $name,
$this->_pkg->getTasksNs().':prompt' => $prompt,
$this->_pkg->getTasksNs().':type' => $type,
);
}
}

View File

@@ -1,186 +0,0 @@
<?php
/**
* <tasks:replace>
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class
*/
require_once 'PEAR/Task/Common.php';
/**
* Implements the replace file task.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Task_Replace extends PEAR_Task_Common
{
public $type = 'simple';
public $phase = PEAR_TASK_PACKAGEANDINSTALL;
public $_replacements;
/**
* Validate the raw xml at parsing-time.
*
* @param PEAR_PackageFile_v2
* @param array raw, parsed xml
* @param PEAR_Config
*/
public static function validateXml($pkg, $xml, $config, $fileXml)
{
if (!isset($xml['attribs'])) {
return array(PEAR_TASK_ERROR_NOATTRIBS);
}
if (!isset($xml['attribs']['type'])) {
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
}
if (!isset($xml['attribs']['to'])) {
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
}
if (!isset($xml['attribs']['from'])) {
return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
}
if ($xml['attribs']['type'] == 'pear-config') {
if (!in_array($xml['attribs']['to'], $config->getKeys())) {
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
$config->getKeys(), );
}
} elseif ($xml['attribs']['type'] == 'php-const') {
if (defined($xml['attribs']['to'])) {
return true;
} else {
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
array('valid PHP constant'), );
}
} elseif ($xml['attribs']['type'] == 'package-info') {
if (in_array(
$xml['attribs']['to'],
array('name', 'summary', 'channel', 'notes', 'extends', 'description',
'release_notes', 'license', 'release-license', 'license-uri',
'version', 'api-version', 'state', 'api-state', 'release_date',
'date', 'time', )
)) {
return true;
} else {
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
array('name', 'summary', 'channel', 'notes', 'extends', 'description',
'release_notes', 'license', 'release-license', 'license-uri',
'version', 'api-version', 'state', 'api-state', 'release_date',
'date', 'time', ), );
}
} else {
return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
array('pear-config', 'package-info', 'php-const'), );
}
return true;
}
/**
* Initialize a task instance with the parameters
* @param array raw, parsed xml
* @param unused
* @param unused
*/
public function init($xml, $attribs, $lastVersion = null)
{
$this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
}
/**
* Do a package.xml 1.0 replacement, with additional package-info fields available
*
* See validateXml() source for the complete list of allowed fields
*
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param string file contents
* @param string the eventual final file location (informational only)
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
* (use $this->throwError), otherwise return the new contents
*/
public function startSession($pkg, $contents, $dest)
{
$subst_from = $subst_to = array();
foreach ($this->_replacements as $a) {
$a = $a['attribs'];
$to = '';
if ($a['type'] == 'pear-config') {
if ($this->installphase == PEAR_TASK_PACKAGE) {
return false;
}
if ($a['to'] == 'master_server') {
$chan = $this->registry->getChannel($pkg->getChannel());
if (!PEAR::isError($chan)) {
$to = $chan->getServer();
} else {
$this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
return false;
}
} else {
if ($this->config->isDefinedLayer('ftp')) {
// try the remote config file first
$to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
if (is_null($to)) {
// then default to local
$to = $this->config->get($a['to'], null, $pkg->getChannel());
}
} else {
$to = $this->config->get($a['to'], null, $pkg->getChannel());
}
}
if (is_null($to)) {
$this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
return false;
}
} elseif ($a['type'] == 'php-const') {
if ($this->installphase == PEAR_TASK_PACKAGE) {
return false;
}
if (defined($a['to'])) {
$to = constant($a['to']);
} else {
$this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
return false;
}
} else {
if ($t = $pkg->packageInfo($a['to'])) {
$to = $t;
} else {
$this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
return false;
}
}
if (!is_null($to)) {
$subst_from[] = $a['from'];
$subst_to[] = $to;
}
}
$this->logger->log(
3, "doing ".sizeof($subst_from).
" substitution(s) for $dest"
);
if (sizeof($subst_from)) {
$contents = str_replace($subst_from, $subst_to, $contents);
}
return $contents;
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* <tasks:replace> - read/write version
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
/**
* Base class
*/
require_once 'PEAR/Task/Replace.php';
/**
* Abstracts the replace task xml.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
class PEAR_Task_Replace_rw extends PEAR_Task_Replace
{
public function __construct(&$pkg, &$config, &$logger, $fileXml)
{
parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
$this->_contents = $fileXml;
$this->_pkg = &$pkg;
$this->_params = array();
}
public function validate()
{
return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
}
public function setInfo($from, $to, $type)
{
$this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
}
public function getName()
{
return 'replace';
}
public function getXml()
{
return $this->_params;
}
}

View File

@@ -1,79 +0,0 @@
<?php
/**
* <tasks:unixeol>
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class
*/
require_once 'PEAR/Task/Common.php';
/**
* Implements the unix line endings file task.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Task_Unixeol extends PEAR_Task_Common
{
public $type = 'simple';
public $phase = PEAR_TASK_PACKAGE;
public $_replacements;
/**
* Validate the raw xml at parsing-time.
*
* @param PEAR_PackageFile_v2
* @param array raw, parsed xml
* @param PEAR_Config
*/
public static function validateXml($pkg, $xml, $config, $fileXml)
{
if ($xml != '') {
return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
}
return true;
}
/**
* Initialize a task instance with the parameters
* @param array raw, parsed xml
* @param unused
* @param unused
*/
public function init($xml, $attribs, $lastVersion = null)
{
}
/**
* Replace all line endings with line endings customized for the current OS
*
* See validateXml() source for the complete list of allowed fields
*
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param string file contents
* @param string the eventual final file location (informational only)
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
* (use $this->throwError), otherwise return the new contents
*/
public function startSession($pkg, $contents, $dest)
{
$this->logger->log(3, "replacing all line endings with \\n in $dest");
return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* <tasks:unixeol> - read/write version
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
/**
* Base class
*/
require_once 'PEAR/Task/Unixeol.php';
/**
* Abstracts the unixeol task xml.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
{
function __construct(&$pkg, &$config, &$logger, $fileXml)
{
parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
$this->_contents = $fileXml;
$this->_pkg = &$pkg;
$this->_params = array();
}
public function validate()
{
return true;
}
public function getName()
{
return 'unixeol';
}
public function getXml()
{
return '';
}
}
?>

View File

@@ -1,80 +0,0 @@
<?php
/**
* <tasks:windowseol>
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class
*/
require_once 'PEAR/Task/Common.php';
/**
* Implements the windows line endsings file task.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Task_Windowseol extends PEAR_Task_Common
{
public $type = 'simple';
public $phase = PEAR_TASK_PACKAGE;
public $_replacements;
/**
* Validate the raw xml at parsing-time.
*
* @param PEAR_PackageFile_v2
* @param array raw, parsed xml
* @param PEAR_Config
*/
public static function validateXml($pkg, $xml, $config, $fileXml)
{
if ($xml != '') {
return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
}
return true;
}
/**
* Initialize a task instance with the parameters
* @param array raw, parsed xml
* @param unused
* @param unused
*/
public function init($xml, $attribs, $lastVersion = null)
{
}
/**
* Replace all line endings with windows line endings
*
* See validateXml() source for the complete list of allowed fields
*
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param string file contents
* @param string the eventual final file location (informational only)
* @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
* (use $this->throwError), otherwise return the new contents
*/
public function startSession($pkg, $contents, $dest)
{
$this->logger->log(3, "replacing all line endings with \\r\\n in $dest");
return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* <tasks:windowseol> - read/write version
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
/**
* Base class
*/
require_once 'PEAR/Task/Windowseol.php';
/**
* Abstracts the windowseol task xml.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
{
function __construct(&$pkg, &$config, &$logger, $fileXml)
{
parent::__construct($config, $logger, PEAR_TASK_PACKAGE);
$this->_contents = $fileXml;
$this->_pkg = &$pkg;
$this->_params = array();
}
public function validate()
{
return true;
}
public function getName()
{
return 'windowseol';
}
public function getXml()
{
return '';
}
}
?>

View File

@@ -1,625 +0,0 @@
<?php
/**
* PEAR_Validate
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**#@+
* Constants for install stage
*/
define('PEAR_VALIDATE_INSTALLING', 1);
define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
define('PEAR_VALIDATE_NORMAL', 3);
define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
define('PEAR_VALIDATE_PACKAGING', 7);
/**#@-*/
require_once 'PEAR/Common.php';
require_once 'PEAR/Validator/PECL.php';
/**
* Validation class for package.xml - channel-level advanced validation
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Validate
{
var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
/**
* @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
var $_packagexml;
/**
* @var int one of the PEAR_VALIDATE_* constants
*/
var $_state = PEAR_VALIDATE_NORMAL;
/**
* Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
* @var array
* @access private
*/
var $_failures = array('error' => array(), 'warning' => array());
/**
* Override this method to handle validation of normal package names
* @param string
* @return bool
* @access protected
*/
function _validPackageName($name)
{
return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
}
/**
* @param string package name to validate
* @param string name of channel-specific validation package
* @final
*/
function validPackageName($name, $validatepackagename = false)
{
if ($validatepackagename) {
if (strtolower($name) == strtolower($validatepackagename)) {
return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
}
}
return $this->_validPackageName($name);
}
/**
* This validates a bundle name, and bundle names must conform
* to the PEAR naming convention, so the method is final and static.
* @param string
* @final
*/
public static function validGroupName($name)
{
return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
}
/**
* Determine whether $state represents a valid stability level
* @param string
* @return bool
* @final
*/
public static function validState($state)
{
return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
}
/**
* Get a list of valid stability levels
* @return array
* @final
*/
public static function getValidStates()
{
return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
}
/**
* Determine whether a version is a properly formatted version number that can be used
* by version_compare
* @param string
* @return bool
* @final
*/
public static function validVersion($ver)
{
return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
function setPackageFile(&$pf)
{
$this->_packagexml = &$pf;
}
/**
* @access private
*/
function _addFailure($field, $reason)
{
$this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
}
/**
* @access private
*/
function _addWarning($field, $reason)
{
$this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
}
function getFailures()
{
$failures = $this->_failures;
$this->_failures = array('warnings' => array(), 'errors' => array());
return $failures;
}
/**
* @param int one of the PEAR_VALIDATE_* constants
*/
function validate($state = null)
{
if (!isset($this->_packagexml)) {
return false;
}
if ($state !== null) {
$this->_state = $state;
}
$this->_failures = array('warnings' => array(), 'errors' => array());
$this->validatePackageName();
$this->validateVersion();
$this->validateMaintainers();
$this->validateDate();
$this->validateSummary();
$this->validateDescription();
$this->validateLicense();
$this->validateNotes();
if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
$this->validateState();
$this->validateFilelist();
} elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
$this->_packagexml->getPackagexmlVersion() == '2.1') {
$this->validateTime();
$this->validateStability();
$this->validateDeps();
$this->validateMainFilelist();
$this->validateReleaseFilelist();
//$this->validateGlobalTasks();
$this->validateChangelog();
}
return !((bool) count($this->_failures['errors']));
}
/**
* @access protected
*/
function validatePackageName()
{
if ($this->_state == PEAR_VALIDATE_PACKAGING ||
$this->_state == PEAR_VALIDATE_NORMAL) {
if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
$this->_packagexml->getPackagexmlVersion() == '2.1') &&
$this->_packagexml->getExtends()) {
$version = $this->_packagexml->getVersion() . '';
$name = $this->_packagexml->getPackage();
$a = explode('.', $version);
$test = array_shift($a);
if ($test == '0') {
return true;
}
$vlen = strlen($test);
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver[0])) {
$majver = substr($majver, 1);
}
if ($majver != $test) {
$this->_addWarning('package', "package $name extends package " .
$this->_packagexml->getExtends() . ' and so the name should ' .
'have a postfix equal to the major version like "' .
$this->_packagexml->getExtends() . $test . '"');
return true;
} elseif (substr($name, 0, strlen($name) - $vlen) !=
$this->_packagexml->getExtends()) {
$this->_addWarning('package', "package $name extends package " .
$this->_packagexml->getExtends() . ' and so the name must ' .
'be an extension like "' . $this->_packagexml->getExtends() .
$test . '"');
return true;
}
}
}
if (!$this->validPackageName($this->_packagexml->getPackage())) {
$this->_addFailure('name', 'package name "' .
$this->_packagexml->getPackage() . '" is invalid');
return false;
}
}
/**
* @access protected
*/
function validateVersion()
{
if ($this->_state != PEAR_VALIDATE_PACKAGING) {
if (!$this->validVersion($this->_packagexml->getVersion())) {
$this->_addFailure('version',
'Invalid version number "' . $this->_packagexml->getVersion() . '"');
}
return false;
}
$version = $this->_packagexml->getVersion();
$versioncomponents = explode('.', $version);
if (count($versioncomponents) != 3) {
$this->_addWarning('version',
'A version number should have 3 decimals (x.y.z)');
return true;
}
$name = $this->_packagexml->getPackage();
// version must be based upon state
switch ($this->_packagexml->getState()) {
case 'snapshot' :
return true;
case 'devel' :
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
} else {
$this->_addWarning('version',
'packages with devel stability must be < version 1.0.0');
}
return true;
break;
case 'alpha' :
case 'beta' :
// check for a package that extends a package,
// like Foo and Foo2
if ($this->_state == PEAR_VALIDATE_PACKAGING) {
if (substr($versioncomponents[2], 1, 2) == 'rc') {
$this->_addFailure('version', 'Release Candidate versions ' .
'must have capital RC, not lower-case rc');
return false;
}
}
if (!$this->_packagexml->getExtends()) {
if ($versioncomponents[0] == '1') {
if ($versioncomponents[2][0] == '0') {
if ($versioncomponents[2] == '0') {
// version 1.*.0000
$this->_addWarning('version',
'version 1.' . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return true;
} elseif (strlen($versioncomponents[2]) > 1) {
// version 1.*.0RC1 or 1.*.0beta24 etc.
return true;
} else {
// version 1.*.0
$this->_addWarning('version',
'version 1.' . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return true;
}
} else {
$this->_addWarning('version',
'bugfix versions (1.3.x where x > 0) probably should ' .
'not be alpha or beta');
return true;
}
} elseif ($versioncomponents[0] != '0') {
$this->_addWarning('version',
'major versions greater than 1 are not allowed for packages ' .
'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
return true;
}
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
}
} else {
$vlen = strlen($versioncomponents[0] . '');
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver[0])) {
$majver = substr($majver, 1);
}
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
$this->_addWarning('version', 'first version number "' .
$versioncomponents[0] . '" must match the postfix of ' .
'package name "' . $name . '" (' .
$majver . ')');
return true;
}
if ($versioncomponents[0] == $majver) {
if ($versioncomponents[2][0] == '0') {
if ($versioncomponents[2] == '0') {
// version 2.*.0000
$this->_addWarning('version',
"version $majver." . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return false;
} elseif (strlen($versioncomponents[2]) > 1) {
// version 2.*.0RC1 or 2.*.0beta24 etc.
return true;
} else {
// version 2.*.0
$this->_addWarning('version',
"version $majver." . $versioncomponents[1] .
'.0 cannot be alpha or beta');
return true;
}
} else {
$this->_addWarning('version',
"bugfix versions ($majver.x.y where y > 0) should " .
'not be alpha or beta');
return true;
}
} elseif ($versioncomponents[0] != '0') {
$this->_addWarning('version',
"only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
return true;
}
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
}
}
return true;
break;
case 'stable' :
if ($versioncomponents[0] == '0') {
$this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
'be stable');
return true;
}
if (!is_numeric($versioncomponents[2])) {
if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
$versioncomponents[2])) {
$this->_addWarning('version', 'version "' . $version . '" or any ' .
'RC/beta/alpha version cannot be stable');
return true;
}
}
// check for a package that extends a package,
// like Foo and Foo2
if ($this->_packagexml->getExtends()) {
$vlen = strlen($versioncomponents[0] . '');
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver[0])) {
$majver = substr($majver, 1);
}
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
$this->_addWarning('version', 'first version number "' .
$versioncomponents[0] . '" must match the postfix of ' .
'package name "' . $name . '" (' .
$majver . ')');
return true;
}
} elseif ($versioncomponents[0] > 1) {
$this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
'1 for any package that does not have an <extends> tag');
}
return true;
break;
default :
return false;
break;
}
}
/**
* @access protected
*/
function validateMaintainers()
{
// maintainers can only be truly validated server-side for most channels
// but allow this customization for those who wish it
return true;
}
/**
* @access protected
*/
function validateDate()
{
if ($this->_state == PEAR_VALIDATE_NORMAL ||
$this->_state == PEAR_VALIDATE_PACKAGING) {
if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
$this->_packagexml->getDate(), $res) ||
count($res) < 4
|| !checkdate($res[2], $res[3], $res[1])
) {
$this->_addFailure('date', 'invalid release date "' .
$this->_packagexml->getDate() . '"');
return false;
}
if ($this->_state == PEAR_VALIDATE_PACKAGING &&
$this->_packagexml->getDate() != date('Y-m-d')) {
$this->_addWarning('date', 'Release Date "' .
$this->_packagexml->getDate() . '" is not today');
}
}
return true;
}
/**
* @access protected
*/
function validateTime()
{
if (!$this->_packagexml->getTime()) {
// default of no time value set
return true;
}
// packager automatically sets time, so only validate if pear validate is called
if ($this->_state = PEAR_VALIDATE_NORMAL) {
if (!preg_match('/\d\d:\d\d:\d\d/',
$this->_packagexml->getTime())) {
$this->_addFailure('time', 'invalid release time "' .
$this->_packagexml->getTime() . '"');
return false;
}
$result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
if ($result === false || empty($matches)) {
$this->_addFailure('time', 'invalid release time "' .
$this->_packagexml->getTime() . '"');
return false;
}
}
return true;
}
/**
* @access protected
*/
function validateState()
{
// this is the closest to "final" php4 can get
if (!PEAR_Validate::validState($this->_packagexml->getState())) {
if (strtolower($this->_packagexml->getState() == 'rc')) {
$this->_addFailure('state', 'RC is not a state, it is a version ' .
'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
}
$this->_addFailure('state', 'invalid release state "' .
$this->_packagexml->getState() . '", must be one of: ' .
implode(', ', PEAR_Validate::getValidStates()));
return false;
}
return true;
}
/**
* @access protected
*/
function validateStability()
{
$ret = true;
$packagestability = $this->_packagexml->getState();
$apistability = $this->_packagexml->getState('api');
if (!PEAR_Validate::validState($packagestability)) {
$this->_addFailure('state', 'invalid release stability "' .
$this->_packagexml->getState() . '", must be one of: ' .
implode(', ', PEAR_Validate::getValidStates()));
$ret = false;
}
$apistates = PEAR_Validate::getValidStates();
array_shift($apistates); // snapshot is not allowed
if (!in_array($apistability, $apistates)) {
$this->_addFailure('state', 'invalid API stability "' .
$this->_packagexml->getState('api') . '", must be one of: ' .
implode(', ', $apistates));
$ret = false;
}
return $ret;
}
/**
* @access protected
*/
function validateSummary()
{
return true;
}
/**
* @access protected
*/
function validateDescription()
{
return true;
}
/**
* @access protected
*/
function validateLicense()
{
return true;
}
/**
* @access protected
*/
function validateNotes()
{
return true;
}
/**
* for package.xml 2.0 only - channels can't use package.xml 1.0
* @access protected
*/
function validateDependencies()
{
return true;
}
/**
* for package.xml 1.0 only
* @access private
*/
function _validateFilelist()
{
return true; // placeholder for now
}
/**
* for package.xml 2.0 only
* @access protected
*/
function validateMainFilelist()
{
return true; // placeholder for now
}
/**
* for package.xml 2.0 only
* @access protected
*/
function validateReleaseFilelist()
{
return true; // placeholder for now
}
/**
* @access protected
*/
function validateChangelog()
{
return true;
}
/**
* @access protected
*/
function validateFilelist()
{
return true;
}
/**
* @access protected
*/
function validateDeps()
{
return true;
}
}

View File

@@ -1,62 +0,0 @@
<?php
/**
* Channel Validator for the pecl.php.net channel
*
* PHP 4 and PHP 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a5
*/
/**
* This is the parent class for all validators
*/
require_once 'PEAR/Validate.php';
/**
* Channel Validator for the pecl.php.net channel
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a5
*/
class PEAR_Validator_PECL extends PEAR_Validate
{
function validateVersion()
{
if ($this->_state == PEAR_VALIDATE_PACKAGING) {
$version = $this->_packagexml->getVersion();
$versioncomponents = explode('.', $version);
$last = array_pop($versioncomponents);
if (substr($last, 1, 2) == 'rc') {
$this->_addFailure('version', 'Release Candidate versions must have ' .
'upper-case RC, not lower-case rc');
return false;
}
}
return true;
}
function validatePackageName()
{
$ret = parent::validatePackageName();
if ($this->_packagexml->getPackageType() == 'extsrc' ||
$this->_packagexml->getPackageType() == 'zendextsrc') {
if (strtolower($this->_packagexml->getPackage()) !=
strtolower($this->_packagexml->getProvidesExtension())) {
$this->_addWarning('providesextension', 'package name "' .
$this->_packagexml->getPackage() . '" is different from extension name "' .
$this->_packagexml->getProvidesExtension() . '"');
}
}
return $ret;
}
}
?>

View File

@@ -1,247 +0,0 @@
<?php
/**
* PEAR_XMLParser
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Parser for any xml file
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_XMLParser
{
/**
* unserilialized data
* @var string $_serializedData
*/
var $_unserializedData = null;
/**
* name of the root tag
* @var string $_root
*/
var $_root = null;
/**
* stack for all data that is found
* @var array $_dataStack
*/
var $_dataStack = array();
/**
* stack for all values that are generated
* @var array $_valStack
*/
var $_valStack = array();
/**
* current tag depth
* @var int $_depth
*/
var $_depth = 0;
/**
* The XML encoding to use
* @var string $encoding
*/
var $encoding = 'ISO-8859-1';
/**
* @return array
*/
function getData()
{
return $this->_unserializedData;
}
/**
* @param string xml content
* @return true|PEAR_Error
*/
function parse($data)
{
if (!extension_loaded('xml')) {
include_once 'PEAR.php';
return PEAR::raiseError("XML Extension not found", 1);
}
$this->_dataStack = $this->_valStack = array();
$this->_depth = 0;
if (
strpos($data, 'encoding="UTF-8"')
|| strpos($data, 'encoding="utf-8"')
|| strpos($data, "encoding='UTF-8'")
|| strpos($data, "encoding='utf-8'")
) {
$this->encoding = 'UTF-8';
}
$xp = xml_parser_create($this->encoding);
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($xp, $this);
xml_set_element_handler($xp, 'startHandler', 'endHandler');
xml_set_character_data_handler($xp, 'cdataHandler');
if (!xml_parse($xp, $data)) {
$msg = xml_error_string(xml_get_error_code($xp));
$line = xml_get_current_line_number($xp);
xml_parser_free($xp);
include_once 'PEAR.php';
return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
}
xml_parser_free($xp);
return true;
}
/**
* Start element handler for XML parser
*
* @access private
* @param object $parser XML parser object
* @param string $element XML element
* @param array $attribs attributes of XML tag
* @return void
*/
function startHandler($parser, $element, $attribs)
{
$this->_depth++;
$this->_dataStack[$this->_depth] = null;
$val = array(
'name' => $element,
'value' => null,
'type' => 'string',
'childrenKeys' => array(),
'aggregKeys' => array()
);
if (count($attribs) > 0) {
$val['children'] = array();
$val['type'] = 'array';
$val['children']['attribs'] = $attribs;
}
array_push($this->_valStack, $val);
}
/**
* post-process data
*
* @param string $data
* @param string $element element name
*/
function postProcess($data, $element)
{
return trim($data);
}
/**
* End element handler for XML parser
*
* @access private
* @param object XML parser object
* @param string
* @return void
*/
function endHandler($parser, $element)
{
$value = array_pop($this->_valStack);
$data = $this->postProcess($this->_dataStack[$this->_depth], $element);
// adjust type of the value
switch (strtolower($value['type'])) {
// unserialize an array
case 'array':
if ($data !== '') {
$value['children']['_content'] = $data;
}
$value['value'] = isset($value['children']) ? $value['children'] : array();
break;
/*
* unserialize a null value
*/
case 'null':
$data = null;
break;
/*
* unserialize any scalar value
*/
default:
settype($data, $value['type']);
$value['value'] = $data;
break;
}
$parent = array_pop($this->_valStack);
if ($parent === null) {
$this->_unserializedData = &$value['value'];
$this->_root = &$value['name'];
return true;
}
// parent has to be an array
if (!isset($parent['children']) || !is_array($parent['children'])) {
$parent['children'] = array();
if ($parent['type'] != 'array') {
$parent['type'] = 'array';
}
}
if (!empty($value['name'])) {
// there already has been a tag with this name
if (in_array($value['name'], $parent['childrenKeys'])) {
// no aggregate has been created for this tag
if (!in_array($value['name'], $parent['aggregKeys'])) {
if (isset($parent['children'][$value['name']])) {
$parent['children'][$value['name']] = array($parent['children'][$value['name']]);
} else {
$parent['children'][$value['name']] = array();
}
array_push($parent['aggregKeys'], $value['name']);
}
array_push($parent['children'][$value['name']], $value['value']);
} else {
$parent['children'][$value['name']] = &$value['value'];
array_push($parent['childrenKeys'], $value['name']);
}
} else {
array_push($parent['children'],$value['value']);
}
array_push($this->_valStack, $parent);
$this->_depth--;
}
/**
* Handler for character data
*
* @access private
* @param object XML parser object
* @param string CDATA
* @return void
*/
function cdataHandler($parser, $cdata)
{
$this->_dataStack[$this->_depth] .= $cdata;
}
}

View File

@@ -1,176 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S<>rgio Gon<6F>alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S<>rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* The Graph.php file contains the definition of the Structures_Graph class
*
* @package Structures_Graph
*/
/* dependencies {{{ */
require_once 'PEAR.php';
require_once 'Structures/Graph/Node.php';
/* }}} */
define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
/* class Structures_Graph {{{ */
/**
* The Structures_Graph class represents a graph data structure.
*
* A Graph is a data structure composed by a set of nodes, connected by arcs.
* Graphs may either be directed or undirected. In a directed graph, arcs are
* directional, and can be traveled only one way. In an undirected graph, arcs
* are bidirectional, and can be traveled both ways.
*
* @author S<>rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S<>rgio Carvalho
* @package Structures_Graph
*/
/* }}} */
class Structures_Graph
{
/**
* List of node objects in this graph
* @access private
*/
var $_nodes = array();
/**
* If the graph is directed or not
* @access private
*/
var $_directed = false;
/**
* Constructor
*
* @param boolean $directed Set to true if the graph is directed.
* Set to false if it is not directed.
*/
public function __construct($directed = true)
{
$this->_directed = $directed;
}
/**
* Old constructor (PHP4-style; kept for BC with extending classes)
*
* @param boolean $directed Set to true if the graph is directed.
* Set to false if it is not directed.
*
* @return void
*/
public function Structures_Graph($directed = true)
{
$this->__construct($directed);
}
/**
* Return true if a graph is directed
*
* @return boolean true if the graph is directed
*/
public function isDirected()
{
return (boolean) $this->_directed;
}
/**
* Add a Node to the Graph
*
* @param Structures_Graph_Node $newNode The node to be added.
*
* @return void
*/
public function addNode(&$newNode)
{
// We only add nodes
if (!is_a($newNode, 'Structures_Graph_Node')) {
return Pear::raiseError(
'Structures_Graph::addNode received an object that is not'
. ' a Structures_Graph_Node',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
//Graphs are node *sets*, so duplicates are forbidden.
// We allow nodes that are exactly equal, but disallow equal references.
foreach ($this->_nodes as $key => $node) {
/*
ZE1 equality operators choke on the recursive cycle introduced
by the _graph field in the Node object.
So, we'll check references the hard way
(change $this->_nodes[$key] and check if the change reflects in
$node)
*/
$savedData = $this->_nodes[$key];
$referenceIsEqualFlag = false;
$this->_nodes[$key] = true;
if ($node === true) {
$this->_nodes[$key] = false;
if ($node === false) {
$referenceIsEqualFlag = true;
}
}
$this->_nodes[$key] = $savedData;
if ($referenceIsEqualFlag) {
return Pear::raiseError(
'Structures_Graph::addNode received an object that is'
. ' a duplicate for this dataset',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
}
$this->_nodes[] =& $newNode;
$newNode->setGraph($this);
}
/**
* Remove a Node from the Graph
*
* @param Structures_Graph_Node $node The node to be removed from the graph
*
* @return void
* @todo This is unimplemented
*/
public function removeNode(&$node)
{
}
/**
* Return the node set, in no particular order.
* For ordered node sets, use a Graph Manipulator insted.
*
* @return array The set of nodes in this graph
* @see Structures_Graph_Manipulator_TopologicalSorter
*/
public function &getNodes()
{
return $this->_nodes;
}
}
?>

View File

@@ -1,134 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S<>rgio Gon<6F>alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S<>rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
*
* @see Structures_Graph_Manipulator_AcyclicTest
* @package Structures_Graph
*/
/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/** */
require_once 'Structures/Graph/Node.php';
/* }}} */
/* class Structures_Graph_Manipulator_AcyclicTest {{{ */
/**
* The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
* which tests whether a graph contains a cycle.
*
* The definition of an acyclic graph used in this manipulator is that of a
* DAG. The graph must be directed, or else it is considered cyclic, even when
* there are no arcs.
*
* @author S<>rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S<>rgio Carvalho
* @package Structures_Graph
*/
class Structures_Graph_Manipulator_AcyclicTest {
/* _nonVisitedInDegree {{{ */
/**
*
* This is a variant of Structures_Graph::inDegree which does
* not count nodes marked as visited.
*
* @return integer Number of non-visited nodes that link to this one
*/
protected static function _nonVisitedInDegree(&$node) {
$result = 0;
$graphNodes =& $node->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
}
return $result;
}
/* }}} */
/* _isAcyclic {{{ */
/**
* Check if the graph is acyclic
*/
protected static function _isAcyclic(&$graph) {
// Mark every node as not visited
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
$refGenerator = array();
foreach($nodeKeys as $key) {
$refGenerator[] = false;
$nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
}
// Iteratively peel off leaf nodes
do {
// Find out which nodes are leafs (excluding visited nodes)
$leafNodes = array();
foreach($nodeKeys as $key) {
if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
$leafNodes[] =& $nodes[$key];
}
}
// Mark leafs as visited
for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
$visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
$visited = true;
$leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
}
} while (sizeof($leafNodes) > 0);
// If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
$result = true;
foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
// Cleanup visited marks
foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
return $result;
}
/* }}} */
/* isAcyclic {{{ */
/**
*
* isAcyclic returns true if a graph contains no cycles, false otherwise.
*
* @return boolean true iff graph is acyclic
*/
public static function isAcyclic(&$graph) {
// We only test graphs
if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
}
/* }}} */
}
/* }}} */
?>

View File

@@ -1,176 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S<>rgio Gon<6F>alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S<>rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
*
* @package Structures_Graph
*/
require_once 'PEAR.php';
require_once 'Structures/Graph.php';
require_once 'Structures/Graph/Node.php';
require_once 'Structures/Graph/Manipulator/AcyclicTest.php';
/**
* The Structures_Graph_Manipulator_TopologicalSorter is a manipulator
* which is able to return the set of nodes in a graph, sorted by topological
* order.
*
* A graph may only be sorted topologically iff it's a DAG. You can test it
* with the Structures_Graph_Manipulator_AcyclicTest.
*
* @author S<>rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S<>rgio Carvalho
* @see Structures_Graph_Manipulator_AcyclicTest
* @package Structures_Graph
*/
class Structures_Graph_Manipulator_TopologicalSorter
{
/**
* This is a variant of Structures_Graph::inDegree which does
* not count nodes marked as visited.
*
* @param object $node Node to check
*
* @return integer Number of non-visited nodes that link to this one
*/
protected static function _nonVisitedInDegree(&$node)
{
$result = 0;
$graphNodes =& $node->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ((!$graphNodes[$key]->getMetadata('topological-sort-visited'))
&& $graphNodes[$key]->connectsTo($node)
) {
$result++;
}
}
return $result;
}
/**
* Sort implementation
*
* @param object $graph Graph to sort
*
* @return void
*/
protected static function _sort(&$graph)
{
// Mark every node as not visited
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
$refGenerator = array();
foreach ($nodeKeys as $key) {
$refGenerator[] = false;
$nodes[$key]->setMetadata(
'topological-sort-visited',
$refGenerator[sizeof($refGenerator) - 1]
);
}
// Iteratively peel off leaf nodes
$topologicalLevel = 0;
do {
// Find out which nodes are leafs (excluding visited nodes)
$leafNodes = array();
foreach ($nodeKeys as $key) {
if ((!$nodes[$key]->getMetadata('topological-sort-visited'))
&& static::_nonVisitedInDegree($nodes[$key]) == 0
) {
$leafNodes[] =& $nodes[$key];
}
}
// Mark leafs as visited
$refGenerator[] = $topologicalLevel;
for ($i = sizeof($leafNodes) - 1; $i>=0; $i--) {
$visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
$visited = true;
$leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
$leafNodes[$i]->setMetadata(
'topological-sort-level',
$refGenerator[sizeof($refGenerator) - 1]
);
}
$topologicalLevel++;
} while (sizeof($leafNodes) > 0);
// Cleanup visited marks
foreach ($nodeKeys as $key) {
$nodes[$key]->unsetMetadata('topological-sort-visited');
}
}
/**
* Sort returns the graph's nodes, sorted by topological order.
*
* The result is an array with as many entries as topological levels.
* Each entry in this array is an array of nodes within
* the given topological level.
*
* @param object $graph Graph to sort
*
* @return array The graph's nodes, sorted by topological order.
*/
public static function sort(&$graph)
{
// We only sort graphs
if (!is_a($graph, 'Structures_Graph')) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort received'
. ' an object that is not a Structures_Graph',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort'
. ' received an graph that has cycles',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
$result = array();
// Fill out result array
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
foreach ($nodeKeys as $key) {
if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) {
$result[$nodes[$key]->getMetadata('topological-sort-level')]
= array();
}
$result[$nodes[$key]->getMetadata('topological-sort-level')][]
=& $nodes[$key];
$nodes[$key]->unsetMetadata('topological-sort-level');
}
return $result;
}
}
?>

View File

@@ -1,342 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S<>rgio Gon<6F>alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S<>rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Node class
*
* @see Structures_Graph_Node
* @package Structures_Graph
*/
/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/* }}} */
/* class Structures_Graph_Node {{{ */
/**
* The Structures_Graph_Node class represents a Node that can be member of a
* graph node set.
*
* A graph node can contain data. Under this API, the node contains default data,
* and key index data. It behaves, thus, both as a regular data node, and as a
* dictionary (or associative array) node.
*
* Regular data is accessed via getData and setData. Key indexed data is accessed
* via getMetadata and setMetadata.
*
* @author S<>rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S<>rgio Carvalho
* @package Structures_Graph
*/
/* }}} */
class Structures_Graph_Node {
/* fields {{{ */
/**
* @access private
*/
var $_data = null;
/** @access private */
var $_metadata = array();
/** @access private */
var $_arcs = array();
/** @access private */
var $_graph = null;
/* }}} */
/* Constructor {{{ */
/**
*
* Constructor
*
* @access public
*/
function __construct() {
}
/* }}} */
/* getGraph {{{ */
/**
*
* Node graph getter
*
* @return Structures_Graph Graph where node is stored
* @access public
*/
function &getGraph() {
return $this->_graph;
}
/* }}} */
/* setGraph {{{ */
/**
*
* Node graph setter. This method should not be called directly. Use Graph::addNode instead.
*
* @param Structures_Graph Set the graph for this node.
* @see Structures_Graph::addNode()
* @access public
*/
function setGraph(&$graph) {
$this->_graph =& $graph;
}
/* }}} */
/* getData {{{ */
/**
*
* Node data getter.
*
* Each graph node can contain a reference to one variable. This is the getter for that reference.
*
* @return mixed Data stored in node
* @access public
*/
function &getData() {
return $this->_data;
}
/* }}} */
/* setData {{{ */
/**
*
* Node data setter
*
* Each graph node can contain a reference to one variable. This is the setter for that reference.
*
* @return mixed Data to store in node
* @access public
*/
function setData(&$data) {
$this->_data =& $data;
}
/* }}} */
/* metadataKeyExists {{{ */
/**
*
* Test for existence of metadata under a given key.
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
*
* @param string Key to test
* @return boolean
* @access public
*/
function metadataKeyExists($key) {
return array_key_exists($key, $this->_metadata);
}
/* }}} */
/* getMetadata {{{ */
/**
*
* Node metadata getter
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method gets the data under the given key. If the key does
* not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
*
* @param string Key
* @param boolean nullIfNonexistent (defaults to false).
* @return mixed Metadata Data stored in node under given key
* @see metadataKeyExists
* @access public
*/
function &getMetadata($key, $nullIfNonexistent = false) {
if (array_key_exists($key, $this->_metadata)) {
return $this->_metadata[$key];
} else {
if ($nullIfNonexistent) {
$a = null;
return $a;
} else {
$a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
return $a;
}
}
}
/* }}} */
/* unsetMetadata {{{ */
/**
*
* Delete metadata by key
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method removes any data that might be stored under the provided key.
* If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
*
* @param string Key
* @access public
*/
function unsetMetadata($key) {
if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
}
/* }}} */
/* setMetadata {{{ */
/**
*
* Node metadata setter
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method stores data under the given key. If the key already exists,
* previously stored data is discarded.
*
* @param string Key
* @param mixed Data
* @access public
*/
function setMetadata($key, &$data) {
$this->_metadata[$key] =& $data;
}
/* }}} */
/* _connectTo {{{ */
/** @access private */
function _connectTo(&$destinationNode) {
$this->_arcs[] =& $destinationNode;
}
/* }}} */
/* connectTo {{{ */
/**
*
* Connect this node to another one.
*
* If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
*
* @param Structures_Graph_Node Node to connect to
* @access public
*/
function connectTo(&$destinationNode) {
// We only connect to nodes
if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
// Nodes must already be in graphs to be connected
if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
// Connect here
$this->_connectTo($destinationNode);
// If graph is undirected, connect back
if (!$this->_graph->isDirected()) {
$destinationNode->_connectTo($this);
}
}
/* }}} */
/* getNeighbours {{{ */
/**
*
* Return nodes connected to this one.
*
* @return array Array of nodes
* @access public
*/
function getNeighbours() {
return $this->_arcs;
}
/* }}} */
/* connectsTo {{{ */
/**
*
* Test wether this node has an arc to the target node
*
* @return boolean True if the two nodes are connected
* @access public
*/
function connectsTo(&$target) {
if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
return in_array($target, $this->getNeighbours(), true);
}
$copy = $target;
$arcKeys = array_keys($this->_arcs);
foreach($arcKeys as $key) {
/* ZE1 chokes on this expression:
if ($target === $arc) return true;
so, we'll use more convoluted stuff
*/
$arc =& $this->_arcs[$key];
$target = true;
if ($arc === true) {
$target = false;
if ($arc === false) {
$target = $copy;
return true;
}
}
}
$target = $copy;
return false;
}
/* }}} */
/* inDegree {{{ */
/**
*
* Calculate the in degree of the node.
*
* The indegree for a node is the number of arcs entering the node. For non directed graphs,
* the indegree is equal to the outdegree.
*
* @return integer In degree of the node
* @access public
*/
function inDegree() {
if ($this->_graph == null) return 0;
if (!$this->_graph->isDirected()) return $this->outDegree();
$result = 0;
$graphNodes =& $this->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ($graphNodes[$key]->connectsTo($this)) $result++;
}
return $result;
}
/* }}} */
/* outDegree {{{ */
/**
*
* Calculate the out degree of the node.
*
* The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
* the outdegree is always equal to the indegree.
*
* @return integer Out degree of the node
* @access public
*/
function outDegree() {
if ($this->_graph == null) return 0;
return sizeof($this->_arcs);
}
/* }}} */
}
?>

View File

@@ -1,630 +0,0 @@
<?php
/**
* File/Directory manipulation
*
* PHP versions 4 and 5
*
* @category pear
* @package System
* @author Tomas V.V.Cox <cox@idecnet.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR.php';
require_once 'Console/Getopt.php';
$GLOBALS['_System_temp_files'] = array();
/**
* System offers cross platform compatible system functions
*
* Static functions for different operations. Should work under
* Unix and Windows. The names and usage has been taken from its respectively
* GNU commands. The functions will return (bool) false on error and will
* trigger the error with the PHP trigger_error() function (you can silence
* the error by prefixing a '@' sign after the function call, but this
* is not recommended practice. Instead use an error handler with
* {@link set_error_handler()}).
*
* Documentation on this class you can find in:
* http://pear.php.net/manual/
*
* Example usage:
* if (!@System::rm('-r file1 dir1')) {
* print "could not delete file1 or dir1";
* }
*
* In case you need to to pass file names with spaces,
* pass the params as an array:
*
* System::rm(array('-r', $file1, $dir1));
*
* @category pear
* @package System
* @author Tomas V.V. Cox <cox@idecnet.com>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.13
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @static
*/
class System
{
/**
* returns the commandline arguments of a function
*
* @param string $argv the commandline
* @param string $short_options the allowed option short-tags
* @param string $long_options the allowed option long-tags
* @return array the given options and there values
*/
public static function _parseArgs($argv, $short_options, $long_options = null)
{
if (!is_array($argv) && $argv !== null) {
/*
// Quote all items that are a short option
$av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
$offset = 0;
foreach ($av as $a) {
$b = trim($a[0]);
if ($b[0] == '"' || $b[0] == "'") {
continue;
}
$escape = escapeshellarg($b);
$pos = $a[1] + $offset;
$argv = substr_replace($argv, $escape, $pos, strlen($b));
$offset += 2;
}
*/
// Find all items, quoted or otherwise
preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
$argv = $av[1];
foreach ($av[2] as $k => $a) {
if (empty($a)) {
continue;
}
$argv[$k] = trim($a) ;
}
}
return Console_Getopt::getopt2($argv, $short_options, $long_options);
}
/**
* Output errors with PHP trigger_error(). You can silence the errors
* with prefixing a "@" sign to the function call: @System::mkdir(..);
*
* @param mixed $error a PEAR error or a string with the error message
* @return bool false
*/
protected static function raiseError($error)
{
if (PEAR::isError($error)) {
$error = $error->getMessage();
}
trigger_error($error, E_USER_WARNING);
return false;
}
/**
* Creates a nested array representing the structure of a directory
*
* System::_dirToStruct('dir1', 0) =>
* Array
* (
* [dirs] => Array
* (
* [0] => dir1
* )
*
* [files] => Array
* (
* [0] => dir1/file2
* [1] => dir1/file3
* )
* )
* @param string $sPath Name of the directory
* @param integer $maxinst max. deep of the lookup
* @param integer $aktinst starting deep of the lookup
* @param bool $silent if true, do not emit errors.
* @return array the structure of the dir
*/
protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
{
$struct = array('dirs' => array(), 'files' => array());
if (($dir = @opendir($sPath)) === false) {
if (!$silent) {
System::raiseError("Could not open dir $sPath");
}
return $struct; // XXX could not open error
}
$struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
$list = array();
while (false !== ($file = readdir($dir))) {
if ($file != '.' && $file != '..') {
$list[] = $file;
}
}
closedir($dir);
natsort($list);
if ($aktinst < $maxinst || $maxinst == 0) {
foreach ($list as $val) {
$path = $sPath . DIRECTORY_SEPARATOR . $val;
if (is_dir($path) && !is_link($path)) {
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
$struct = array_merge_recursive($struct, $tmp);
} else {
$struct['files'][] = $path;
}
}
}
return $struct;
}
/**
* Creates a nested array representing the structure of a directory and files
*
* @param array $files Array listing files and dirs
* @return array
* @static
* @see System::_dirToStruct()
*/
protected static function _multipleToStruct($files)
{
$struct = array('dirs' => array(), 'files' => array());
settype($files, 'array');
foreach ($files as $file) {
if (is_dir($file) && !is_link($file)) {
$tmp = System::_dirToStruct($file, 0);
$struct = array_merge_recursive($tmp, $struct);
} else {
if (!in_array($file, $struct['files'])) {
$struct['files'][] = $file;
}
}
}
return $struct;
}
/**
* The rm command for removing files.
* Supports multiple files and dirs and also recursive deletes
*
* @param string $args the arguments for rm
* @return mixed PEAR_Error or true for success
* @static
* @access public
*/
public static function rm($args)
{
$opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
foreach ($opts[0] as $opt) {
if ($opt[0] == 'r') {
$do_recursive = true;
}
}
$ret = true;
if (isset($do_recursive)) {
$struct = System::_multipleToStruct($opts[1]);
foreach ($struct['files'] as $file) {
if (!@unlink($file)) {
$ret = false;
}
}
rsort($struct['dirs']);
foreach ($struct['dirs'] as $dir) {
if (!@rmdir($dir)) {
$ret = false;
}
}
} else {
foreach ($opts[1] as $file) {
$delete = (is_dir($file)) ? 'rmdir' : 'unlink';
if (!@$delete($file)) {
$ret = false;
}
}
}
return $ret;
}
/**
* Make directories.
*
* The -p option will create parent directories
* @param string $args the name of the director(y|ies) to create
* @return bool True for success
*/
public static function mkDir($args)
{
$opts = System::_parseArgs($args, 'pm:');
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
$mode = 0777; // default mode
foreach ($opts[0] as $opt) {
if ($opt[0] == 'p') {
$create_parents = true;
} elseif ($opt[0] == 'm') {
// if the mode is clearly an octal number (starts with 0)
// convert it to decimal
if (strlen($opt[1]) && $opt[1][0] == '0') {
$opt[1] = octdec($opt[1]);
} else {
// convert to int
$opt[1] += 0;
}
$mode = $opt[1];
}
}
$ret = true;
if (isset($create_parents)) {
foreach ($opts[1] as $dir) {
$dirstack = array();
while ((!file_exists($dir) || !is_dir($dir)) &&
$dir != DIRECTORY_SEPARATOR) {
array_unshift($dirstack, $dir);
$dir = dirname($dir);
}
while ($newdir = array_shift($dirstack)) {
if (!is_writeable(dirname($newdir))) {
$ret = false;
break;
}
if (!mkdir($newdir, $mode)) {
$ret = false;
}
}
}
} else {
foreach($opts[1] as $dir) {
if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
$ret = false;
}
}
}
return $ret;
}
/**
* Concatenate files
*
* Usage:
* 1) $var = System::cat('sample.txt test.txt');
* 2) System::cat('sample.txt test.txt > final.txt');
* 3) System::cat('sample.txt test.txt >> final.txt');
*
* Note: as the class use fopen, urls should work also
*
* @param string $args the arguments
* @return boolean true on success
*/
public static function &cat($args)
{
$ret = null;
$files = array();
if (!is_array($args)) {
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
}
$count_args = count($args);
for ($i = 0; $i < $count_args; $i++) {
if ($args[$i] == '>') {
$mode = 'wb';
$outputfile = $args[$i+1];
break;
} elseif ($args[$i] == '>>') {
$mode = 'ab+';
$outputfile = $args[$i+1];
break;
} else {
$files[] = $args[$i];
}
}
$outputfd = false;
if (isset($mode)) {
if (!$outputfd = fopen($outputfile, $mode)) {
$err = System::raiseError("Could not open $outputfile");
return $err;
}
$ret = true;
}
foreach ($files as $file) {
if (!$fd = fopen($file, 'r')) {
System::raiseError("Could not open $file");
continue;
}
while ($cont = fread($fd, 2048)) {
if (is_resource($outputfd)) {
fwrite($outputfd, $cont);
} else {
$ret .= $cont;
}
}
fclose($fd);
}
if (is_resource($outputfd)) {
fclose($outputfd);
}
return $ret;
}
/**
* Creates temporary files or directories. This function will remove
* the created files when the scripts finish its execution.
*
* Usage:
* 1) $tempfile = System::mktemp("prefix");
* 2) $tempdir = System::mktemp("-d prefix");
* 3) $tempfile = System::mktemp();
* 4) $tempfile = System::mktemp("-t /var/tmp prefix");
*
* prefix -> The string that will be prepended to the temp name
* (defaults to "tmp").
* -d -> A temporary dir will be created instead of a file.
* -t -> The target dir where the temporary (file|dir) will be created. If
* this param is missing by default the env vars TMP on Windows or
* TMPDIR in Unix will be used. If these vars are also missing
* c:\windows\temp or /tmp will be used.
*
* @param string $args The arguments
* @return mixed the full path of the created (file|dir) or false
* @see System::tmpdir()
*/
public static function mktemp($args = null)
{
static $first_time = true;
$opts = System::_parseArgs($args, 't:d');
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
foreach ($opts[0] as $opt) {
if ($opt[0] == 'd') {
$tmp_is_dir = true;
} elseif ($opt[0] == 't') {
$tmpdir = $opt[1];
}
}
$prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
if (!isset($tmpdir)) {
$tmpdir = System::tmpdir();
}
if (!System::mkDir(array('-p', $tmpdir))) {
return false;
}
$tmp = tempnam($tmpdir, $prefix);
if (isset($tmp_is_dir)) {
unlink($tmp); // be careful possible race condition here
if (!mkdir($tmp, 0700)) {
return System::raiseError("Unable to create temporary directory $tmpdir");
}
}
$GLOBALS['_System_temp_files'][] = $tmp;
if (isset($tmp_is_dir)) {
//$GLOBALS['_System_temp_files'][] = dirname($tmp);
}
if ($first_time) {
PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
$first_time = false;
}
return $tmp;
}
/**
* Remove temporary files created my mkTemp. This function is executed
* at script shutdown time
*/
public static function _removeTmpFiles()
{
if (count($GLOBALS['_System_temp_files'])) {
$delete = $GLOBALS['_System_temp_files'];
array_unshift($delete, '-r');
System::rm($delete);
$GLOBALS['_System_temp_files'] = array();
}
}
/**
* Get the path of the temporal directory set in the system
* by looking in its environments variables.
* Note: php.ini-recommended removes the "E" from the variables_order setting,
* making unavaible the $_ENV array, that s why we do tests with _ENV
*
* @return string The temporary directory on the system
*/
public static function tmpdir()
{
if (OS_WINDOWS) {
if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
return $var;
}
if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
return $var;
}
if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
return $var;
}
if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
return $var;
}
return getenv('SystemRoot') . '\temp';
}
if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
return $var;
}
return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp');
}
/**
* The "which" command (show the full path of a command)
*
* @param string $program The command to search for
* @param mixed $fallback Value to return if $program is not found
*
* @return mixed A string with the full path or false if not found
* @author Stig Bakken <ssb@php.net>
*/
public static function which($program, $fallback = false)
{
// enforce API
if (!is_string($program) || '' == $program) {
return $fallback;
}
// full path given
if (basename($program) != $program) {
$path_elements[] = dirname($program);
$program = basename($program);
} else {
$path = getenv('PATH');
if (!$path) {
$path = getenv('Path'); // some OSes are just stupid enough to do this
}
$path_elements = explode(PATH_SEPARATOR, $path);
}
if (OS_WINDOWS) {
$exe_suffixes = getenv('PATHEXT')
? explode(PATH_SEPARATOR, getenv('PATHEXT'))
: array('.exe','.bat','.cmd','.com');
// allow passing a command.exe param
if (strpos($program, '.') !== false) {
array_unshift($exe_suffixes, '');
}
} else {
$exe_suffixes = array('');
}
foreach ($exe_suffixes as $suff) {
foreach ($path_elements as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
// It's possible to run a .bat on Windows that is_executable
// would return false for. The is_executable check is meaningless...
if (OS_WINDOWS) {
if (file_exists($file)) {
return $file;
}
} else {
if (is_executable($file)) {
return $file;
}
}
}
}
return $fallback;
}
/**
* The "find" command
*
* Usage:
*
* System::find($dir);
* System::find("$dir -type d");
* System::find("$dir -type f");
* System::find("$dir -name *.php");
* System::find("$dir -name *.php -name *.htm*");
* System::find("$dir -maxdepth 1");
*
* Params implemented:
* $dir -> Start the search at this directory
* -type d -> return only directories
* -type f -> return only files
* -maxdepth <n> -> max depth of recursion
* -name <pattern> -> search pattern (bash style). Multiple -name param allowed
*
* @param mixed Either array or string with the command line
* @return array Array of found files
*/
public static function find($args)
{
if (!is_array($args)) {
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
}
$dir = realpath(array_shift($args));
if (!$dir) {
return array();
}
$patterns = array();
$depth = 0;
$do_files = $do_dirs = true;
$args_count = count($args);
for ($i = 0; $i < $args_count; $i++) {
switch ($args[$i]) {
case '-type':
if (in_array($args[$i+1], array('d', 'f'))) {
if ($args[$i+1] == 'd') {
$do_files = false;
} else {
$do_dirs = false;
}
}
$i++;
break;
case '-name':
$name = preg_quote($args[$i+1], '#');
// our magic characters ? and * have just been escaped,
// so now we change the escaped versions to PCRE operators
$name = strtr($name, array('\?' => '.', '\*' => '.*'));
$patterns[] = '('.$name.')';
$i++;
break;
case '-maxdepth':
$depth = $args[$i+1];
break;
}
}
$path = System::_dirToStruct($dir, $depth, 0, true);
if ($do_files && $do_dirs) {
$files = array_merge($path['files'], $path['dirs']);
} elseif ($do_dirs) {
$files = $path['dirs'];
} else {
$files = $path['files'];
}
if (count($patterns)) {
$dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
$pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
$ret = array();
$files_count = count($files);
for ($i = 0; $i < $files_count; $i++) {
// only search in the part of the file below the current directory
$filepart = basename($files[$i]);
if (preg_match($pattern, $filepart)) {
$ret[] = $files[$i];
}
}
return $ret;
}
return $files;
}
}

View File

@@ -1,963 +0,0 @@
<?php
/**
* XML_Util
*
* XML Utilities package
*
* PHP versions 4 and 5
*
* LICENSE:
*
* Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
* 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.
* * The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*
* @category XML
* @package XML_Util
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_Util
*/
/**
* Error code for invalid chars in XML name
*/
define('XML_UTIL_ERROR_INVALID_CHARS', 51);
/**
* Error code for invalid chars in XML name
*/
define('XML_UTIL_ERROR_INVALID_START', 52);
/**
* Error code for non-scalar tag content
*/
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
/**
* Error code for missing tag name
*/
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
/**
* Replace XML entities
*/
define('XML_UTIL_REPLACE_ENTITIES', 1);
/**
* Embedd content in a CData Section
*/
define('XML_UTIL_CDATA_SECTION', 5);
/**
* Do not replace entitites
*/
define('XML_UTIL_ENTITIES_NONE', 0);
/**
* Replace all XML entitites
* This setting will replace <, >, ", ' and &
*/
define('XML_UTIL_ENTITIES_XML', 1);
/**
* Replace only required XML entitites
* This setting will replace <, " and &
*/
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
/**
* Replace HTML entitites
* @link http://www.php.net/htmlentities
*/
define('XML_UTIL_ENTITIES_HTML', 3);
/**
* Do not collapse any empty tags.
*/
define('XML_UTIL_COLLAPSE_NONE', 0);
/**
* Collapse all empty tags.
*/
define('XML_UTIL_COLLAPSE_ALL', 1);
/**
* Collapse only empty XHTML tags that have no end tag.
*/
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
/**
* Utility class for working with XML documents
*
* @category XML
* @package XML_Util
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version Release: 1.4.5
* @link http://pear.php.net/package/XML_Util
*/
class XML_Util
{
/**
* Return API version
*
* @return string $version API version
*/
public static function apiVersion()
{
return '1.4';
}
/**
* Replace XML entities
*
* With the optional second parameter, you may select, which
* entities should be replaced.
*
* <code>
* require_once 'XML/Util.php';
*
* // replace XML entites:
* $string = XML_Util::replaceEntities('This string contains < & >.');
* </code>
*
* With the optional third parameter, you may pass the character encoding
* <code>
* require_once 'XML/Util.php';
*
* // replace XML entites in UTF-8:
* $string = XML_Util::replaceEntities(
* 'This string contains < & > as well as ä, ö, ß, à and ê',
* XML_UTIL_ENTITIES_HTML,
* 'UTF-8'
* );
* </code>
*
* @param string $string string where XML special chars
* should be replaced
* @param int $replaceEntities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
* by the htmlentities() function
*
* @return string string with replaced chars
* @see reverseEntities()
*/
public static function replaceEntities(
$string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
) {
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_XML:
return strtr(
$string,
array(
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
'\'' => '&apos;'
)
);
break;
case XML_UTIL_ENTITIES_XML_REQUIRED:
return strtr(
$string,
array(
'&' => '&amp;',
'<' => '&lt;',
'"' => '&quot;'
)
);
break;
case XML_UTIL_ENTITIES_HTML:
return htmlentities($string, ENT_COMPAT, $encoding);
break;
}
return $string;
}
/**
* Reverse XML entities
*
* With the optional second parameter, you may select, which
* entities should be reversed.
*
* <code>
* require_once 'XML/Util.php';
*
* // reverse XML entites:
* $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
* </code>
*
* With the optional third parameter, you may pass the character encoding
* <code>
* require_once 'XML/Util.php';
*
* // reverse XML entites in UTF-8:
* $string = XML_Util::reverseEntities(
* 'This string contains &lt; &amp; &gt; as well as'
* . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
* XML_UTIL_ENTITIES_HTML,
* 'UTF-8'
* );
* </code>
*
* @param string $string string where XML special chars
* should be replaced
* @param int $replaceEntities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
* by the html_entity_decode() function
*
* @return string string with replaced chars
* @see replaceEntities()
*/
public static function reverseEntities(
$string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
) {
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_XML:
return strtr(
$string,
array(
'&amp;' => '&',
'&gt;' => '>',
'&lt;' => '<',
'&quot;' => '"',
'&apos;' => '\''
)
);
break;
case XML_UTIL_ENTITIES_XML_REQUIRED:
return strtr(
$string,
array(
'&amp;' => '&',
'&lt;' => '<',
'&quot;' => '"'
)
);
break;
case XML_UTIL_ENTITIES_HTML:
return html_entity_decode($string, ENT_COMPAT, $encoding);
break;
}
return $string;
}
/**
* Build an xml declaration
*
* <code>
* require_once 'XML/Util.php';
*
* // get an XML declaration:
* $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
* </code>
*
* @param string $version xml version
* @param string $encoding character encoding
* @param bool $standalone document is standalone (or not)
*
* @return string xml declaration
* @uses attributesToString() to serialize the attributes of the
* XML declaration
*/
public static function getXMLDeclaration(
$version = '1.0', $encoding = null, $standalone = null
) {
$attributes = array(
'version' => $version,
);
// add encoding
if ($encoding !== null) {
$attributes['encoding'] = $encoding;
}
// add standalone, if specified
if ($standalone !== null) {
$attributes['standalone'] = $standalone ? 'yes' : 'no';
}
return sprintf(
'<?xml%s?>',
XML_Util::attributesToString($attributes, false)
);
}
/**
* Build a document type declaration
*
* <code>
* require_once 'XML/Util.php';
*
* // get a doctype declaration:
* $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
* </code>
*
* @param string $root name of the root tag
* @param string $uri uri of the doctype definition
* (or array with uri and public id)
* @param string $internalDtd internal dtd entries
*
* @return string doctype declaration
* @since 0.2
*/
public static function getDocTypeDeclaration(
$root, $uri = null, $internalDtd = null
) {
if (is_array($uri)) {
$ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
} elseif (!empty($uri)) {
$ref = sprintf(' SYSTEM "%s"', $uri);
} else {
$ref = '';
}
if (empty($internalDtd)) {
return sprintf('<!DOCTYPE %s%s>', $root, $ref);
} else {
return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
}
}
/**
* Create string representation of an attribute list
*
* <code>
* require_once 'XML/Util.php';
*
* // build an attribute string
* $att = array(
* 'foo' => 'bar',
* 'argh' => 'tomato'
* );
*
* $attList = XML_Util::attributesToString($att);
* </code>
*
* @param array $attributes attribute array
* @param bool|array $sort sort attribute list alphabetically,
* may also be an assoc array containing
* the keys 'sort', 'multiline', 'indent',
* 'linebreak' and 'entities'
* @param bool $multiline use linebreaks, if more than
* one attribute is given
* @param string $indent string used for indentation of
* multiline attributes
* @param string $linebreak string used for linebreaks of
* multiline attributes
* @param int $entities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_NONE,
* XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
*
* @return string string representation of the attributes
* @uses replaceEntities() to replace XML entities in attribute values
* @todo allow sort also to be an options array
*/
public static function attributesToString(
$attributes, $sort = true, $multiline = false,
$indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
) {
/*
* second parameter may be an array
*/
if (is_array($sort)) {
if (isset($sort['multiline'])) {
$multiline = $sort['multiline'];
}
if (isset($sort['indent'])) {
$indent = $sort['indent'];
}
if (isset($sort['linebreak'])) {
$multiline = $sort['linebreak'];
}
if (isset($sort['entities'])) {
$entities = $sort['entities'];
}
if (isset($sort['sort'])) {
$sort = $sort['sort'];
} else {
$sort = true;
}
}
$string = '';
if (is_array($attributes) && !empty($attributes)) {
if ($sort) {
ksort($attributes);
}
if (!$multiline || count($attributes) == 1) {
foreach ($attributes as $key => $value) {
if ($entities != XML_UTIL_ENTITIES_NONE) {
if ($entities === XML_UTIL_CDATA_SECTION) {
$entities = XML_UTIL_ENTITIES_XML;
}
$value = XML_Util::replaceEntities($value, $entities);
}
$string .= ' ' . $key . '="' . $value . '"';
}
} else {
$first = true;
foreach ($attributes as $key => $value) {
if ($entities != XML_UTIL_ENTITIES_NONE) {
$value = XML_Util::replaceEntities($value, $entities);
}
if ($first) {
$string .= ' ' . $key . '="' . $value . '"';
$first = false;
} else {
$string .= $linebreak . $indent . $key . '="' . $value . '"';
}
}
}
}
return $string;
}
/**
* Collapses empty tags.
*
* @param string $xml XML
* @param int $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
* or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
*
* @return string XML
*/
public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
{
if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
// it's already an empty tag
return $xml;
}
switch ($mode) {
case XML_UTIL_COLLAPSE_ALL:
$preg1 =
'~<' .
'(?:' .
'(https?://[^:\s]+:\w+)' . // <http://foo.com:bar ($1)
'|(\w+:\w+)' . // <foo:bar ($2)
'|(\w+)' . // <foo ($3)
')+' .
'([^>]*)' . // attributes ($4)
'>' .
'<\/(\1|\2|\3)>' . // 1, 2, or 3 again ($5)
'~s'
;
$preg2 =
'<' .
'${1}${2}${3}' . // tag (only one should have been populated)
'${4}' . // attributes
' />'
;
return (preg_replace($preg1, $preg2, $xml)?:$xml);
break;
case XML_UTIL_COLLAPSE_XHTML_ONLY:
return (
preg_replace(
'/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
. 'param)([^>]*)><\/\\1>/s',
'<\\1\\2 />',
$xml
) ?: $xml
);
break;
case XML_UTIL_COLLAPSE_NONE:
// fall thru
default:
return $xml;
}
}
/**
* Create a tag
*
* This method will call XML_Util::createTagFromArray(), which
* is more flexible.
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML tag:
* $tag = XML_Util::createTag('myNs:myTag',
* array('foo' => 'bar'),
* 'This is inside the tag',
* 'http://www.w3c.org/myNs#');
* </code>
*
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param mixed $content the content
* @param string $namespaceUri URI of the namespace
* @param int $replaceEntities whether to replace XML special chars in
* content, embedd it in a CData section
* or none of both
* @param bool $multiline whether to create a multiline tag where
* each attribute gets written to a single line
* @param string $indent string used to indent attributes
* (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
* @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag
*
* @return string XML tag
* @see createTagFromArray()
* @uses createTagFromArray() to create the tag
*/
public static function createTag(
$qname, $attributes = array(), $content = null,
$namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
) {
$tag = array(
'qname' => $qname,
'attributes' => $attributes
);
// add tag content
if ($content !== null) {
$tag['content'] = $content;
}
// add namespace Uri
if ($namespaceUri !== null) {
$tag['namespaceUri'] = $namespaceUri;
}
return XML_Util::createTagFromArray(
$tag, $replaceEntities, $multiline,
$indent, $linebreak, $sortAttributes,
$collapseTagMode
);
}
/**
* Create a tag from an array.
* This method awaits an array in the following format
* <pre>
* array(
* // qualified name of the tag
* 'qname' => $qname
*
* // namespace prefix (optional, if qname is specified or no namespace)
* 'namespace' => $namespace
*
* // local part of the tagname (optional, if qname is specified)
* 'localpart' => $localpart,
*
* // array containing all attributes (optional)
* 'attributes' => array(),
*
* // tag content (optional)
* 'content' => $content,
*
* // namespaceUri for the given namespace (optional)
* 'namespaceUri' => $namespaceUri
* )
* </pre>
*
* <code>
* require_once 'XML/Util.php';
*
* $tag = array(
* 'qname' => 'foo:bar',
* 'namespaceUri' => 'http://foo.com',
* 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
* 'content' => 'I\'m inside the tag',
* );
* // creating a tag with qualified name and namespaceUri
* $string = XML_Util::createTagFromArray($tag);
* </code>
*
* @param array $tag tag definition
* @param int $replaceEntities whether to replace XML special chars in
* content, embedd it in a CData section
* or none of both
* @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
* @param string $indent string used to indent attributes
* (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
* @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag
*
* @return string XML tag
*
* @see createTag()
* @uses attributesToString() to serialize the attributes of the tag
* @uses splitQualifiedName() to get local part and namespace of a qualified name
* @uses createCDataSection()
* @uses collapseEmptyTags()
* @uses raiseError()
*/
public static function createTagFromArray(
$tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
) {
if (isset($tag['content']) && !is_scalar($tag['content'])) {
return XML_Util::raiseError(
'Supplied non-scalar value as tag content',
XML_UTIL_ERROR_NON_SCALAR_CONTENT
);
}
if (!isset($tag['qname']) && !isset($tag['localPart'])) {
return XML_Util::raiseError(
'You must either supply a qualified name '
. '(qname) or local tag name (localPart).',
XML_UTIL_ERROR_NO_TAG_NAME
);
}
// if no attributes hav been set, use empty attributes
if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
$tag['attributes'] = array();
}
if (isset($tag['namespaces'])) {
foreach ($tag['namespaces'] as $ns => $uri) {
$tag['attributes']['xmlns:' . $ns] = $uri;
}
}
if (!isset($tag['qname'])) {
// qualified name is not given
// check for namespace
if (isset($tag['namespace']) && !empty($tag['namespace'])) {
$tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
} else {
$tag['qname'] = $tag['localPart'];
}
} elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
// namespace URI is set, but no namespace
$parts = XML_Util::splitQualifiedName($tag['qname']);
$tag['localPart'] = $parts['localPart'];
if (isset($parts['namespace'])) {
$tag['namespace'] = $parts['namespace'];
}
}
if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
// is a namespace given
if (isset($tag['namespace']) && !empty($tag['namespace'])) {
$tag['attributes']['xmlns:' . $tag['namespace']]
= $tag['namespaceUri'];
} else {
// define this Uri as the default namespace
$tag['attributes']['xmlns'] = $tag['namespaceUri'];
}
}
if (!array_key_exists('content', $tag)) {
$tag['content'] = '';
}
// check for multiline attributes
if ($multiline === true) {
if ($indent === '_auto') {
$indent = str_repeat(' ', (strlen($tag['qname'])+2));
}
}
// create attribute list
$attList = XML_Util::attributesToString(
$tag['attributes'],
$sortAttributes, $multiline, $indent, $linebreak
);
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_NONE:
break;
case XML_UTIL_CDATA_SECTION:
$tag['content'] = XML_Util::createCDataSection($tag['content']);
break;
default:
$tag['content'] = XML_Util::replaceEntities(
$tag['content'], $replaceEntities
);
break;
}
$tag = sprintf(
'<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
$tag['qname']
);
return self::collapseEmptyTags($tag, $collapseTagMode);
}
/**
* Create a start element
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createStartElement('myNs:myTag',
* array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
* </code>
*
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param string $namespaceUri URI of the namespace
* @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents
* attributes so they start at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
*
* @return string XML start element
* @see createEndElement(), createTag()
*/
public static function createStartElement(
$qname, $attributes = array(), $namespaceUri = null,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true
) {
// if no attributes hav been set, use empty attributes
if (!isset($attributes) || !is_array($attributes)) {
$attributes = array();
}
if ($namespaceUri != null) {
$parts = XML_Util::splitQualifiedName($qname);
}
// check for multiline attributes
if ($multiline === true) {
if ($indent === '_auto') {
$indent = str_repeat(' ', (strlen($qname)+2));
}
}
if ($namespaceUri != null) {
// is a namespace given
if (isset($parts['namespace']) && !empty($parts['namespace'])) {
$attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
} else {
// define this Uri as the default namespace
$attributes['xmlns'] = $namespaceUri;
}
}
// create attribute list
$attList = XML_Util::attributesToString(
$attributes, $sortAttributes,
$multiline, $indent, $linebreak
);
$element = sprintf('<%s%s>', $qname, $attList);
return $element;
}
/**
* Create an end element
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createEndElement('myNs:myTag');
* </code>
*
* @param string $qname qualified tagname (including namespace)
*
* @return string XML end element
* @see createStartElement(), createTag()
*/
public static function createEndElement($qname)
{
$element = sprintf('</%s>', $qname);
return $element;
}
/**
* Create an XML comment
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createComment('I am a comment');
* </code>
*
* @param string $content content of the comment
*
* @return string XML comment
*/
public static function createComment($content)
{
$comment = sprintf('<!-- %s -->', $content);
return $comment;
}
/**
* Create a CData section
*
* <code>
* require_once 'XML/Util.php';
*
* // create a CData section
* $tag = XML_Util::createCDataSection('I am content.');
* </code>
*
* @param string $data data of the CData section
*
* @return string CData section with content
*/
public static function createCDataSection($data)
{
return sprintf(
'<![CDATA[%s]]>',
preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))
);
}
/**
* Split qualified name and return namespace and local part
*
* <code>
* require_once 'XML/Util.php';
*
* // split qualified tag
* $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
* </code>
* the returned array will contain two elements:
* <pre>
* array(
* 'namespace' => 'xslt',
* 'localPart' => 'stylesheet'
* );
* </pre>
*
* @param string $qname qualified tag name
* @param string $defaultNs default namespace (optional)
*
* @return array array containing namespace and local part
*/
public static function splitQualifiedName($qname, $defaultNs = null)
{
if (strstr($qname, ':')) {
$tmp = explode(':', $qname);
return array(
'namespace' => $tmp[0],
'localPart' => $tmp[1]
);
}
return array(
'namespace' => $defaultNs,
'localPart' => $qname
);
}
/**
* Check, whether string is valid XML name
*
* <p>XML names are used for tagname, attribute names and various
* other, lesser known entities.</p>
* <p>An XML name may only consist of alphanumeric characters,
* dashes, undescores and periods, and has to start with a letter
* or an underscore.</p>
*
* <code>
* require_once 'XML/Util.php';
*
* // verify tag name
* $result = XML_Util::isValidName('invalidTag?');
* if (is_a($result, 'PEAR_Error')) {
* print 'Invalid XML name: ' . $result->getMessage();
* }
* </code>
*
* @param string $string string that should be checked
*
* @return mixed true, if string is a valid XML name, PEAR error otherwise
*
* @todo support for other charsets
* @todo PEAR CS - unable to avoid 85-char limit on second preg_match
*/
public static function isValidName($string)
{
// check for invalid chars
if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) {
return XML_Util::raiseError(
'XML names may only start with letter or underscore',
XML_UTIL_ERROR_INVALID_START
);
}
// check for invalid chars
$match = preg_match(
'/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
. '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
$string
);
if (!$match) {
return XML_Util::raiseError(
'XML names may only contain alphanumeric '
. 'chars, period, hyphen, colon and underscores',
XML_UTIL_ERROR_INVALID_CHARS
);
}
// XML name is valid
return true;
}
/**
* Replacement for XML_Util::raiseError
*
* Avoids the necessity to always require
* PEAR.php
*
* @param string $msg error message
* @param int $code error code
*
* @return PEAR_Error
* @todo PEAR CS - should this use include_once instead?
*/
public static function raiseError($msg, $code)
{
include_once 'PEAR.php';
return PEAR::raiseError($msg, $code);
}
}
?>

View File

@@ -1,488 +0,0 @@
<?php
/**
* PEAR, the PHP Extension and Application Repository
*
* Command line interface
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
*/
@ob_end_clean();
if (!defined('PEAR_RUNTYPE')) {
// this is defined in peclcmd.php as 'pecl'
define('PEAR_RUNTYPE', 'pear');
}
define('PEAR_IGNORE_BACKTRACE', 1);
/**
* @nodep Gtk
*/
//the space is needed for windows include paths with trailing backslash
// http://pear.php.net/bugs/bug.php?id=19482
if ('/opt/plesk/php/7.4/share/pear ' != '@'.'include_path'.'@ ') {
ini_set('include_path', trim('/opt/plesk/php/7.4/share/pear '). PATH_SEPARATOR . get_include_path());
$raw = false;
} else {
// this is a raw, uninstalled pear, either a cvs checkout, or php distro
ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path());
$raw = true;
}
@ini_set('allow_url_fopen', true);
@set_time_limit(0);
ob_implicit_flush(true);
@ini_set('track_errors', true);
@ini_set('html_errors', false);
$_PEAR_PHPDIR = '#$%^&*';
set_error_handler('error_handler');
$pear_package_version = "1.10.13";
require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/Config.php';
require_once 'PEAR/Command.php';
require_once 'Console/Getopt.php';
PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();
$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
unset($argv[1]);
$argv = array_values($argv);
}
$progname = PEAR_RUNTYPE;
array_shift($argv);
$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
if (PEAR::isError($options)) {
usage($options);
}
$opts = $options[0];
$fetype = 'CLI';
if ($progname == 'gpear' || $progname == 'pear-gtk') {
$fetype = 'Gtk2';
} else {
foreach ($opts as $opt) {
if ($opt[0] == 'G') {
$fetype = 'Gtk2';
}
}
}
$pear_user_config = '';
$pear_system_config = '';
$store_user_config = false;
$store_system_config = false;
$verbose = 1;
foreach ($opts as $opt) {
switch ($opt[0]) {
case 'c':
$pear_user_config = $opt[1];
break;
case 'C':
$pear_system_config = $opt[1];
break;
}
}
PEAR_Command::setFrontendType($fetype);
$ui = &PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);
if (PEAR::isError($config)) {
$_file = '';
if ($pear_user_config !== false) {
$_file .= $pear_user_config;
}
if ($pear_system_config !== false) {
$_file .= '/' . $pear_system_config;
}
if ($_file == '/') {
$_file = 'The default config file';
}
$config->getMessage();
$ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
// We stop, we have no idea where we are :)
exit(1);
}
// this is used in the error handler to retrieve a relative path
$_PEAR_PHPDIR = $config->get('php_dir');
$ui->setConfig($config);
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
$verbose = $config->get("verbose");
$cmdopts = array();
if ($raw) {
if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
$found = false;
foreach ($opts as $opt) {
if ($opt[0] == 'd' || $opt[0] == 'D') {
// the user knows what they are doing, and are setting config values
$found = true;
}
}
if (!$found) {
// no prior runs, try to install PEAR
$parent = dirname(__FILE__);
if (strpos($parent, 'scripts')) {
$grandparent = dirname($parent);
$packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
$pearbase = $grandparent;
} else {
$packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
$pearbase = $parent;
}
if (file_exists($packagexml)) {
$options[1] = array(
'install',
$packagexml
);
$config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
$config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
$config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
$config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
$config->set(
'ext_dir',
$pearbase . DIRECTORY_SEPARATOR . 'extensions'
);
$config->set('bin_dir', $pearbase);
$config->mergeConfigFile($pearbase . 'pear.ini', false);
$config->store();
$config->set('auto_discover', 1);
}
}
}
}
foreach ($opts as $opt) {
$param = !empty($opt[1]) ? $opt[1] : true;
switch ($opt[0]) {
case 'd':
if ($param === true) {
die(
'Invalid usage of "-d" option, expected -d config_value=value, ' .
'received "-d"' . "\n"
);
}
$possible = explode('=', $param);
if (count($possible) != 2) {
die(
'Invalid usage of "-d" option, expected ' .
'-d config_value=value, received "' . $param . '"' . "\n"
);
}
list($key, $value) = explode('=', $param);
$config->set($key, $value, 'user');
break;
case 'D':
if ($param === true) {
die(
'Invalid usage of "-d" option, expected ' .
'-d config_value=value, received "-d"' . "\n"
);
}
$possible = explode('=', $param);
if (count($possible) != 2) {
die(
'Invalid usage of "-d" option, expected ' .
'-d config_value=value, received "' . $param . '"' . "\n"
);
}
list($key, $value) = explode('=', $param);
$config->set($key, $value, 'system');
break;
case 's':
$store_user_config = true;
break;
case 'S':
$store_system_config = true;
break;
case 'u':
$config->remove($param, 'user');
break;
case 'v':
$config->set('verbose', $config->get('verbose') + 1);
break;
case 'q':
$config->set('verbose', $config->get('verbose') - 1);
break;
case 'V':
usage(null, 'version');
case 'c':
case 'C':
break;
default:
// all non pear params goes to the command
$cmdopts[$opt[0]] = $param;
break;
}
}
if ($store_system_config) {
$config->store('system');
}
if ($store_user_config) {
$config->store('user');
}
$command = (isset($options[1][0])) ? $options[1][0] : null;
if (empty($command) && ($store_user_config || $store_system_config)) {
exit;
}
if ($fetype == 'Gtk2') {
if (!$config->validConfiguration()) {
PEAR::raiseError(
"CRITICAL ERROR: no existing valid configuration files found in " .
"files '$pear_user_config' or '$pear_system_config', " .
"please copy an existing configuration file to one of these " .
"locations, or use the -c and -s options to create one"
);
}
Gtk::main();
} else {
do {
if ($command == 'help') {
usage(null, isset($options[1][1]) ? $options[1][1] : null);
}
if (!$config->validConfiguration()) {
PEAR::raiseError(
"CRITICAL ERROR: no existing valid configuration files found " .
"in files '$pear_user_config' or '$pear_system_config', " .
"please copy an existing configuration file to one of " .
"these locations, or use the -c and -s options to create one"
);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$cmd = PEAR_Command::factory($command, $config);
PEAR::popErrorHandling();
if (PEAR::isError($cmd)) {
usage(null, isset($options[1][0]) ? $options[1][0] : null);
}
$short_args = $long_args = null;
PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
array_shift($options[1]);
$tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);
if (PEAR::isError($tmp)) {
break;
}
list($tmpopt, $params) = $tmp;
$opts = array();
foreach ($tmpopt as $foo => $tmp2) {
list($opt, $value) = $tmp2;
if ($value === null) {
$value = true; // options without args
}
if (strlen($opt) == 1) {
$cmdoptions = $cmd->getOptions($command);
foreach ($cmdoptions as $o => $d) {
if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
$opts[$o] = $value;
}
}
} else {
if (substr($opt, 0, 2) == '--') {
$opts[substr($opt, 2)] = $value;
}
}
}
$ok = $cmd->run($command, $opts, $params);
if ($ok === false) {
PEAR::raiseError("unknown command `$command'");
}
if (PEAR::isError($ok)) {
PEAR::setErrorHandling(
PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
);
PEAR::raiseError($ok);
}
} while (false);
}
// {{{ usage()
/**
* Display usage information
*
* @param mixed $error Optional error message
* @param mixed $helpsubject Optional subject/command to display help for
*
* @return void
*/
function usage($error = null, $helpsubject = null)
{
global $progname, $all_commands;
$stdout = fopen('php://stdout', 'w');
if (PEAR::isError($error)) {
fputs($stdout, $error->getMessage() . "\n");
} elseif ($error !== null) {
fputs($stdout, "$error\n");
}
if ($helpsubject != null) {
$put = cmdHelp($helpsubject);
} else {
$put = "Commands:\n";
$maxlen = max(array_map("strlen", $all_commands));
$formatstr = "%-{$maxlen}s %s\n";
ksort($all_commands);
foreach ($all_commands as $cmd => $class) {
$put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
}
$put .=
"Usage: $progname [options] command [command-options] <parameters>\n".
"Type \"$progname help options\" to list all options.\n".
"Type \"$progname help shortcuts\" to list all command shortcuts.\n".
"Type \"$progname help version\" or ".
"\"$progname version\" to list version information.\n".
"Type \"$progname help <command>\" to get the help ".
"for the specified command.";
}
fputs($stdout, "$put\n");
fclose($stdout);
if ($error === null) {
exit(0);
}
exit(1);
}
/**
* Return help string for specified command
*
* @param string $command Command to return help for
*
* @return void
*/
function cmdHelp($command)
{
global $progname, $all_commands, $config;
if ($command == "options") {
return
"Options:\n".
" -v increase verbosity level (default 1)\n".
" -q be quiet, decrease verbosity level\n".
" -c file find user configuration in `file'\n".
" -C file find system configuration in `file'\n".
" -d foo=bar set user config variable `foo' to `bar'\n".
" -D foo=bar set system config variable `foo' to `bar'\n".
" -G start in graphical (Gtk) mode\n".
" -s store user configuration\n".
" -S store system configuration\n".
" -u foo unset `foo' in the user configuration\n".
" -h, -? display help/usage (this message)\n".
" -V version information\n";
} elseif ($command == "shortcuts") {
$sc = PEAR_Command::getShortcuts();
$ret = "Shortcuts:\n";
foreach ($sc as $s => $c) {
$ret .= sprintf(" %-8s %s\n", $s, $c);
}
return $ret;
} elseif ($command == "version") {
return "PEAR Version: ".$GLOBALS['pear_package_version'].
"\nPHP Version: ".phpversion().
"\nZend Engine Version: ".zend_version().
"\nRunning on: ".php_uname();
} elseif ($help = PEAR_Command::getHelp($command)) {
if (is_string($help)) {
return "$progname $command [options] $help\n";
}
if ($help[1] === null) {
return "$progname $command $help[0]";
}
return "$progname $command [options] $help[0]\n$help[1]";
}
return "Command '$command' is not valid, try '$progname help'";
}
// }}}
/**
* error_handler
*
* @param mixed $errno Error number
* @param mixed $errmsg Message
* @param mixed $file Filename
* @param mixed $line Line number
*
* @access public
* @return boolean
*/
function error_handler($errno, $errmsg, $file, $line)
{
if ($errno & E_STRICT) {
return; // E_STRICT
}
if ($errno & E_DEPRECATED) {
return; // E_DEPRECATED
}
if (!(error_reporting() & $errno) &&
isset($GLOBALS['config']) &&
$GLOBALS['config']->get('verbose') < 4
) {
return false; // @silenced error, show all if debug is high enough
}
$errortype = array (
E_DEPRECATED => 'Deprecated Warning',
E_ERROR => "Error",
E_WARNING => "Warning",
E_PARSE => "Parsing Error",
E_STRICT => 'Strict Warning',
E_NOTICE => "Notice",
E_CORE_ERROR => "Core Error",
E_CORE_WARNING => "Core Warning",
E_COMPILE_ERROR => "Compile Error",
E_COMPILE_WARNING => "Compile Warning",
E_USER_ERROR => "User Error",
E_USER_WARNING => "User Warning",
E_USER_NOTICE => "User Notice"
);
$prefix = $errortype[$errno];
global $_PEAR_PHPDIR;
if (stristr($file, $_PEAR_PHPDIR)) {
$file = substr($file, strlen($_PEAR_PHPDIR) + 1);
} else {
$file = basename($file);
}
print "\n$prefix: $errmsg in $file on line $line\n";
return false;
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* indent-tabs-mode: nil
* mode: php
* End:
*/
// vim600:syn=php

Some files were not shown because too many files have changed in this diff Show More