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