Хранилища Subversion ant

Редакция

Содержимое файла | Последнее изменение | Открыть журнал | RSS

Редакция Автор № строки Строка
69 alex-w 1
<?php
2
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
3
/**
4
 * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
5
 * channel-update, channel-info, channel-alias, channel-discover commands)
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: This source file is subject to version 3.0 of the PHP license
10
 * that is available through the world-wide-web at the following URI:
11
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
12
 * the PHP License and are unable to obtain it through the web, please
13
 * send a note to license@php.net so we can mail you a copy immediately.
14
 *
15
 * @category   pear
16
 * @package    PEAR
17
 * @author     Stig Bakken <ssb@php.net>
18
 * @author     Greg Beaver <cellog@php.net>
19
 * @copyright  1997-2008 The PHP Group
20
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
21
 * @version    CVS: $Id: Channels.php,v 1.57 2008/01/03 20:26:36 cellog Exp $
22
 * @link       http://pear.php.net/package/PEAR
23
 * @since      File available since Release 1.4.0a1
24
 */
25
 
26
/**
27
 * base class
28
 */
29
require_once 'PEAR/Command/Common.php';
30
 
31
/**
32
 * PEAR commands for managing channels.
33
 *
34
 * @category   pear
35
 * @package    PEAR
36
 * @author     Greg Beaver <cellog@php.net>
37
 * @copyright  1997-2008 The PHP Group
38
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
39
 * @version    Release: 1.7.2
40
 * @link       http://pear.php.net/package/PEAR
41
 * @since      Class available since Release 1.4.0a1
42
 */
43
class PEAR_Command_Channels extends PEAR_Command_Common
44
{
45
    // {{{ properties
46
 
47
    var $commands = array(
48
        'list-channels' => array(
49
            'summary' => 'List Available Channels',
50
            'function' => 'doList',
51
            'shortcut' => 'lc',
52
            'options' => array(),
53
            'doc' => '
54
List all available channels for installation.
55
',
56
            ),
57
        'update-channels' => array(
58
            'summary' => 'Update the Channel List',
59
            'function' => 'doUpdateAll',
60
            'shortcut' => 'uc',
61
            'options' => array(),
62
            'doc' => '
63
List all installed packages in all channels.
64
'
65
            ),
66
        'channel-delete' => array(
67
            'summary' => 'Remove a Channel From the List',
68
            'function' => 'doDelete',
69
            'shortcut' => 'cde',
70
            'options' => array(),
71
            'doc' => '<channel name>
72
Delete a channel from the registry.  You may not
73
remove any channel that has installed packages.
74
'
75
            ),
76
        'channel-add' => array(
77
            'summary' => 'Add a Channel',
78
            'function' => 'doAdd',
79
            'shortcut' => 'ca',
80
            'options' => array(),
81
            'doc' => '<channel.xml>
82
Add a private channel to the channel list.  Note that all
83
public channels should be synced using "update-channels".
84
Parameter may be either a local file or remote URL to a
85
channel.xml.
86
'
87
            ),
88
        'channel-update' => array(
89
            'summary' => 'Update an Existing Channel',
90
            'function' => 'doUpdate',
91
            'shortcut' => 'cu',
92
            'options' => array(
93
                'force' => array(
94
                    'shortopt' => 'f',
95
                    'doc' => 'will force download of new channel.xml if an existing channel name is used',
96
                    ),
97
                'channel' => array(
98
                    'shortopt' => 'c',
99
                    'arg' => 'CHANNEL',
100
                    'doc' => 'will force download of new channel.xml if an existing channel name is used',
101
                    ),
102
),
103
            'doc' => '[<channel.xml>|<channel name>]
104
Update a channel in the channel list directly.  Note that all
105
public channels can be synced using "update-channels".
106
Parameter may be a local or remote channel.xml, or the name of
107
an existing channel.
108
'
109
            ),
110
        'channel-info' => array(
111
            'summary' => 'Retrieve Information on a Channel',
112
            'function' => 'doInfo',
113
            'shortcut' => 'ci',
114
            'options' => array(),
115
            'doc' => '<package>
116
List the files in an installed package.
117
'
118
            ),
119
        'channel-alias' => array(
120
            'summary' => 'Specify an alias to a channel name',
121
            'function' => 'doAlias',
122
            'shortcut' => 'cha',
123
            'options' => array(),
124
            'doc' => '<channel> <alias>
125
Specify a specific alias to use for a channel name.
126
The alias may not be an existing channel name or
127
alias.
128
'
129
            ),
130
        'channel-discover' => array(
131
            'summary' => 'Initialize a Channel from its server',
132
            'function' => 'doDiscover',
133
            'shortcut' => 'di',
134
            'options' => array(),
135
            'doc' => '[<channel.xml>|<channel name>]
136
Initialize a channel from its server and create a local channel.xml.
137
If <channel name> is in the format "<username>:<password>@<channel>" then
138
<username> and <password> will be set as the login username/password for
139
<channel>. Use caution when passing the username/password in this way, as
140
it may allow other users on your computer to briefly view your username/
141
password via the system\'s process list.
142
'
143
            ),
144
        );
145
 
146
    // }}}
147
    // {{{ constructor
148
 
149
    /**
150
     * PEAR_Command_Registry constructor.
151
     *
152
     * @access public
153
     */
154
    function PEAR_Command_Channels(&$ui, &$config)
155
    {
156
        parent::PEAR_Command_Common($ui, $config);
157
    }
158
 
159
    // }}}
160
 
161
    // {{{ doList()
162
 
163
    function _sortChannels($a, $b)
164
    {
165
        return strnatcasecmp($a->getName(), $b->getName());
166
    }
167
 
168
    function doList($command, $options, $params)
169
    {
170
        $reg = &$this->config->getRegistry();
171
        $registered = $reg->getChannels();
172
        usort($registered, array(&$this, '_sortchannels'));
173
        $i = $j = 0;
174
        $data = array(
175
            'caption' => 'Registered Channels:',
176
            'border' => true,
177
            'headline' => array('Channel', 'Summary')
178
            );
179
        foreach ($registered as $channel) {
180
            $data['data'][] = array($channel->getName(),
181
                                      $channel->getSummary());
182
        }
183
        if (count($registered)==0) {
184
            $data = '(no registered channels)';
185
        }
186
        $this->ui->outputData($data, $command);
187
        return true;
188
    }
189
 
190
    function doUpdateAll($command, $options, $params)
191
    {
192
        $reg = &$this->config->getRegistry();
193
        $channels = $reg->getChannels();
194
 
195
        $success = true;
196
        foreach ($channels as $channel) {
197
            if ($channel->getName() != '__uri') {
198
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
199
                $err = $this->doUpdate('channel-update',
200
                                          $options,
201
                                          array($channel->getName()));
202
                if (PEAR::isError($err)) {
203
                    $this->ui->outputData($err->getMessage(), $command);
204
                    $success = false;
205
                } else {
206
                    $success &= $err;
207
                }
208
            }
209
        }
210
        return $success;
211
    }
212
 
213
    function doInfo($command, $options, $params)
214
    {
215
        if (sizeof($params) != 1) {
216
            return $this->raiseError("No channel specified");
217
        }
218
        $reg = &$this->config->getRegistry();
219
        $channel = strtolower($params[0]);
220
        if ($reg->channelExists($channel)) {
221
            $chan = $reg->getChannel($channel);
222
            if (PEAR::isError($chan)) {
223
                return $this->raiseError($chan);
224
            }
225
        } else {
226
            if (strpos($channel, '://')) {
227
                $downloader = &$this->getDownloader();
228
                $tmpdir = $this->config->get('temp_dir');
229
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
230
                $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
231
                PEAR::staticPopErrorHandling();
232
                if (PEAR::isError($loc)) {
233
                    return $this->raiseError('Cannot open "' . $channel .
234
                        '" (' . $loc->getMessage() . ')');
235
                } else {
236
                    $contents = implode('', file($loc));
237
                }
238
            } else {
239
                if (file_exists($params[0])) {
240
                    $fp = fopen($params[0], 'r');
241
                    if (!$fp) {
242
                        return $this->raiseError('Cannot open "' . $params[0] . '"');
243
                    }
244
                } else {
245
                    return $this->raiseError('Unknown channel "' . $channel . '"');
246
                }
247
                $contents = '';
248
                while (!feof($fp)) {
249
                    $contents .= fread($fp, 1024);
250
                }
251
                fclose($fp);
252
            }
253
            if (!class_exists('PEAR_ChannelFile')) {
254
                require_once 'PEAR/ChannelFile.php';
255
            }
256
            $chan = new PEAR_ChannelFile;
257
            $chan->fromXmlString($contents);
258
            $chan->validate();
259
            if ($errs = $chan->getErrors(true)) {
260
                foreach ($errs as $err) {
261
                    $this->ui->outputData($err['level'] . ': ' . $err['message']);
262
                }
263
                return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
264
            }
265
        }
266
        if ($chan) {
267
            $channel = $chan->getName();
268
            $caption = 'Channel ' . $channel . ' Information:';
269
            $data1 = array(
270
                'caption' => $caption,
271
                'border' => true);
272
            $data1['data']['server'] = array('Name and Server', $chan->getName());
273
            if ($chan->getAlias() != $chan->getName()) {
274
                $data1['data']['alias'] = array('Alias', $chan->getAlias());
275
            }
276
            $data1['data']['summary'] = array('Summary', $chan->getSummary());
277
            $validate = $chan->getValidationPackage();
278
            $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
279
            $data1['data']['vpackageversion'] =
280
                array('Validation Package Version', $validate['attribs']['version']);
281
            $d = array();
282
            $d['main'] = $data1;
283
 
284
            $data['data'] = array();
285
            $data['caption'] = 'Server Capabilities';
286
            $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
287
            $capabilities = $chan->getFunctions('xmlrpc');
288
            $soaps = $chan->getFunctions('soap');
289
            if ($capabilities || $soaps || $chan->supportsREST()) {
290
                if ($capabilities) {
291
                    if (!isset($capabilities[0])) {
292
                        $capabilities = array($capabilities);
293
                    }
294
                    foreach ($capabilities as $protocol) {
295
                        $data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
296
                            $protocol['_content']);
297
                    }
298
                }
299
                if ($soaps) {
300
                    if (!isset($soaps[0])) {
301
                        $soaps = array($soaps);
302
                    }
303
                    foreach ($soaps as $protocol) {
304
                        $data['data'][] = array('soap', $protocol['attribs']['version'],
305
                            $protocol['_content']);
306
                    }
307
                }
308
                if ($chan->supportsREST()) {
309
                    $funcs = $chan->getFunctions('rest');
310
                    if (!isset($funcs[0])) {
311
                        $funcs = array($funcs);
312
                    }
313
                    foreach ($funcs as $protocol) {
314
                        $data['data'][] = array('rest', $protocol['attribs']['type'],
315
                            $protocol['_content']);
316
                    }
317
                }
318
            } else {
319
                $data['data'][] = array('No supported protocols');
320
            }
321
            $d['protocols'] = $data;
322
            $data['data'] = array();
323
            $mirrors = $chan->getMirrors();
324
            if ($mirrors) {
325
                $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
326
                unset($data['headline']);
327
                foreach ($mirrors as $mirror) {
328
                    $data['data'][] = array($mirror['attribs']['host']);
329
                    $d['mirrors'] = $data;
330
                }
331
                foreach ($mirrors as $i => $mirror) {
332
                    $data['data'] = array();
333
                    $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
334
                    $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
335
                    $capabilities = $chan->getFunctions('xmlrpc', $mirror['attribs']['host']);
336
                    $soaps = $chan->getFunctions('soap', $mirror['attribs']['host']);
337
                    if ($capabilities || $soaps || $chan->supportsREST($mirror['attribs']['host'])) {
338
                        if ($capabilities) {
339
                            if (!isset($capabilities[0])) {
340
                                $capabilities = array($capabilities);
341
                            }
342
                            foreach ($capabilities as $protocol) {
343
                                $data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
344
                                    $protocol['_content']);
345
                            }
346
                        }
347
                        if ($soaps) {
348
                            if (!isset($soaps[0])) {
349
                                $soaps = array($soaps);
350
                            }
351
                            foreach ($soaps as $protocol) {
352
                                $data['data'][] = array('soap', $protocol['attribs']['version'],
353
                                    $protocol['_content']);
354
                            }
355
                        }
356
                        if ($chan->supportsREST($mirror['attribs']['host'])) {
357
                            $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
358
                            if (!isset($funcs[0])) {
359
                                $funcs = array($funcs);
360
                            }
361
                            foreach ($funcs as $protocol) {
362
                                $data['data'][] = array('rest', $protocol['attribs']['type'],
363
                                    $protocol['_content']);
364
                            }
365
                        }
366
                    } else {
367
                        $data['data'][] = array('No supported protocols');
368
                    }
369
                    $d['mirrorprotocols' . $i] = $data;
370
                }
371
            }
372
            $this->ui->outputData($d, 'channel-info');
373
        } else {
374
            return $this->raiseError('Serious error: Channel "' . $params[0] .
375
                '" has a corrupted registry entry');
376
        }
377
    }
378
 
379
    // }}}
380
 
381
    function doDelete($command, $options, $params)
382
    {
383
        if (sizeof($params) != 1) {
384
            return $this->raiseError('channel-delete: no channel specified');
385
        }
386
        $reg = &$this->config->getRegistry();
387
        if (!$reg->channelExists($params[0])) {
388
            return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
389
        }
390
        $channel = $reg->channelName($params[0]);
391
        if ($channel == 'pear.php.net') {
392
            return $this->raiseError('Cannot delete the pear.php.net channel');
393
        }
394
        if ($channel == 'pecl.php.net') {
395
            return $this->raiseError('Cannot delete the pecl.php.net channel');
396
        }
397
        if ($channel == '__uri') {
398
            return $this->raiseError('Cannot delete the __uri pseudo-channel');
399
        }
400
        if (PEAR::isError($err = $reg->listPackages($channel))) {
401
            return $err;
402
        }
403
        if (count($err)) {
404
            return $this->raiseError('Channel "' . $channel .
405
                '" has installed packages, cannot delete');
406
        }
407
        if (!$reg->deleteChannel($channel)) {
408
            return $this->raiseError('Channel "' . $channel . '" deletion failed');
409
        } else {
410
            $this->config->deleteChannel($channel);
411
            $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
412
        }
413
    }
414
 
415
    function doAdd($command, $options, $params)
416
    {
417
        if (sizeof($params) != 1) {
418
            return $this->raiseError('channel-add: no channel file specified');
419
        }
420
        if (strpos($params[0], '://')) {
421
            $downloader = &$this->getDownloader();
422
            $tmpdir = $this->config->get('temp_dir');
423
            if (!file_exists($tmpdir)) {
424
                require_once 'System.php';
425
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
426
                $err = System::mkdir(array('-p', $tmpdir));
427
                PEAR::staticPopErrorHandling();
428
                if (PEAR::isError($err)) {
429
                    return $this->raiseError('channel-add: temp_dir does not exist: "' .
430
                        $tmpdir .
431
                        '" - You can change this location with "pear config-set temp_dir"');
432
                }
433
            }
434
            if (!is_writable($tmpdir)) {
435
                return $this->raiseError('channel-add: temp_dir is not writable: "' .
436
                    $tmpdir .
437
                    '" - You can change this location with "pear config-set temp_dir"');
438
            }
439
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
440
            $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
441
            PEAR::staticPopErrorHandling();
442
            if (PEAR::isError($loc)) {
443
                return $this->raiseError('channel-add: Cannot open "' . $params[0] .
444
                    '" (' . $loc->getMessage() . ')');
445
            } else {
446
                list($loc, $lastmodified) = $loc;
447
                $contents = implode('', file($loc));
448
            }
449
        } else {
450
            $lastmodified = $fp = false;
451
            if (file_exists($params[0])) {
452
                $fp = fopen($params[0], 'r');
453
            }
454
            if (!$fp) {
455
                return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
456
            }
457
            $contents = '';
458
            while (!feof($fp)) {
459
                $contents .= fread($fp, 1024);
460
            }
461
            fclose($fp);
462
        }
463
        if (!class_exists('PEAR_ChannelFile')) {
464
            require_once 'PEAR/ChannelFile.php';
465
        }
466
        $channel = new PEAR_ChannelFile;
467
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
468
        $result = $channel->fromXmlString($contents);
469
        PEAR::staticPopErrorHandling();
470
        if (!$result) {
471
            $exit = false;
472
            if (count($errors = $channel->getErrors(true))) {
473
                foreach ($errors as $error) {
474
                    $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
475
                    if (!$exit) {
476
                        $exit = $error['level'] == 'error' ? true : false;
477
                    }
478
                }
479
                if ($exit) {
480
                    return $this->raiseError('channel-add: invalid channel.xml file');
481
                }
482
            }
483
        }
484
        $reg = &$this->config->getRegistry();
485
        if ($reg->channelExists($channel->getName())) {
486
            return $this->raiseError('channel-add: Channel "' . $channel->getName() .
487
                '" exists, use channel-update to update entry');
488
        }
489
        $ret = $reg->addChannel($channel, $lastmodified);
490
        if (PEAR::isError($ret)) {
491
            return $ret;
492
        }
493
        if (!$ret) {
494
            return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
495
                '" to registry failed');
496
        }
497
        $this->config->setChannels($reg->listChannels());
498
        $this->config->writeConfigFile();
499
        $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
500
    }
501
 
502
    function doUpdate($command, $options, $params)
503
    {
504
        $tmpdir = $this->config->get('temp_dir');
505
        if (!file_exists($tmpdir)) {
506
            require_once 'System.php';
507
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
508
            $err = System::mkdir(array('-p', $tmpdir));
509
            PEAR::staticPopErrorHandling();
510
            if (PEAR::isError($err)) {
511
                return $this->raiseError('channel-add: temp_dir does not exist: "' .
512
                    $tmpdir .
513
                    '" - You can change this location with "pear config-set temp_dir"');
514
            }
515
        }
516
        if (!is_writable($tmpdir)) {
517
            return $this->raiseError('channel-add: temp_dir is not writable: "' .
518
                $tmpdir .
519
                '" - You can change this location with "pear config-set temp_dir"');
520
        }
521
        $reg = &$this->config->getRegistry();
522
        if (sizeof($params) != 1) {
523
            return $this->raiseError("No channel file specified");
524
        }
525
        $lastmodified = false;
526
        if ((!file_exists($params[0]) || is_dir($params[0]))
527
              && $reg->channelExists(strtolower($params[0]))) {
528
            $c = $reg->getChannel(strtolower($params[0]));
529
            if (PEAR::isError($c)) {
530
                return $this->raiseError($c);
531
            }
532
            $this->ui->outputData("Updating channel \"$params[0]\"", $command);
533
            $dl = &$this->getDownloader(array());
534
            // if force is specified, use a timestamp of "1" to force retrieval
535
            $lastmodified = isset($options['force']) ? false : $c->lastModified();
536
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
537
            $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
538
                $this->ui, $tmpdir, null, $lastmodified);
539
            PEAR::staticPopErrorHandling();
540
            if (PEAR::isError($contents)) {
541
                return $this->raiseError('Cannot retrieve channel.xml for channel "' .
542
                    $c->getName() . '" (' . $contents->getMessage() . ')');
543
            }
544
            list($contents, $lastmodified) = $contents;
545
            if (!$contents) {
546
                $this->ui->outputData("Channel \"$params[0]\" is up to date");
547
                return;
548
            }
549
            $contents = implode('', file($contents));
550
            if (!class_exists('PEAR_ChannelFile')) {
551
                require_once 'PEAR/ChannelFile.php';
552
            }
553
            $channel = new PEAR_ChannelFile;
554
            $channel->fromXmlString($contents);
555
            if (!$channel->getErrors()) {
556
                // security check: is the downloaded file for the channel we got it from?
557
                if (strtolower($channel->getName()) != strtolower($c->getName())) {
558
                    if (isset($options['force'])) {
559
                        $this->ui->log(0, 'WARNING: downloaded channel definition file' .
560
                            ' for channel "' . $channel->getName() . '" from channel "' .
561
                            strtolower($c->getName()) . '"');
562
                    } else {
563
                        return $this->raiseError('ERROR: downloaded channel definition file' .
564
                            ' for channel "' . $channel->getName() . '" from channel "' .
565
                            strtolower($c->getName()) . '"');
566
                    }
567
                }
568
            }
569
        } else {
570
            if (strpos($params[0], '://')) {
571
                $dl = &$this->getDownloader();
572
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
573
                $loc = $dl->downloadHttp($params[0],
574
                    $this->ui, $tmpdir, null, $lastmodified);
575
                PEAR::staticPopErrorHandling();
576
                if (PEAR::isError($loc)) {
577
                    return $this->raiseError("Cannot open " . $params[0] .
578
                         ' (' . $loc->getMessage() . ')');
579
                } else {
580
                    list($loc, $lastmodified) = $loc;
581
                    $contents = implode('', file($loc));
582
                }
583
            } else {
584
                $fp = false;
585
                if (file_exists($params[0])) {
586
                    $fp = fopen($params[0], 'r');
587
                }
588
                if (!$fp) {
589
                    return $this->raiseError("Cannot open " . $params[0]);
590
                }
591
                $contents = '';
592
                while (!feof($fp)) {
593
                    $contents .= fread($fp, 1024);
594
                }
595
                fclose($fp);
596
            }
597
            if (!class_exists('PEAR_ChannelFile')) {
598
                require_once 'PEAR/ChannelFile.php';
599
            }
600
            $channel = new PEAR_ChannelFile;
601
            $channel->fromXmlString($contents);
602
        }
603
        $exit = false;
604
        if (count($errors = $channel->getErrors(true))) {
605
            foreach ($errors as $error) {
606
                $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
607
                if (!$exit) {
608
                    $exit = $error['level'] == 'error' ? true : false;
609
                }
610
            }
611
            if ($exit) {
612
                return $this->raiseError('Invalid channel.xml file');
613
            }
614
        }
615
        if (!$reg->channelExists($channel->getName())) {
616
            return $this->raiseError('Error: Channel "' . $channel->getName() .
617
                '" does not exist, use channel-add to add an entry');
618
        }
619
        $ret = $reg->updateChannel($channel, $lastmodified);
620
        if (PEAR::isError($ret)) {
621
            return $ret;
622
        }
623
        if (!$ret) {
624
            return $this->raiseError('Updating Channel "' . $channel->getName() .
625
                '" in registry failed');
626
        }
627
        $this->config->setChannels($reg->listChannels());
628
        $this->config->writeConfigFile();
629
        $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
630
    }
631
 
632
    function &getDownloader()
633
    {
634
        if (!class_exists('PEAR_Downloader')) {
635
            require_once 'PEAR/Downloader.php';
636
        }
637
        $a = new PEAR_Downloader($this->ui, array(), $this->config);
638
        return $a;
639
    }
640
 
641
    function doAlias($command, $options, $params)
642
    {
643
        $reg = &$this->config->getRegistry();
644
        if (sizeof($params) == 1) {
645
            return $this->raiseError('No channel alias specified');
646
        }
647
        if (sizeof($params) != 2) {
648
            return $this->raiseError(
649
                'Invalid format, correct is: channel-alias channel alias');
650
        }
651
        if (!$reg->channelExists($params[0], true)) {
652
            if ($reg->isAlias($params[0])) {
653
                $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
654
                    strtolower($params[1]) . '")';
655
            } else {
656
                $extra = '';
657
            }
658
            return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
659
        }
660
        if ($reg->isAlias($params[1])) {
661
            return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
662
                'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
663
        }
664
        $chan = &$reg->getChannel($params[0]);
665
        if (PEAR::isError($chan)) {
666
            return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
667
                '" information (' . $chan->getMessage() . ')');
668
        }
669
        // make it a local alias
670
        if (!$chan->setAlias(strtolower($params[1]), true)) {
671
            return $this->raiseError('Alias "' . strtolower($params[1]) .
672
                '" is not a valid channel alias');
673
        }
674
        $reg->updateChannel($chan);
675
        $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
676
            strtolower($params[1]) . '"');
677
    }
678
 
679
    /**
680
     * The channel-discover command
681
     *
682
     * @param string $command command name
683
     * @param array  $options option_name => value
684
     * @param array  $params  list of additional parameters.
685
     *               $params[0] should contain a string with either:
686
     *               - <channel name> or
687
     *               - <username>:<password>@<channel name>
688
     * @return null|PEAR_Error
689
     */
690
    function doDiscover($command, $options, $params)
691
    {
692
        $reg = &$this->config->getRegistry();
693
        if (sizeof($params) != 1) {
694
            return $this->raiseError("No channel server specified");
695
        }
696
 
697
        // Look for the possible input format "<username>:<password>@<channel>"
698
        if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
699
            $username = $matches[1];
700
            $password = $matches[2];
701
            $channel = $matches[3];
702
        } else {
703
            $channel = $params[0];
704
        }
705
 
706
        if ($reg->channelExists($channel)) {
707
            if ($reg->isAlias($channel)) {
708
                return $this->raiseError("A channel alias named \"$channel\" " .
709
                    'already exists, aliasing channel "' . $reg->channelName($channel)
710
                    . '"');
711
            } else {
712
                return $this->raiseError("Channel \"$channel\" is already initialized");
713
            }
714
        }
715
        $this->pushErrorHandling(PEAR_ERROR_RETURN);
716
        $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
717
        $this->popErrorHandling();
718
        if (PEAR::isError($err)) {
719
            return $this->raiseError("Discovery of channel \"$channel\" failed (" .
720
                $err->getMessage() . ')');
721
        }
722
 
723
        // Store username/password if they were given
724
        // Arguably we should do a logintest on the channel here, but since
725
        // that's awkward on a REST-based channel (even "pear login" doesn't
726
        // do it for those), and XML-RPC is deprecated, it's fairly pointless.
727
        if (isset($username)) {
728
            $this->config->set('username', $username, 'user', $channel);
729
            $this->config->set('password', $password, 'user', $channel);
730
            $this->config->store();
731
            $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
732
        }
733
 
734
        $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
735
    }
736
}
737
?>