Хранилища Subversion ant

Редакция

Редакция 69 | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS

Редакция 69 Редакция 87
1
<?php
1
<?php
2
/**
2
/**
3
 * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
3
 * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
4
 * clear-cache commands)
4
 * clear-cache commands)
5
 *
5
 *
6
 * PHP versions 4 and 5
6
 * PHP versions 4 and 5
7
 *
7
 *
8
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * LICENSE: This source file is subject to version 3.0 of the PHP license
9
 * that is available through the world-wide-web at the following URI:
9
 * that is available through the world-wide-web at the following URI:
10
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
11
 * the PHP License and are unable to obtain it through the web, please
11
 * the PHP License and are unable to obtain it through the web, please
12
 * send a note to license@php.net so we can mail you a copy immediately.
12
 * send a note to license@php.net so we can mail you a copy immediately.
13
 *
13
 *
14
 * @category   pear
14
 * @category   pear
15
 * @package    PEAR
15
 * @package    PEAR
16
 * @author     Stig Bakken <ssb@php.net>
16
 * @author     Stig Bakken <ssb@php.net>
17
 * @author     Greg Beaver <cellog@php.net>
17
 * @author     Greg Beaver <cellog@php.net>
18
 * @copyright  1997-2008 The PHP Group
18
 * @copyright  1997-2008 The PHP Group
19
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
19
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
20
 * @version    CVS: $Id: Remote.php,v 1.107 2008/04/11 01:16:40 dufuz Exp $
20
 * @version    CVS: $Id: Remote.php,v 1.107 2008/04/11 01:16:40 dufuz Exp $
21
 * @link       http://pear.php.net/package/PEAR
21
 * @link       http://pear.php.net/package/PEAR
22
 * @since      File available since Release 0.1
22
 * @since      File available since Release 0.1
23
 */
23
 */
24
24
25
/**
25
/**
26
 * base class
26
 * base class
27
 */
27
 */
28
require_once 'PEAR/Command/Common.php';
28
require_once 'PEAR/Command/Common.php';
29
require_once 'PEAR/REST.php';
29
require_once 'PEAR/REST.php';
30
30
31
/**
31
/**
32
 * PEAR commands for remote server querying
32
 * PEAR commands for remote server querying
33
 *
33
 *
34
 * @category   pear
34
 * @category   pear
35
 * @package    PEAR
35
 * @package    PEAR
36
 * @author     Stig Bakken <ssb@php.net>
36
 * @author     Stig Bakken <ssb@php.net>
37
 * @author     Greg Beaver <cellog@php.net>
37
 * @author     Greg Beaver <cellog@php.net>
38
 * @copyright  1997-2008 The PHP Group
38
 * @copyright  1997-2008 The PHP Group
39
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
39
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
40
 * @version    Release: 1.7.2
40
 * @version    Release: 1.7.2
41
 * @link       http://pear.php.net/package/PEAR
41
 * @link       http://pear.php.net/package/PEAR
42
 * @since      Class available since Release 0.1
42
 * @since      Class available since Release 0.1
43
 */
43
 */
44
class PEAR_Command_Remote extends PEAR_Command_Common
44
class PEAR_Command_Remote extends PEAR_Command_Common
45
{
45
{
46
    // {{{ command definitions
46
    // {{{ command definitions
47
47
48
    var $commands = array(
48
    var $commands = array(
49
        'remote-info' => array(
49
        'remote-info' => array(
50
            'summary' => 'Information About Remote Packages',
50
            'summary' => 'Information About Remote Packages',
51
            'function' => 'doRemoteInfo',
51
            'function' => 'doRemoteInfo',
52
            'shortcut' => 'ri',
52
            'shortcut' => 'ri',
53
            'options' => array(),
53
            'options' => array(),
54
            'doc' => '<package>
54
            'doc' => '<package>
55
Get details on a package from the server.',
55
Get details on a package from the server.',
56
            ),
56
            ),
57
        'list-upgrades' => array(
57
        'list-upgrades' => array(
58
            'summary' => 'List Available Upgrades',
58
            'summary' => 'List Available Upgrades',
59
            'function' => 'doListUpgrades',
59
            'function' => 'doListUpgrades',
60
            'shortcut' => 'lu',
60
            'shortcut' => 'lu',
61
            'options' => array(
61
            'options' => array(
62
                'channelinfo' => array(
62
                'channelinfo' => array(
63
                    'shortopt' => 'i',
63
                    'shortopt' => 'i',
64
                    'doc' => 'output fully channel-aware data, even on failure',
64
                    'doc' => 'output fully channel-aware data, even on failure',
65
                    ),
65
                    ),
66
            ),
66
            ),
67
            'doc' => '[preferred_state]
67
            'doc' => '[preferred_state]
68
List releases on the server of packages you have installed where
68
List releases on the server of packages you have installed where
69
a newer version is available with the same release state (stable etc.)
69
a newer version is available with the same release state (stable etc.)
70
or the state passed as the second parameter.'
70
or the state passed as the second parameter.'
71
            ),
71
            ),
72
        'remote-list' => array(
72
        'remote-list' => array(
73
            'summary' => 'List Remote Packages',
73
            'summary' => 'List Remote Packages',
74
            'function' => 'doRemoteList',
74
            'function' => 'doRemoteList',
75
            'shortcut' => 'rl',
75
            'shortcut' => 'rl',
76
            'options' => array(
76
            'options' => array(
77
                'channel' =>
77
                'channel' =>
78
                    array(
78
                    array(
79
                    'shortopt' => 'c',
79
                    'shortopt' => 'c',
80
                    'doc' => 'specify a channel other than the default channel',
80
                    'doc' => 'specify a channel other than the default channel',
81
                    'arg' => 'CHAN',
81
                    'arg' => 'CHAN',
82
                    )
82
                    )
83
                ),
83
                ),
84
            'doc' => '
84
            'doc' => '
85
Lists the packages available on the configured server along with the
85
Lists the packages available on the configured server along with the
86
latest stable release of each package.',
86
latest stable release of each package.',
87
            ),
87
            ),
88
        'search' => array(
88
        'search' => array(
89
            'summary' => 'Search remote package database',
89
            'summary' => 'Search remote package database',
90
            'function' => 'doSearch',
90
            'function' => 'doSearch',
91
            'shortcut' => 'sp',
91
            'shortcut' => 'sp',
92
            'options' => array(
92
            'options' => array(
93
                'channel' =>
93
                'channel' =>
94
                    array(
94
                    array(
95
                    'shortopt' => 'c',
95
                    'shortopt' => 'c',
96
                    'doc' => 'specify a channel other than the default channel',
96
                    'doc' => 'specify a channel other than the default channel',
97
                    'arg' => 'CHAN',
97
                    'arg' => 'CHAN',
98
                    ),
98
                    ),
99
                'allchannels' => array(
99
                'allchannels' => array(
100
                    'shortopt' => 'a',
100
                    'shortopt' => 'a',
101
                    'doc' => 'search packages from all known channels',
101
                    'doc' => 'search packages from all known channels',
102
                    ),
102
                    ),
103
                'channelinfo' => array(
103
                'channelinfo' => array(
104
                    'shortopt' => 'i',
104
                    'shortopt' => 'i',
105
                    'doc' => 'output fully channel-aware data, even on failure',
105
                    'doc' => 'output fully channel-aware data, even on failure',
106
                    ),
106
                    ),
107
                ),
107
                ),
108
            'doc' => '[packagename] [packageinfo]
108
            'doc' => '[packagename] [packageinfo]
109
Lists all packages which match the search parameters.  The first
109
Lists all packages which match the search parameters.  The first
110
parameter is a fragment of a packagename.  The default channel
110
parameter is a fragment of a packagename.  The default channel
111
will be used unless explicitly overridden.  The second parameter
111
will be used unless explicitly overridden.  The second parameter
112
will be used to match any portion of the summary/description',
112
will be used to match any portion of the summary/description',
113
            ),
113
            ),
114
        'list-all' => array(
114
        'list-all' => array(
115
            'summary' => 'List All Packages',
115
            'summary' => 'List All Packages',
116
            'function' => 'doListAll',
116
            'function' => 'doListAll',
117
            'shortcut' => 'la',
117
            'shortcut' => 'la',
118
            'options' => array(
118
            'options' => array(
119
                'channel' =>
119
                'channel' =>
120
                    array(
120
                    array(
121
                    'shortopt' => 'c',
121
                    'shortopt' => 'c',
122
                    'doc' => 'specify a channel other than the default channel',
122
                    'doc' => 'specify a channel other than the default channel',
123
                    'arg' => 'CHAN',
123
                    'arg' => 'CHAN',
124
                    ),
124
                    ),
125
                'channelinfo' => array(
125
                'channelinfo' => array(
126
                    'shortopt' => 'i',
126
                    'shortopt' => 'i',
127
                    'doc' => 'output fully channel-aware data, even on failure',
127
                    'doc' => 'output fully channel-aware data, even on failure',
128
                    ),
128
                    ),
129
                ),
129
                ),
130
            'doc' => '
130
            'doc' => '
131
Lists the packages available on the configured server along with the
131
Lists the packages available on the configured server along with the
132
latest stable release of each package.',
132
latest stable release of each package.',
133
            ),
133
            ),
134
        'download' => array(
134
        'download' => array(
135
            'summary' => 'Download Package',
135
            'summary' => 'Download Package',
136
            'function' => 'doDownload',
136
            'function' => 'doDownload',
137
            'shortcut' => 'd',
137
            'shortcut' => 'd',
138
            'options' => array(
138
            'options' => array(
139
                'nocompress' => array(
139
                'nocompress' => array(
140
                    'shortopt' => 'Z',
140
                    'shortopt' => 'Z',
141
                    'doc' => 'download an uncompressed (.tar) file',
141
                    'doc' => 'download an uncompressed (.tar) file',
142
                    ),
142
                    ),
143
                ),
143
                ),
144
            'doc' => '<package>...
144
            'doc' => '<package>...
145
Download package tarballs.  The files will be named as suggested by the
145
Download package tarballs.  The files will be named as suggested by the
146
server, for example if you download the DB package and the latest stable
146
server, for example if you download the DB package and the latest stable
147
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
147
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
148
            ),
148
            ),
149
        'clear-cache' => array(
149
        'clear-cache' => array(
150
            'summary' => 'Clear Web Services Cache',
150
            'summary' => 'Clear Web Services Cache',
151
            'function' => 'doClearCache',
151
            'function' => 'doClearCache',
152
            'shortcut' => 'cc',
152
            'shortcut' => 'cc',
153
            'options' => array(),
153
            'options' => array(),
154
            'doc' => '
154
            'doc' => '
155
Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
155
Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
156
parameter.
156
parameter.
157
',
157
',
158
            ),
158
            ),
159
        );
159
        );
160
160
161
    // }}}
161
    // }}}
162
    // {{{ constructor
162
    // {{{ constructor
163
163
164
    /**
164
    /**
165
     * PEAR_Command_Remote constructor.
165
     * PEAR_Command_Remote constructor.
166
     *
166
     *
167
     * @access public
167
     * @access public
168
     */
168
     */
169
    function PEAR_Command_Remote(&$ui, &$config)
169
    function PEAR_Command_Remote(&$ui, &$config)
170
    {
170
    {
171
        parent::PEAR_Command_Common($ui, $config);
171
        parent::PEAR_Command_Common($ui, $config);
172
    }
172
    }
173
173
174
    // }}}
174
    // }}}
175
175
176
    function _checkChannelForStatus($channel, $chan)
176
    function _checkChannelForStatus($channel, $chan)
177
    {
177
    {
178
        if (PEAR::isError($chan)) {
178
        if (PEAR::isError($chan)) {
179
            $this->raiseError($chan);
179
            $this->raiseError($chan);
180
        }
180
        }
181
        if (!is_a($chan, 'PEAR_ChannelFile')) {
181
        if (!is_a($chan, 'PEAR_ChannelFile')) {
182
            return $this->raiseError('Internal corruption error: invalid channel "' .
182
            return $this->raiseError('Internal corruption error: invalid channel "' .
183
                $channel . '"');
183
                $channel . '"');
184
        }
184
        }
185
        $rest = new PEAR_REST($this->config);
185
        $rest = new PEAR_REST($this->config);
186
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
186
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
187
        $mirror = $this->config->get('preferred_mirror', null,
187
        $mirror = $this->config->get('preferred_mirror', null,
188
                                     $channel);
188
                                     $channel);
189
        $a = $rest->downloadHttp('http://' . $channel .
189
        $a = $rest->downloadHttp('http://' . $channel .
190
            '/channel.xml', $chan->lastModified());
190
            '/channel.xml', $chan->lastModified());
191
        PEAR::staticPopErrorHandling();
191
        PEAR::staticPopErrorHandling();
192
        if (!PEAR::isError($a) && $a) {
192
        if (!PEAR::isError($a) && $a) {
193
            $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
193
            $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
194
                'updated its protocols, use "channel-update ' . $channel .
194
                'updated its protocols, use "channel-update ' . $channel .
195
                '" to update');
195
                '" to update');
196
        }
196
        }
197
    }
197
    }
198
198
199
    // {{{ doRemoteInfo()
199
    // {{{ doRemoteInfo()
200
200
201
    function doRemoteInfo($command, $options, $params)
201
    function doRemoteInfo($command, $options, $params)
202
    {
202
    {
203
        if (sizeof($params) != 1) {
203
        if (sizeof($params) != 1) {
204
            return $this->raiseError("$command expects one param: the remote package name");
204
            return $this->raiseError("$command expects one param: the remote package name");
205
        }
205
        }
206
        $savechannel = $channel = $this->config->get('default_channel');
206
        $savechannel = $channel = $this->config->get('default_channel');
207
        $reg = &$this->config->getRegistry();
207
        $reg = &$this->config->getRegistry();
208
        $package = $params[0];
208
        $package = $params[0];
209
        $parsed = $reg->parsePackageName($package, $channel);
209
        $parsed = $reg->parsePackageName($package, $channel);
210
        if (PEAR::isError($parsed)) {
210
        if (PEAR::isError($parsed)) {
211
            return $this->raiseError('Invalid package name "' . $package . '"');
211
            return $this->raiseError('Invalid package name "' . $package . '"');
212
        }
212
        }
213
213
214
        $channel = $parsed['channel'];
214
        $channel = $parsed['channel'];
215
        $this->config->set('default_channel', $channel);
215
        $this->config->set('default_channel', $channel);
216
        $chan = $reg->getChannel($channel);
216
        $chan = $reg->getChannel($channel);
217
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
217
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
218
            return $e;
218
            return $e;
219
        }
219
        }
220
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
220
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
221
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
221
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
222
            $rest = &$this->config->getREST('1.0', array());
222
            $rest = &$this->config->getREST('1.0', array());
223
            $info = $rest->packageInfo($base, $parsed['package'], $channel);
223
            $info = $rest->packageInfo($base, $parsed['package'], $channel);
224
        } else {
224
        } else {
225
            $r = &$this->config->getRemote();
225
            $r = &$this->config->getRemote();
226
            $info = $r->call('package.info', $parsed['package']);
226
            $info = $r->call('package.info', $parsed['package']);
227
        }
227
        }
228
        if (PEAR::isError($info)) {
228
        if (PEAR::isError($info)) {
229
            $this->config->set('default_channel', $savechannel);
229
            $this->config->set('default_channel', $savechannel);
230
            return $this->raiseError($info);
230
            return $this->raiseError($info);
231
        }
231
        }
232
        if (!isset($info['name'])) {
232
        if (!isset($info['name'])) {
233
            return $this->raiseError('No remote package "' . $package . '" was found');
233
            return $this->raiseError('No remote package "' . $package . '" was found');
234
        }
234
        }
235
235
236
        $installed = $reg->packageInfo($info['name'], null, $channel);
236
        $installed = $reg->packageInfo($info['name'], null, $channel);
237
        $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
237
        $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
238
        if (is_array($info['installed'])) {
238
        if (is_array($info['installed'])) {
239
            $info['installed'] = $info['installed']['release'];
239
            $info['installed'] = $info['installed']['release'];
240
        }
240
        }
241
241
242
        $this->ui->outputData($info, $command);
242
        $this->ui->outputData($info, $command);
243
        $this->config->set('default_channel', $savechannel);
243
        $this->config->set('default_channel', $savechannel);
244
244
245
        return true;
245
        return true;
246
    }
246
    }
247
247
248
    // }}}
248
    // }}}
249
    // {{{ doRemoteList()
249
    // {{{ doRemoteList()
250
250
251
    function doRemoteList($command, $options, $params)
251
    function doRemoteList($command, $options, $params)
252
    {
252
    {
253
        $savechannel = $channel = $this->config->get('default_channel');
253
        $savechannel = $channel = $this->config->get('default_channel');
254
        $reg = &$this->config->getRegistry();
254
        $reg = &$this->config->getRegistry();
255
        if (isset($options['channel'])) {
255
        if (isset($options['channel'])) {
256
            $channel = $options['channel'];
256
            $channel = $options['channel'];
257
            if ($reg->channelExists($channel)) {
257
            if ($reg->channelExists($channel)) {
258
                $this->config->set('default_channel', $channel);
258
                $this->config->set('default_channel', $channel);
259
            } else {
259
            } else {
260
                return $this->raiseError('Channel "' . $channel . '" does not exist');
260
                return $this->raiseError('Channel "' . $channel . '" does not exist');
261
            }
261
            }
262
        }
262
        }
263
        $chan = $reg->getChannel($channel);
263
        $chan = $reg->getChannel($channel);
264
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
264
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
265
            return $e;
265
            return $e;
266
        }
266
        }
267
        $list_options = false;
267
        $list_options = false;
268
        if ($this->config->get('preferred_state') == 'stable') {
268
        if ($this->config->get('preferred_state') == 'stable') {
269
            $list_options = true;
269
            $list_options = true;
270
        }
270
        }
271
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
271
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
272
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
272
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
273
            // use faster list-all if available
273
            // use faster list-all if available
274
            $rest = &$this->config->getREST('1.1', array());
274
            $rest = &$this->config->getREST('1.1', array());
275
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
275
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
276
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
276
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
277
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
277
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
278
            $rest = &$this->config->getREST('1.0', array());
278
            $rest = &$this->config->getREST('1.0', array());
279
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
279
            $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
280
        } else {
280
        } else {
281
            $r = &$this->config->getRemote();
281
            $r = &$this->config->getRemote();
282
            if ($channel == 'pear.php.net') {
282
            if ($channel == 'pear.php.net') {
283
                // hack because of poor pearweb design
283
                // hack because of poor pearweb design
284
                $available = $r->call('package.listAll', true, $list_options, false);
284
                $available = $r->call('package.listAll', true, $list_options, false);
285
            } else {
285
            } else {
286
                $available = $r->call('package.listAll', true, $list_options);
286
                $available = $r->call('package.listAll', true, $list_options);
287
            }
287
            }
288
        }
288
        }
289
        if (PEAR::isError($available)) {
289
        if (PEAR::isError($available)) {
290
            $this->config->set('default_channel', $savechannel);
290
            $this->config->set('default_channel', $savechannel);
291
            return $this->raiseError($available);
291
            return $this->raiseError($available);
292
        }
292
        }
293
        $i = $j = 0;
293
        $i = $j = 0;
294
        $data = array(
294
        $data = array(
295
            'caption' => 'Channel ' . $channel . ' Available packages:',
295
            'caption' => 'Channel ' . $channel . ' Available packages:',
296
            'border' => true,
296
            'border' => true,
297
            'headline' => array('Package', 'Version'),
297
            'headline' => array('Package', 'Version'),
298
            'channel' => $channel
298
            'channel' => $channel
299
            );
299
            );
300
        if (count($available)==0) {
300
        if (count($available)==0) {
301
            $data = '(no packages available yet)';
301
            $data = '(no packages available yet)';
302
        } else {
302
        } else {
303
            foreach ($available as $name => $info) {
303
            foreach ($available as $name => $info) {
304
                $data['data'][] = array($name, (isset($info['stable']) && $info['stable'])
304
                $data['data'][] = array($name, (isset($info['stable']) && $info['stable'])
305
                    ? $info['stable'] : '-n/a-');
305
                    ? $info['stable'] : '-n/a-');
306
            }
306
            }
307
        }
307
        }
308
        $this->ui->outputData($data, $command);
308
        $this->ui->outputData($data, $command);
309
        $this->config->set('default_channel', $savechannel);
309
        $this->config->set('default_channel', $savechannel);
310
        return true;
310
        return true;
311
    }
311
    }
312
312
313
    // }}}
313
    // }}}
314
    // {{{ doListAll()
314
    // {{{ doListAll()
315
315
316
    function doListAll($command, $options, $params)
316
    function doListAll($command, $options, $params)
317
    {
317
    {
318
        $savechannel = $channel = $this->config->get('default_channel');
318
        $savechannel = $channel = $this->config->get('default_channel');
319
        $reg = &$this->config->getRegistry();
319
        $reg = &$this->config->getRegistry();
320
        if (isset($options['channel'])) {
320
        if (isset($options['channel'])) {
321
            $channel = $options['channel'];
321
            $channel = $options['channel'];
322
            if ($reg->channelExists($channel)) {
322
            if ($reg->channelExists($channel)) {
323
                $this->config->set('default_channel', $channel);
323
                $this->config->set('default_channel', $channel);
324
            } else {
324
            } else {
325
                return $this->raiseError("Channel \"$channel\" does not exist");
325
                return $this->raiseError("Channel \"$channel\" does not exist");
326
            }
326
            }
327
        }
327
        }
328
        $list_options = false;
328
        $list_options = false;
329
        if ($this->config->get('preferred_state') == 'stable') {
329
        if ($this->config->get('preferred_state') == 'stable') {
330
            $list_options = true;
330
            $list_options = true;
331
        }
331
        }
332
        $chan = $reg->getChannel($channel);
332
        $chan = $reg->getChannel($channel);
333
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
333
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
334
            return $e;
334
            return $e;
335
        }
335
        }
336
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
336
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
337
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
337
              $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
338
            // use faster list-all if available
338
            // use faster list-all if available
339
            $rest = &$this->config->getREST('1.1', array());
339
            $rest = &$this->config->getREST('1.1', array());
340
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
340
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
341
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
341
        } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
342
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
342
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
343
            $rest = &$this->config->getREST('1.0', array());
343
            $rest = &$this->config->getREST('1.0', array());
344
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
344
            $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
345
        } else {
345
        } else {
346
            $r = &$this->config->getRemote();
346
            $r = &$this->config->getRemote();
347
            if ($channel == 'pear.php.net') {
347
            if ($channel == 'pear.php.net') {
348
                // hack because of poor pearweb design
348
                // hack because of poor pearweb design
349
                $available = $r->call('package.listAll', true, $list_options, false);
349
                $available = $r->call('package.listAll', true, $list_options, false);
350
            } else {
350
            } else {
351
                $available = $r->call('package.listAll', true, $list_options);
351
                $available = $r->call('package.listAll', true, $list_options);
352
            }
352
            }
353
        }
353
        }
354
        if (PEAR::isError($available)) {
354
        if (PEAR::isError($available)) {
355
            $this->config->set('default_channel', $savechannel);
355
            $this->config->set('default_channel', $savechannel);
356
            return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
356
            return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
357
        }
357
        }
358
        $data = array(
358
        $data = array(
359
            'caption' => 'All packages [Channel ' . $channel . ']:',
359
            'caption' => 'All packages [Channel ' . $channel . ']:',
360
            'border' => true,
360
            'border' => true,
361
            'headline' => array('Package', 'Latest', 'Local'),
361
            'headline' => array('Package', 'Latest', 'Local'),
362
            'channel' => $channel,
362
            'channel' => $channel,
363
            );
363
            );
364
        if (isset($options['channelinfo'])) {
364
        if (isset($options['channelinfo'])) {
365
            // add full channelinfo
365
            // add full channelinfo
366
            $data['caption'] = 'Channel ' . $channel . ' All packages:';
366
            $data['caption'] = 'Channel ' . $channel . ' All packages:';
367
            $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
367
            $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
368
                'Description', 'Dependencies');
368
                'Description', 'Dependencies');
369
        }
369
        }
370
        $local_pkgs = $reg->listPackages($channel);
370
        $local_pkgs = $reg->listPackages($channel);
371
371
372
        foreach ($available as $name => $info) {
372
        foreach ($available as $name => $info) {
373
            $installed = $reg->packageInfo($name, null, $channel);
373
            $installed = $reg->packageInfo($name, null, $channel);
374
            if (is_array($installed['version'])) {
374
            if (is_array($installed['version'])) {
375
                $installed['version'] = $installed['version']['release'];
375
                $installed['version'] = $installed['version']['release'];
376
            }
376
            }
377
            $desc = $info['summary'];
377
            $desc = $info['summary'];
378
            if (isset($params[$name])) {
378
            if (isset($params[$name])) {
379
                $desc .= "\n\n".$info['description'];
379
                $desc .= "\n\n".$info['description'];
380
            }
380
            }
381
            if (isset($options['mode']))
381
            if (isset($options['mode']))
382
            {
382
            {
383
                if ($options['mode'] == 'installed' && !isset($installed['version'])) {
383
                if ($options['mode'] == 'installed' && !isset($installed['version'])) {
384
                    continue;
384
                    continue;
385
                }
385
                }
386
                if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
386
                if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
387
                    continue;
387
                    continue;
388
                }
388
                }
389
                if ($options['mode'] == 'upgrades'
389
                if ($options['mode'] == 'upgrades'
390
                      && (!isset($installed['version']) || version_compare($installed['version'],
390
                      && (!isset($installed['version']) || version_compare($installed['version'],
391
                      $info['stable'], '>='))) {
391
                      $info['stable'], '>='))) {
392
                    continue;
392
                    continue;
393
                }
393
                }
394
            }
394
            }
395
            $pos = array_search(strtolower($name), $local_pkgs);
395
            $pos = array_search(strtolower($name), $local_pkgs);
396
            if ($pos !== false) {
396
            if ($pos !== false) {
397
                unset($local_pkgs[$pos]);
397
                unset($local_pkgs[$pos]);
398
            }
398
            }
399
399
400
            if (isset($info['stable']) && !$info['stable']) {
400
            if (isset($info['stable']) && !$info['stable']) {
401
                $info['stable'] = null;
401
                $info['stable'] = null;
402
            }
402
            }
403
403
404
            if (isset($options['channelinfo'])) {
404
            if (isset($options['channelinfo'])) {
405
                // add full channelinfo
405
                // add full channelinfo
406
                if ($info['stable'] === $info['unstable']) {
406
                if ($info['stable'] === $info['unstable']) {
407
                    $state = $info['state'];
407
                    $state = $info['state'];
408
                } else {
408
                } else {
409
                    $state = 'stable';
409
                    $state = 'stable';
410
                }
410
                }
411
                $latest = $info['stable'].' ('.$state.')';
411
                $latest = $info['stable'].' ('.$state.')';
412
                $local = '';
412
                $local = '';
413
                if (isset($installed['version'])) {
413
                if (isset($installed['version'])) {
414
                    $inst_state = $reg->packageInfo($name, 'release_state', $channel);
414
                    $inst_state = $reg->packageInfo($name, 'release_state', $channel);
415
                    $local = $installed['version'].' ('.$inst_state.')';
415
                    $local = $installed['version'].' ('.$inst_state.')';
416
                }
416
                }
417
417
418
                $packageinfo = array(
418
                $packageinfo = array(
419
                    $channel,
419
                    $channel,
420
                    $name,
420
                    $name,
421
                    $latest,
421
                    $latest,
422
                    $local,
422
                    $local,
423
                    isset($desc) ? $desc : null,
423
                    isset($desc) ? $desc : null,
424
                    isset($info['deps']) ? $info['deps'] : null,
424
                    isset($info['deps']) ? $info['deps'] : null,
425
                );
425
                );
426
            } else {
426
            } else {
427
                $packageinfo = array(
427
                $packageinfo = array(
428
                    $reg->channelAlias($channel) . '/' . $name,
428
                    $reg->channelAlias($channel) . '/' . $name,
429
                    isset($info['stable']) ? $info['stable'] : null,
429
                    isset($info['stable']) ? $info['stable'] : null,
430
                    isset($installed['version']) ? $installed['version'] : null,
430
                    isset($installed['version']) ? $installed['version'] : null,
431
                    isset($desc) ? $desc : null,
431
                    isset($desc) ? $desc : null,
432
                    isset($info['deps']) ? $info['deps'] : null,
432
                    isset($info['deps']) ? $info['deps'] : null,
433
                );
433
                );
434
            }
434
            }
435
            $data['data'][$info['category']][] = $packageinfo;
435
            $data['data'][$info['category']][] = $packageinfo;
436
        }
436
        }
437
437
438
        if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
438
        if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
439
            $this->config->set('default_channel', $savechannel);
439
            $this->config->set('default_channel', $savechannel);
440
            $this->ui->outputData($data, $command);
440
            $this->ui->outputData($data, $command);
441
            return true;
441
            return true;
442
        }
442
        }
443
        foreach ($local_pkgs as $name) {
443
        foreach ($local_pkgs as $name) {
444
            $info = &$reg->getPackage($name, $channel);
444
            $info = &$reg->getPackage($name, $channel);
445
            $data['data']['Local'][] = array(
445
            $data['data']['Local'][] = array(
446
                $reg->channelAlias($channel) . '/' . $info->getPackage(),
446
                $reg->channelAlias($channel) . '/' . $info->getPackage(),
447
                '',
447
                '',
448
                $info->getVersion(),
448
                $info->getVersion(),
449
                $info->getSummary(),
449
                $info->getSummary(),
450
                $info->getDeps()
450
                $info->getDeps()
451
                );
451
                );
452
        }
452
        }
453
453
454
        $this->config->set('default_channel', $savechannel);
454
        $this->config->set('default_channel', $savechannel);
455
        $this->ui->outputData($data, $command);
455
        $this->ui->outputData($data, $command);
456
        return true;
456
        return true;
457
    }
457
    }
458
458
459
    // }}}
459
    // }}}
460
    // {{{ doSearch()
460
    // {{{ doSearch()
461
461
462
    function doSearch($command, $options, $params)
462
    function doSearch($command, $options, $params)
463
    {
463
    {
464
        if ((!isset($params[0]) || empty($params[0]))
464
        if ((!isset($params[0]) || empty($params[0]))
465
            && (!isset($params[1]) || empty($params[1])))
465
            && (!isset($params[1]) || empty($params[1])))
466
        {
466
        {
467
            return $this->raiseError('no valid search string supplied');
467
            return $this->raiseError('no valid search string supplied');
468
        };
468
        };
469
469
470
        $channelinfo = isset($options['channelinfo']);
470
        $channelinfo = isset($options['channelinfo']);
471
        $reg = &$this->config->getRegistry();
471
        $reg = &$this->config->getRegistry();
472
        if (isset($options['allchannels'])) {
472
        if (isset($options['allchannels'])) {
473
            // search all channels
473
            // search all channels
474
            unset($options['allchannels']);
474
            unset($options['allchannels']);
475
            $channels = $reg->getChannels();
475
            $channels = $reg->getChannels();
476
            $errors = array();
476
            $errors = array();
477
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
477
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
478
            foreach ($channels as $channel) {
478
            foreach ($channels as $channel) {
479
                if ($channel->getName() != '__uri') {
479
                if ($channel->getName() != '__uri') {
480
                    $options['channel'] = $channel->getName();
480
                    $options['channel'] = $channel->getName();
481
                    $ret = $this->doSearch($command, $options, $params);
481
                    $ret = $this->doSearch($command, $options, $params);
482
                    if (PEAR::isError($ret)) {
482
                    if (PEAR::isError($ret)) {
483
                        $errors[] = $ret;
483
                        $errors[] = $ret;
484
                    }
484
                    }
485
                }
485
                }
486
            }
486
            }
487
            PEAR::staticPopErrorHandling();
487
            PEAR::staticPopErrorHandling();
488
            if (count($errors) !== 0) {
488
            if (count($errors) !== 0) {
489
                // for now, only give first error
489
                // for now, only give first error
490
                return PEAR::raiseError($errors[0]);
490
                return PEAR::raiseError($errors[0]);
491
            }
491
            }
492
492
493
            return true;
493
            return true;
494
        }
494
        }
495
495
496
        $savechannel = $channel = $this->config->get('default_channel');
496
        $savechannel = $channel = $this->config->get('default_channel');
497
        $package = $params[0];
497
        $package = $params[0];
498
        $summary = isset($params[1]) ? $params[1] : false;
498
        $summary = isset($params[1]) ? $params[1] : false;
499
        if (isset($options['channel'])) {
499
        if (isset($options['channel'])) {
500
            $reg = &$this->config->getRegistry();
500
            $reg = &$this->config->getRegistry();
501
            $channel = $options['channel'];
501
            $channel = $options['channel'];
502
            if ($reg->channelExists($channel)) {
502
            if ($reg->channelExists($channel)) {
503
                $this->config->set('default_channel', $channel);
503
                $this->config->set('default_channel', $channel);
504
            } else {
504
            } else {
505
                return $this->raiseError('Channel "' . $channel . '" does not exist');
505
                return $this->raiseError('Channel "' . $channel . '" does not exist');
506
            }
506
            }
507
        }
507
        }
508
        $chan = $reg->getChannel($channel);
508
        $chan = $reg->getChannel($channel);
509
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
509
        if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
510
            return $e;
510
            return $e;
511
        }
511
        }
512
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
512
        if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
513
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
513
              $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
514
            $rest = &$this->config->getREST('1.0', array());
514
            $rest = &$this->config->getREST('1.0', array());
515
            $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
515
            $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
516
        } else {
516
        } else {
517
            $r = &$this->config->getRemote();
517
            $r = &$this->config->getRemote();
518
            $available = $r->call('package.search', $package, $summary, true,
518
            $available = $r->call('package.search', $package, $summary, true,
519
                $this->config->get('preferred_state') == 'stable', true);
519
                $this->config->get('preferred_state') == 'stable', true);
520
        }
520
        }
521
        if (PEAR::isError($available)) {
521
        if (PEAR::isError($available)) {
522
            $this->config->set('default_channel', $savechannel);
522
            $this->config->set('default_channel', $savechannel);
523
            return $this->raiseError($available);
523
            return $this->raiseError($available);
524
        }
524
        }
525
        if (!$available && !$channelinfo) {
525
        if (!$available && !$channelinfo) {
526
            // clean exit when not found, no error !
526
            // clean exit when not found, no error !
527
            $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
527
            $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
528
            $this->ui->outputData($data);
528
            $this->ui->outputData($data);
529
            $this->config->set('default_channel', $channel);
529
            $this->config->set('default_channel', $channel);
530
            return true;
530
            return true;
531
        }
531
        }
532
        if ($channelinfo) {
532
        if ($channelinfo) {
533
            $data = array(
533
            $data = array(
534
                'caption' => 'Matched packages, channel ' . $channel . ':',
534
                'caption' => 'Matched packages, channel ' . $channel . ':',
535
                'border' => true,
535
                'border' => true,
536
                'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
536
                'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
537
                'channel' => $channel
537
                'channel' => $channel
538
                );
538
                );
539
        } else {
539
        } else {
540
            $data = array(
540
            $data = array(
541
                'caption' => 'Matched packages, channel ' . $channel . ':',
541
                'caption' => 'Matched packages, channel ' . $channel . ':',
542
                'border' => true,
542
                'border' => true,
543
                'headline' => array('Package', 'Stable/(Latest)', 'Local'),
543
                'headline' => array('Package', 'Stable/(Latest)', 'Local'),
544
                'channel' => $channel
544
                'channel' => $channel
545
                );
545
                );
546
        }
546
        }
547
547
548
        if (!$available && $channelinfo) {
548
        if (!$available && $channelinfo) {
549
            unset($data['headline']);
549
            unset($data['headline']);
550
            $data['data'] = 'No packages found that match pattern "' . $package . '".';
550
            $data['data'] = 'No packages found that match pattern "' . $package . '".';
551
            $available = array();
551
            $available = array();
552
        }
552
        }
553
        foreach ($available as $name => $info) {
553
        foreach ($available as $name => $info) {
554
            $installed = $reg->packageInfo($name, null, $channel);
554
            $installed = $reg->packageInfo($name, null, $channel);
555
            $desc = $info['summary'];
555
            $desc = $info['summary'];
556
            if (isset($params[$name]))
556
            if (isset($params[$name]))
557
                $desc .= "\n\n".$info['description'];
557
                $desc .= "\n\n".$info['description'];
558
558
559
            if (!isset($info['stable']) || !$info['stable']) {
559
            if (!isset($info['stable']) || !$info['stable']) {
560
                $version_remote = 'none';
560
                $version_remote = 'none';
561
            } else {
561
            } else {
562
                if ($info['unstable']) {
562
                if ($info['unstable']) {
563
                    $version_remote = $info['unstable'];
563
                    $version_remote = $info['unstable'];
564
                } else {
564
                } else {
565
                    $version_remote = $info['stable'];
565
                    $version_remote = $info['stable'];
566
                }
566
                }
567
                $version_remote .= ' ('.$info['state'].')';
567
                $version_remote .= ' ('.$info['state'].')';
568
            }
568
            }
569
            $version = is_array($installed['version']) ? $installed['version']['release'] :
569
            $version = is_array($installed['version']) ? $installed['version']['release'] :
570
                $installed['version'];
570
                $installed['version'];
571
            if ($channelinfo) {
571
            if ($channelinfo) {
572
                $packageinfo = array(
572
                $packageinfo = array(
573
                    $channel,
573
                    $channel,
574
                    $name,
574
                    $name,
575
                    $version_remote,
575
                    $version_remote,
576
                    $version,
576
                    $version,
577
                    $desc,
577
                    $desc,
578
                );
578
                );
579
            } else {
579
            } else {
580
                $packageinfo = array(
580
                $packageinfo = array(
581
                    $name,
581
                    $name,
582
                    $version_remote,
582
                    $version_remote,
583
                    $version,
583
                    $version,
584
                    $desc,
584
                    $desc,
585
                );
585
                );
586
            }
586
            }
587
            $data['data'][$info['category']][] = $packageinfo;
587
            $data['data'][$info['category']][] = $packageinfo;
588
        }
588
        }
589
        $this->ui->outputData($data, $command);
589
        $this->ui->outputData($data, $command);
590
        $this->config->set('default_channel', $channel);
590
        $this->config->set('default_channel', $channel);
591
        return true;
591
        return true;
592
    }
592
    }
593
593
594
    // }}}
594
    // }}}
595
    function &getDownloader($options)
595
    function &getDownloader($options)
596
    {
596
    {
597
        if (!class_exists('PEAR_Downloader')) {
597
        if (!class_exists('PEAR_Downloader')) {
598
            require_once 'PEAR/Downloader.php';
598
            require_once 'PEAR/Downloader.php';
599
        }
599
        }
600
        $a = &new PEAR_Downloader($this->ui, $options, $this->config);
600
        $a = &new PEAR_Downloader($this->ui, $options, $this->config);
601
        return $a;
601
        return $a;
602
    }
602
    }
603
    // {{{ doDownload()
603
    // {{{ doDownload()
604
604
605
    function doDownload($command, $options, $params)
605
    function doDownload($command, $options, $params)
606
    {
606
    {
607
        // make certain that dependencies are ignored
607
        // make certain that dependencies are ignored
608
        $options['downloadonly'] = 1;
608
        $options['downloadonly'] = 1;
609
609
610
        // eliminate error messages for preferred_state-related errors
610
        // eliminate error messages for preferred_state-related errors
611
        /* TODO: Should be an option, but until now download does respect
611
        /* TODO: Should be an option, but until now download does respect
612
           prefered state */
612
           prefered state */
613
        /* $options['ignorepreferred_state'] = 1; */
613
        /* $options['ignorepreferred_state'] = 1; */
614
        // eliminate error messages for preferred_state-related errors
614
        // eliminate error messages for preferred_state-related errors
615
615
616
        $downloader = &$this->getDownloader($options);
616
        $downloader = &$this->getDownloader($options);
617
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
617
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
618
        $e = $downloader->setDownloadDir(getcwd());
618
        $e = $downloader->setDownloadDir(getcwd());
619
        PEAR::staticPopErrorHandling();
619
        PEAR::staticPopErrorHandling();
620
        if (PEAR::isError($e)) {
620
        if (PEAR::isError($e)) {
621
            return $this->raiseError('Current directory is not writeable, cannot download');
621
            return $this->raiseError('Current directory is not writeable, cannot download');
622
        }
622
        }
623
        $errors = array();
623
        $errors = array();
624
        $downloaded = array();
624
        $downloaded = array();
625
        $err = $downloader->download($params);
625
        $err = $downloader->download($params);
626
        if (PEAR::isError($err)) {
626
        if (PEAR::isError($err)) {
627
            return $err;
627
            return $err;
628
        }
628
        }
629
        $errors = $downloader->getErrorMsgs();
629
        $errors = $downloader->getErrorMsgs();
630
        if (count($errors)) {
630
        if (count($errors)) {
631
            foreach ($errors as $error) {
631
            foreach ($errors as $error) {
632
                $this->ui->outputData($error);
632
                $this->ui->outputData($error);
633
            }
633
            }
634
            return $this->raiseError("$command failed");
634
            return $this->raiseError("$command failed");
635
        }
635
        }
636
        $downloaded = $downloader->getDownloadedPackages();
636
        $downloaded = $downloader->getDownloadedPackages();
637
        foreach ($downloaded as $pkg) {
637
        foreach ($downloaded as $pkg) {
638
            $this->ui->outputData("File $pkg[file] downloaded", $command);
638
            $this->ui->outputData("File $pkg[file] downloaded", $command);
639
        }
639
        }
640
        return true;
640
        return true;
641
    }
641
    }
642
642
643
    function downloadCallback($msg, $params = null)
643
    function downloadCallback($msg, $params = null)
644
    {
644
    {
645
        if ($msg == 'done') {
645
        if ($msg == 'done') {
646
            $this->bytes_downloaded = $params;
646
            $this->bytes_downloaded = $params;
647
        }
647
        }
648
    }
648
    }
649
649
650
    // }}}
650
    // }}}
651
    // {{{ doListUpgrades()
651
    // {{{ doListUpgrades()
652
652
653
    function doListUpgrades($command, $options, $params)
653
    function doListUpgrades($command, $options, $params)
654
    {
654
    {
655
        require_once 'PEAR/Common.php';
655
        require_once 'PEAR/Common.php';
656
        if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
656
        if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
657
            return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
657
            return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
658
        }
658
        }
659
        $savechannel = $channel = $this->config->get('default_channel');
659
        $savechannel = $channel = $this->config->get('default_channel');
660
        $reg = &$this->config->getRegistry();
660
        $reg = &$this->config->getRegistry();
661
        foreach ($reg->listChannels() as $channel) {
661
        foreach ($reg->listChannels() as $channel) {
662
            $inst = array_flip($reg->listPackages($channel));
662
            $inst = array_flip($reg->listPackages($channel));
663
            if (!count($inst)) {
663
            if (!count($inst)) {
664
                continue;
664
                continue;
665
            }
665
            }
666
            if ($channel == '__uri') {
666
            if ($channel == '__uri') {
667
                continue;
667
                continue;
668
            }
668
            }
669
            $this->config->set('default_channel', $channel);
669
            $this->config->set('default_channel', $channel);
670
            if (empty($params[0])) {
670
            if (empty($params[0])) {
671
                $state = $this->config->get('preferred_state');
671
                $state = $this->config->get('preferred_state');
672
            } else {
672
            } else {
673
                $state = $params[0];
673
                $state = $params[0];
674
            }
674
            }
675
            $caption = $channel . ' Available Upgrades';
675
            $caption = $channel . ' Available Upgrades';
676
            $chan = $reg->getChannel($channel);
676
            $chan = $reg->getChannel($channel);
677
            if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
677
            if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
678
                return $e;
678
                return $e;
679
            }
679
            }
680
            if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
680
            if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
681
                  $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
681
                  $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
682
                $rest = &$this->config->getREST('1.0', array());
682
                $rest = &$this->config->getREST('1.0', array());
683
                if (empty($state) || $state == 'any') {
683
                if (empty($state) || $state == 'any') {
684
                    $state = false;
684
                    $state = false;
685
                } else {
685
                } else {
686
                    $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
686
                    $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
687
                }
687
                }
688
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
688
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
689
                $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
689
                $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
690
                PEAR::staticPopErrorHandling();
690
                PEAR::staticPopErrorHandling();
691
            } else {
691
            } else {
692
                $remote = &$this->config->getRemote();
692
                $remote = &$this->config->getRemote();
693
                $remote->pushErrorHandling(PEAR_ERROR_RETURN);
693
                $remote->pushErrorHandling(PEAR_ERROR_RETURN);
694
                if (empty($state) || $state == 'any') {
694
                if (empty($state) || $state == 'any') {
695
                    $latest = $remote->call("package.listLatestReleases");
695
                    $latest = $remote->call("package.listLatestReleases");
696
                } else {
696
                } else {
697
                    $latest = $remote->call("package.listLatestReleases", $state);
697
                    $latest = $remote->call("package.listLatestReleases", $state);
698
                    $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
698
                    $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
699
                }
699
                }
700
                $remote->popErrorHandling();
700
                $remote->popErrorHandling();
701
            }
701
            }
702
            if (PEAR::isError($latest)) {
702
            if (PEAR::isError($latest)) {
703
                $this->ui->outputData($latest->getMessage());
703
                $this->ui->outputData($latest->getMessage());
704
                continue;
704
                continue;
705
            }
705
            }
706
            $caption .= ':';
706
            $caption .= ':';
707
            if (PEAR::isError($latest)) {
707
            if (PEAR::isError($latest)) {
708
                $this->config->set('default_channel', $savechannel);
708
                $this->config->set('default_channel', $savechannel);
709
                return $latest;
709
                return $latest;
710
            }
710
            }
711
            $data = array(
711
            $data = array(
712
                'caption' => $caption,
712
                'caption' => $caption,
713
                'border' => 1,
713
                'border' => 1,
714
                'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
714
                'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
715
                'channel' => $channel
715
                'channel' => $channel
716
                );
716
                );
717
            foreach ((array)$latest as $pkg => $info) {
717
            foreach ((array)$latest as $pkg => $info) {
718
                $package = strtolower($pkg);
718
                $package = strtolower($pkg);
719
                if (!isset($inst[$package])) {
719
                if (!isset($inst[$package])) {
720
                    // skip packages we don't have installed
720
                    // skip packages we don't have installed
721
                    continue;
721
                    continue;
722
                }
722
                }
723
                extract($info);
723
                extract($info);
724
                $inst_version = $reg->packageInfo($package, 'version', $channel);
724
                $inst_version = $reg->packageInfo($package, 'version', $channel);
725
                $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
725
                $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
726
                if (version_compare("$version", "$inst_version", "le")) {
726
                if (version_compare("$version", "$inst_version", "le")) {
727
                    // installed version is up-to-date
727
                    // installed version is up-to-date
728
                    continue;
728
                    continue;
729
                }
729
                }
730
                if ($filesize >= 20480) {
730
                if ($filesize >= 20480) {
731
                    $filesize += 1024 - ($filesize % 1024);
731
                    $filesize += 1024 - ($filesize % 1024);
732
                    $fs = sprintf("%dkB", $filesize / 1024);
732
                    $fs = sprintf("%dkB", $filesize / 1024);
733
                } elseif ($filesize > 0) {
733
                } elseif ($filesize > 0) {
734
                    $filesize += 103 - ($filesize % 103);
734
                    $filesize += 103 - ($filesize % 103);
735
                    $fs = sprintf("%.1fkB", $filesize / 1024.0);
735
                    $fs = sprintf("%.1fkB", $filesize / 1024.0);
736
                } else {
736
                } else {
737
                    $fs = "  -"; // XXX center instead
737
                    $fs = "  -"; // XXX center instead
738
                }
738
                }
739
                $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
739
                $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
740
            }
740
            }
741
            if (isset($options['channelinfo'])) {
741
            if (isset($options['channelinfo'])) {
742
                if (empty($data['data'])) {
742
                if (empty($data['data'])) {
743
                    unset($data['headline']);
743
                    unset($data['headline']);
744
                    if (count($inst) == 0) {
744
                    if (count($inst) == 0) {
745
                        $data['data'] = '(no packages installed)';
745
                        $data['data'] = '(no packages installed)';
746
                    } else {
746
                    } else {
747
                        $data['data'] = '(no upgrades available)';
747
                        $data['data'] = '(no upgrades available)';
748
                    }
748
                    }
749
                }
749
                }
750
                $this->ui->outputData($data, $command);
750
                $this->ui->outputData($data, $command);
751
            } else {
751
            } else {
752
                if (empty($data['data'])) {
752
                if (empty($data['data'])) {
753
                    $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
753
                    $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
754
                } else {
754
                } else {
755
                    $this->ui->outputData($data, $command);
755
                    $this->ui->outputData($data, $command);
756
                }
756
                }
757
            }
757
            }
758
        }
758
        }
759
        $this->config->set('default_channel', $savechannel);
759
        $this->config->set('default_channel', $savechannel);
760
        return true;
760
        return true;
761
    }
761
    }
762
762
763
    // }}}
763
    // }}}
764
    // {{{ doClearCache()
764
    // {{{ doClearCache()
765
765
766
    function doClearCache($command, $options, $params)
766
    function doClearCache($command, $options, $params)
767
    {
767
    {
768
        $cache_dir = $this->config->get('cache_dir');
768
        $cache_dir = $this->config->get('cache_dir');
769
        $verbose = $this->config->get('verbose');
769
        $verbose = $this->config->get('verbose');
770
        $output = '';
770
        $output = '';
771
        if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
771
        if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
772
            return $this->raiseError("$cache_dir does not exist or is not a directory");
772
            return $this->raiseError("$cache_dir does not exist or is not a directory");
773
        }
773
        }
774
        if (!($dp = @opendir($cache_dir))) {
774
        if (!($dp = @opendir($cache_dir))) {
775
            return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
775
            return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
776
        }
776
        }
777
        if ($verbose >= 1) {
777
        if ($verbose >= 1) {
778
            $output .= "reading directory $cache_dir\n";
778
            $output .= "reading directory $cache_dir\n";
779
        }
779
        }
780
        $num = 0;
780
        $num = 0;
781
        while ($ent = readdir($dp)) {
781
        while ($ent = readdir($dp)) {
782
            if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}\\z/', $ent) ||
782
            if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}\\z/', $ent) ||
783
                  preg_match('/rest.cache(file|id)\\z/', $ent)) {
783
                  preg_match('/rest.cache(file|id)\\z/', $ent)) {
784
                $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
784
                $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
785
                if (file_exists($path)) {
785
                if (file_exists($path)) {
786
                    $ok = @unlink($path);
786
                    $ok = @unlink($path);
787
                } else {
787
                } else {
788
                    $ok = false;
788
                    $ok = false;
789
                    $php_errormsg = '';
789
                    $php_errormsg = '';
790
                }
790
                }
791
                if ($ok) {
791
                if ($ok) {
792
                    if ($verbose >= 2) {
792
                    if ($verbose >= 2) {
793
                        $output .= "deleted $path\n";
793
                        $output .= "deleted $path\n";
794
                    }
794
                    }
795
                    $num++;
795
                    $num++;
796
                } elseif ($verbose >= 1) {
796
                } elseif ($verbose >= 1) {
797
                    $output .= "failed to delete $path $php_errormsg\n";
797
                    $output .= "failed to delete $path $php_errormsg\n";
798
                }
798
                }
799
            }
799
            }
800
        }
800
        }
801
        closedir($dp);
801
        closedir($dp);
802
        if ($verbose >= 1) {
802
        if ($verbose >= 1) {
803
            $output .= "$num cache entries cleared\n";
803
            $output .= "$num cache entries cleared\n";
804
        }
804
        }
805
        $this->ui->outputData(rtrim($output), $command);
805
        $this->ui->outputData(rtrim($output), $command);
806
        return $num;
806
        return $num;
807
    }
807
    }
808
808
809
    // }}}
809
    // }}}
810
}
810
}
811
811
812
?>
812
?>
813
 
813