| Current File : /home/mmdealscpanel/yummmdeals.com/PEAR.zip |
PK �1[����
Config.phpnu �[��� <?php
/**
* PEAR_Config, customized configuration handling for the PEAR Installer
*
* 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
*/
/**
* Required for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Registry.php';
require_once 'PEAR/Installer/Role.php';
require_once 'System.php';
/**
* Last created PEAR_Config instance.
* @var object
*/
$GLOBALS['_PEAR_Config_instance'] = null;
if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
$PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
} else {
$PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
}
// Below we define constants with default values for all configuration
// parameters except username/password. All of them can have their
// defaults set through environment variables. The reason we use the
// PHP_ prefix is for some security, PHP protects environment
// variables starting with PHP_*.
// default channel and preferred mirror is based on whether we are invoked through
// the "pear" or the "pecl" command
if (!defined('PEAR_RUNTYPE')) {
define('PEAR_RUNTYPE', 'pear');
}
if (PEAR_RUNTYPE == 'pear') {
define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
} else {
define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
}
if (getenv('PHP_PEAR_SYSCONF_DIR')) {
define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
} elseif (getenv('SystemRoot')) {
define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
} else {
define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
}
// Default for master_server
if (getenv('PHP_PEAR_MASTER_SERVER')) {
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
} else {
define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
}
// Default for http_proxy
if (getenv('PHP_PEAR_HTTP_PROXY')) {
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
} elseif (getenv('http_proxy')) {
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
} else {
define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
}
// Default for php_dir
if (getenv('PHP_PEAR_INSTALL_DIR')) {
define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
}
// Default for metadata_dir
if (getenv('PHP_PEAR_METADATA_DIR')) {
define('PEAR_CONFIG_DEFAULT_METADATA_DIR', getenv('PHP_PEAR_METADATA_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_METADATA_DIR', '');
}
// Default for ext_dir
if (getenv('PHP_PEAR_EXTENSION_DIR')) {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
} else {
if (ini_get('extension_dir')) {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
} elseif (defined('PEAR_EXTENSION_DIR') &&
file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
} elseif (defined('PHP_EXTENSION_DIR')) {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
} else {
define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
}
}
// Default for doc_dir
if (getenv('PHP_PEAR_DOC_DIR')) {
define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_DOC_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
}
// Default for bin_dir
if (getenv('PHP_PEAR_BIN_DIR')) {
define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
}
// Default for data_dir
if (getenv('PHP_PEAR_DATA_DIR')) {
define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_DATA_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
}
// Default for cfg_dir
if (getenv('PHP_PEAR_CFG_DIR')) {
define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_CFG_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
}
// Default for www_dir
if (getenv('PHP_PEAR_WWW_DIR')) {
define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_WWW_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
}
// Default for man_dir
if (getenv('PHP_PEAR_MAN_DIR')) {
define('PEAR_CONFIG_DEFAULT_MAN_DIR', getenv('PHP_PEAR_MAN_DIR'));
} else {
if (defined('PHP_MANDIR')) { // Added in PHP5.3.7
define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_MANDIR);
} else {
define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_PREFIX . DIRECTORY_SEPARATOR .
'local' . DIRECTORY_SEPARATOR .'man');
}
}
// Default for test_dir
if (getenv('PHP_PEAR_TEST_DIR')) {
define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_TEST_DIR',
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
}
// Default for temp_dir
if (getenv('PHP_PEAR_TEMP_DIR')) {
define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'temp');
}
// Default for cache_dir
if (getenv('PHP_PEAR_CACHE_DIR')) {
define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'cache');
}
// Default for download_dir
if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
} else {
define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
DIRECTORY_SEPARATOR . 'download');
}
// Default for php_bin
if (getenv('PHP_PEAR_PHP_BIN')) {
define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
} else {
define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
}
// Default for verbose
if (getenv('PHP_PEAR_VERBOSE')) {
define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
} else {
define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
}
// Default for preferred_state
if (getenv('PHP_PEAR_PREFERRED_STATE')) {
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
} else {
define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
}
// Default for umask
if (getenv('PHP_PEAR_UMASK')) {
define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
} else {
define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
}
// Default for cache_ttl
if (getenv('PHP_PEAR_CACHE_TTL')) {
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
} else {
define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
}
// Default for sig_type
if (getenv('PHP_PEAR_SIG_TYPE')) {
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
} else {
define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
}
// Default for sig_bin
if (getenv('PHP_PEAR_SIG_BIN')) {
define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
} else {
define('PEAR_CONFIG_DEFAULT_SIG_BIN',
System::which(
'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
}
// Default for sig_keydir
if (getenv('PHP_PEAR_SIG_KEYDIR')) {
define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
} else {
define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
}
/**
* This is a class for storing configuration data, keeping track of
* which are system-defined, user-defined or defaulted.
* @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.16
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Config extends PEAR
{
/**
* Array of config files used.
*
* @var array layer => config file
*/
var $files = array(
'system' => '',
'user' => '',
);
var $layers = array();
/**
* Configuration data, two-dimensional array where the first
* dimension is the config layer ('user', 'system' and 'default'),
* and the second dimension is keyname => value.
*
* The order in the first dimension is important! Earlier
* layers will shadow later ones when a config value is
* requested (if a 'user' value exists, it will be returned first,
* then 'system' and finally 'default').
*
* @var array layer => array(keyname => value, ...)
*/
var $configuration = array(
'user' => array(),
'system' => array(),
'default' => array(),
);
/**
* Configuration values that can be set for a channel
*
* All other configuration values can only have a global value
* @var array
* @access private
*/
var $_channelConfigInfo = array(
'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
);
/**
* Channels that can be accessed
* @see setChannels()
* @var array
* @access private
*/
var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
/**
* This variable is used to control the directory values returned
* @see setInstallRoot();
* @var string|false
* @access private
*/
var $_installRoot = false;
/**
* If requested, this will always refer to the registry
* contained in php_dir
* @var PEAR_Registry
*/
var $_registry = array();
/**
* @var array
* @access private
*/
var $_regInitialized = array();
/**
* @var bool
* @access private
*/
var $_noRegistry = false;
/**
* amount of errors found while parsing config
* @var integer
* @access private
*/
var $_errorsFound = 0;
var $_lastError = null;
/**
* Information about the configuration data. Stores the type,
* default value and a documentation string for each configuration
* value.
*
* @var array layer => array(infotype => value, ...)
*/
var $configuration_info = array(
// Channels/Internet Access
'default_channel' => array(
'type' => 'string',
'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
'doc' => 'the default channel to use for all non explicit commands',
'prompt' => 'Default Channel',
'group' => 'Internet Access',
),
'preferred_mirror' => array(
'type' => 'string',
'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
'doc' => 'the default server or mirror to use for channel actions',
'prompt' => 'Default Channel Mirror',
'group' => 'Internet Access',
),
'remote_config' => array(
'type' => 'password',
'default' => '',
'doc' => 'ftp url of remote configuration file to use for synchronized install',
'prompt' => 'Remote Configuration File',
'group' => 'Internet Access',
),
'auto_discover' => array(
'type' => 'integer',
'default' => 0,
'doc' => 'whether to automatically discover new channels',
'prompt' => 'Auto-discover new Channels',
'group' => 'Internet Access',
),
// Internet Access
'master_server' => array(
'type' => 'string',
'default' => 'pear.php.net',
'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
'prompt' => 'PEAR server [DEPRECATED]',
'group' => 'Internet Access',
),
'http_proxy' => array(
'type' => 'string',
'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
'doc' => 'HTTP proxy (host:port) to use when downloading packages',
'prompt' => 'HTTP Proxy Server Address',
'group' => 'Internet Access',
),
// File Locations
'php_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
'doc' => 'directory where .php files are installed',
'prompt' => 'PEAR directory',
'group' => 'File Locations',
),
'ext_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
'doc' => 'directory where loadable extensions are installed',
'prompt' => 'PHP extension directory',
'group' => 'File Locations',
),
'doc_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
'doc' => 'directory where documentation is installed',
'prompt' => 'PEAR documentation directory',
'group' => 'File Locations',
),
'bin_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
'doc' => 'directory where executables are installed',
'prompt' => 'PEAR executables directory',
'group' => 'File Locations',
),
'data_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
'doc' => 'directory where data files are installed',
'prompt' => 'PEAR data directory',
'group' => 'File Locations (Advanced)',
),
'cfg_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
'doc' => 'directory where modifiable configuration files are installed',
'prompt' => 'PEAR configuration file directory',
'group' => 'File Locations (Advanced)',
),
'www_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
'doc' => 'directory where www frontend files (html/js) are installed',
'prompt' => 'PEAR www files directory',
'group' => 'File Locations (Advanced)',
),
'man_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_MAN_DIR,
'doc' => 'directory where unix manual pages are installed',
'prompt' => 'Systems manpage files directory',
'group' => 'File Locations (Advanced)',
),
'test_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
'doc' => 'directory where regression tests are installed',
'prompt' => 'PEAR test directory',
'group' => 'File Locations (Advanced)',
),
'cache_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
'doc' => 'directory which is used for web service cache',
'prompt' => 'PEAR Installer cache directory',
'group' => 'File Locations (Advanced)',
),
'temp_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
'doc' => 'directory which is used for all temp files',
'prompt' => 'PEAR Installer temp directory',
'group' => 'File Locations (Advanced)',
),
'download_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
'doc' => 'directory which is used for all downloaded files',
'prompt' => 'PEAR Installer download directory',
'group' => 'File Locations (Advanced)',
),
'php_bin' => array(
'type' => 'file',
'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
'doc' => 'PHP CLI/CGI binary for executing scripts',
'prompt' => 'PHP CLI/CGI binary',
'group' => 'File Locations (Advanced)',
),
'php_prefix' => array(
'type' => 'string',
'default' => '',
'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
'prompt' => '--program-prefix passed to PHP\'s ./configure',
'group' => 'File Locations (Advanced)',
),
'php_suffix' => array(
'type' => 'string',
'default' => '',
'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
'prompt' => '--program-suffix passed to PHP\'s ./configure',
'group' => 'File Locations (Advanced)',
),
'php_ini' => array(
'type' => 'file',
'default' => '',
'doc' => 'location of php.ini in which to enable PECL extensions on install',
'prompt' => 'php.ini location',
'group' => 'File Locations (Advanced)',
),
'metadata_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_METADATA_DIR,
'doc' => 'directory where metadata files are installed (registry, filemap, channels, ...)',
'prompt' => 'PEAR metadata directory',
'group' => 'File Locations (Advanced)',
),
// Maintainers
'username' => array(
'type' => 'string',
'default' => '',
'doc' => '(maintainers) your PEAR account name',
'prompt' => 'PEAR username (for maintainers)',
'group' => 'Maintainers',
),
'password' => array(
'type' => 'password',
'default' => '',
'doc' => '(maintainers) your PEAR account password',
'prompt' => 'PEAR password (for maintainers)',
'group' => 'Maintainers',
),
// Advanced
'verbose' => array(
'type' => 'integer',
'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
'doc' => 'verbosity level
0: really quiet
1: somewhat quiet
2: verbose
3: debug',
'prompt' => 'Debug Log Level',
'group' => 'Advanced',
),
'preferred_state' => array(
'type' => 'set',
'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
'valid_set' => array(
'stable', 'beta', 'alpha', 'devel', 'snapshot'),
'prompt' => 'Preferred Package State',
'group' => 'Advanced',
),
'umask' => array(
'type' => 'mask',
'default' => PEAR_CONFIG_DEFAULT_UMASK,
'doc' => 'umask used when creating files (Unix-like systems only)',
'prompt' => 'Unix file mask',
'group' => 'Advanced',
),
'cache_ttl' => array(
'type' => 'integer',
'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
'doc' => 'amount of secs where the local cache is used and not updated',
'prompt' => 'Cache TimeToLive',
'group' => 'Advanced',
),
'sig_type' => array(
'type' => 'set',
'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
'doc' => 'which package signature mechanism to use',
'valid_set' => array('gpg'),
'prompt' => 'Package Signature Type',
'group' => 'Maintainers',
),
'sig_bin' => array(
'type' => 'string',
'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
'doc' => 'which package signature mechanism to use',
'prompt' => 'Signature Handling Program',
'group' => 'Maintainers',
),
'sig_keyid' => array(
'type' => 'string',
'default' => '',
'doc' => 'which key to use for signing with',
'prompt' => 'Signature Key Id',
'group' => 'Maintainers',
),
'sig_keydir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
'doc' => 'directory where signature keys are located',
'prompt' => 'Signature Key Directory',
'group' => 'Maintainers',
),
// __channels is reserved - used for channel-specific configuration
);
/**
* Constructor.
*
* @param string file to read user-defined options from
* @param string file to read system-wide defaults from
* @param bool determines whether a registry object "follows"
* the value of php_dir (is automatically created
* and moved when php_dir is changed)
* @param bool if true, fails if configuration files cannot be loaded
*
* @access public
*
* @see PEAR_Config::singleton
*/
function __construct($user_file = '', $system_file = '', $ftp_file = false,
$strict = true)
{
parent::__construct();
PEAR_Installer_Role::initializeConfig($this);
$sl = DIRECTORY_SEPARATOR;
if (empty($user_file)) {
if (OS_WINDOWS) {
$user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
} else {
$user_file = getenv('HOME') . $sl . '.pearrc';
}
}
if (empty($system_file)) {
$system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
if (OS_WINDOWS) {
$system_file .= 'pearsys.ini';
} else {
$system_file .= 'pear.conf';
}
}
$this->layers = array_keys($this->configuration);
$this->files['user'] = $user_file;
$this->files['system'] = $system_file;
if ($user_file && file_exists($user_file)) {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$this->readConfigFile($user_file, 'user', $strict);
$this->popErrorHandling();
if ($this->_errorsFound > 0) {
return;
}
}
if ($system_file && @file_exists($system_file)) {
$this->mergeConfigFile($system_file, false, 'system', $strict);
if ($this->_errorsFound > 0) {
return;
}
}
if (!$ftp_file) {
$ftp_file = $this->get('remote_config');
}
if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
$this->readFTPConfigFile($ftp_file);
}
foreach ($this->configuration_info as $key => $info) {
$this->configuration['default'][$key] = $info['default'];
}
$this->_registry['default'] = new PEAR_Registry(
$this->configuration['default']['php_dir'], false, false,
$this->configuration['default']['metadata_dir']);
$this->_registry['default']->setConfig($this, false);
$this->_regInitialized['default'] = false;
//$GLOBALS['_PEAR_Config_instance'] = &$this;
}
/**
* Return the default locations of user and system configuration files
*/
public static function getDefaultConfigFiles()
{
$sl = DIRECTORY_SEPARATOR;
if (OS_WINDOWS) {
return array(
'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
);
}
return array(
'user' => getenv('HOME') . $sl . '.pearrc',
'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
);
}
/**
* Static singleton method. If you want to keep only one instance
* of this class in use, this method will give you a reference to
* the last created PEAR_Config object if one exists, or create a
* new object.
*
* @param string (optional) file to read user-defined options from
* @param string (optional) file to read system-wide defaults from
*
* @return object an existing or new PEAR_Config instance
*
* @see PEAR_Config::PEAR_Config
*/
public static function &singleton($user_file = '', $system_file = '', $strict = true)
{
if (is_object($GLOBALS['_PEAR_Config_instance'])) {
return $GLOBALS['_PEAR_Config_instance'];
}
$t_conf = new PEAR_Config($user_file, $system_file, false, $strict);
if ($t_conf->_errorsFound > 0) {
return $t_conf->_lastError;
}
$GLOBALS['_PEAR_Config_instance'] = &$t_conf;
return $GLOBALS['_PEAR_Config_instance'];
}
/**
* Determine whether any configuration files have been detected, and whether a
* registry object can be retrieved from this configuration.
* @return bool
* @since PEAR 1.4.0a1
*/
function validConfiguration()
{
if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
return true;
}
return false;
}
/**
* Reads configuration data from a file. All existing values in
* the config layer are discarded and replaced with data from the
* file.
* @param string file to read from, if NULL or not specified, the
* last-used file for the same layer (second param) is used
* @param string config layer to insert data into ('user' or 'system')
* @return bool TRUE on success or a PEAR error on failure
*/
function readConfigFile($file = null, $layer = 'user', $strict = true)
{
if (empty($this->files[$layer])) {
return $this->raiseError("unknown config layer `$layer'");
}
if ($file === null) {
$file = $this->files[$layer];
}
$data = $this->_readConfigDataFrom($file);
if (PEAR::isError($data)) {
if (!$strict) {
return true;
}
$this->_errorsFound++;
$this->_lastError = $data;
return $data;
}
$this->files[$layer] = $file;
$this->_decodeInput($data);
$this->configuration[$layer] = $data;
$this->_setupChannels();
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get('metadata_dir', $layer, 'pear.php.net'));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
}
return true;
}
/**
* @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
* @return true|PEAR_Error
*/
function readFTPConfigFile($path)
{
do { // poor man's try
if (!class_exists('PEAR_FTP')) {
if (!class_exists('PEAR_Common')) {
require_once 'PEAR/Common.php';
}
if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
require_once 'PEAR/FTP.php';
}
}
if (!class_exists('PEAR_FTP')) {
return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
}
$this->_ftp = new PEAR_FTP;
$this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
$e = $this->_ftp->init($path);
if (PEAR::isError($e)) {
$this->_ftp->popErrorHandling();
return $e;
}
$tmp = System::mktemp('-d');
PEAR_Common::addTempFile($tmp);
$e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
'pear.ini', false, FTP_BINARY);
if (PEAR::isError($e)) {
$this->_ftp->popErrorHandling();
return $e;
}
PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
$this->_ftp->disconnect();
$this->_ftp->popErrorHandling();
$this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
$e = $this->readConfigFile(null, 'ftp');
if (PEAR::isError($e)) {
return $e;
}
$fail = array();
foreach ($this->configuration_info as $key => $val) {
if (in_array($this->getGroup($key),
array('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
// any directory configs must be set for this to work
if (!isset($this->configuration['ftp'][$key])) {
$fail[] = $key;
}
}
}
if (!count($fail)) {
return true;
}
$fail = '"' . implode('", "', $fail) . '"';
unset($this->files['ftp']);
unset($this->configuration['ftp']);
return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
'directory configuration variables. These variables were not set: ' .
$fail);
} while (false); // poor man's catch
unset($this->files['ftp']);
return PEAR::raiseError('no remote host specified');
}
/**
* Reads the existing configurations and creates the _channels array from it
*/
function _setupChannels()
{
$set = array_flip(array_values($this->_channels));
foreach ($this->configuration as $layer => $data) {
$i = 1000;
if (isset($data['__channels']) && is_array($data['__channels'])) {
foreach ($data['__channels'] as $channel => $info) {
$set[$channel] = $i++;
}
}
}
$this->_channels = array_values(array_flip($set));
$this->setChannels($this->_channels);
}
function deleteChannel($channel)
{
$ch = strtolower($channel);
foreach ($this->configuration as $layer => $data) {
if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
unset($this->configuration[$layer]['__channels'][$ch]);
}
}
$this->_channels = array_flip($this->_channels);
unset($this->_channels[$ch]);
$this->_channels = array_flip($this->_channels);
}
/**
* Merges data into a config layer from a file. Does the same
* thing as readConfigFile, except it does not replace all
* existing values in the config layer.
* @param string file to read from
* @param bool whether to overwrite existing data (default TRUE)
* @param string config layer to insert data into ('user' or 'system')
* @param string if true, errors are returned if file opening fails
* @return bool TRUE on success or a PEAR error on failure
*/
function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
{
if (empty($this->files[$layer])) {
return $this->raiseError("unknown config layer `$layer'");
}
if ($file === null) {
$file = $this->files[$layer];
}
$data = $this->_readConfigDataFrom($file);
if (PEAR::isError($data)) {
if (!$strict) {
return true;
}
$this->_errorsFound++;
$this->_lastError = $data;
return $data;
}
$this->_decodeInput($data);
if ($override) {
$this->configuration[$layer] =
PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
} else {
$this->configuration[$layer] =
PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
}
$this->_setupChannels();
if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get('metadata_dir', $layer, 'pear.php.net'));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
}
return true;
}
/**
* @param array
* @param array
* @return array
*/
public static function arrayMergeRecursive($arr2, $arr1)
{
$ret = array();
foreach ($arr2 as $key => $data) {
if (!isset($arr1[$key])) {
$ret[$key] = $data;
unset($arr1[$key]);
continue;
}
if (is_array($data)) {
if (!is_array($arr1[$key])) {
$ret[$key] = $arr1[$key];
unset($arr1[$key]);
continue;
}
$ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
unset($arr1[$key]);
}
}
return array_merge($ret, $arr1);
}
/**
* Writes data into a config layer from a file.
*
* @param string|null file to read from, or null for default
* @param string config layer to insert data into ('user' or
* 'system')
* @param string|null data to write to config file or null for internal data [DEPRECATED]
* @return bool TRUE on success or a PEAR error on failure
*/
function writeConfigFile($file = null, $layer = 'user', $data = null)
{
$this->_lazyChannelSetup($layer);
if ($layer == 'both' || $layer == 'all') {
foreach ($this->files as $type => $file) {
$err = $this->writeConfigFile($file, $type, $data);
if (PEAR::isError($err)) {
return $err;
}
}
return true;
}
if (empty($this->files[$layer])) {
return $this->raiseError("unknown config file type `$layer'");
}
if ($file === null) {
$file = $this->files[$layer];
}
$data = ($data === null) ? $this->configuration[$layer] : $data;
$this->_encodeOutput($data);
$opt = array('-p', dirname($file));
if (!@System::mkDir($opt)) {
return $this->raiseError("could not create directory: " . dirname($file));
}
if (file_exists($file) && is_file($file) && !is_writeable($file)) {
return $this->raiseError("no write access to $file!");
}
$fp = @fopen($file, "w");
if (!$fp) {
return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
}
$contents = "#PEAR_Config 0.9\n" . serialize($data);
if (!@fwrite($fp, $contents)) {
return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
}
return true;
}
/**
* Reads configuration data from a file and returns the parsed data
* in an array.
*
* @param string file to read from
* @return array configuration data or a PEAR error on failure
* @access private
*/
function _readConfigDataFrom($file)
{
$fp = false;
if (file_exists($file)) {
$fp = @fopen($file, "r");
}
if (!$fp) {
return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
}
$size = filesize($file);
fclose($fp);
$contents = file_get_contents($file);
if (empty($contents)) {
return $this->raiseError('Configuration file "' . $file . '" is empty');
}
$version = false;
if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
$version = $matches[1];
$contents = substr($contents, strlen($matches[0]));
} else {
// Museum config file
if (substr($contents,0,2) == 'a:') {
$version = '0.1';
}
}
if ($version && version_compare("$version", '1', '<')) {
$data = @unserialize($contents);
if (!is_array($data) && !$data) {
if ($contents == serialize(false)) {
$data = array();
} else {
$err = $this->raiseError("PEAR_Config: bad data in $file");
return $err;
}
}
if (!is_array($data)) {
if (strlen(trim($contents)) > 0) {
$error = "PEAR_Config: bad data in $file";
$err = $this->raiseError($error);
return $err;
}
$data = array();
}
// add parsing of newer formats here...
} else {
$err = $this->raiseError("$file: unknown version `$version'");
return $err;
}
return $data;
}
/**
* Gets the file used for storing the config for a layer
*
* @param string $layer 'user' or 'system'
*/
function getConfFile($layer)
{
return $this->files[$layer];
}
/**
* @param string Configuration class name, used for detecting duplicate calls
* @param array information on a role as parsed from its xml file
* @return true|PEAR_Error
* @access private
*/
function _addConfigVars($class, $vars)
{
static $called = array();
if (isset($called[$class])) {
return;
}
$called[$class] = 1;
if (count($vars) > 3) {
return $this->raiseError('Roles can only define 3 new config variables or less');
}
foreach ($vars as $name => $var) {
if (!is_array($var)) {
return $this->raiseError('Configuration information must be an array');
}
if (!isset($var['type'])) {
return $this->raiseError('Configuration information must contain a type');
} elseif (!in_array($var['type'],
array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
return $this->raiseError(
'Configuration type must be one of directory, file, string, ' .
'mask, set, or password');
}
if (!isset($var['default'])) {
return $this->raiseError(
'Configuration information must contain a default value ("default" index)');
}
if (is_array($var['default'])) {
$real_default = '';
foreach ($var['default'] as $config_var => $val) {
if (strpos($config_var, 'text') === 0) {
$real_default .= $val;
} elseif (strpos($config_var, 'constant') === 0) {
if (!defined($val)) {
return $this->raiseError(
'Unknown constant "' . $val . '" requested in ' .
'default value for configuration variable "' .
$name . '"');
}
$real_default .= constant($val);
} elseif (isset($this->configuration_info[$config_var])) {
$real_default .=
$this->configuration_info[$config_var]['default'];
} else {
return $this->raiseError(
'Unknown request for "' . $config_var . '" value in ' .
'default value for configuration variable "' .
$name . '"');
}
}
$var['default'] = $real_default;
}
if ($var['type'] == 'integer') {
$var['default'] = (integer) $var['default'];
}
if (!isset($var['doc'])) {
return $this->raiseError(
'Configuration information must contain a summary ("doc" index)');
}
if (!isset($var['prompt'])) {
return $this->raiseError(
'Configuration information must contain a simple prompt ("prompt" index)');
}
if (!isset($var['group'])) {
return $this->raiseError(
'Configuration information must contain a simple group ("group" index)');
}
if (isset($this->configuration_info[$name])) {
return $this->raiseError('Configuration variable "' . $name .
'" already exists');
}
$this->configuration_info[$name] = $var;
// fix bug #7351: setting custom config variable in a channel fails
$this->_channelConfigInfo[] = $name;
}
return true;
}
/**
* Encodes/scrambles configuration data before writing to files.
* Currently, 'password' values will be base64-encoded as to avoid
* that people spot cleartext passwords by accident.
*
* @param array (reference) array to encode values in
* @return bool TRUE on success
* @access private
*/
function _encodeOutput(&$data)
{
foreach ($data as $key => $value) {
if ($key == '__channels') {
foreach ($data['__channels'] as $channel => $blah) {
$this->_encodeOutput($data['__channels'][$channel]);
}
}
if (!isset($this->configuration_info[$key])) {
continue;
}
$type = $this->configuration_info[$key]['type'];
switch ($type) {
// we base64-encode passwords so they are at least
// not shown in plain by accident
case 'password': {
$data[$key] = base64_encode($data[$key]);
break;
}
case 'mask': {
$data[$key] = octdec($data[$key]);
break;
}
}
}
return true;
}
/**
* Decodes/unscrambles configuration data after reading from files.
*
* @param array (reference) array to encode values in
* @return bool TRUE on success
* @access private
*
* @see PEAR_Config::_encodeOutput
*/
function _decodeInput(&$data)
{
if (!is_array($data)) {
return true;
}
foreach ($data as $key => $value) {
if ($key == '__channels') {
foreach ($data['__channels'] as $channel => $blah) {
$this->_decodeInput($data['__channels'][$channel]);
}
}
if (!isset($this->configuration_info[$key])) {
continue;
}
$type = $this->configuration_info[$key]['type'];
switch ($type) {
case 'password': {
$data[$key] = base64_decode($data[$key]);
break;
}
case 'mask': {
$data[$key] = decoct($data[$key]);
break;
}
}
}
return true;
}
/**
* Retrieve the default channel.
*
* On startup, channels are not initialized, so if the default channel is not
* pear.php.net, then initialize the config.
* @param string registry layer
* @return string|false
*/
function getDefaultChannel($layer = null)
{
$ret = false;
if ($layer === null) {
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer]['default_channel'])) {
$ret = $this->configuration[$layer]['default_channel'];
break;
}
}
} elseif (isset($this->configuration[$layer]['default_channel'])) {
$ret = $this->configuration[$layer]['default_channel'];
}
if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
$ret = 'pecl.php.net';
}
if ($ret) {
if ($ret != 'pear.php.net') {
$this->_lazyChannelSetup();
}
return $ret;
}
return PEAR_CONFIG_DEFAULT_CHANNEL;
}
/**
* Returns a configuration value, prioritizing layers as per the
* layers property.
*
* @param string config key
* @return mixed the config value, or NULL if not found
* @access public
*/
function get($key, $layer = null, $channel = false)
{
if (!isset($this->configuration_info[$key])) {
return null;
}
if ($key == '__channels') {
return null;
}
if ($key == 'default_channel') {
return $this->getDefaultChannel($layer);
}
if (!$channel) {
$channel = $this->getDefaultChannel();
} elseif ($channel != 'pear.php.net') {
$this->_lazyChannelSetup();
}
$channel = strtolower($channel);
$test = (in_array($key, $this->_channelConfigInfo)) ?
$this->_getChannelValue($key, $layer, $channel) :
null;
if ($test !== null) {
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath($test, $this->_installRoot);
}
}
return $test;
}
if ($layer === null) {
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer][$key])) {
$test = $this->configuration[$layer][$key];
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath($test, $this->_installRoot);
}
}
if ($key == 'preferred_mirror') {
$reg = &$this->getRegistry();
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}
if (!$chan->getMirror($test) && $chan->getName() != $test) {
return $channel; // mirror does not exist
}
}
}
return $test;
}
}
} elseif (isset($this->configuration[$layer][$key])) {
$test = $this->configuration[$layer][$key];
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array('File Locations', 'File Locations (Advanced)')) &&
$this->getType($key) == 'directory') {
return $this->_prependPath($test, $this->_installRoot);
}
}
if ($key == 'preferred_mirror') {
$reg = &$this->getRegistry();
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}
if (!$chan->getMirror($test) && $chan->getName() != $test) {
return $channel; // mirror does not exist
}
}
}
return $test;
}
return null;
}
/**
* Returns a channel-specific configuration value, prioritizing layers as per the
* layers property.
*
* @param string config key
* @return mixed the config value, or NULL if not found
* @access private
*/
function _getChannelValue($key, $layer, $channel)
{
if ($key == '__channels' || $channel == 'pear.php.net') {
return null;
}
$ret = null;
if ($layer === null) {
foreach ($this->layers as $ilayer) {
if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
$ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
break;
}
}
} elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
$ret = $this->configuration[$layer]['__channels'][$channel][$key];
}
if ($key != 'preferred_mirror') {
return $ret;
}
if ($ret !== null) {
$reg = &$this->getRegistry($layer);
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}
if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
return $channel; // mirror does not exist
}
}
return $ret;
}
if ($channel != $this->getDefaultChannel($layer)) {
return $channel; // we must use the channel name as the preferred mirror
// if the user has not chosen an alternate
}
return $this->getDefaultChannel($layer);
}
/**
* Set a config value in a specific layer (defaults to 'user').
* Enforces the types defined in the configuration_info array. An
* integer config variable will be cast to int, and a set config
* variable will be validated against its legal values.
*
* @param string config key
* @param string config value
* @param string (optional) config layer
* @param string channel to set this value for, or null for global value
* @return bool TRUE on success, FALSE on failure
*/
function set($key, $value, $layer = 'user', $channel = false)
{
if ($key == '__channels') {
return false;
}
if (!isset($this->configuration[$layer])) {
return false;
}
if ($key == 'default_channel') {
// can only set this value globally
$channel = 'pear.php.net';
if ($value != 'pear.php.net') {
$this->_lazyChannelSetup($layer);
}
}
if ($key == 'preferred_mirror') {
if ($channel == '__uri') {
return false; // can't set the __uri pseudo-channel's mirror
}
$reg = &$this->getRegistry($layer);
if (is_object($reg)) {
$chan = $reg->getChannel($channel ? $channel : 'pear.php.net');
if (PEAR::isError($chan)) {
return false;
}
if (!$chan->getMirror($value) && $chan->getName() != $value) {
return false; // mirror does not exist
}
}
}
if (!isset($this->configuration_info[$key])) {
return false;
}
extract($this->configuration_info[$key]);
switch ($type) {
case 'integer':
$value = (int)$value;
break;
case 'set': {
// If a valid_set is specified, require the value to
// be in the set. If there is no valid_set, accept
// any value.
if ($valid_set) {
reset($valid_set);
if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
(key($valid_set) !== 0 && empty($valid_set[$value])))
{
return false;
}
}
break;
}
}
if (!$channel) {
$channel = $this->get('default_channel', null, 'pear.php.net');
}
if (!in_array($channel, $this->_channels)) {
$this->_lazyChannelSetup($layer);
$reg = &$this->getRegistry($layer);
if ($reg) {
$channel = $reg->channelName($channel);
}
if (!in_array($channel, $this->_channels)) {
return false;
}
}
if ($channel != 'pear.php.net') {
if (in_array($key, $this->_channelConfigInfo)) {
$this->configuration[$layer]['__channels'][$channel][$key] = $value;
return true;
}
return false;
}
if ($key == 'default_channel') {
if (!isset($reg)) {
$reg = &$this->getRegistry($layer);
if (!$reg) {
$reg = &$this->getRegistry();
}
}
if ($reg) {
$value = $reg->channelName($value);
}
if (!$value) {
return false;
}
}
$this->configuration[$layer][$key] = $value;
if ($key == 'php_dir' && !$this->_noRegistry) {
if (!isset($this->_registry[$layer]) ||
$value != $this->_registry[$layer]->install_dir) {
$this->_registry[$layer] = new PEAR_Registry($value);
$this->_regInitialized[$layer] = false;
$this->_registry[$layer]->setConfig($this, false);
}
}
return true;
}
function _lazyChannelSetup($uselayer = false)
{
if ($this->_noRegistry) {
return;
}
$merge = false;
foreach ($this->_registry as $layer => $p) {
if ($uselayer && $uselayer != $layer) {
continue;
}
if (!$this->_regInitialized[$layer]) {
if ($layer == 'default' && isset($this->_registry['user']) ||
isset($this->_registry['system'])) {
// only use the default registry if there are no alternatives
continue;
}
if (!is_object($this->_registry[$layer])) {
if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get('metadata_dir', $layer, 'pear.php.net'));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
return;
}
}
$this->setChannels($this->_registry[$layer]->listChannels(), $merge);
$this->_regInitialized[$layer] = true;
$merge = true;
}
}
}
/**
* Set the list of channels.
*
* This should be set via a call to {@link PEAR_Registry::listChannels()}
* @param array
* @param bool
* @return bool success of operation
*/
function setChannels($channels, $merge = false)
{
if (!is_array($channels)) {
return false;
}
if ($merge) {
$this->_channels = array_merge($this->_channels, $channels);
} else {
$this->_channels = $channels;
}
foreach ($channels as $channel) {
$channel = strtolower($channel);
if ($channel == 'pear.php.net') {
continue;
}
foreach ($this->layers as $layer) {
if (!isset($this->configuration[$layer]['__channels'])) {
$this->configuration[$layer]['__channels'] = array();
}
if (!isset($this->configuration[$layer]['__channels'][$channel])
|| !is_array($this->configuration[$layer]['__channels'][$channel])) {
$this->configuration[$layer]['__channels'][$channel] = array();
}
}
}
return true;
}
/**
* Get the type of a config value.
*
* @param string config key
*
* @return string type, one of "string", "integer", "file",
* "directory", "set" or "password".
*
* @access public
*
*/
function getType($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key]['type'];
}
return false;
}
/**
* Get the documentation for a config value.
*
* @param string config key
* @return string documentation string
*
* @access public
*
*/
function getDocs($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key]['doc'];
}
return false;
}
/**
* Get the short documentation for a config value.
*
* @param string config key
* @return string short documentation string
*
* @access public
*
*/
function getPrompt($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key]['prompt'];
}
return false;
}
/**
* Get the parameter group for a config key.
*
* @param string config key
* @return string parameter group
*
* @access public
*
*/
function getGroup($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key]['group'];
}
return false;
}
/**
* Get the list of parameter groups.
*
* @return array list of parameter groups
*
* @access public
*
*/
function getGroups()
{
$tmp = array();
foreach ($this->configuration_info as $key => $info) {
$tmp[$info['group']] = 1;
}
return array_keys($tmp);
}
/**
* Get the list of the parameters in a group.
*
* @param string $group parameter group
* @return array list of parameters in $group
*
* @access public
*
*/
function getGroupKeys($group)
{
$keys = array();
foreach ($this->configuration_info as $key => $info) {
if ($info['group'] == $group) {
$keys[] = $key;
}
}
return $keys;
}
/**
* Get the list of allowed set values for a config value. Returns
* NULL for config values that are not sets.
*
* @param string config key
* @return array enumerated array of set values, or NULL if the
* config key is unknown or not a set
*
* @access public
*
*/
function getSetValues($key)
{
if (isset($this->configuration_info[$key]) &&
isset($this->configuration_info[$key]['type']) &&
$this->configuration_info[$key]['type'] == 'set')
{
$valid_set = $this->configuration_info[$key]['valid_set'];
reset($valid_set);
if (key($valid_set) === 0) {
return $valid_set;
}
return array_keys($valid_set);
}
return null;
}
/**
* Get all the current config keys.
*
* @return array simple array of config keys
*
* @access public
*/
function getKeys()
{
$keys = array();
foreach ($this->layers as $layer) {
$test = $this->configuration[$layer];
if (isset($test['__channels'])) {
foreach ($test['__channels'] as $channel => $configs) {
$keys = array_merge($keys, $configs);
}
}
unset($test['__channels']);
$keys = array_merge($keys, $test);
}
return array_keys($keys);
}
/**
* Remove the a config key from a specific config layer.
*
* @param string config key
* @param string (optional) config layer
* @param string (optional) channel (defaults to default channel)
* @return bool TRUE on success, FALSE on failure
*
* @access public
*/
function remove($key, $layer = 'user', $channel = null)
{
if ($channel === null) {
$channel = $this->getDefaultChannel();
}
if ($channel !== 'pear.php.net') {
if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
unset($this->configuration[$layer]['__channels'][$channel][$key]);
return true;
}
}
if (isset($this->configuration[$layer][$key])) {
unset($this->configuration[$layer][$key]);
return true;
}
return false;
}
/**
* Temporarily remove an entire config layer. USE WITH CARE!
*
* @param string config key
* @param string (optional) config layer
* @return bool TRUE on success, FALSE on failure
*
* @access public
*/
function removeLayer($layer)
{
if (isset($this->configuration[$layer])) {
$this->configuration[$layer] = array();
return true;
}
return false;
}
/**
* Stores configuration data in a layer.
*
* @param string config layer to store
* @return bool TRUE on success, or PEAR error on failure
*
* @access public
*/
function store($layer = 'user', $data = null)
{
return $this->writeConfigFile(null, $layer, $data);
}
/**
* Tells what config layer that gets to define a key.
*
* @param string config key
* @param boolean return the defining channel
*
* @return string|array the config layer, or an empty string if not found.
*
* if $returnchannel, the return is an array array('layer' => layername,
* 'channel' => channelname), or an empty string if not found
*
* @access public
*/
function definedBy($key, $returnchannel = false)
{
foreach ($this->layers as $layer) {
$channel = $this->getDefaultChannel();
if ($channel !== 'pear.php.net') {
if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
if ($returnchannel) {
return array('layer' => $layer, 'channel' => $channel);
}
return $layer;
}
}
if (isset($this->configuration[$layer][$key])) {
if ($returnchannel) {
return array('layer' => $layer, 'channel' => 'pear.php.net');
}
return $layer;
}
}
return '';
}
/**
* Tells whether a given key exists as a config value.
*
* @param string config key
* @return bool whether <config key> exists in this object
*
* @access public
*/
function isDefined($key)
{
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer][$key])) {
return true;
}
}
return false;
}
/**
* Tells whether a given config layer exists.
*
* @param string config layer
* @return bool whether <config layer> exists in this object
*
* @access public
*/
function isDefinedLayer($layer)
{
return isset($this->configuration[$layer]);
}
/**
* Returns the layers defined (except the 'default' one)
*
* @return array of the defined layers
*/
function getLayers()
{
$cf = $this->configuration;
unset($cf['default']);
return array_keys($cf);
}
function apiVersion()
{
return '1.1';
}
/**
* @return PEAR_Registry
*/
function &getRegistry($use = null)
{
$layer = $use === null ? 'user' : $use;
if (isset($this->_registry[$layer])) {
return $this->_registry[$layer];
} elseif ($use === null && isset($this->_registry['system'])) {
return $this->_registry['system'];
} elseif ($use === null && isset($this->_registry['default'])) {
return $this->_registry['default'];
} elseif ($use) {
$a = false;
return $a;
}
// only go here if null was passed in
echo "CRITICAL ERROR: Registry could not be initialized from any value";
exit(1);
}
/**
* This is to allow customization like the use of installroot
* @param PEAR_Registry
* @return bool
*/
function setRegistry(&$reg, $layer = 'user')
{
if ($this->_noRegistry) {
return false;
}
if (!in_array($layer, array('user', 'system'))) {
return false;
}
$this->_registry[$layer] = &$reg;
if (is_object($reg)) {
$this->_registry[$layer]->setConfig($this, false);
}
return true;
}
function noRegistry()
{
$this->_noRegistry = true;
}
/**
* @return PEAR_REST
*/
function &getREST($version, $options = array())
{
$version = str_replace('.', '', $version);
if (!class_exists($class = 'PEAR_REST_' . $version)) {
require_once 'PEAR/REST/' . $version . '.php';
}
$remote = new $class($this, $options);
return $remote;
}
/**
* The ftp server is set in {@link readFTPConfigFile()}. It exists only if a
* remote configuration file has been specified
* @return PEAR_FTP|false
*/
function &getFTP()
{
if (isset($this->_ftp)) {
return $this->_ftp;
}
$a = false;
return $a;
}
static function _prependPath($path, $prepend)
{
if (strlen($prepend) > 0) {
if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
if (preg_match('/^[a-z]:/i', $prepend)) {
$prepend = substr($prepend, 2);
} elseif ($prepend[0] != '\\') {
$prepend = "\\$prepend";
}
$path = substr($path, 0, 2) . $prepend . substr($path, 2);
} else {
$path = $prepend . $path;
}
}
return $path;
}
/**
* @param string|false installation directory to prepend to all _dir variables, or false to
* disable
*/
function setInstallRoot($root)
{
if (substr($root, -1) == DIRECTORY_SEPARATOR) {
$root = substr($root, 0, -1);
}
$old = $this->_installRoot;
$this->_installRoot = $root;
if (($old != $root) && !$this->_noRegistry) {
foreach (array_keys($this->_registry) as $layer) {
if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
continue;
}
$this->_registry[$layer] =
new PEAR_Registry(
$this->get('php_dir', $layer, 'pear.php.net'), false, false,
$this->get('metadata_dir', $layer, 'pear.php.net'));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
}
}
}
}
PK �1[�`�eEA EA REST.phpnu �[��� <?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.16
* @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.16/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;
}
}
PK �1[��ym6 m6
Exception.phpnu �[��� <?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.16
* @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 .= '…';
$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> </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();
}
}PK �1[r"�� �� ChannelFile.phpnu �[��� <?php
/**
* PEAR_ChannelFile, the channel handling 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 error handling
*/
require_once 'PEAR/ErrorStack.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Common.php';
/**
* Error code if the channel.xml <channel> tag does not contain a valid version
*/
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
/**
* Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
* currently
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
/**
* Error code if parsing is attempted with no xml extension
*/
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
/**
* Error code if creating the xml parser resource fails
*/
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
/**
* Error code used for all sax xml parsing errors
*/
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
/**#@+
* Validation errors
*/
/**
* Error code when channel name is missing
*/
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
/**
* Error code when channel name is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
/**
* Error code when channel summary is missing
*/
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
/**
* Error code when channel summary is multi-line
*/
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
/**
* Error code when channel server is missing for protocol
*/
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
/**
* Error code when channel server is invalid for protocol
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
/**
* Error code when a mirror name is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
/**
* Error code when a mirror type is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
/**
* Error code when an attempt is made to generate xml, but the parsed content is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
/**
* Error code when an empty package name validate regex is passed in
*/
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
/**
* Error code when a <function> tag has no version
*/
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
/**
* Error code when a <function> tag has no name
*/
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
/**
* Error code when a <validatepackage> tag has no name
*/
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
/**
* Error code when a <validatepackage> tag has no version attribute
*/
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
/**
* Error code when a mirror does not exist but is called for in one of the set*
* methods.
*/
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
/**
* Error code when a server port is not numeric
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
/**
* Error code when <static> contains no version attribute
*/
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
/**
* Error code when <baseurl> contains no type attribute in a <rest> protocol definition
*/
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
/**
* Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
*/
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
/**
* Error code when ssl attribute is present and is not "yes"
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
/**#@-*/
/**
* Mirror types allowed. Currently only internet servers are recognized.
*/
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server');
/**
* The Channel handling class
*
* @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.16
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_ChannelFile
{
/**
* @access private
* @var PEAR_ErrorStack
* @access private
*/
var $_stack;
/**
* Supported channel.xml versions, for parsing
* @var array
* @access private
*/
var $_supportedVersions = array('1.0');
/**
* Parsed channel information
* @var array
* @access private
*/
var $_channelInfo;
/**
* index into the subchannels array, used for parsing xml
* @var int
* @access private
*/
var $_subchannelIndex;
/**
* index into the mirrors array, used for parsing xml
* @var int
* @access private
*/
var $_mirrorIndex;
/**
* Flag used to determine the validity of parsed content
* @var boolean
* @access private
*/
var $_isValid = false;
function __construct()
{
$this->_stack = new PEAR_ErrorStack('PEAR_ChannelFile');
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
$this->_isValid = false;
}
/**
* @return array
* @access protected
*/
function _getErrorMessage()
{
return
array(
PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
PEAR_CHANNELFILE_ERROR_NO_VERSION =>
'No version number found in <channel> tag',
PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
'%error%',
PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
'Unable to create XML parser',
PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
'%error%',
PEAR_CHANNELFILE_ERROR_NO_NAME =>
'Missing channel name',
PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
'Invalid channel %tag% "%name%"',
PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
'Missing channel summary',
PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
'Channel summary should be on one line, but is multi-line',
PEAR_CHANNELFILE_ERROR_NO_HOST =>
'Missing channel server for %type% server',
PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
'Server name "%server%" is invalid for %type% server',
PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
'Invalid mirror name "%name%", mirror type %type%',
PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
'Invalid mirror type "%type%"',
PEAR_CHANNELFILE_ERROR_INVALID =>
'Cannot generate xml, contents are invalid',
PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
'packagenameregex cannot be empty',
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
'%parent% %protocol% function has no version',
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
'%parent% %protocol% function has no name',
PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
'%parent% rest baseurl has no type',
PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
'Validation package has no name in <validatepackage> tag',
PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
'Validation package "%package%" has no version',
PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
'Mirror "%mirror%" does not exist',
PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
'Port "%port%" must be numeric',
PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
'<static> tag must contain version attribute',
PEAR_CHANNELFILE_URI_CANT_MIRROR =>
'The __uri pseudo-channel cannot have mirrors',
PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
'%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
);
}
/**
* @param string contents of package.xml file
* @return bool success of parsing
*/
function fromXmlString($data)
{
if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
if (!in_array($channelversion[1], $this->_supportedVersions)) {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
array('version' => $channelversion[1]));
return false;
}
$parser = new PEAR_XMLParser;
$result = $parser->parse($data);
if ($result !== true) {
if ($result->getCode() == 1) {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
array('error' => $result->getMessage()));
} else {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
}
return false;
}
$this->_channelInfo = $parser->getData();
return true;
} else {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
return false;
}
}
/**
* @return array
*/
function toArray()
{
if (!$this->_isValid && !$this->validate()) {
return false;
}
return $this->_channelInfo;
}
/**
* @param array
*
* @return PEAR_ChannelFile|false false if invalid
*/
public static function &fromArray(
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
) {
$a = new PEAR_ChannelFile($compatibility, $stackClass);
$a->_fromArray($data);
if (!$a->validate()) {
$a = false;
return $a;
}
return $a;
}
/**
* Unlike {@link fromArray()} this does not do any validation
*
* @param array
*
* @return PEAR_ChannelFile
*/
public static function &fromArrayWithErrors(
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
) {
$a = new PEAR_ChannelFile($compatibility, $stackClass);
$a->_fromArray($data);
return $a;
}
/**
* @param array
* @access private
*/
function _fromArray($data)
{
$this->_channelInfo = $data;
}
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getErrors($purge = false)
{
return $this->_stack->getErrors($purge);
}
/**
* 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";
}
}
return $data;
}
/**
* Parse a channel.xml file. Expects the name of
* a channel xml file as input.
*
* @param string $descfile name of channel xml file
* @return bool success of parsing
*/
function fromXmlFile($descfile)
{
if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
(!$fp = fopen($descfile, 'r'))) {
require_once 'PEAR.php';
return PEAR::raiseError("Unable to open $descfile");
}
// read the whole thing so we only get one cdata callback
// for each block of cdata
fclose($fp);
$data = file_get_contents($descfile);
return $this->fromXmlString($data);
}
/**
* Parse channel information from different sources
*
* This method is able to extract information about a channel
* from an .xml file or a string
*
* @access public
* @param string Filename of the source or the source itself
* @return bool
*/
function fromAny($info)
{
if (is_string($info) && file_exists($info) && strlen($info) < 255) {
$tmp = substr($info, -4);
if ($tmp == '.xml') {
$info = $this->fromXmlFile($info);
} else {
$fp = fopen($info, "r");
$test = fread($fp, 5);
fclose($fp);
if ($test == "<?xml") {
$info = $this->fromXmlFile($info);
}
}
if (PEAR::isError($info)) {
require_once 'PEAR.php';
return PEAR::raiseError($info);
}
}
if (is_string($info)) {
$info = $this->fromXmlString($info);
}
return $info;
}
/**
* Return an XML document based on previous parsing and modifications
*
* @return string XML data
*
* @access public
*/
function toXml()
{
if (!$this->_isValid && !$this->validate()) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
return false;
}
if (!isset($this->_channelInfo['attribs']['version'])) {
$this->_channelInfo['attribs']['version'] = '1.0';
}
$channelInfo = $this->_channelInfo;
$ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
$ret .= "<channel version=\"" .
$channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
. $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
$channelInfo['attribs']['version'] . ".xsd\">
<name>$channelInfo[name]</name>
<summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
";
if (isset($channelInfo['suggestedalias'])) {
$ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
}
if (isset($channelInfo['validatepackage'])) {
$ret .= ' <validatepackage version="' .
$channelInfo['validatepackage']['attribs']['version']. '">' .
htmlspecialchars($channelInfo['validatepackage']['_content']) .
"</validatepackage>\n";
}
$ret .= " <servers>\n";
$ret .= ' <primary';
if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
$ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
}
if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
$ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
}
$ret .= ">\n";
if (isset($channelInfo['servers']['primary']['rest'])) {
$ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], ' ');
}
$ret .= " </primary>\n";
if (isset($channelInfo['servers']['mirror'])) {
$ret .= $this->_makeMirrorsXml($channelInfo);
}
$ret .= " </servers>\n";
$ret .= "</channel>";
return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
}
/**
* Generate the <rest> tag
* @access private
*/
function _makeRestXml($info, $indent)
{
$ret = $indent . "<rest>\n";
if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
$info['baseurl'] = array($info['baseurl']);
}
if (isset($info['baseurl'])) {
foreach ($info['baseurl'] as $url) {
$ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
$ret .= ">" . $url['_content'] . "</baseurl>\n";
}
}
$ret .= $indent . "</rest>\n";
return $ret;
}
/**
* Generate the <mirrors> tag
* @access private
*/
function _makeMirrorsXml($channelInfo)
{
$ret = "";
if (!isset($channelInfo['servers']['mirror'][0])) {
$channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
}
foreach ($channelInfo['servers']['mirror'] as $mirror) {
$ret .= ' <mirror host="' . $mirror['attribs']['host'] . '"';
if (isset($mirror['attribs']['port'])) {
$ret .= ' port="' . $mirror['attribs']['port'] . '"';
}
if (isset($mirror['attribs']['ssl'])) {
$ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
}
$ret .= ">\n";
if (isset($mirror['rest'])) {
if (isset($mirror['rest'])) {
$ret .= $this->_makeRestXml($mirror['rest'], ' ');
}
$ret .= " </mirror>\n";
} else {
$ret .= "/>\n";
}
}
return $ret;
}
/**
* Generate the <functions> tag
* @access private
*/
function _makeFunctionsXml($functions, $indent, $rest = false)
{
$ret = '';
if (!isset($functions[0])) {
$functions = array($functions);
}
foreach ($functions as $function) {
$ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
if ($rest) {
$ret .= ' uri="' . $function['attribs']['uri'] . '"';
}
$ret .= ">" . $function['_content'] . "</function>\n";
}
return $ret;
}
/**
* Validation error. Also marks the object contents as invalid
* @param error code
* @param array error information
* @access private
*/
function _validateError($code, $params = array())
{
$this->_stack->push($code, 'error', $params);
$this->_isValid = false;
}
/**
* Validation warning. Does not mark the object contents invalid.
* @param error code
* @param array error information
* @access private
*/
function _validateWarning($code, $params = array())
{
$this->_stack->push($code, 'warning', $params);
}
/**
* Validate parsed file.
*
* @access public
* @return boolean
*/
function validate()
{
$this->_isValid = true;
$info = $this->_channelInfo;
if (empty($info['name'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
} elseif (!$this->validChannelServer($info['name'])) {
if ($info['name'] != '__uri') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
'name' => $info['name']));
}
}
if (empty($info['summary'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
} elseif (strpos(trim($info['summary']), "\n") !== false) {
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $info['summary']));
}
if (isset($info['suggestedalias'])) {
if (!$this->validChannelServer($info['suggestedalias'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
}
}
if (isset($info['localalias'])) {
if (!$this->validChannelServer($info['localalias'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'localalias', 'name' =>$info['localalias']));
}
}
if (isset($info['validatepackage'])) {
if (!isset($info['validatepackage']['_content'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
}
if (!isset($info['validatepackage']['attribs']['version'])) {
$content = isset($info['validatepackage']['_content']) ?
$info['validatepackage']['_content'] :
null;
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
array('package' => $content));
}
}
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
!is_numeric($info['servers']['primary']['attribs']['port'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
array('port' => $info['servers']['primary']['attribs']['port']));
}
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
$info['servers']['primary']['attribs']['ssl'] != 'yes') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
array('ssl' => $info['servers']['primary']['attribs']['ssl'],
'server' => $info['name']));
}
if (isset($info['servers']['primary']['rest']) &&
isset($info['servers']['primary']['rest']['baseurl'])) {
$this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
}
if (isset($info['servers']['mirror'])) {
if ($this->_channelInfo['name'] == '__uri') {
$this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
}
if (!isset($info['servers']['mirror'][0])) {
$info['servers']['mirror'] = array($info['servers']['mirror']);
}
foreach ($info['servers']['mirror'] as $mirror) {
if (!isset($mirror['attribs']['host'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
array('type' => 'mirror'));
} elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
}
if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
}
if (isset($mirror['rest'])) {
$this->_validateFunctions('rest', $mirror['rest']['baseurl'],
$mirror['attribs']['host']);
}
}
}
return $this->_isValid;
}
/**
* @param string rest - protocol name this function applies to
* @param array the functions
* @param string the name of the parent element (mirror name, for instance)
*/
function _validateFunctions($protocol, $functions, $parent = '')
{
if (!isset($functions[0])) {
$functions = array($functions);
}
foreach ($functions as $function) {
if (!isset($function['_content']) || empty($function['_content'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
array('parent' => $parent, 'protocol' => $protocol));
}
if ($protocol == 'rest') {
if (!isset($function['attribs']['type']) ||
empty($function['attribs']['type'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
array('parent' => $parent, 'protocol' => $protocol));
}
} else {
if (!isset($function['attribs']['version']) ||
empty($function['attribs']['version'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
array('parent' => $parent, 'protocol' => $protocol));
}
}
}
}
/**
* Test whether a string contains a valid channel server.
* @param string $ver the package version to test
* @return bool
*/
function validChannelServer($server)
{
if ($server == '__uri') {
return true;
}
return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
}
/**
* @return string|false
*/
function getName()
{
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return false;
}
/**
* @return string|false
*/
function getServer()
{
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return false;
}
/**
* @return int|80 port number to connect to
*/
function getPort($mirror = false)
{
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir['attribs']['port'])) {
return $mir['attribs']['port'];
}
if ($this->getSSL($mirror)) {
return 443;
}
return 80;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
return $this->_channelInfo['servers']['primary']['attribs']['port'];
}
if ($this->getSSL()) {
return 443;
}
return 80;
}
/**
* @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
*/
function getSSL($mirror = false)
{
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir['attribs']['ssl'])) {
return true;
}
return false;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
return true;
}
return false;
}
/**
* @return string|false
*/
function getSummary()
{
if (isset($this->_channelInfo['summary'])) {
return $this->_channelInfo['summary'];
}
return false;
}
/**
* @param string protocol type
* @param string Mirror name
* @return array|false
*/
function getFunctions($protocol, $mirror = false)
{
if ($this->getName() == '__uri') {
return false;
}
$function = $protocol == 'rest' ? 'baseurl' : 'function';
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir[$protocol][$function])) {
return $mir[$protocol][$function];
}
}
return false;
}
if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
return $this->_channelInfo['servers']['primary'][$protocol][$function];
}
return false;
}
/**
* @param string Protocol type
* @param string Function name (null to return the
* first protocol of the type requested)
* @param string Mirror name, if any
* @return array
*/
function getFunction($type, $name = null, $mirror = false)
{
$protocols = $this->getFunctions($type, $mirror);
if (!$protocols) {
return false;
}
foreach ($protocols as $protocol) {
if ($name === null) {
return $protocol;
}
if ($protocol['_content'] != $name) {
continue;
}
return $protocol;
}
return false;
}
/**
* @param string protocol type
* @param string protocol name
* @param string version
* @param string mirror name
* @return boolean
*/
function supports($type, $name = null, $mirror = false, $version = '1.0')
{
$protocols = $this->getFunctions($type, $mirror);
if (!$protocols) {
return false;
}
foreach ($protocols as $protocol) {
if ($protocol['attribs']['version'] != $version) {
continue;
}
if ($name === null) {
return true;
}
if ($protocol['_content'] != $name) {
continue;
}
return true;
}
return false;
}
/**
* Determines whether a channel supports Representational State Transfer (REST) protocols
* for retrieving channel information
* @param string
* @return bool
*/
function supportsREST($mirror = false)
{
if ($mirror == $this->_channelInfo['name']) {
$mirror = false;
}
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
return isset($mir['rest']);
}
return false;
}
return isset($this->_channelInfo['servers']['primary']['rest']);
}
/**
* Get the URL to access a base resource.
*
* Hyperlinks in the returned xml will be used to retrieve the proper information
* needed. This allows extreme extensibility and flexibility in implementation
* @param string Resource Type to retrieve
*/
function getBaseURL($resourceType, $mirror = false)
{
if ($mirror == $this->_channelInfo['name']) {
$mirror = false;
}
if ($mirror) {
$mir = $this->getMirror($mirror);
if (!$mir) {
return false;
}
$rest = $mir['rest'];
} else {
$rest = $this->_channelInfo['servers']['primary']['rest'];
}
if (!isset($rest['baseurl'][0])) {
$rest['baseurl'] = array($rest['baseurl']);
}
foreach ($rest['baseurl'] as $baseurl) {
if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
return $baseurl['_content'];
}
}
return false;
}
/**
* Since REST does not implement RPC, provide this as a logical wrapper around
* resetFunctions for REST
* @param string|false mirror name, if any
*/
function resetREST($mirror = false)
{
return $this->resetFunctions('rest', $mirror);
}
/**
* Empty all protocol definitions
* @param string protocol type
* @param string|false mirror name, if any
*/
function resetFunctions($type, $mirror = false)
{
if ($mirror) {
if (isset($this->_channelInfo['servers']['mirror'])) {
$mirrors = $this->_channelInfo['servers']['mirror'];
if (!isset($mirrors[0])) {
$mirrors = array($mirrors);
}
foreach ($mirrors as $i => $mir) {
if ($mir['attribs']['host'] == $mirror) {
if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
unset($this->_channelInfo['servers']['mirror'][$i][$type]);
}
return true;
}
}
return false;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary'][$type])) {
unset($this->_channelInfo['servers']['primary'][$type]);
}
return true;
}
/**
* Set a channel's protocols to the protocols supported by pearweb
*/
function setDefaultPEARProtocols($version = '1.0', $mirror = false)
{
switch ($version) {
case '1.0' :
$this->resetREST($mirror);
if (!isset($this->_channelInfo['servers'])) {
$this->_channelInfo['servers'] = array('primary' =>
array('rest' => array()));
} elseif (!isset($this->_channelInfo['servers']['primary'])) {
$this->_channelInfo['servers']['primary'] = array('rest' => array());
}
return true;
break;
default :
return false;
break;
}
}
/**
* @return array
*/
function getMirrors()
{
if (isset($this->_channelInfo['servers']['mirror'])) {
$mirrors = $this->_channelInfo['servers']['mirror'];
if (!isset($mirrors[0])) {
$mirrors = array($mirrors);
}
return $mirrors;
}
return array();
}
/**
* Get the unserialized XML representing a mirror
* @return array|false
*/
function getMirror($server)
{
foreach ($this->getMirrors() as $mirror) {
if ($mirror['attribs']['host'] == $server) {
return $mirror;
}
}
return false;
}
/**
* @param string
* @return string|false
* @error PEAR_CHANNELFILE_ERROR_NO_NAME
* @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
*/
function setName($name)
{
return $this->setServer($name);
}
/**
* Set the socket number (port) that is used to connect to this channel
* @param integer
* @param string|false name of the mirror server, or false for the primary
*/
function setPort($port, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
return true;
}
}
return false;
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
$this->_isValid = false;
return true;
}
}
$this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
$this->_isValid = false;
return true;
}
/**
* Set the socket number (port) that is used to connect to this channel
* @param bool Determines whether to turn on SSL support or turn it off
* @param string|false name of the mirror server, or false for the primary
*/
function setSSL($ssl = true, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
if (!$ssl) {
if (isset($this->_channelInfo['servers']['mirror'][$i]
['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
}
} else {
$this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
}
return true;
}
}
return false;
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
if (!$ssl) {
if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
}
} else {
$this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
}
$this->_isValid = false;
return true;
}
}
if ($ssl) {
$this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
} else {
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
}
}
$this->_isValid = false;
return true;
}
/**
* @param string
* @return string|false
* @error PEAR_CHANNELFILE_ERROR_NO_SERVER
* @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
*/
function setServer($server, $mirror = false)
{
if (empty($server)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
return false;
} elseif (!$this->validChannelServer($server)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'name', 'name' => $server));
return false;
}
if ($mirror) {
$found = false;
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$found = true;
break;
}
}
if (!$found) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
return true;
}
$this->_channelInfo['name'] = $server;
return true;
}
/**
* @param string
* @return boolean success
* @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
* @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
*/
function setSummary($summary)
{
if (empty($summary)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
return false;
} elseif (strpos(trim($summary), "\n") !== false) {
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $summary));
}
$this->_channelInfo['summary'] = $summary;
return true;
}
/**
* @param string
* @param boolean determines whether the alias is in channel.xml or local
* @return boolean success
*/
function setAlias($alias, $local = false)
{
if (!$this->validChannelServer($alias)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'suggestedalias', 'name' => $alias));
return false;
}
if ($local) {
$this->_channelInfo['localalias'] = $alias;
} else {
$this->_channelInfo['suggestedalias'] = $alias;
}
return true;
}
/**
* @return string
*/
function getAlias()
{
if (isset($this->_channelInfo['localalias'])) {
return $this->_channelInfo['localalias'];
}
if (isset($this->_channelInfo['suggestedalias'])) {
return $this->_channelInfo['suggestedalias'];
}
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return '';
}
/**
* Set the package validation object if it differs from PEAR's default
* The class must be includeable via changing _ in the classname to path separator,
* but no checking of this is made.
* @param string|false pass in false to reset to the default packagename regex
* @return boolean success
*/
function setValidationPackage($validateclass, $version)
{
if (empty($validateclass)) {
unset($this->_channelInfo['validatepackage']);
}
$this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
$this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
}
/**
* Add a protocol to the provides section
* @param string protocol type
* @param string protocol version
* @param string protocol name, if any
* @param string mirror name, if this is a mirror's protocol
* @return bool
*/
function addFunction($type, $version, $name = '', $mirror = false)
{
if ($mirror) {
return $this->addMirrorFunction($mirror, $type, $version, $name);
}
$set = array('attribs' => array('version' => $version), '_content' => $name);
if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
if (!isset($this->_channelInfo['servers'])) {
$this->_channelInfo['servers'] = array('primary' =>
array($type => array()));
} elseif (!isset($this->_channelInfo['servers']['primary'])) {
$this->_channelInfo['servers']['primary'] = array($type => array());
}
$this->_channelInfo['servers']['primary'][$type]['function'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
$this->_channelInfo['servers']['primary'][$type]['function'] = array(
$this->_channelInfo['servers']['primary'][$type]['function']);
}
$this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
return true;
}
/**
* Add a protocol to a mirror's provides section
* @param string mirror name (server)
* @param string protocol type
* @param string protocol version
* @param string protocol name, if any
*/
function addMirrorFunction($mirror, $type, $version, $name = '')
{
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$setmirror = false;
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$setmirror = &$this->_channelInfo['servers']['mirror'][$i];
break;
}
}
} else {
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$setmirror = &$this->_channelInfo['servers']['mirror'];
}
}
if (!$setmirror) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$set = array('attribs' => array('version' => $version), '_content' => $name);
if (!isset($setmirror[$type]['function'])) {
$setmirror[$type]['function'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($setmirror[$type]['function'][0])) {
$setmirror[$type]['function'] = array($setmirror[$type]['function']);
}
$setmirror[$type]['function'][] = $set;
$this->_isValid = false;
return true;
}
/**
* @param string Resource Type this url links to
* @param string URL
* @param string|false mirror name, if this is not a primary server REST base URL
*/
function setBaseURL($resourceType, $url, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$setmirror = false;
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$setmirror = &$this->_channelInfo['servers']['mirror'][$i];
break;
}
}
} else {
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$setmirror = &$this->_channelInfo['servers']['mirror'];
}
}
} else {
$setmirror = &$this->_channelInfo['servers']['primary'];
}
$set = array('attribs' => array('type' => $resourceType), '_content' => $url);
if (!isset($setmirror['rest'])) {
$setmirror['rest'] = array();
}
if (!isset($setmirror['rest']['baseurl'])) {
$setmirror['rest']['baseurl'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($setmirror['rest']['baseurl'][0])) {
$setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
}
foreach ($setmirror['rest']['baseurl'] as $i => $url) {
if ($url['attribs']['type'] == $resourceType) {
$this->_isValid = false;
$setmirror['rest']['baseurl'][$i] = $set;
return true;
}
}
$setmirror['rest']['baseurl'][] = $set;
$this->_isValid = false;
return true;
}
/**
* @param string mirror server
* @param int mirror http port
* @return boolean
*/
function addMirror($server, $port = null)
{
if ($this->_channelInfo['name'] == '__uri') {
return false; // the __uri channel cannot have mirrors by definition
}
$set = array('attribs' => array('host' => $server));
if (is_numeric($port)) {
$set['attribs']['port'] = $port;
}
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_channelInfo['servers']['mirror'] = $set;
return true;
}
if (!isset($this->_channelInfo['servers']['mirror'][0])) {
$this->_channelInfo['servers']['mirror'] =
array($this->_channelInfo['servers']['mirror']);
}
$this->_channelInfo['servers']['mirror'][] = $set;
return true;
}
/**
* Retrieve the name of the validation package for this channel
* @return string|false
*/
function getValidationPackage()
{
if (!$this->_isValid && !$this->validate()) {
return false;
}
if (!isset($this->_channelInfo['validatepackage'])) {
return array('attribs' => array('version' => 'default'),
'_content' => 'PEAR_Validate');
}
return $this->_channelInfo['validatepackage'];
}
/**
* Retrieve the object that can be used for custom validation
* @param string|false the name of the package to validate. If the package is
* the channel validation package, PEAR_Validate is returned
* @return PEAR_Validate|false false is returned if the validation package
* cannot be located
*/
function &getValidationObject($package = false)
{
if (!class_exists('PEAR_Validate')) {
require_once 'PEAR/Validate.php';
}
if (!$this->_isValid) {
if (!$this->validate()) {
$a = false;
return $a;
}
}
if (isset($this->_channelInfo['validatepackage'])) {
if ($package == $this->_channelInfo['validatepackage']) {
// channel validation packages are always validated by PEAR_Validate
$val = new PEAR_Validate;
return $val;
}
if (!class_exists(str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']))) {
if ($this->isIncludeable(str_replace('_', '/',
$this->_channelInfo['validatepackage']['_content']) . '.php')) {
include_once str_replace('_', '/',
$this->_channelInfo['validatepackage']['_content']) . '.php';
$vclass = str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']);
$val = new $vclass;
} else {
$a = false;
return $a;
}
} else {
$vclass = str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']);
$val = new $vclass;
}
} else {
$val = new PEAR_Validate;
}
return $val;
}
function isIncludeable($path)
{
$possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($possibilities as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
&& is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
return true;
}
}
return false;
}
/**
* This function is used by the channel updater and retrieves a value set by
* the registry, or the current time if it has not been set
* @return string
*/
function lastModified()
{
if (isset($this->_channelInfo['_lastmodified'])) {
return $this->_channelInfo['_lastmodified'];
}
return time();
}
}
PK �1[��gk�U �U Validate.phpnu �[��� <?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.16
* @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;
}
}PK �1[d֣S� � Command/Pickle.xmlnu �[��� <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 "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.
</doc>
</pickle>
</commands>PK �1[�z��k<