Subversion Repositories Applications.gtt

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
94 jpm 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-2006 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.46 2006/07/17 18:19:25 pajoye 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-2006 The PHP Group
38
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
39
 * @version    Release: 1.5.1
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 creates the local channel.xml.
137
'
138
            ),
139
        );
140
 
141
    // }}}
142
    // {{{ constructor
143
 
144
    /**
145
     * PEAR_Command_Registry constructor.
146
     *
147
     * @access public
148
     */
149
    function PEAR_Command_Channels(&$ui, &$config)
150
    {
151
        parent::PEAR_Command_Common($ui, $config);
152
    }
153
 
154
    // }}}
155
 
156
    // {{{ doList()
157
 
158
    function _sortChannels($a, $b)
159
    {
160
        return strnatcasecmp($a->getName(), $b->getName());
161
    }
162
 
163
    function doList($command, $options, $params)
164
    {
165
        $reg = &$this->config->getRegistry();
166
        $registered = $reg->getChannels();
167
        usort($registered, array(&$this, '_sortchannels'));
168
        $i = $j = 0;
169
        $data = array(
170
            'caption' => 'Registered Channels:',
171
            'border' => true,
172
            'headline' => array('Channel', 'Summary')
173
            );
174
        foreach ($registered as $channel) {
175
            $data['data'][] = array($channel->getName(),
176
                                      $channel->getSummary());
177
        }
178
        if (count($registered)==0) {
179
            $data = '(no registered channels)';
180
        }
181
        $this->ui->outputData($data, $command);
182
        return true;
183
    }
184
 
185
    function doUpdateAll($command, $options, $params)
186
    {
187
        $reg = &$this->config->getRegistry();
188
        $savechannel = $this->config->get('default_channel');
189
        if (isset($options['channel'])) {
190
            if (!$reg->channelExists($options['channel'])) {
191
                return $this->raiseError('Unknown channel "' . $options['channel'] . '"');
192
            }
193
            $this->config->set('default_channel', $options['channel']);
194
        } else {
195
            $this->config->set('default_channel', 'pear.php.net');
196
        }
197
        $remote = &$this->config->getRemote();
198
        $channels = $remote->call('channel.listAll');
199
        if (PEAR::isError($channels)) {
200
            $this->config->set('default_channel', $savechannel);
201
            return $channels;
202
        }
203
        if (!is_array($channels) || isset($channels['faultCode'])) {
204
            $this->config->set('default_channel', $savechannel);
205
            return $this->raiseError("Incorrect channel listing returned from channel '$chan'");
206
        }
207
        if (!count($channels)) {
208
            $data = 'no updates available';
209
        }
210
        $dl = &$this->getDownloader();
211
        if (!class_exists('System')) {
212
            require_once 'System.php';
213
        }
214
        $tmpdir = System::mktemp(array('-d'));
215
        foreach ($channels as $channel) {
216
            $channel = $channel[0];
217
            $save = $channel;
218
            if ($reg->channelExists($channel, true)) {
219
                $this->ui->outputData("Updating channel \"$channel\"", $command);
220
                $test = $reg->getChannel($channel, true);
221
                if (PEAR::isError($test)) {
222
                    $this->ui->outputData("Channel '$channel' is corrupt in registry!", $command);
223
                    $lastmodified = false;
224
                } else {
225
                    $lastmodified = $test->lastModified();
226
 
227
                }
228
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
229
                $contents = $dl->downloadHttp('http://' . $test->getName() . '/channel.xml',
230
                    $this->ui, $tmpdir, null, $lastmodified);
231
                PEAR::staticPopErrorHandling();
232
                if (PEAR::isError($contents)) {
233
                    $this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' .
234
                        $test->getName() . '"', $command);
235
                    continue;
236
                }
237
                if (!$contents) {
238
                    $this->ui->outputData("Channel \"$channel\" is up-to-date", $command);
239
                    continue;
240
                }
241
                list($contents, $lastmodified) = $contents;
242
                $info = implode('', file($contents));
243
                if (!$info) {
244
                    $this->ui->outputData("Channel \"$channel\" is up-to-date", $command);
245
                    continue;
246
                }
247
                if (!class_exists('PEAR_ChannelFile')) {
248
                    require_once 'PEAR/ChannelFile.php';
249
                }
250
                $channelinfo = new PEAR_ChannelFile;
251
                $channelinfo->fromXmlString($info);
252
                if ($channelinfo->getErrors()) {
253
                    $this->ui->outputData("Downloaded channel data from channel \"$channel\" " .
254
                        'is corrupt, skipping', $command);
255
                    continue;
256
                }
257
                $channel = $channelinfo;
258
                if ($channel->getName() != $save) {
259
                    $this->ui->outputData('ERROR: Security risk - downloaded channel ' .
260
                        'definition file for channel "'
261
                        . $channel->getName() . ' from channel "' . $save .
262
                        '".  To use anyway, use channel-update', $command);
263
                    continue;
264
                }
265
                $reg->updateChannel($channel, $lastmodified);
266
            } else {
267
                if ($reg->isAlias($channel)) {
268
                    $temp = &$reg->getChannel($channel);
269
                    if (PEAR::isError($temp)) {
270
                        return $this->raiseError($temp);
271
                    }
272
                    $temp->setAlias($temp->getName(), true); // set the alias to the channel name
273
                    if ($reg->channelExists($temp->getName())) {
274
                        $this->ui->outputData('ERROR: existing channel "' . $temp->getName() .
275
                            '" is aliased to "' . $channel . '" already and cannot be ' .
276
                            're-aliased to "' . $temp->getName() . '" because a channel with ' .
277
                            'that name or alias already exists!  Please re-alias and try ' .
278
                            'again.', $command);
279
                        continue;
280
                    }
281
                }
282
                $this->ui->outputData("Adding new channel \"$channel\"", $command);
283
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
284
                $contents = $dl->downloadHttp('http://' . $channel . '/channel.xml',
285
                    $this->ui, $tmpdir, null, false);
286
                PEAR::staticPopErrorHandling();
287
                if (PEAR::isError($contents)) {
288
                    $this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' .
289
                        $channel . '"', $command);
290
                    continue;
291
                }
292
                list($contents, $lastmodified) = $contents;
293
                $info = implode('', file($contents));
294
                if (!class_exists('PEAR_ChannelFile')) {
295
                    require_once 'PEAR/ChannelFile.php';
296
                }
297
                $channelinfo = new PEAR_Channelfile;
298
                $channelinfo->fromXmlString($info);
299
                if ($channelinfo->getErrors()) {
300
                    $this->ui->outputData("Downloaded channel data from channel \"$channel\"" .
301
                        ' is corrupt, skipping', $command);
302
                    continue;
303
                }
304
                $channel = $channelinfo;
305
                if ($channel->getName() != $save) {
306
                    $this->ui->outputData('ERROR: Security risk - downloaded channel ' .
307
                        'definition file for channel "'
308
                        . $channel->getName() . '" from channel "' . $save .
309
                        '".  To use anyway, use channel-update', $command);
310
                    continue;
311
                }
312
                $reg->addChannel($channel, $lastmodified);
313
            }
314
        }
315
        $this->config->set('default_channel', $savechannel);
316
        $this->ui->outputData('update-channels complete', $command);
317
        return true;
318
    }
319
 
320
    function doInfo($command, $options, $params)
321
    {
322
        if (sizeof($params) != 1) {
323
            return $this->raiseError("No channel specified");
324
        }
325
        $reg = &$this->config->getRegistry();
326
        $channel = strtolower($params[0]);
327
        if ($reg->channelExists($channel)) {
328
            $chan = $reg->getChannel($channel);
329
            if (PEAR::isError($chan)) {
330
                return $this->raiseError($chan);
331
            }
332
        } else {
333
            if (strpos($channel, '://')) {
334
                $downloader = &$this->getDownloader();
335
                if (!class_exists('System')) {
336
                    require_once 'System.php';
337
                }
338
                $tmpdir = System::mktemp(array('-d'));
339
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
340
                $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
341
                PEAR::staticPopErrorHandling();
342
                if (PEAR::isError($loc)) {
343
                    return $this->raiseError('Cannot open "' . $channel . '"');
344
                } else {
345
                    $contents = implode('', file($loc));
346
                }
347
            } else {
348
                if (file_exists($params[0])) {
349
                    $fp = fopen($params[0], 'r');
350
                    if (!$fp) {
351
                        return $this->raiseError('Cannot open "' . $params[0] . '"');
352
                    }
353
                } else {
354
                    return $this->raiseError('Unknown channel "' . $channel . '"');
355
                }
356
                $contents = '';
357
                while (!feof($fp)) {
358
                    $contents .= fread($fp, 1024);
359
                }
360
                fclose($fp);
361
            }
362
            if (!class_exists('PEAR_ChannelFile')) {
363
                require_once 'PEAR/ChannelFile.php';
364
            }
365
            $chan = new PEAR_ChannelFile;
366
            $chan->fromXmlString($contents);
367
            $chan->validate();
368
            if ($errs = $chan->getErrors(true)) {
369
                foreach ($errs as $err) {
370
                    $this->ui->outputData($err['level'] . ': ' . $err['message']);
371
                }
372
                return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
373
            }
374
        }
375
        if ($chan) {
376
            $channel = $chan->getName();
377
            $caption = 'Channel ' . $channel . ' Information:';
378
            $data1 = array(
379
                'caption' => $caption,
380
                'border' => true);
381
            $data1['data']['server'] = array('Name and Server', $chan->getName());
382
            if ($chan->getAlias() != $chan->getName()) {
383
                $data1['data']['alias'] = array('Alias', $chan->getAlias());
384
            }
385
            $data1['data']['summary'] = array('Summary', $chan->getSummary());
386
            $validate = $chan->getValidationPackage();
387
            $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
388
            $data1['data']['vpackageversion'] =
389
                array('Validation Package Version', $validate['attribs']['version']);
390
            $d = array();
391
            $d['main'] = $data1;
392
 
393
            $data['data'] = array();
394
            $data['caption'] = 'Server Capabilities';
395
            $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
396
            $capabilities = $chan->getFunctions('xmlrpc');
397
            $soaps = $chan->getFunctions('soap');
398
            if ($capabilities || $soaps || $chan->supportsREST()) {
399
                if ($capabilities) {
400
                    if (!isset($capabilities[0])) {
401
                        $capabilities = array($capabilities);
402
                    }
403
                    foreach ($capabilities as $protocol) {
404
                        $data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
405
                            $protocol['_content']);
406
                    }
407
                }
408
                if ($soaps) {
409
                    if (!isset($soaps[0])) {
410
                        $soaps = array($soaps);
411
                    }
412
                    foreach ($soaps as $protocol) {
413
                        $data['data'][] = array('soap', $protocol['attribs']['version'],
414
                            $protocol['_content']);
415
                    }
416
                }
417
                if ($chan->supportsREST()) {
418
                    $funcs = $chan->getFunctions('rest');
419
                    if (!isset($funcs[0])) {
420
                        $funcs = array($funcs);
421
                    }
422
                    foreach ($funcs as $protocol) {
423
                        $data['data'][] = array('rest', $protocol['attribs']['type'],
424
                            $protocol['_content']);
425
                    }
426
                }
427
            } else {
428
                $data['data'][] = array('No supported protocols');
429
            }
430
            $d['protocols'] = $data;
431
            $data['data'] = array();
432
            $mirrors = $chan->getMirrors();
433
            if ($mirrors) {
434
                $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
435
                unset($data['headline']);
436
                foreach ($mirrors as $mirror) {
437
                    $data['data'][] = array($mirror['attribs']['host']);
438
                    $d['mirrors'] = $data;
439
                }
440
                foreach ($mirrors as $mirror) {
441
                    $data['data'] = array();
442
                    $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
443
                    $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
444
                    $capabilities = $chan->getFunctions('xmlrpc', $mirror['attribs']['host']);
445
                    $soaps = $chan->getFunctions('soap', $mirror['attribs']['host']);
446
                    if ($capabilities || $soaps || $chan->supportsREST($mirror['attribs']['host'])) {
447
                        if ($capabilities) {
448
                            if (!isset($capabilities[0])) {
449
                                $capabilities = array($capabilities);
450
                            }
451
                            foreach ($capabilities as $protocol) {
452
                                $data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
453
                                    $protocol['_content']);
454
                            }
455
                        }
456
                        if ($soaps) {
457
                            if (!isset($soaps[0])) {
458
                                $soaps = array($soaps);
459
                            }
460
                            foreach ($soaps as $protocol) {
461
                                $data['data'][] = array('soap', $protocol['attribs']['version'],
462
                                    $protocol['_content']);
463
                            }
464
                        }
465
                        if ($chan->supportsREST($mirror['attribs']['host'])) {
466
                            $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
467
                            if (!isset($funcs[0])) {
468
                                $funcs = array($funcs);
469
                            }
470
                            foreach ($funcs as $protocol) {
471
                                $data['data'][] = array('rest', $protocol['attribs']['type'],
472
                                    $protocol['_content']);
473
                            }
474
                        }
475
                    } else {
476
                        $data['data'][] = array('No supported protocols');
477
                    }
478
                    $d['mirrorprotocols'] = $data;
479
                }
480
            }
481
            $this->ui->outputData($d, 'channel-info');
482
        } else {
483
            return $this->raiseError('Serious error: Channel "' . $params[0] .
484
                '" has a corrupted registry entry');
485
        }
486
    }
487
 
488
    // }}}
489
 
490
    function doDelete($command, $options, $params)
491
    {
492
        if (sizeof($params) != 1) {
493
            return $this->raiseError('channel-delete: no channel specified');
494
        }
495
        $reg = &$this->config->getRegistry();
496
        if (!$reg->channelExists($params[0])) {
497
            return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
498
        }
499
        $channel = $reg->channelName($params[0]);
500
        if ($channel == 'pear.php.net') {
501
            return $this->raiseError('Cannot delete the pear.php.net channel');
502
        }
503
        if ($channel == 'pecl.php.net') {
504
            return $this->raiseError('Cannot delete the pecl.php.net channel');
505
        }
506
        if ($channel == '__uri') {
507
            return $this->raiseError('Cannot delete the __uri pseudo-channel');
508
        }
509
        if (PEAR::isError($err = $reg->listPackages($channel))) {
510
            return $err;
511
        }
512
        if (count($err)) {
513
            return $this->raiseError('Channel "' . $channel .
514
                '" has installed packages, cannot delete');
515
        }
516
        if (!$reg->deleteChannel($channel)) {
517
            return $this->raiseError('Channel "' . $channel . '" deletion failed');
518
        } else {
519
            $this->config->deleteChannel($channel);
520
            $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
521
        }
522
    }
523
 
524
    function doAdd($command, $options, $params)
525
    {
526
        if (sizeof($params) != 1) {
527
            return $this->raiseError('channel-add: no channel file specified');
528
        }
529
        if (strpos($params[0], '://')) {
530
            $downloader = &$this->getDownloader();
531
            if (!class_exists('System')) {
532
                require_once 'System.php';
533
            }
534
            $tmpdir = System::mktemp(array('-d'));
535
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
536
            $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
537
            PEAR::staticPopErrorHandling();
538
            if (PEAR::isError($loc)) {
539
                return $this->raiseError('channel-add: Cannot open "' . $params[0] . '"');
540
            } else {
541
                list($loc, $lastmodified) = $loc;
542
                $contents = implode('', file($loc));
543
            }
544
        } else {
545
            $lastmodified = $fp = false;
546
            if (file_exists($params[0])) {
547
                $fp = fopen($params[0], 'r');
548
            }
549
            if (!$fp) {
550
                return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
551
            }
552
            $contents = '';
553
            while (!feof($fp)) {
554
                $contents .= fread($fp, 1024);
555
            }
556
            fclose($fp);
557
        }
558
        if (!class_exists('PEAR_ChannelFile')) {
559
            require_once 'PEAR/ChannelFile.php';
560
        }
561
        $channel = new PEAR_ChannelFile;
562
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
563
        $result = $channel->fromXmlString($contents);
564
        PEAR::staticPopErrorHandling();
565
        if (!$result) {
566
            $exit = false;
567
            if (count($errors = $channel->getErrors(true))) {
568
                foreach ($errors as $error) {
569
                    $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
570
                    if (!$exit) {
571
                        $exit = $error['level'] == 'error' ? true : false;
572
                    }
573
                }
574
                if ($exit) {
575
                    return $this->raiseError('channel-add: invalid channel.xml file');
576
                }
577
            }
578
        }
579
        $reg = &$this->config->getRegistry();
580
        if ($reg->channelExists($channel->getName())) {
581
            return $this->raiseError('channel-add: Channel "' . $channel->getName() .
582
                '" exists, use channel-update to update entry');
583
        }
584
        $ret = $reg->addChannel($channel, $lastmodified);
585
        if (PEAR::isError($ret)) {
586
            return $ret;
587
        }
588
        if (!$ret) {
589
            return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
590
                '" to registry failed');
591
        }
592
        $this->config->setChannels($reg->listChannels());
593
        $this->config->writeConfigFile();
594
        $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
595
    }
596
 
597
    function doUpdate($command, $options, $params)
598
    {
599
        if (!class_exists('System')) {
600
            require_once 'System.php';
601
        }
602
        $tmpdir = System::mktemp(array('-d'));
603
        $reg = &$this->config->getRegistry();
604
        if (sizeof($params) != 1) {
605
            return $this->raiseError("No channel file specified");
606
        }
607
        $lastmodified = false;
608
        if ((!file_exists($params[0]) || is_dir($params[0]))
609
              && $reg->channelExists(strtolower($params[0]))) {
610
            $c = $reg->getChannel(strtolower($params[0]));
611
            if (PEAR::isError($c)) {
612
                return $this->raiseError($c);
613
            }
614
            $this->ui->outputData('Retrieving channel.xml from remote server');
615
            $dl = &$this->getDownloader(array());
616
            // if force is specified, use a timestamp of "1" to force retrieval
617
            $lastmodified = isset($options['force']) ? false : $c->lastModified();
618
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
619
            $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
620
                $this->ui, $tmpdir, null, $lastmodified);
621
            PEAR::staticPopErrorHandling();
622
            if (PEAR::isError($contents)) {
623
                return $this->raiseError('Cannot retrieve channel.xml for channel "' .
624
                    $c->getName() . '"');
625
            }
626
            list($contents, $lastmodified) = $contents;
627
            if (!$contents) {
628
                $this->ui->outputData("Channel $params[0] channel.xml is up to date");
629
                return;
630
            }
631
            $contents = implode('', file($contents));
632
            if (!class_exists('PEAR_ChannelFile')) {
633
                require_once 'PEAR/ChannelFile.php';
634
            }
635
            $channel = new PEAR_ChannelFile;
636
            $channel->fromXmlString($contents);
637
            if (!$channel->getErrors()) {
638
                // security check: is the downloaded file for the channel we got it from?
639
                if (strtolower($channel->getName()) != strtolower($c->getName())) {
640
                    if (isset($options['force'])) {
641
                        $this->ui->log(0, 'WARNING: downloaded channel definition file' .
642
                            ' for channel "' . $channel->getName() . '" from channel "' .
643
                            strtolower($c->getName()) . '"');
644
                    } else {
645
                        return $this->raiseError('ERROR: downloaded channel definition file' .
646
                            ' for channel "' . $channel->getName() . '" from channel "' .
647
                            strtolower($c->getName()) . '"');
648
                    }
649
                }
650
            }
651
        } else {
652
            if (strpos($params[0], '://')) {
653
                $dl = &$this->getDownloader();
654
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
655
                $loc = $dl->downloadHttp($params[0],
656
                    $this->ui, $tmpdir, null, $lastmodified);
657
                PEAR::staticPopErrorHandling();
658
                if (PEAR::isError($loc)) {
659
                    return $this->raiseError("Cannot open " . $params[0]);
660
                } else {
661
                    list($loc, $lastmodified) = $loc;
662
                    $contents = implode('', file($loc));
663
                }
664
            } else {
665
                $fp = false;
666
                if (file_exists($params[0])) {
667
                    $fp = fopen($params[0], 'r');
668
                }
669
                if (!$fp) {
670
                    return $this->raiseError("Cannot open " . $params[0]);
671
                }
672
                $contents = '';
673
                while (!feof($fp)) {
674
                    $contents .= fread($fp, 1024);
675
                }
676
                fclose($fp);
677
            }
678
            if (!class_exists('PEAR_ChannelFile')) {
679
                require_once 'PEAR/ChannelFile.php';
680
            }
681
            $channel = new PEAR_ChannelFile;
682
            $channel->fromXmlString($contents);
683
        }
684
        $exit = false;
685
        if (count($errors = $channel->getErrors(true))) {
686
            foreach ($errors as $error) {
687
                $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
688
                if (!$exit) {
689
                    $exit = $error['level'] == 'error' ? true : false;
690
                }
691
            }
692
            if ($exit) {
693
                return $this->raiseError('Invalid channel.xml file');
694
            }
695
        }
696
        if (!$reg->channelExists($channel->getName())) {
697
            return $this->raiseError('Error: Channel "' . $channel->getName() .
698
                '" does not exist, use channel-add to add an entry');
699
        }
700
        $ret = $reg->updateChannel($channel, $lastmodified);
701
        if (PEAR::isError($ret)) {
702
            return $ret;
703
        }
704
        if (!$ret) {
705
            return $this->raiseError('Updating Channel "' . $channel->getName() .
706
                '" in registry failed');
707
        }
708
        $this->config->setChannels($reg->listChannels());
709
        $this->config->writeConfigFile();
710
        $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
711
    }
712
 
713
    function &getDownloader()
714
    {
715
        if (!class_exists('PEAR_Downloader')) {
716
            require_once 'PEAR/Downloader.php';
717
        }
718
        $a = new PEAR_Downloader($this->ui, array(), $this->config);
719
        return $a;
720
    }
721
 
722
    function doAlias($command, $options, $params)
723
    {
724
        $reg = &$this->config->getRegistry();
725
        if (sizeof($params) == 1) {
726
            return $this->raiseError('No channel alias specified');
727
        }
728
        if (sizeof($params) != 2) {
729
            return $this->raiseError(
730
                'Invalid format, correct is: channel-alias channel alias');
731
        }
732
        if (!$reg->channelExists($params[0], true)) {
733
            if ($reg->isAlias($params[0])) {
734
                $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
735
                    strtolower($params[1]) . '")';
736
            } else {
737
                $extra = '';
738
            }
739
            return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
740
        }
741
        if ($reg->isAlias($params[1])) {
742
            return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
743
                'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
744
        }
745
        $chan = &$reg->getChannel($params[0]);
746
        if (PEAR::isError($chan)) {
747
            return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
748
                '" information (' . $chan->getMessage() . ')');
749
        }
750
        // make it a local alias
751
        if (!$chan->setAlias(strtolower($params[1]), true)) {
752
            return $this->raiseError('Alias "' . strtolower($params[1]) .
753
                '" is not a valid channel alias');
754
        }
755
        $reg->updateChannel($chan);
756
        $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
757
            strtolower($params[1]) . '"');
758
    }
759
 
760
    function doDiscover($command, $options, $params)
761
    {
762
        $reg = &$this->config->getRegistry();
763
        if (sizeof($params) != 1) {
764
            return $this->raiseError("No channel server specified");
765
        }
766
        if ($reg->channelExists($params[0])) {
767
            if ($reg->isAlias($params[0])) {
768
                return $this->raiseError("A channel alias named \"$params[0]\" " .
769
                    'already exists, aliasing channel "' . $reg->channelName($params[0])
770
                    . '"');
771
            } else {
772
                return $this->raiseError("Channel \"$params[0]\" is already initialized");
773
            }
774
        }
775
        $this->pushErrorHandling(PEAR_ERROR_RETURN);
776
        $err = $this->doAdd($command, $options, array('http://' . $params[0] . '/channel.xml'));
777
        $this->popErrorHandling();
778
        if (PEAR::isError($err)) {
779
            return $this->raiseError("Discovery of channel \"$params[0]\" failed (" .
780
                $err->getMessage() . ')');
781
        }
782
        $this->ui->outputData("Discovery of channel \"$params[0]\" succeeded", $command);
783
    }
784
}
785
?>