2 // /* vim: set expandtab tabstop=4 shiftwidth=4: */
4 * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
5 * channel-update, channel-info, channel-alias, channel-discover commands)
11 * @author Stig Bakken <ssb@php.net>
12 * @author Greg Beaver <cellog@php.net>
13 * @copyright 1997-2009 The Authors
14 * @license http://opensource.org/licenses/bsd-license.php New BSD License
15 * @link http://pear.php.net/package/PEAR
16 * @since File available since Release 1.4.0a1
22 require_once 'PEAR/Command/Common.php';
24 define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
27 * PEAR commands for managing channels.
31 * @author Greg Beaver <cellog@php.net>
32 * @copyright 1997-2009 The Authors
33 * @license http://opensource.org/licenses/bsd-license.php New BSD License
34 * @version Release: 1.10.4
35 * @link http://pear.php.net/package/PEAR
36 * @since Class available since Release 1.4.0a1
38 class PEAR_Command_Channels extends PEAR_Command_Common
40 var $commands = array(
41 'list-channels' => array(
42 'summary' => 'List Available Channels',
43 'function' => 'doList',
47 List all available channels for installation.
50 'update-channels' => array(
51 'summary' => 'Update the Channel List',
52 'function' => 'doUpdateAll',
56 List all installed packages in all channels.
59 'channel-delete' => array(
60 'summary' => 'Remove a Channel From the List',
61 'function' => 'doDelete',
64 'doc' => '<channel name>
65 Delete a channel from the registry. You may not
66 remove any channel that has installed packages.
69 'channel-add' => array(
70 'summary' => 'Add a Channel',
71 'function' => 'doAdd',
74 'doc' => '<channel.xml>
75 Add a private channel to the channel list. Note that all
76 public channels should be synced using "update-channels".
77 Parameter may be either a local file or remote URL to a
81 'channel-update' => array(
82 'summary' => 'Update an Existing Channel',
83 'function' => 'doUpdate',
88 'doc' => 'will force download of new channel.xml if an existing channel name is used',
93 'doc' => 'will force download of new channel.xml if an existing channel name is used',
96 'doc' => '[<channel.xml>|<channel name>]
97 Update a channel in the channel list directly. Note that all
98 public channels can be synced using "update-channels".
99 Parameter may be a local or remote channel.xml, or the name of
103 'channel-info' => array(
104 'summary' => 'Retrieve Information on a Channel',
105 'function' => 'doInfo',
107 'options' => array(),
109 List the files in an installed package.
112 'channel-alias' => array(
113 'summary' => 'Specify an alias to a channel name',
114 'function' => 'doAlias',
116 'options' => array(),
117 'doc' => '<channel> <alias>
118 Specify a specific alias to use for a channel name.
119 The alias may not be an existing channel name or
123 'channel-discover' => array(
124 'summary' => 'Initialize a Channel from its server',
125 'function' => 'doDiscover',
127 'options' => array(),
128 'doc' => '[<channel.xml>|<channel name>]
129 Initialize a channel from its server and create a local channel.xml.
130 If <channel name> is in the format "<username>:<password>@<channel>" then
131 <username> and <password> will be set as the login username/password for
132 <channel>. Use caution when passing the username/password in this way, as
133 it may allow other users on your computer to briefly view your username/
134 password via the system\'s process list.
137 'channel-login' => array(
138 'summary' => 'Connects and authenticates to remote channel server',
140 'function' => 'doLogin',
141 'options' => array(),
142 'doc' => '<channel name>
143 Log in to a remote channel server. If <channel name> is not supplied,
144 the default channel is used. To use remote functions in the installer
145 that require any kind of privileges, you need to log in first. The
146 username and password you enter here will be stored in your per-user
147 PEAR configuration (~/.pearrc on Unix-like systems). After logging
148 in, your username and password will be sent along in subsequent
149 operations on the remote server.',
151 'channel-logout' => array(
152 'summary' => 'Logs out from the remote channel server',
154 'function' => 'doLogout',
155 'options' => array(),
156 'doc' => '<channel name>
157 Logs out from a remote channel server. If <channel name> is not supplied,
158 the default channel is used. This command does not actually connect to the
159 remote server, it only deletes the stored username and password from your user
165 * PEAR_Command_Registry constructor.
169 function __construct(&$ui, &$config)
171 parent::__construct($ui, $config);
174 function _sortChannels($a, $b)
176 return strnatcasecmp($a->getName(), $b->getName());
179 function doList($command, $options, $params)
181 $reg = &$this->config->getRegistry();
182 $registered = $reg->getChannels();
183 usort($registered, array(&$this, '_sortchannels'));
186 'caption' => 'Registered Channels:',
188 'headline' => array('Channel', 'Alias', 'Summary')
190 foreach ($registered as $channel) {
191 $data['data'][] = array($channel->getName(),
192 $channel->getAlias(),
193 $channel->getSummary());
196 if (count($registered) === 0) {
197 $data = '(no registered channels)';
199 $this->ui->outputData($data, $command);
203 function doUpdateAll($command, $options, $params)
205 $reg = &$this->config->getRegistry();
206 $channels = $reg->getChannels();
209 foreach ($channels as $channel) {
210 if ($channel->getName() != '__uri') {
211 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
212 $err = $this->doUpdate('channel-update',
214 array($channel->getName()));
215 if (PEAR::isError($err)) {
216 $this->ui->outputData($err->getMessage(), $command);
226 function doInfo($command, $options, $params)
228 if (count($params) !== 1) {
229 return $this->raiseError("No channel specified");
232 $reg = &$this->config->getRegistry();
233 $channel = strtolower($params[0]);
234 if ($reg->channelExists($channel)) {
235 $chan = $reg->getChannel($channel);
236 if (PEAR::isError($chan)) {
237 return $this->raiseError($chan);
240 if (strpos($channel, '://')) {
241 $downloader = &$this->getDownloader();
242 $tmpdir = $this->config->get('temp_dir');
243 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
244 $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
245 PEAR::staticPopErrorHandling();
246 if (PEAR::isError($loc)) {
247 return $this->raiseError('Cannot open "' . $channel .
248 '" (' . $loc->getMessage() . ')');
250 $contents = implode('', file($loc));
253 if (!file_exists($params[0])) {
254 return $this->raiseError('Unknown channel "' . $channel . '"');
257 $fp = fopen($params[0], 'r');
259 return $this->raiseError('Cannot open "' . $params[0] . '"');
264 $contents .= fread($fp, 1024);
269 if (!class_exists('PEAR_ChannelFile')) {
270 require_once 'PEAR/ChannelFile.php';
273 $chan = new PEAR_ChannelFile;
274 $chan->fromXmlString($contents);
276 if ($errs = $chan->getErrors(true)) {
277 foreach ($errs as $err) {
278 $this->ui->outputData($err['level'] . ': ' . $err['message']);
280 return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
285 return $this->raiseError('Serious error: Channel "' . $params[0] .
286 '" has a corrupted registry entry');
289 $channel = $chan->getName();
290 $caption = 'Channel ' . $channel . ' Information:';
292 'caption' => $caption,
294 $data1['data']['server'] = array('Name and Server', $chan->getName());
295 if ($chan->getAlias() != $chan->getName()) {
296 $data1['data']['alias'] = array('Alias', $chan->getAlias());
299 $data1['data']['summary'] = array('Summary', $chan->getSummary());
300 $validate = $chan->getValidationPackage();
301 $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
302 $data1['data']['vpackageversion'] =
303 array('Validation Package Version', $validate['attribs']['version']);
307 $data['data'] = array();
308 $data['caption'] = 'Server Capabilities';
309 $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
310 if ($chan->supportsREST()) {
311 if ($chan->supportsREST()) {
312 $funcs = $chan->getFunctions('rest');
313 if (!isset($funcs[0])) {
314 $funcs = array($funcs);
316 foreach ($funcs as $protocol) {
317 $data['data'][] = array('rest', $protocol['attribs']['type'],
318 $protocol['_content']);
322 $data['data'][] = array('No supported protocols');
325 $d['protocols'] = $data;
326 $data['data'] = array();
327 $mirrors = $chan->getMirrors();
329 $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
330 unset($data['headline']);
331 foreach ($mirrors as $mirror) {
332 $data['data'][] = array($mirror['attribs']['host']);
333 $d['mirrors'] = $data;
336 foreach ($mirrors as $i => $mirror) {
337 $data['data'] = array();
338 $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
339 $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
340 if ($chan->supportsREST($mirror['attribs']['host'])) {
341 if ($chan->supportsREST($mirror['attribs']['host'])) {
342 $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
343 if (!isset($funcs[0])) {
344 $funcs = array($funcs);
347 foreach ($funcs as $protocol) {
348 $data['data'][] = array('rest', $protocol['attribs']['type'],
349 $protocol['_content']);
353 $data['data'][] = array('No supported protocols');
355 $d['mirrorprotocols' . $i] = $data;
358 $this->ui->outputData($d, 'channel-info');
363 function doDelete($command, $options, $params)
365 if (count($params) !== 1) {
366 return $this->raiseError('channel-delete: no channel specified');
369 $reg = &$this->config->getRegistry();
370 if (!$reg->channelExists($params[0])) {
371 return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
374 $channel = $reg->channelName($params[0]);
375 if ($channel == 'pear.php.net') {
376 return $this->raiseError('Cannot delete the pear.php.net channel');
379 if ($channel == 'pecl.php.net') {
380 return $this->raiseError('Cannot delete the pecl.php.net channel');
383 if ($channel == 'doc.php.net') {
384 return $this->raiseError('Cannot delete the doc.php.net channel');
387 if ($channel == '__uri') {
388 return $this->raiseError('Cannot delete the __uri pseudo-channel');
391 if (PEAR::isError($err = $reg->listPackages($channel))) {
396 return $this->raiseError('Channel "' . $channel .
397 '" has installed packages, cannot delete');
400 if (!$reg->deleteChannel($channel)) {
401 return $this->raiseError('Channel "' . $channel . '" deletion failed');
403 $this->config->deleteChannel($channel);
404 $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
408 function doAdd($command, $options, $params)
410 if (count($params) !== 1) {
411 return $this->raiseError('channel-add: no channel file specified');
414 if (strpos($params[0], '://')) {
415 $downloader = &$this->getDownloader();
416 $tmpdir = $this->config->get('temp_dir');
417 if (!file_exists($tmpdir)) {
418 require_once 'System.php';
419 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
420 $err = System::mkdir(array('-p', $tmpdir));
421 PEAR::staticPopErrorHandling();
422 if (PEAR::isError($err)) {
423 return $this->raiseError('channel-add: temp_dir does not exist: "' .
425 '" - You can change this location with "pear config-set temp_dir"');
429 if (!is_writable($tmpdir)) {
430 return $this->raiseError('channel-add: temp_dir is not writable: "' .
432 '" - You can change this location with "pear config-set temp_dir"');
435 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
436 $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
437 PEAR::staticPopErrorHandling();
438 if (PEAR::isError($loc)) {
439 return $this->raiseError('channel-add: Cannot open "' . $params[0] .
440 '" (' . $loc->getMessage() . ')');
443 list($loc, $lastmodified) = $loc;
444 $contents = implode('', file($loc));
446 $lastmodified = $fp = false;
447 if (file_exists($params[0])) {
448 $fp = fopen($params[0], 'r');
452 return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
457 $contents .= fread($fp, 1024);
462 if (!class_exists('PEAR_ChannelFile')) {
463 require_once 'PEAR/ChannelFile.php';
466 $channel = new PEAR_ChannelFile;
467 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
468 $result = $channel->fromXmlString($contents);
469 PEAR::staticPopErrorHandling();
472 if (count($errors = $channel->getErrors(true))) {
473 foreach ($errors as $error) {
474 $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
476 $exit = $error['level'] == 'error' ? true : false;
480 return $this->raiseError('channel-add: invalid channel.xml file');
485 $reg = &$this->config->getRegistry();
486 if ($reg->channelExists($channel->getName())) {
487 return $this->raiseError('channel-add: Channel "' . $channel->getName() .
488 '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
491 $ret = $reg->addChannel($channel, $lastmodified);
492 if (PEAR::isError($ret)) {
497 return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
498 '" to registry failed');
501 $this->config->setChannels($reg->listChannels());
502 $this->config->writeConfigFile();
503 $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
506 function doUpdate($command, $options, $params)
508 if (count($params) !== 1) {
509 return $this->raiseError("No channel file specified");
512 $tmpdir = $this->config->get('temp_dir');
513 if (!file_exists($tmpdir)) {
514 require_once 'System.php';
515 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
516 $err = System::mkdir(array('-p', $tmpdir));
517 PEAR::staticPopErrorHandling();
518 if (PEAR::isError($err)) {
519 return $this->raiseError('channel-add: temp_dir does not exist: "' .
521 '" - You can change this location with "pear config-set temp_dir"');
525 if (!is_writable($tmpdir)) {
526 return $this->raiseError('channel-add: temp_dir is not writable: "' .
528 '" - You can change this location with "pear config-set temp_dir"');
531 $reg = &$this->config->getRegistry();
532 $lastmodified = false;
533 if ((!file_exists($params[0]) || is_dir($params[0]))
534 && $reg->channelExists(strtolower($params[0]))) {
535 $c = $reg->getChannel(strtolower($params[0]));
536 if (PEAR::isError($c)) {
537 return $this->raiseError($c);
540 $this->ui->outputData("Updating channel \"$params[0]\"", $command);
541 $dl = &$this->getDownloader(array());
542 // if force is specified, use a timestamp of "1" to force retrieval
543 $lastmodified = isset($options['force']) ? false : $c->lastModified();
544 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
545 $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
546 $this->ui, $tmpdir, null, $lastmodified);
547 PEAR::staticPopErrorHandling();
548 if (PEAR::isError($contents)) {
549 // Attempt to fall back to https
550 $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
551 $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
552 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
553 $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
554 $this->ui, $tmpdir, null, $lastmodified);
555 PEAR::staticPopErrorHandling();
556 if (PEAR::isError($contents)) {
557 return $this->raiseError('Cannot retrieve channel.xml for channel "' .
558 $c->getName() . '" (' . $contents->getMessage() . ')');
562 list($contents, $lastmodified) = $contents;
564 $this->ui->outputData("Channel \"$params[0]\" is up to date");
568 $contents = implode('', file($contents));
569 if (!class_exists('PEAR_ChannelFile')) {
570 require_once 'PEAR/ChannelFile.php';
573 $channel = new PEAR_ChannelFile;
574 $channel->fromXmlString($contents);
575 if (!$channel->getErrors()) {
576 // security check: is the downloaded file for the channel we got it from?
577 if (strtolower($channel->getName()) != strtolower($c->getName())) {
578 if (!isset($options['force'])) {
579 return $this->raiseError('ERROR: downloaded channel definition file' .
580 ' for channel "' . $channel->getName() . '" from channel "' .
581 strtolower($c->getName()) . '"');
584 $this->ui->log(0, 'WARNING: downloaded channel definition file' .
585 ' for channel "' . $channel->getName() . '" from channel "' .
586 strtolower($c->getName()) . '"');
590 if (strpos($params[0], '://')) {
591 $dl = &$this->getDownloader();
592 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
593 $loc = $dl->downloadHttp($params[0],
594 $this->ui, $tmpdir, null, $lastmodified);
595 PEAR::staticPopErrorHandling();
596 if (PEAR::isError($loc)) {
597 return $this->raiseError("Cannot open " . $params[0] .
598 ' (' . $loc->getMessage() . ')');
601 list($loc, $lastmodified) = $loc;
602 $contents = implode('', file($loc));
605 if (file_exists($params[0])) {
606 $fp = fopen($params[0], 'r');
610 return $this->raiseError("Cannot open " . $params[0]);
615 $contents .= fread($fp, 1024);
620 if (!class_exists('PEAR_ChannelFile')) {
621 require_once 'PEAR/ChannelFile.php';
624 $channel = new PEAR_ChannelFile;
625 $channel->fromXmlString($contents);
629 if (count($errors = $channel->getErrors(true))) {
630 foreach ($errors as $error) {
631 $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
633 $exit = $error['level'] == 'error' ? true : false;
637 return $this->raiseError('Invalid channel.xml file');
641 if (!$reg->channelExists($channel->getName())) {
642 return $this->raiseError('Error: Channel "' . $channel->getName() .
643 '" does not exist, use channel-add to add an entry');
646 $ret = $reg->updateChannel($channel, $lastmodified);
647 if (PEAR::isError($ret)) {
652 return $this->raiseError('Updating Channel "' . $channel->getName() .
653 '" in registry failed');
656 $this->config->setChannels($reg->listChannels());
657 $this->config->writeConfigFile();
658 $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
661 function &getDownloader()
663 if (!class_exists('PEAR_Downloader')) {
664 require_once 'PEAR/Downloader.php';
666 $a = new PEAR_Downloader($this->ui, array(), $this->config);
670 function doAlias($command, $options, $params)
672 if (count($params) === 1) {
673 return $this->raiseError('No channel alias specified');
676 if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
677 return $this->raiseError(
678 'Invalid format, correct is: channel-alias channel alias');
681 $reg = &$this->config->getRegistry();
682 if (!$reg->channelExists($params[0], true)) {
684 if ($reg->isAlias($params[0])) {
685 $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
686 strtolower($params[1]) . '")';
689 return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
692 if ($reg->isAlias($params[1])) {
693 return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
694 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
697 $chan = $reg->getChannel($params[0]);
698 if (PEAR::isError($chan)) {
699 return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
700 '" information (' . $chan->getMessage() . ')');
703 // make it a local alias
704 if (!$chan->setAlias(strtolower($params[1]), true)) {
705 return $this->raiseError('Alias "' . strtolower($params[1]) .
706 '" is not a valid channel alias');
709 $reg->updateChannel($chan);
710 $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
711 strtolower($params[1]) . '"');
715 * The channel-discover command
717 * @param string $command command name
718 * @param array $options option_name => value
719 * @param array $params list of additional parameters.
720 * $params[0] should contain a string with either:
721 * - <channel name> or
722 * - <username>:<password>@<channel name>
723 * @return null|PEAR_Error
725 function doDiscover($command, $options, $params)
727 if (count($params) !== 1) {
728 return $this->raiseError("No channel server specified");
731 // Look for the possible input format "<username>:<password>@<channel>"
732 if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
733 $username = $matches[1];
734 $password = $matches[2];
735 $channel = $matches[3];
737 $channel = $params[0];
740 $reg = &$this->config->getRegistry();
741 if ($reg->channelExists($channel)) {
742 if (!$reg->isAlias($channel)) {
743 return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
746 return $this->raiseError("A channel alias named \"$channel\" " .
747 'already exists, aliasing channel "' . $reg->channelName($channel)
751 $this->pushErrorHandling(PEAR_ERROR_RETURN);
752 $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
753 $this->popErrorHandling();
754 if (PEAR::isError($err)) {
755 if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
756 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
757 $err->getMessage() . ')');
759 // Attempt fetch via https
760 $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
761 $this->ui->outputData("Trying to discover channel $channel over https:// instead");
762 $this->pushErrorHandling(PEAR_ERROR_RETURN);
763 $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
764 $this->popErrorHandling();
765 if (PEAR::isError($err)) {
766 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
767 $err->getMessage() . ')');
771 // Store username/password if they were given
772 // Arguably we should do a logintest on the channel here, but since
773 // that's awkward on a REST-based channel (even "pear login" doesn't
774 // do it for those), and XML-RPC is deprecated, it's fairly pointless.
775 if (isset($username)) {
776 $this->config->set('username', $username, 'user', $channel);
777 $this->config->set('password', $password, 'user', $channel);
778 $this->config->store();
779 $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
782 $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
786 * Execute the 'login' command.
788 * @param string $command command name
789 * @param array $options option_name => value
790 * @param array $params list of additional parameters
792 * @return bool TRUE on success or
793 * a PEAR error on failure
797 function doLogin($command, $options, $params)
799 $reg = &$this->config->getRegistry();
801 // If a parameter is supplied, use that as the channel to log in to
802 $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
804 $chan = $reg->getChannel($channel);
805 if (PEAR::isError($chan)) {
806 return $this->raiseError($chan);
809 $server = $this->config->get('preferred_mirror', null, $channel);
810 $username = $this->config->get('username', null, $channel);
811 if (empty($username)) {
812 $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
814 $this->ui->outputData("Logging in to $server.", $command);
816 list($username, $password) = $this->ui->userDialog(
818 array('Username', 'Password'),
819 array('text', 'password'),
822 $username = trim($username);
823 $password = trim($password);
825 $ourfile = $this->config->getConfFile('user');
827 $ourfile = $this->config->getConfFile('system');
830 $this->config->set('username', $username, 'user', $channel);
831 $this->config->set('password', $password, 'user', $channel);
833 if ($chan->supportsREST()) {
838 return $this->raiseError('Login failed!');
841 $this->ui->outputData("Logged in.", $command);
842 // avoid changing any temporary settings changed with -d
843 $ourconfig = new PEAR_Config($ourfile, $ourfile);
844 $ourconfig->set('username', $username, 'user', $channel);
845 $ourconfig->set('password', $password, 'user', $channel);
852 * Execute the 'logout' command.
854 * @param string $command command name
855 * @param array $options option_name => value
856 * @param array $params list of additional parameters
858 * @return bool TRUE on success or
859 * a PEAR error on failure
863 function doLogout($command, $options, $params)
865 $reg = &$this->config->getRegistry();
867 // If a parameter is supplied, use that as the channel to log in to
868 $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
870 $chan = $reg->getChannel($channel);
871 if (PEAR::isError($chan)) {
872 return $this->raiseError($chan);
875 $server = $this->config->get('preferred_mirror', null, $channel);
876 $this->ui->outputData("Logging out from $server.", $command);
877 $this->config->remove('username', 'user', $channel);
878 $this->config->remove('password', 'user', $channel);
879 $this->config->store();