Хранилища Subversion ant

Редакция

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

Редакция 69 Редакция 94
1
<?php
1
<?php
2
/**
2
/**
3
 * PEAR_ChannelFile, the channel handling class
3
 * PEAR_ChannelFile, the channel handling class
4
 *
4
 *
5
 * PHP versions 4 and 5
5
 * PHP versions 4 and 5
6
 *
6
 *
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * that is available through the world-wide-web at the following URI:
8
 * that is available through the world-wide-web at the following URI:
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * the PHP License and are unable to obtain it through the web, please
10
 * the PHP License and are unable to obtain it through the web, please
11
 * send a note to license@php.net so we can mail you a copy immediately.
11
 * send a note to license@php.net so we can mail you a copy immediately.
12
 *
12
 *
13
 * @category   pear
13
 * @category   pear
14
 * @package    PEAR
14
 * @package    PEAR
15
 * @author     Greg Beaver <cellog@php.net>
15
 * @author     Greg Beaver <cellog@php.net>
16
 * @copyright  1997-2008 The PHP Group
16
 * @copyright  1997-2008 The PHP Group
17
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
17
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
18
 * @version    CVS: $Id: ChannelFile.php,v 1.80 2008/01/03 20:26:34 cellog Exp $
18
 * @version    CVS: $Id: ChannelFile.php,v 1.80 2008/01/03 20:26:34 cellog Exp $
19
 * @link       http://pear.php.net/package/PEAR
19
 * @link       http://pear.php.net/package/PEAR
20
 * @since      File available since Release 1.4.0a1
20
 * @since      File available since Release 1.4.0a1
21
 */
21
 */
22
22
23
/**
23
/**
24
 * Needed for error handling
24
 * Needed for error handling
25
 */
25
 */
26
require_once 'PEAR/ErrorStack.php';
26
require_once 'PEAR/ErrorStack.php';
27
require_once 'PEAR/XMLParser.php';
27
require_once 'PEAR/XMLParser.php';
28
require_once 'PEAR/Common.php';
28
require_once 'PEAR/Common.php';
29
29
30
/**
30
/**
31
 * Error code if the channel.xml <channel> tag does not contain a valid version
31
 * Error code if the channel.xml <channel> tag does not contain a valid version
32
 */
32
 */
33
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
33
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
34
/**
34
/**
35
 * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
35
 * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
36
 * currently
36
 * currently
37
 */
37
 */
38
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
38
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
39
39
40
/**
40
/**
41
 * Error code if parsing is attempted with no xml extension
41
 * Error code if parsing is attempted with no xml extension
42
 */
42
 */
43
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
43
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
44
44
45
/**
45
/**
46
 * Error code if creating the xml parser resource fails
46
 * Error code if creating the xml parser resource fails
47
 */
47
 */
48
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
48
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
49
49
50
/**
50
/**
51
 * Error code used for all sax xml parsing errors
51
 * Error code used for all sax xml parsing errors
52
 */
52
 */
53
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
53
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
54
54
55
/**#@+
55
/**#@+
56
 * Validation errors
56
 * Validation errors
57
 */
57
 */
58
/**
58
/**
59
 * Error code when channel name is missing
59
 * Error code when channel name is missing
60
 */
60
 */
61
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
61
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
62
/**
62
/**
63
 * Error code when channel name is invalid
63
 * Error code when channel name is invalid
64
 */
64
 */
65
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
65
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
66
/**
66
/**
67
 * Error code when channel summary is missing
67
 * Error code when channel summary is missing
68
 */
68
 */
69
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
69
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
70
/**
70
/**
71
 * Error code when channel summary is multi-line
71
 * Error code when channel summary is multi-line
72
 */
72
 */
73
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
73
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
74
/**
74
/**
75
 * Error code when channel server is missing for xmlrpc or soap protocol
75
 * Error code when channel server is missing for xmlrpc or soap protocol
76
 */
76
 */
77
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
77
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
78
/**
78
/**
79
 * Error code when channel server is invalid for xmlrpc or soap protocol
79
 * Error code when channel server is invalid for xmlrpc or soap protocol
80
 */
80
 */
81
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
81
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
82
/**
82
/**
83
 * Error code when a mirror name is invalid
83
 * Error code when a mirror name is invalid
84
 */
84
 */
85
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
85
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
86
/**
86
/**
87
 * Error code when a mirror type is invalid
87
 * Error code when a mirror type is invalid
88
 */
88
 */
89
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
89
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
90
/**
90
/**
91
 * Error code when an attempt is made to generate xml, but the parsed content is invalid
91
 * Error code when an attempt is made to generate xml, but the parsed content is invalid
92
 */
92
 */
93
define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
93
define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
94
/**
94
/**
95
 * Error code when an empty package name validate regex is passed in
95
 * Error code when an empty package name validate regex is passed in
96
 */
96
 */
97
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
97
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
98
/**
98
/**
99
 * Error code when a <function> tag has no version
99
 * Error code when a <function> tag has no version
100
 */
100
 */
101
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
101
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
102
/**
102
/**
103
 * Error code when a <function> tag has no name
103
 * Error code when a <function> tag has no name
104
 */
104
 */
105
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
105
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
106
/**
106
/**
107
 * Error code when a <validatepackage> tag has no name
107
 * Error code when a <validatepackage> tag has no name
108
 */
108
 */
109
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
109
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
110
/**
110
/**
111
 * Error code when a <validatepackage> tag has no version attribute
111
 * Error code when a <validatepackage> tag has no version attribute
112
 */
112
 */
113
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
113
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
114
/**
114
/**
115
 * Error code when a mirror does not exist but is called for in one of the set*
115
 * Error code when a mirror does not exist but is called for in one of the set*
116
 * methods.
116
 * methods.
117
 */
117
 */
118
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
118
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
119
/**
119
/**
120
 * Error code when a server port is not numeric
120
 * Error code when a server port is not numeric
121
 */
121
 */
122
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
122
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
123
/**
123
/**
124
 * Error code when <static> contains no version attribute
124
 * Error code when <static> contains no version attribute
125
 */
125
 */
126
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
126
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
127
/**
127
/**
128
 * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
128
 * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
129
 */
129
 */
130
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
130
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
131
/**
131
/**
132
 * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
132
 * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
133
 */
133
 */
134
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
134
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
135
/**
135
/**
136
 * Error code when ssl attribute is present and is not "yes"
136
 * Error code when ssl attribute is present and is not "yes"
137
 */
137
 */
138
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
138
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
139
/**#@-*/
139
/**#@-*/
140
140
141
/**
141
/**
142
 * Mirror types allowed.  Currently only internet servers are recognized.
142
 * Mirror types allowed.  Currently only internet servers are recognized.
143
 */
143
 */
144
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
144
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
145
145
146
146
147
/**
147
/**
148
 * The Channel handling class
148
 * The Channel handling class
149
 *
149
 *
150
 * @category   pear
150
 * @category   pear
151
 * @package    PEAR
151
 * @package    PEAR
152
 * @author     Greg Beaver <cellog@php.net>
152
 * @author     Greg Beaver <cellog@php.net>
153
 * @copyright  1997-2008 The PHP Group
153
 * @copyright  1997-2008 The PHP Group
154
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
154
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
155
 * @version    Release: 1.7.2
155
 * @version    Release: 1.7.2
156
 * @link       http://pear.php.net/package/PEAR
156
 * @link       http://pear.php.net/package/PEAR
157
 * @since      Class available since Release 1.4.0a1
157
 * @since      Class available since Release 1.4.0a1
158
 */
158
 */
159
class PEAR_ChannelFile {
159
class PEAR_ChannelFile {
160
    /**
160
    /**
161
     * @access private
161
     * @access private
162
     * @var PEAR_ErrorStack
162
     * @var PEAR_ErrorStack
163
     * @access private
163
     * @access private
164
     */
164
     */
165
    var $_stack;
165
    var $_stack;
166
   
166
   
167
    /**
167
    /**
168
     * Supported channel.xml versions, for parsing
168
     * Supported channel.xml versions, for parsing
169
     * @var array
169
     * @var array
170
     * @access private
170
     * @access private
171
     */
171
     */
172
    var $_supportedVersions = array('1.0');
172
    var $_supportedVersions = array('1.0');
173
173
174
    /**
174
    /**
175
     * Parsed channel information
175
     * Parsed channel information
176
     * @var array
176
     * @var array
177
     * @access private
177
     * @access private
178
     */
178
     */
179
    var $_channelInfo;
179
    var $_channelInfo;
180
180
181
    /**
181
    /**
182
     * index into the subchannels array, used for parsing xml
182
     * index into the subchannels array, used for parsing xml
183
     * @var int
183
     * @var int
184
     * @access private
184
     * @access private
185
     */
185
     */
186
    var $_subchannelIndex;
186
    var $_subchannelIndex;
187
187
188
    /**
188
    /**
189
     * index into the mirrors array, used for parsing xml
189
     * index into the mirrors array, used for parsing xml
190
     * @var int
190
     * @var int
191
     * @access private
191
     * @access private
192
     */
192
     */
193
    var $_mirrorIndex;
193
    var $_mirrorIndex;
194
   
194
   
195
    /**
195
    /**
196
     * Flag used to determine the validity of parsed content
196
     * Flag used to determine the validity of parsed content
197
     * @var boolean
197
     * @var boolean
198
     * @access private
198
     * @access private
199
     */
199
     */
200
    var $_isValid = false;
200
    var $_isValid = false;
201
201
202
    function PEAR_ChannelFile()
202
    function PEAR_ChannelFile()
203
    {
203
    {
204
        $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
204
        $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
205
        $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
205
        $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
206
        $this->_isValid = false;
206
        $this->_isValid = false;
207
    }
207
    }
208
   
208
   
209
    /**
209
    /**
210
     * @return array
210
     * @return array
211
     * @access protected
211
     * @access protected
212
     */
212
     */
213
    function _getErrorMessage()
213
    function _getErrorMessage()
214
    {
214
    {
215
        return
215
        return
216
            array(
216
            array(
217
                PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
217
                PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
218
                    'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
218
                    'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
219
                PEAR_CHANNELFILE_ERROR_NO_VERSION =>
219
                PEAR_CHANNELFILE_ERROR_NO_VERSION =>
220
                    'No version number found in <channel> tag',
220
                    'No version number found in <channel> tag',
221
                PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
221
                PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
222
                    '%error%',
222
                    '%error%',
223
                PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
223
                PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
224
                    'Unable to create XML parser',
224
                    'Unable to create XML parser',
225
                PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
225
                PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
226
                    '%error%',
226
                    '%error%',
227
                PEAR_CHANNELFILE_ERROR_NO_NAME =>
227
                PEAR_CHANNELFILE_ERROR_NO_NAME =>
228
                    'Missing channel name',
228
                    'Missing channel name',
229
                PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
229
                PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
230
                    'Invalid channel %tag% "%name%"',
230
                    'Invalid channel %tag% "%name%"',
231
                PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
231
                PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
232
                    'Missing channel summary',
232
                    'Missing channel summary',
233
                PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
233
                PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
234
                    'Channel summary should be on one line, but is multi-line',
234
                    'Channel summary should be on one line, but is multi-line',
235
                PEAR_CHANNELFILE_ERROR_NO_HOST =>
235
                PEAR_CHANNELFILE_ERROR_NO_HOST =>
236
                    'Missing channel server for %type% server',
236
                    'Missing channel server for %type% server',
237
                PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
237
                PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
238
                    'Server name "%server%" is invalid for %type% server',
238
                    'Server name "%server%" is invalid for %type% server',
239
                PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
239
                PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
240
                    'Invalid mirror name "%name%", mirror type %type%',
240
                    'Invalid mirror name "%name%", mirror type %type%',
241
                PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
241
                PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
242
                    'Invalid mirror type "%type%"',
242
                    'Invalid mirror type "%type%"',
243
                PEAR_CHANNELFILE_ERROR_INVALID =>
243
                PEAR_CHANNELFILE_ERROR_INVALID =>
244
                    'Cannot generate xml, contents are invalid',
244
                    'Cannot generate xml, contents are invalid',
245
                PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
245
                PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
246
                    'packagenameregex cannot be empty',
246
                    'packagenameregex cannot be empty',
247
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
247
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
248
                    '%parent% %protocol% function has no version',
248
                    '%parent% %protocol% function has no version',
249
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
249
                PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
250
                    '%parent% %protocol% function has no name',
250
                    '%parent% %protocol% function has no name',
251
                PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
251
                PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
252
                    '%parent% rest baseurl has no type',
252
                    '%parent% rest baseurl has no type',
253
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
253
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
254
                    'Validation package has no name in <validatepackage> tag',
254
                    'Validation package has no name in <validatepackage> tag',
255
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
255
                PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
256
                    'Validation package "%package%" has no version',
256
                    'Validation package "%package%" has no version',
257
                PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
257
                PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
258
                    'Mirror "%mirror%" does not exist',
258
                    'Mirror "%mirror%" does not exist',
259
                PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
259
                PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
260
                    'Port "%port%" must be numeric',
260
                    'Port "%port%" must be numeric',
261
                PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
261
                PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
262
                    '<static> tag must contain version attribute',
262
                    '<static> tag must contain version attribute',
263
                PEAR_CHANNELFILE_URI_CANT_MIRROR =>
263
                PEAR_CHANNELFILE_URI_CANT_MIRROR =>
264
                    'The __uri pseudo-channel cannot have mirrors',
264
                    'The __uri pseudo-channel cannot have mirrors',
265
                PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
265
                PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
266
                    '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
266
                    '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
267
            );
267
            );
268
    }
268
    }
269
269
270
    /**
270
    /**
271
     * @param string contents of package.xml file
271
     * @param string contents of package.xml file
272
     * @return bool success of parsing
272
     * @return bool success of parsing
273
     */
273
     */
274
    function fromXmlString($data)
274
    function fromXmlString($data)
275
    {
275
    {
276
        if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
276
        if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
277
            if (!in_array($channelversion[1], $this->_supportedVersions)) {
277
            if (!in_array($channelversion[1], $this->_supportedVersions)) {
278
                $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
278
                $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
279
                    array('version' => $channelversion[1]));
279
                    array('version' => $channelversion[1]));
280
                return false;
280
                return false;
281
            }
281
            }
282
            $parser = new PEAR_XMLParser;
282
            $parser = new PEAR_XMLParser;
283
            $result = $parser->parse($data);
283
            $result = $parser->parse($data);
284
            if ($result !== true) {
284
            if ($result !== true) {
285
                if ($result->getCode() == 1) {
285
                if ($result->getCode() == 1) {
286
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
286
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
287
                        array('error' => $result->getMessage()));
287
                        array('error' => $result->getMessage()));
288
                } else {
288
                } else {
289
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
289
                    $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
290
                }
290
                }
291
                return false;
291
                return false;
292
            }
292
            }
293
            $this->_channelInfo = $parser->getData();
293
            $this->_channelInfo = $parser->getData();
294
            return true;
294
            return true;
295
        } else {
295
        } else {
296
            $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
296
            $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
297
            return false;
297
            return false;
298
        }
298
        }
299
    }
299
    }
300
   
300
   
301
    /**
301
    /**
302
     * @return array
302
     * @return array
303
     */
303
     */
304
    function toArray()
304
    function toArray()
305
    {
305
    {
306
        if (!$this->_isValid && !$this->validate()) {
306
        if (!$this->_isValid && !$this->validate()) {
307
            return false;
307
            return false;
308
        }
308
        }
309
        return $this->_channelInfo;
309
        return $this->_channelInfo;
310
    }
310
    }
311
   
311
   
312
    /**
312
    /**
313
     * @param array
313
     * @param array
314
     * @static
314
     * @static
315
     * @return PEAR_ChannelFile|false false if invalid
315
     * @return PEAR_ChannelFile|false false if invalid
316
     */
316
     */
317
    function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
317
    function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
318
    {
318
    {
319
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
319
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
320
        $a->_fromArray($data);
320
        $a->_fromArray($data);
321
        if (!$a->validate()) {
321
        if (!$a->validate()) {
322
            $a = false;
322
            $a = false;
323
            return $a;
323
            return $a;
324
        }
324
        }
325
        return $a;
325
        return $a;
326
    }
326
    }
327
327
328
    /**
328
    /**
329
     * Unlike {@link fromArray()} this does not do any validation
329
     * Unlike {@link fromArray()} this does not do any validation
330
     * @param array
330
     * @param array
331
     * @static
331
     * @static
332
     * @return PEAR_ChannelFile
332
     * @return PEAR_ChannelFile
333
     */
333
     */
334
    function &fromArrayWithErrors($data, $compatibility = false,
334
    function &fromArrayWithErrors($data, $compatibility = false,
335
                                  $stackClass = 'PEAR_ErrorStack')
335
                                  $stackClass = 'PEAR_ErrorStack')
336
    {
336
    {
337
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
337
        $a = new PEAR_ChannelFile($compatibility, $stackClass);
338
        $a->_fromArray($data);
338
        $a->_fromArray($data);
339
        return $a;
339
        return $a;
340
    }
340
    }
341
   
341
   
342
    /**
342
    /**
343
     * @param array
343
     * @param array
344
     * @access private
344
     * @access private
345
     */
345
     */
346
    function _fromArray($data)
346
    function _fromArray($data)
347
    {
347
    {
348
        $this->_channelInfo = $data;
348
        $this->_channelInfo = $data;
349
    }
349
    }
350
   
350
   
351
    /**
351
    /**
352
     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
352
     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
353
     * @param boolean determines whether to purge the error stack after retrieving
353
     * @param boolean determines whether to purge the error stack after retrieving
354
     * @return array
354
     * @return array
355
     */
355
     */
356
    function getErrors($purge = false)
356
    function getErrors($purge = false)
357
    {
357
    {
358
        return $this->_stack->getErrors($purge);
358
        return $this->_stack->getErrors($purge);
359
    }
359
    }
360
360
361
    /**
361
    /**
362
     * Unindent given string (?)
362
     * Unindent given string (?)
363
     *
363
     *
364
     * @param string $str The string that has to be unindented.
364
     * @param string $str The string that has to be unindented.
365
     * @return string
365
     * @return string
366
     * @access private
366
     * @access private
367
     */
367
     */
368
    function _unIndent($str)
368
    function _unIndent($str)
369
    {
369
    {
370
        // remove leading newlines
370
        // remove leading newlines
371
        $str = preg_replace('/^[\r\n]+/', '', $str);
371
        $str = preg_replace('/^[\r\n]+/', '', $str);
372
        // find whitespace at the beginning of the first line
372
        // find whitespace at the beginning of the first line
373
        $indent_len = strspn($str, " \t");
373
        $indent_len = strspn($str, " \t");
374
        $indent = substr($str, 0, $indent_len);
374
        $indent = substr($str, 0, $indent_len);
375
        $data = '';
375
        $data = '';
376
        // remove the same amount of whitespace from following lines
376
        // remove the same amount of whitespace from following lines
377
        foreach (explode("\n", $str) as $line) {
377
        foreach (explode("\n", $str) as $line) {
378
            if (substr($line, 0, $indent_len) == $indent) {
378
            if (substr($line, 0, $indent_len) == $indent) {
379
                $data .= substr($line, $indent_len) . "\n";
379
                $data .= substr($line, $indent_len) . "\n";
380
            }
380
            }
381
        }
381
        }
382
        return $data;
382
        return $data;
383
    }
383
    }
384
384
385
    /**
385
    /**
386
     * Parse a channel.xml file.  Expects the name of
386
     * Parse a channel.xml file.  Expects the name of
387
     * a channel xml file as input.
387
     * a channel xml file as input.
388
     *
388
     *
389
     * @param string  $descfile  name of channel xml file
389
     * @param string  $descfile  name of channel xml file
390
     * @return bool success of parsing
390
     * @return bool success of parsing
391
     */
391
     */
392
    function fromXmlFile($descfile)
392
    function fromXmlFile($descfile)
393
    {
393
    {
394
        if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
394
        if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
395
             (!$fp = fopen($descfile, 'r'))) {
395
             (!$fp = fopen($descfile, 'r'))) {
396
            require_once 'PEAR.php';
396
            require_once 'PEAR.php';
397
            return PEAR::raiseError("Unable to open $descfile");
397
            return PEAR::raiseError("Unable to open $descfile");
398
        }
398
        }
399
399
400
        // read the whole thing so we only get one cdata callback
400
        // read the whole thing so we only get one cdata callback
401
        // for each block of cdata
401
        // for each block of cdata
402
        fclose($fp);
402
        fclose($fp);
403
        $data = file_get_contents($descfile);
403
        $data = file_get_contents($descfile);
404
        return $this->fromXmlString($data);
404
        return $this->fromXmlString($data);
405
    }
405
    }
406
406
407
    /**
407
    /**
408
     * Parse channel information from different sources
408
     * Parse channel information from different sources
409
     *
409
     *
410
     * This method is able to extract information about a channel
410
     * This method is able to extract information about a channel
411
     * from an .xml file or a string
411
     * from an .xml file or a string
412
     *
412
     *
413
     * @access public
413
     * @access public
414
     * @param  string Filename of the source or the source itself
414
     * @param  string Filename of the source or the source itself
415
     * @return bool
415
     * @return bool
416
     */
416
     */
417
    function fromAny($info)
417
    function fromAny($info)
418
    {
418
    {
419
        if (is_string($info) && file_exists($info) && strlen($info) < 255) {
419
        if (is_string($info) && file_exists($info) && strlen($info) < 255) {
420
            $tmp = substr($info, -4);
420
            $tmp = substr($info, -4);
421
            if ($tmp == '.xml') {
421
            if ($tmp == '.xml') {
422
                $info = $this->fromXmlFile($info);
422
                $info = $this->fromXmlFile($info);
423
            } else {
423
            } else {
424
                $fp = fopen($info, "r");
424
                $fp = fopen($info, "r");
425
                $test = fread($fp, 5);
425
                $test = fread($fp, 5);
426
                fclose($fp);
426
                fclose($fp);
427
                if ($test == "<?xml") {
427
                if ($test == "<?xml") {
428
                    $info = $this->fromXmlFile($info);
428
                    $info = $this->fromXmlFile($info);
429
                }
429
                }
430
            }
430
            }
431
            if (PEAR::isError($info)) {
431
            if (PEAR::isError($info)) {
432
                require_once 'PEAR.php';
432
                require_once 'PEAR.php';
433
                return PEAR::raiseError($info);
433
                return PEAR::raiseError($info);
434
            }
434
            }
435
        }
435
        }
436
        if (is_string($info)) {
436
        if (is_string($info)) {
437
            $info = $this->fromXmlString($info);
437
            $info = $this->fromXmlString($info);
438
        }
438
        }
439
        return $info;
439
        return $info;
440
    }
440
    }
441
441
442
    /**
442
    /**
443
     * Return an XML document based on previous parsing and modifications
443
     * Return an XML document based on previous parsing and modifications
444
     *
444
     *
445
     * @return string XML data
445
     * @return string XML data
446
     *
446
     *
447
     * @access public
447
     * @access public
448
     */
448
     */
449
    function toXml()
449
    function toXml()
450
    {
450
    {
451
        if (!$this->_isValid && !$this->validate()) {
451
        if (!$this->_isValid && !$this->validate()) {
452
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
452
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
453
            return false;
453
            return false;
454
        }
454
        }
455
        if (!isset($this->_channelInfo['attribs']['version'])) {
455
        if (!isset($this->_channelInfo['attribs']['version'])) {
456
            $this->_channelInfo['attribs']['version'] = '1.0';
456
            $this->_channelInfo['attribs']['version'] = '1.0';
457
        }
457
        }
458
        $channelInfo = $this->_channelInfo;
458
        $channelInfo = $this->_channelInfo;
459
        $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
459
        $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
460
        $ret .= "<channel version=\"" .
460
        $ret .= "<channel version=\"" .
461
            $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
461
            $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
462
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
462
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
463
  xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
463
  xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
464
            . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
464
            . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
465
            $channelInfo['attribs']['version'] . ".xsd\">
465
            $channelInfo['attribs']['version'] . ".xsd\">
466
 <name>$channelInfo[name]</name>
466
 <name>$channelInfo[name]</name>
467
 <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
467
 <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
468
";
468
";
469
        if (isset($channelInfo['suggestedalias'])) {
469
        if (isset($channelInfo['suggestedalias'])) {
470
            $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
470
            $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
471
        }
471
        }
472
        if (isset($channelInfo['validatepackage'])) {
472
        if (isset($channelInfo['validatepackage'])) {
473
            $ret .= ' <validatepackage version="' .
473
            $ret .= ' <validatepackage version="' .
474
                $channelInfo['validatepackage']['attribs']['version']. '">' .
474
                $channelInfo['validatepackage']['attribs']['version']. '">' .
475
                htmlspecialchars($channelInfo['validatepackage']['_content']) .
475
                htmlspecialchars($channelInfo['validatepackage']['_content']) .
476
                "</validatepackage>\n";
476
                "</validatepackage>\n";
477
        }
477
        }
478
        $ret .= " <servers>\n";
478
        $ret .= " <servers>\n";
479
        $ret .= '  <primary';
479
        $ret .= '  <primary';
480
        if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
480
        if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
481
            $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
481
            $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
482
        }
482
        }
483
        if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
483
        if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
484
            $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
484
            $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
485
        }
485
        }
486
        $ret .= ">\n";
486
        $ret .= ">\n";
487
        if (isset($channelInfo['servers']['primary']['xmlrpc'])) {
487
        if (isset($channelInfo['servers']['primary']['xmlrpc'])) {
488
            $ret .= $this->_makeXmlrpcXml($channelInfo['servers']['primary']['xmlrpc'], '   ');
488
            $ret .= $this->_makeXmlrpcXml($channelInfo['servers']['primary']['xmlrpc'], '   ');
489
        }
489
        }
490
        if (isset($channelInfo['servers']['primary']['rest'])) {
490
        if (isset($channelInfo['servers']['primary']['rest'])) {
491
            $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
491
            $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
492
        }
492
        }
493
        if (isset($channelInfo['servers']['primary']['soap'])) {
493
        if (isset($channelInfo['servers']['primary']['soap'])) {
494
            $ret .= $this->_makeSoapXml($channelInfo['servers']['primary']['soap'], '   ');
494
            $ret .= $this->_makeSoapXml($channelInfo['servers']['primary']['soap'], '   ');
495
        }
495
        }
496
        $ret .= "  </primary>\n";
496
        $ret .= "  </primary>\n";
497
        if (isset($channelInfo['servers']['mirror'])) {
497
        if (isset($channelInfo['servers']['mirror'])) {
498
            $ret .= $this->_makeMirrorsXml($channelInfo);
498
            $ret .= $this->_makeMirrorsXml($channelInfo);
499
        }
499
        }
500
        $ret .= " </servers>\n";
500
        $ret .= " </servers>\n";
501
        $ret .= "</channel>";
501
        $ret .= "</channel>";
502
        return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
502
        return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
503
    }
503
    }
504
504
505
    /**
505
    /**
506
     * Generate the <xmlrpc> tag
506
     * Generate the <xmlrpc> tag
507
     * @access private
507
     * @access private
508
     */
508
     */
509
    function _makeXmlrpcXml($info, $indent)
509
    function _makeXmlrpcXml($info, $indent)
510
    {
510
    {
511
        $ret = $indent . "<xmlrpc";
511
        $ret = $indent . "<xmlrpc";
512
        if (isset($info['attribs']['path'])) {
512
        if (isset($info['attribs']['path'])) {
513
            $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"';
513
            $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"';
514
        }
514
        }
515
        $ret .= ">\n";
515
        $ret .= ">\n";
516
        $ret .= $this->_makeFunctionsXml($info['function'], "$indent ");
516
        $ret .= $this->_makeFunctionsXml($info['function'], "$indent ");
517
        $ret .= $indent . "</xmlrpc>\n";
517
        $ret .= $indent . "</xmlrpc>\n";
518
        return $ret;
518
        return $ret;
519
    }
519
    }
520
520
521
    /**
521
    /**
522
     * Generate the <soap> tag
522
     * Generate the <soap> tag
523
     * @access private
523
     * @access private
524
     */
524
     */
525
    function _makeSoapXml($info, $indent)
525
    function _makeSoapXml($info, $indent)
526
    {
526
    {
527
        $ret = $indent . "<soap";
527
        $ret = $indent . "<soap";
528
        if (isset($info['attribs']['path'])) {
528
        if (isset($info['attribs']['path'])) {
529
            $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"';
529
            $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"';
530
        }
530
        }
531
        $ret .= ">\n";
531
        $ret .= ">\n";
532
        $ret .= $this->_makeFunctionsXml($info['function'], "$indent ");
532
        $ret .= $this->_makeFunctionsXml($info['function'], "$indent ");
533
        $ret .= $indent . "</soap>\n";
533
        $ret .= $indent . "</soap>\n";
534
        return $ret;
534
        return $ret;
535
    }
535
    }
536
536
537
    /**
537
    /**
538
     * Generate the <rest> tag
538
     * Generate the <rest> tag
539
     * @access private
539
     * @access private
540
     */
540
     */
541
    function _makeRestXml($info, $indent)
541
    function _makeRestXml($info, $indent)
542
    {
542
    {
543
        $ret = $indent . "<rest>\n";
543
        $ret = $indent . "<rest>\n";
544
        if (!isset($info['baseurl'][0])) {
544
        if (!isset($info['baseurl'][0])) {
545
            $info['baseurl'] = array($info['baseurl']);
545
            $info['baseurl'] = array($info['baseurl']);
546
        }
546
        }
547
        foreach ($info['baseurl'] as $url) {
547
        foreach ($info['baseurl'] as $url) {
548
            $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
548
            $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
549
            $ret .= ">" . $url['_content'] . "</baseurl>\n";
549
            $ret .= ">" . $url['_content'] . "</baseurl>\n";
550
        }
550
        }
551
        $ret .= $indent . "</rest>\n";
551
        $ret .= $indent . "</rest>\n";
552
        return $ret;
552
        return $ret;
553
    }
553
    }
554
554
555
    /**
555
    /**
556
     * Generate the <mirrors> tag
556
     * Generate the <mirrors> tag
557
     * @access private
557
     * @access private
558
     */
558
     */
559
    function _makeMirrorsXml($channelInfo)
559
    function _makeMirrorsXml($channelInfo)
560
    {
560
    {
561
        $ret = "";
561
        $ret = "";
562
        if (!isset($channelInfo['servers']['mirror'][0])) {
562
        if (!isset($channelInfo['servers']['mirror'][0])) {
563
            $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
563
            $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
564
        }
564
        }
565
        foreach ($channelInfo['servers']['mirror'] as $mirror) {
565
        foreach ($channelInfo['servers']['mirror'] as $mirror) {
566
            $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
566
            $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
567
            if (isset($mirror['attribs']['port'])) {
567
            if (isset($mirror['attribs']['port'])) {
568
                $ret .= ' port="' . $mirror['attribs']['port'] . '"';
568
                $ret .= ' port="' . $mirror['attribs']['port'] . '"';
569
            }
569
            }
570
            if (isset($mirror['attribs']['ssl'])) {
570
            if (isset($mirror['attribs']['ssl'])) {
571
                $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
571
                $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
572
            }
572
            }
573
            $ret .= ">\n";
573
            $ret .= ">\n";
574
            if (isset($mirror['xmlrpc']) || isset($mirror['soap'])) {
574
            if (isset($mirror['xmlrpc']) || isset($mirror['soap'])) {
575
                if (isset($mirror['xmlrpc'])) {
575
                if (isset($mirror['xmlrpc'])) {
576
                    $ret .= $this->_makeXmlrpcXml($mirror['xmlrpc'], '   ');
576
                    $ret .= $this->_makeXmlrpcXml($mirror['xmlrpc'], '   ');
577
                }
577
                }
578
                if (isset($mirror['rest'])) {
578
                if (isset($mirror['rest'])) {
579
                    $ret .= $this->_makeRestXml($mirror['rest'], '   ');
579
                    $ret .= $this->_makeRestXml($mirror['rest'], '   ');
580
                }
580
                }
581
                if (isset($mirror['soap'])) {
581
                if (isset($mirror['soap'])) {
582
                    $ret .= $this->_makeSoapXml($mirror['soap'], '   ');
582
                    $ret .= $this->_makeSoapXml($mirror['soap'], '   ');
583
                }
583
                }
584
                $ret .= "  </mirror>\n";
584
                $ret .= "  </mirror>\n";
585
            } else {
585
            } else {
586
                $ret .= "/>\n";
586
                $ret .= "/>\n";
587
            }
587
            }
588
        }
588
        }
589
        return $ret;
589
        return $ret;
590
    }
590
    }
591
591
592
    /**
592
    /**
593
     * Generate the <functions> tag
593
     * Generate the <functions> tag
594
     * @access private
594
     * @access private
595
     */
595
     */
596
    function _makeFunctionsXml($functions, $indent, $rest = false)
596
    function _makeFunctionsXml($functions, $indent, $rest = false)
597
    {
597
    {
598
        $ret = '';
598
        $ret = '';
599
        if (!isset($functions[0])) {
599
        if (!isset($functions[0])) {
600
            $functions = array($functions);
600
            $functions = array($functions);
601
        }
601
        }
602
        foreach ($functions as $function) {
602
        foreach ($functions as $function) {
603
            $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
603
            $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
604
            if ($rest) {
604
            if ($rest) {
605
                $ret .= ' uri="' . $function['attribs']['uri'] . '"';
605
                $ret .= ' uri="' . $function['attribs']['uri'] . '"';
606
            }
606
            }
607
            $ret .= ">" . $function['_content'] . "</function>\n";
607
            $ret .= ">" . $function['_content'] . "</function>\n";
608
        }
608
        }
609
        return $ret;
609
        return $ret;
610
    }
610
    }
611
611
612
    /**
612
    /**
613
     * Validation error.  Also marks the object contents as invalid
613
     * Validation error.  Also marks the object contents as invalid
614
     * @param error code
614
     * @param error code
615
     * @param array error information
615
     * @param array error information
616
     * @access private
616
     * @access private
617
     */
617
     */
618
    function _validateError($code, $params = array())
618
    function _validateError($code, $params = array())
619
    {
619
    {
620
        $this->_stack->push($code, 'error', $params);
620
        $this->_stack->push($code, 'error', $params);
621
        $this->_isValid = false;
621
        $this->_isValid = false;
622
    }
622
    }
623
623
624
    /**
624
    /**
625
     * Validation warning.  Does not mark the object contents invalid.
625
     * Validation warning.  Does not mark the object contents invalid.
626
     * @param error code
626
     * @param error code
627
     * @param array error information
627
     * @param array error information
628
     * @access private
628
     * @access private
629
     */
629
     */
630
    function _validateWarning($code, $params = array())
630
    function _validateWarning($code, $params = array())
631
    {
631
    {
632
        $this->_stack->push($code, 'warning', $params);
632
        $this->_stack->push($code, 'warning', $params);
633
    }
633
    }
634
634
635
    /**
635
    /**
636
     * Validate parsed file.
636
     * Validate parsed file.
637
     *
637
     *
638
     * @access public
638
     * @access public
639
     * @return boolean
639
     * @return boolean
640
     */
640
     */
641
    function validate()
641
    function validate()
642
    {
642
    {
643
        $this->_isValid = true;
643
        $this->_isValid = true;
644
        $info = $this->_channelInfo;
644
        $info = $this->_channelInfo;
645
        if (empty($info['name'])) {
645
        if (empty($info['name'])) {
646
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
646
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
647
        } elseif (!$this->validChannelServer($info['name'])) {
647
        } elseif (!$this->validChannelServer($info['name'])) {
648
            if ($info['name'] != '__uri') {
648
            if ($info['name'] != '__uri') {
649
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
649
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
650
                    'name' => $info['name']));
650
                    'name' => $info['name']));
651
            }
651
            }
652
        }
652
        }
653
        if (empty($info['summary'])) {
653
        if (empty($info['summary'])) {
654
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
654
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
655
        } elseif (strpos(trim($info['summary']), "\n") !== false) {
655
        } elseif (strpos(trim($info['summary']), "\n") !== false) {
656
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
656
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
657
                array('summary' => $info['summary']));
657
                array('summary' => $info['summary']));
658
        }
658
        }
659
        if (isset($info['suggestedalias'])) {
659
        if (isset($info['suggestedalias'])) {
660
            if (!$this->validChannelServer($info['suggestedalias'])) {
660
            if (!$this->validChannelServer($info['suggestedalias'])) {
661
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
661
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
662
                    array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
662
                    array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
663
            }
663
            }
664
        }
664
        }
665
        if (isset($info['localalias'])) {
665
        if (isset($info['localalias'])) {
666
            if (!$this->validChannelServer($info['localalias'])) {
666
            if (!$this->validChannelServer($info['localalias'])) {
667
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
667
                $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
668
                    array('tag' => 'localalias', 'name' =>$info['localalias']));
668
                    array('tag' => 'localalias', 'name' =>$info['localalias']));
669
            }
669
            }
670
        }
670
        }
671
        if (isset($info['validatepackage'])) {
671
        if (isset($info['validatepackage'])) {
672
            if (!isset($info['validatepackage']['_content'])) {
672
            if (!isset($info['validatepackage']['_content'])) {
673
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
673
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
674
            }
674
            }
675
            if (!isset($info['validatepackage']['attribs']['version'])) {
675
            if (!isset($info['validatepackage']['attribs']['version'])) {
676
                $content = isset($info['validatepackage']['_content']) ?
676
                $content = isset($info['validatepackage']['_content']) ?
677
                    $info['validatepackage']['_content'] :
677
                    $info['validatepackage']['_content'] :
678
                    null;
678
                    null;
679
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
679
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
680
                    array('package' => $content));
680
                    array('package' => $content));
681
            }
681
            }
682
        }
682
        }
683
        if (isset($info['servers']['primary']['attribs']['port']) &&
683
        if (isset($info['servers']['primary']['attribs']['port']) &&
684
              !is_numeric($info['servers']['primary']['attribs']['port'])) {
684
              !is_numeric($info['servers']['primary']['attribs']['port'])) {
685
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
685
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
686
                array('port' => $info['servers']['primary']['attribs']['port']));
686
                array('port' => $info['servers']['primary']['attribs']['port']));
687
        }
687
        }
688
        if (isset($info['servers']['primary']['attribs']['ssl']) &&
688
        if (isset($info['servers']['primary']['attribs']['ssl']) &&
689
              $info['servers']['primary']['attribs']['ssl'] != 'yes') {
689
              $info['servers']['primary']['attribs']['ssl'] != 'yes') {
690
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
690
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
691
                array('ssl' => $info['servers']['primary']['attribs']['ssl'],
691
                array('ssl' => $info['servers']['primary']['attribs']['ssl'],
692
                    'server' => $info['name']));
692
                    'server' => $info['name']));
693
        }
693
        }
694
694
695
        if (isset($info['servers']['primary']['xmlrpc']) &&
695
        if (isset($info['servers']['primary']['xmlrpc']) &&
696
              isset($info['servers']['primary']['xmlrpc']['function'])) {
696
              isset($info['servers']['primary']['xmlrpc']['function'])) {
697
            $this->_validateFunctions('xmlrpc', $info['servers']['primary']['xmlrpc']['function']);
697
            $this->_validateFunctions('xmlrpc', $info['servers']['primary']['xmlrpc']['function']);
698
        }
698
        }
699
        if (isset($info['servers']['primary']['soap']) &&
699
        if (isset($info['servers']['primary']['soap']) &&
700
              isset($info['servers']['primary']['soap']['function'])) {
700
              isset($info['servers']['primary']['soap']['function'])) {
701
            $this->_validateFunctions('soap', $info['servers']['primary']['soap']['function']);
701
            $this->_validateFunctions('soap', $info['servers']['primary']['soap']['function']);
702
        }
702
        }
703
        if (isset($info['servers']['primary']['rest']) &&
703
        if (isset($info['servers']['primary']['rest']) &&
704
              isset($info['servers']['primary']['rest']['baseurl'])) {
704
              isset($info['servers']['primary']['rest']['baseurl'])) {
705
            $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
705
            $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
706
        }
706
        }
707
        if (isset($info['servers']['mirror'])) {
707
        if (isset($info['servers']['mirror'])) {
708
            if ($this->_channelInfo['name'] == '__uri') {
708
            if ($this->_channelInfo['name'] == '__uri') {
709
                $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
709
                $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
710
            }
710
            }
711
            if (!isset($info['servers']['mirror'][0])) {
711
            if (!isset($info['servers']['mirror'][0])) {
712
                $info['servers']['mirror'] = array($info['servers']['mirror']);
712
                $info['servers']['mirror'] = array($info['servers']['mirror']);
713
            }
713
            }
714
            foreach ($info['servers']['mirror'] as $mirror) {
714
            foreach ($info['servers']['mirror'] as $mirror) {
715
                if (!isset($mirror['attribs']['host'])) {
715
                if (!isset($mirror['attribs']['host'])) {
716
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
716
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
717
                      array('type' => 'mirror'));
717
                      array('type' => 'mirror'));
718
                } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
718
                } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
719
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
719
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
720
                        array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
720
                        array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
721
                }
721
                }
722
                if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
722
                if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
723
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
723
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
724
                        array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
724
                        array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
725
                }
725
                }
726
                if (isset($mirror['xmlrpc'])) {
726
                if (isset($mirror['xmlrpc'])) {
727
                    $this->_validateFunctions('xmlrpc',
727
                    $this->_validateFunctions('xmlrpc',
728
                        $mirror['xmlrpc']['function'], $mirror['attribs']['host']);
728
                        $mirror['xmlrpc']['function'], $mirror['attribs']['host']);
729
                }
729
                }
730
                if (isset($mirror['soap'])) {
730
                if (isset($mirror['soap'])) {
731
                    $this->_validateFunctions('soap', $mirror['soap']['function'],
731
                    $this->_validateFunctions('soap', $mirror['soap']['function'],
732
                        $mirror['attribs']['host']);
732
                        $mirror['attribs']['host']);
733
                }
733
                }
734
                if (isset($mirror['rest'])) {
734
                if (isset($mirror['rest'])) {
735
                    $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
735
                    $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
736
                        $mirror['attribs']['host']);
736
                        $mirror['attribs']['host']);
737
                }
737
                }
738
            }
738
            }
739
        }
739
        }
740
        return $this->_isValid;
740
        return $this->_isValid;
741
    }
741
    }
742
742
743
    /**
743
    /**
744
     * @param string xmlrpc or soap - protocol name this function applies to
744
     * @param string xmlrpc or soap - protocol name this function applies to
745
     * @param array the functions
745
     * @param array the functions
746
     * @param string the name of the parent element (mirror name, for instance)
746
     * @param string the name of the parent element (mirror name, for instance)
747
     */
747
     */
748
    function _validateFunctions($protocol, $functions, $parent = '')
748
    function _validateFunctions($protocol, $functions, $parent = '')
749
    {
749
    {
750
        if (!isset($functions[0])) {
750
        if (!isset($functions[0])) {
751
            $functions = array($functions);
751
            $functions = array($functions);
752
        }
752
        }
753
        foreach ($functions as $function) {
753
        foreach ($functions as $function) {
754
            if (!isset($function['_content']) || empty($function['_content'])) {
754
            if (!isset($function['_content']) || empty($function['_content'])) {
755
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
755
                $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
756
                    array('parent' => $parent, 'protocol' => $protocol));
756
                    array('parent' => $parent, 'protocol' => $protocol));
757
            }
757
            }
758
            if ($protocol == 'rest') {
758
            if ($protocol == 'rest') {
759
                if (!isset($function['attribs']['type']) ||
759
                if (!isset($function['attribs']['type']) ||
760
                      empty($function['attribs']['type'])) {
760
                      empty($function['attribs']['type'])) {
761
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_BASEURLTYPE,
761
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_BASEURLTYPE,
762
                        array('parent' => $parent, 'protocol' => $protocol));
762
                        array('parent' => $parent, 'protocol' => $protocol));
763
                }
763
                }
764
            } else {
764
            } else {
765
                if (!isset($function['attribs']['version']) ||
765
                if (!isset($function['attribs']['version']) ||
766
                      empty($function['attribs']['version'])) {
766
                      empty($function['attribs']['version'])) {
767
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
767
                    $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
768
                        array('parent' => $parent, 'protocol' => $protocol));
768
                        array('parent' => $parent, 'protocol' => $protocol));
769
                }
769
                }
770
            }
770
            }
771
        }
771
        }
772
    }
772
    }
773
773
774
    /**
774
    /**
775
     * Test whether a string contains a valid channel server.
775
     * Test whether a string contains a valid channel server.
776
     * @param string $ver the package version to test
776
     * @param string $ver the package version to test
777
     * @return bool
777
     * @return bool
778
     */
778
     */
779
    function validChannelServer($server)
779
    function validChannelServer($server)
780
    {
780
    {
781
        if ($server == '__uri') {
781
        if ($server == '__uri') {
782
            return true;
782
            return true;
783
        }
783
        }
784
        return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
784
        return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
785
    }
785
    }
786
786
787
    /**
787
    /**
788
     * @return string|false
788
     * @return string|false
789
     */
789
     */
790
    function getName()
790
    function getName()
791
    {
791
    {
792
        if (isset($this->_channelInfo['name'])) {
792
        if (isset($this->_channelInfo['name'])) {
793
            return $this->_channelInfo['name'];
793
            return $this->_channelInfo['name'];
794
        } else {
794
        } else {
795
            return false;
795
            return false;
796
        }
796
        }
797
    }
797
    }
798
798
799
    /**
799
    /**
800
     * @return string|false
800
     * @return string|false
801
     */
801
     */
802
    function getServer()
802
    function getServer()
803
    {
803
    {
804
        if (isset($this->_channelInfo['name'])) {
804
        if (isset($this->_channelInfo['name'])) {
805
            return $this->_channelInfo['name'];
805
            return $this->_channelInfo['name'];
806
        } else {
806
        } else {
807
            return false;
807
            return false;
808
        }
808
        }
809
    }
809
    }
810
810
811
    /**
811
    /**
812
     * @return int|80 port number to connect to
812
     * @return int|80 port number to connect to
813
     */
813
     */
814
    function getPort($mirror = false)
814
    function getPort($mirror = false)
815
    {
815
    {
816
        if ($mirror) {
816
        if ($mirror) {
817
            if ($mir = $this->getMirror($mirror)) {
817
            if ($mir = $this->getMirror($mirror)) {
818
                if (isset($mir['attribs']['port'])) {
818
                if (isset($mir['attribs']['port'])) {
819
                    return $mir['attribs']['port'];
819
                    return $mir['attribs']['port'];
820
                } else {
820
                } else {
821
                    if ($this->getSSL($mirror)) {
821
                    if ($this->getSSL($mirror)) {
822
                        return 443;
822
                        return 443;
823
                    }
823
                    }
824
                    return 80;
824
                    return 80;
825
                }
825
                }
826
            }
826
            }
827
            return false;
827
            return false;
828
        }
828
        }
829
        if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
829
        if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
830
            return $this->_channelInfo['servers']['primary']['attribs']['port'];
830
            return $this->_channelInfo['servers']['primary']['attribs']['port'];
831
        }
831
        }
832
        if ($this->getSSL()) {
832
        if ($this->getSSL()) {
833
            return 443;
833
            return 443;
834
        }
834
        }
835
        return 80;
835
        return 80;
836
    }
836
    }
837
837
838
    /**
838
    /**
839
     * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
839
     * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
840
     */
840
     */
841
    function getSSL($mirror = false)
841
    function getSSL($mirror = false)
842
    {
842
    {
843
        if ($mirror) {
843
        if ($mirror) {
844
            if ($mir = $this->getMirror($mirror)) {
844
            if ($mir = $this->getMirror($mirror)) {
845
                if (isset($mir['attribs']['ssl'])) {
845
                if (isset($mir['attribs']['ssl'])) {
846
                    return true;
846
                    return true;
847
                } else {
847
                } else {
848
                    return false;
848
                    return false;
849
                }
849
                }
850
            }
850
            }
851
            return false;
851
            return false;
852
        }
852
        }
853
        if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
853
        if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
854
            return true;
854
            return true;
855
        }
855
        }
856
        return false;
856
        return false;
857
    }
857
    }
858
858
859
    /**
859
    /**
860
     * @return string|false
860
     * @return string|false
861
     */
861
     */
862
    function getSummary()
862
    function getSummary()
863
    {
863
    {
864
        if (isset($this->_channelInfo['summary'])) {
864
        if (isset($this->_channelInfo['summary'])) {
865
            return $this->_channelInfo['summary'];
865
            return $this->_channelInfo['summary'];
866
        } else {
866
        } else {
867
            return false;
867
            return false;
868
        }
868
        }
869
    }
869
    }
870
870
871
    /**
871
    /**
872
     * @param string xmlrpc or soap
872
     * @param string xmlrpc or soap
873
     * @param string|false mirror name or false for primary server
873
     * @param string|false mirror name or false for primary server
874
     */
874
     */
875
    function getPath($protocol, $mirror = false)
875
    function getPath($protocol, $mirror = false)
876
    {  
876
    {  
877
        if (!in_array($protocol, array('xmlrpc', 'soap'))) {
877
        if (!in_array($protocol, array('xmlrpc', 'soap'))) {
878
            return false;
878
            return false;
879
        }
879
        }
880
        if ($mirror) {
880
        if ($mirror) {
881
            if (!($mir = $this->getMirror($mirror))) {
881
            if (!($mir = $this->getMirror($mirror))) {
882
                return false;
882
                return false;
883
            }
883
            }
884
            if (isset($mir[$protocol]['attribs']['path'])) {
884
            if (isset($mir[$protocol]['attribs']['path'])) {
885
                return $mir[$protocol]['attribs']['path'];
885
                return $mir[$protocol]['attribs']['path'];
886
            } else {
886
            } else {
887
                return $protocol . '.php';
887
                return $protocol . '.php';
888
            }
888
            }
889
        } elseif (isset($this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'])) {
889
        } elseif (isset($this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'])) {
890
            return $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'];
890
            return $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'];
891
        }
891
        }
892
        return $protocol . '.php';
892
        return $protocol . '.php';
893
    }
893
    }
894
894
895
    /**
895
    /**
896
     * @param string protocol type (xmlrpc, soap)
896
     * @param string protocol type (xmlrpc, soap)
897
     * @param string Mirror name
897
     * @param string Mirror name
898
     * @return array|false
898
     * @return array|false
899
     */
899
     */
900
    function getFunctions($protocol, $mirror = false)
900
    function getFunctions($protocol, $mirror = false)
901
    {
901
    {
902
        if ($this->getName() == '__uri') {
902
        if ($this->getName() == '__uri') {
903
            return false;
903
            return false;
904
        }
904
        }
905
        if ($protocol == 'rest') {
905
        if ($protocol == 'rest') {
906
            $function = 'baseurl';
906
            $function = 'baseurl';
907
        } else {
907
        } else {
908
            $function = 'function';
908
            $function = 'function';
909
        }
909
        }
910
        if ($mirror) {
910
        if ($mirror) {
911
            if ($mir = $this->getMirror($mirror)) {
911
            if ($mir = $this->getMirror($mirror)) {
912
                if (isset($mir[$protocol][$function])) {
912
                if (isset($mir[$protocol][$function])) {
913
                    return $mir[$protocol][$function];
913
                    return $mir[$protocol][$function];
914
                }
914
                }
915
            }
915
            }
916
            return false;
916
            return false;
917
        }
917
        }
918
        if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
918
        if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
919
            return $this->_channelInfo['servers']['primary'][$protocol][$function];
919
            return $this->_channelInfo['servers']['primary'][$protocol][$function];
920
        } else {
920
        } else {
921
            return false;
921
            return false;
922
        }
922
        }
923
    }
923
    }
924
924
925
    /**
925
    /**
926
     * @param string Protocol type
926
     * @param string Protocol type
927
     * @param string Function name (null to return the
927
     * @param string Function name (null to return the
928
     *               first protocol of the type requested)
928
     *               first protocol of the type requested)
929
     * @param string Mirror name, if any
929
     * @param string Mirror name, if any
930
     * @return array
930
     * @return array
931
     */
931
     */
932
     function getFunction($type, $name = null, $mirror = false)
932
     function getFunction($type, $name = null, $mirror = false)
933
     {
933
     {
934
        $protocols = $this->getFunctions($type, $mirror);
934
        $protocols = $this->getFunctions($type, $mirror);
935
        if (!$protocols) {
935
        if (!$protocols) {
936
            return false;
936
            return false;
937
        }
937
        }
938
        foreach ($protocols as $protocol) {
938
        foreach ($protocols as $protocol) {
939
            if ($name === null) {
939
            if ($name === null) {
940
                return $protocol;
940
                return $protocol;
941
            }
941
            }
942
            if ($protocol['_content'] != $name) {
942
            if ($protocol['_content'] != $name) {
943
                continue;
943
                continue;
944
            }
944
            }
945
            return $protocol;
945
            return $protocol;
946
        }
946
        }
947
        return false;
947
        return false;
948
     }
948
     }
949
949
950
    /**
950
    /**
951
     * @param string protocol type
951
     * @param string protocol type
952
     * @param string protocol name
952
     * @param string protocol name
953
     * @param string version
953
     * @param string version
954
     * @param string mirror name
954
     * @param string mirror name
955
     * @return boolean
955
     * @return boolean
956
     */
956
     */
957
    function supports($type, $name = null, $mirror = false, $version = '1.0')
957
    function supports($type, $name = null, $mirror = false, $version = '1.0')
958
    {
958
    {
959
        $protocols = $this->getFunctions($type, $mirror);
959
        $protocols = $this->getFunctions($type, $mirror);
960
        if (!$protocols) {
960
        if (!$protocols) {
961
            return false;
961
            return false;
962
        }
962
        }
963
        foreach ($protocols as $protocol) {
963
        foreach ($protocols as $protocol) {
964
            if ($protocol['attribs']['version'] != $version) {
964
            if ($protocol['attribs']['version'] != $version) {
965
                continue;
965
                continue;
966
            }
966
            }
967
            if ($name === null) {
967
            if ($name === null) {
968
                return true;
968
                return true;
969
            }
969
            }
970
            if ($protocol['_content'] != $name) {
970
            if ($protocol['_content'] != $name) {
971
                continue;
971
                continue;
972
            }
972
            }
973
            return true;
973
            return true;
974
        }
974
        }
975
        return false;
975
        return false;
976
    }
976
    }
977
977
978
    /**
978
    /**
979
     * Determines whether a channel supports Representational State Transfer (REST) protocols
979
     * Determines whether a channel supports Representational State Transfer (REST) protocols
980
     * for retrieving channel information
980
     * for retrieving channel information
981
     * @param string
981
     * @param string
982
     * @return bool
982
     * @return bool
983
     */
983
     */
984
    function supportsREST($mirror = false)
984
    function supportsREST($mirror = false)
985
    {
985
    {
986
        if ($mirror == $this->_channelInfo['name']) {
986
        if ($mirror == $this->_channelInfo['name']) {
987
            $mirror = false;
987
            $mirror = false;
988
        }
988
        }
989
        if ($mirror) {
989
        if ($mirror) {
990
            if ($mir = $this->getMirror($mirror)) {
990
            if ($mir = $this->getMirror($mirror)) {
991
                return isset($mir['rest']);
991
                return isset($mir['rest']);
992
            }
992
            }
993
            return false;
993
            return false;
994
        }
994
        }
995
        return isset($this->_channelInfo['servers']['primary']['rest']);
995
        return isset($this->_channelInfo['servers']['primary']['rest']);
996
    }
996
    }
997
997
998
    /**
998
    /**
999
     * Get the URL to access a base resource.
999
     * Get the URL to access a base resource.
1000
     *
1000
     *
1001
     * Hyperlinks in the returned xml will be used to retrieve the proper information
1001
     * Hyperlinks in the returned xml will be used to retrieve the proper information
1002
     * needed.  This allows extreme extensibility and flexibility in implementation
1002
     * needed.  This allows extreme extensibility and flexibility in implementation
1003
     * @param string Resource Type to retrieve
1003
     * @param string Resource Type to retrieve
1004
     */
1004
     */
1005
    function getBaseURL($resourceType, $mirror = false)
1005
    function getBaseURL($resourceType, $mirror = false)
1006
    {
1006
    {
1007
        if ($mirror == $this->_channelInfo['name']) {
1007
        if ($mirror == $this->_channelInfo['name']) {
1008
            $mirror = false;
1008
            $mirror = false;
1009
        }
1009
        }
1010
        if ($mirror) {
1010
        if ($mirror) {
1011
            if ($mir = $this->getMirror($mirror)) {
1011
            if ($mir = $this->getMirror($mirror)) {
1012
                $rest = $mir['rest'];
1012
                $rest = $mir['rest'];
1013
            } else {
1013
            } else {
1014
                return false;
1014
                return false;
1015
            }
1015
            }
1016
        } else {
1016
        } else {
1017
            $rest = $this->_channelInfo['servers']['primary']['rest'];
1017
            $rest = $this->_channelInfo['servers']['primary']['rest'];
1018
        }
1018
        }
1019
        if (!isset($rest['baseurl'][0])) {
1019
        if (!isset($rest['baseurl'][0])) {
1020
            $rest['baseurl'] = array($rest['baseurl']);
1020
            $rest['baseurl'] = array($rest['baseurl']);
1021
        }
1021
        }
1022
        foreach ($rest['baseurl'] as $baseurl) {
1022
        foreach ($rest['baseurl'] as $baseurl) {
1023
            if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
1023
            if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
1024
                return $baseurl['_content'];
1024
                return $baseurl['_content'];
1025
            }
1025
            }
1026
        }
1026
        }
1027
        return false;
1027
        return false;
1028
    }
1028
    }
1029
1029
1030
    /**
1030
    /**
1031
     * Since REST does not implement RPC, provide this as a logical wrapper around
1031
     * Since REST does not implement RPC, provide this as a logical wrapper around
1032
     * resetFunctions for REST
1032
     * resetFunctions for REST
1033
     * @param string|false mirror name, if any
1033
     * @param string|false mirror name, if any
1034
     */
1034
     */
1035
    function resetREST($mirror = false)
1035
    function resetREST($mirror = false)
1036
    {
1036
    {
1037
        return $this->resetFunctions('rest', $mirror);
1037
        return $this->resetFunctions('rest', $mirror);
1038
    }
1038
    }
1039
1039
1040
    /**
1040
    /**
1041
     * Empty all protocol definitions
1041
     * Empty all protocol definitions
1042
     * @param string protocol type (xmlrpc, soap)
1042
     * @param string protocol type (xmlrpc, soap)
1043
     * @param string|false mirror name, if any
1043
     * @param string|false mirror name, if any
1044
     */
1044
     */
1045
    function resetFunctions($type, $mirror = false)
1045
    function resetFunctions($type, $mirror = false)
1046
    {
1046
    {
1047
        if ($mirror) {
1047
        if ($mirror) {
1048
            if (isset($this->_channelInfo['servers']['mirror'])) {
1048
            if (isset($this->_channelInfo['servers']['mirror'])) {
1049
                $mirrors = $this->_channelInfo['servers']['mirror'];
1049
                $mirrors = $this->_channelInfo['servers']['mirror'];
1050
                if (!isset($mirrors[0])) {
1050
                if (!isset($mirrors[0])) {
1051
                    $mirrors = array($mirrors);
1051
                    $mirrors = array($mirrors);
1052
                }
1052
                }
1053
                foreach ($mirrors as $i => $mir) {
1053
                foreach ($mirrors as $i => $mir) {
1054
                    if ($mir['attribs']['host'] == $mirror) {
1054
                    if ($mir['attribs']['host'] == $mirror) {
1055
                        if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
1055
                        if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
1056
                            unset($this->_channelInfo['servers']['mirror'][$i][$type]);
1056
                            unset($this->_channelInfo['servers']['mirror'][$i][$type]);
1057
                        }
1057
                        }
1058
                        return true;
1058
                        return true;
1059
                    }
1059
                    }
1060
                }
1060
                }
1061
                return false;
1061
                return false;
1062
            } else {
1062
            } else {
1063
                return false;
1063
                return false;
1064
            }
1064
            }
1065
        } else {
1065
        } else {
1066
            if (isset($this->_channelInfo['servers']['primary'][$type])) {
1066
            if (isset($this->_channelInfo['servers']['primary'][$type])) {
1067
                unset($this->_channelInfo['servers']['primary'][$type]);
1067
                unset($this->_channelInfo['servers']['primary'][$type]);
1068
            }
1068
            }
1069
            return true;
1069
            return true;
1070
        }
1070
        }
1071
    }
1071
    }
1072
1072
1073
    /**
1073
    /**
1074
     * Set a channel's protocols to the protocols supported by pearweb
1074
     * Set a channel's protocols to the protocols supported by pearweb
1075
     */
1075
     */
1076
    function setDefaultPEARProtocols($version = '1.0', $mirror = false)
1076
    function setDefaultPEARProtocols($version = '1.0', $mirror = false)
1077
    {
1077
    {
1078
        switch ($version) {
1078
        switch ($version) {
1079
            case '1.0' :
1079
            case '1.0' :
1080
                $this->resetFunctions('xmlrpc', $mirror);
1080
                $this->resetFunctions('xmlrpc', $mirror);
1081
                $this->resetFunctions('soap', $mirror);
1081
                $this->resetFunctions('soap', $mirror);
1082
                $this->resetREST($mirror);
1082
                $this->resetREST($mirror);
1083
                $this->addFunction('xmlrpc', '1.0', 'logintest', $mirror);
1083
                $this->addFunction('xmlrpc', '1.0', 'logintest', $mirror);
1084
                $this->addFunction('xmlrpc', '1.0', 'package.listLatestReleases', $mirror);
1084
                $this->addFunction('xmlrpc', '1.0', 'package.listLatestReleases', $mirror);
1085
                $this->addFunction('xmlrpc', '1.0', 'package.listAll', $mirror);
1085
                $this->addFunction('xmlrpc', '1.0', 'package.listAll', $mirror);
1086
                $this->addFunction('xmlrpc', '1.0', 'package.info', $mirror);
1086
                $this->addFunction('xmlrpc', '1.0', 'package.info', $mirror);
1087
                $this->addFunction('xmlrpc', '1.0', 'package.getDownloadURL', $mirror);
1087
                $this->addFunction('xmlrpc', '1.0', 'package.getDownloadURL', $mirror);
1088
                $this->addFunction('xmlrpc', '1.1', 'package.getDownloadURL', $mirror);
1088
                $this->addFunction('xmlrpc', '1.1', 'package.getDownloadURL', $mirror);
1089
                $this->addFunction('xmlrpc', '1.0', 'package.getDepDownloadURL', $mirror);
1089
                $this->addFunction('xmlrpc', '1.0', 'package.getDepDownloadURL', $mirror);
1090
                $this->addFunction('xmlrpc', '1.1', 'package.getDepDownloadURL', $mirror);
1090
                $this->addFunction('xmlrpc', '1.1', 'package.getDepDownloadURL', $mirror);
1091
                $this->addFunction('xmlrpc', '1.0', 'package.search', $mirror);
1091
                $this->addFunction('xmlrpc', '1.0', 'package.search', $mirror);
1092
                $this->addFunction('xmlrpc', '1.0', 'channel.listAll', $mirror);
1092
                $this->addFunction('xmlrpc', '1.0', 'channel.listAll', $mirror);
1093
                return true;
1093
                return true;
1094
            break;
1094
            break;
1095
            default :
1095
            default :
1096
                return false;
1096
                return false;
1097
            break;
1097
            break;
1098
        }
1098
        }
1099
    }
1099
    }
1100
   
1100
   
1101
    /**
1101
    /**
1102
     * @return array
1102
     * @return array
1103
     */
1103
     */
1104
    function getMirrors()
1104
    function getMirrors()
1105
    {
1105
    {
1106
        if (isset($this->_channelInfo['servers']['mirror'])) {
1106
        if (isset($this->_channelInfo['servers']['mirror'])) {
1107
            $mirrors = $this->_channelInfo['servers']['mirror'];
1107
            $mirrors = $this->_channelInfo['servers']['mirror'];
1108
            if (!isset($mirrors[0])) {
1108
            if (!isset($mirrors[0])) {
1109
                $mirrors = array($mirrors);
1109
                $mirrors = array($mirrors);
1110
            }
1110
            }
1111
            return $mirrors;
1111
            return $mirrors;
1112
        } else {
1112
        } else {
1113
            return array();
1113
            return array();
1114
        }
1114
        }
1115
    }
1115
    }
1116
1116
1117
    /**
1117
    /**
1118
     * Get the unserialized XML representing a mirror
1118
     * Get the unserialized XML representing a mirror
1119
     * @return array|false
1119
     * @return array|false
1120
     */
1120
     */
1121
    function getMirror($server)
1121
    function getMirror($server)
1122
    {
1122
    {
1123
        foreach ($this->getMirrors() as $mirror) {
1123
        foreach ($this->getMirrors() as $mirror) {
1124
            if ($mirror['attribs']['host'] == $server) {
1124
            if ($mirror['attribs']['host'] == $server) {
1125
                return $mirror;
1125
                return $mirror;
1126
            }
1126
            }
1127
        }
1127
        }
1128
        return false;
1128
        return false;
1129
    }
1129
    }
1130
1130
1131
    /**
1131
    /**
1132
     * @param string
1132
     * @param string
1133
     * @return string|false
1133
     * @return string|false
1134
     * @error PEAR_CHANNELFILE_ERROR_NO_NAME
1134
     * @error PEAR_CHANNELFILE_ERROR_NO_NAME
1135
     * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
1135
     * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
1136
     */
1136
     */
1137
    function setName($name)
1137
    function setName($name)
1138
    {
1138
    {
1139
        return $this->setServer($name);
1139
        return $this->setServer($name);
1140
    }
1140
    }
1141
1141
1142
    /**
1142
    /**
1143
     * Set the socket number (port) that is used to connect to this channel
1143
     * Set the socket number (port) that is used to connect to this channel
1144
     * @param integer
1144
     * @param integer
1145
     * @param string|false name of the mirror server, or false for the primary
1145
     * @param string|false name of the mirror server, or false for the primary
1146
     */
1146
     */
1147
    function setPort($port, $mirror = false)
1147
    function setPort($port, $mirror = false)
1148
    {
1148
    {
1149
        if ($mirror) {
1149
        if ($mirror) {
1150
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1150
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1151
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1151
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1152
                    array('mirror' => $mirror));
1152
                    array('mirror' => $mirror));
1153
                return false;
1153
                return false;
1154
            }
1154
            }
1155
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1155
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1156
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1156
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1157
                    if ($mirror == $mir['attribs']['host']) {
1157
                    if ($mirror == $mir['attribs']['host']) {
1158
                        $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
1158
                        $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
1159
                        return true;
1159
                        return true;
1160
                    }
1160
                    }
1161
                }
1161
                }
1162
                return false;
1162
                return false;
1163
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1163
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1164
                $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
1164
                $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
1165
                $this->_isValid = false;
1165
                $this->_isValid = false;
1166
                return true;
1166
                return true;
1167
            }
1167
            }
1168
        }
1168
        }
1169
        $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
1169
        $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
1170
        $this->_isValid = false;
1170
        $this->_isValid = false;
1171
        return true;
1171
        return true;
1172
    }
1172
    }
1173
1173
1174
    /**
1174
    /**
1175
     * Set the socket number (port) that is used to connect to this channel
1175
     * Set the socket number (port) that is used to connect to this channel
1176
     * @param bool Determines whether to turn on SSL support or turn it off
1176
     * @param bool Determines whether to turn on SSL support or turn it off
1177
     * @param string|false name of the mirror server, or false for the primary
1177
     * @param string|false name of the mirror server, or false for the primary
1178
     */
1178
     */
1179
    function setSSL($ssl = true, $mirror = false)
1179
    function setSSL($ssl = true, $mirror = false)
1180
    {
1180
    {
1181
        if ($mirror) {
1181
        if ($mirror) {
1182
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1182
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1183
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1183
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1184
                    array('mirror' => $mirror));
1184
                    array('mirror' => $mirror));
1185
                return false;
1185
                return false;
1186
            }
1186
            }
1187
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1187
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1188
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1188
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1189
                    if ($mirror == $mir['attribs']['host']) {
1189
                    if ($mirror == $mir['attribs']['host']) {
1190
                        if (!$ssl) {
1190
                        if (!$ssl) {
1191
                            if (isset($this->_channelInfo['servers']['mirror'][$i]
1191
                            if (isset($this->_channelInfo['servers']['mirror'][$i]
1192
                                  ['attribs']['ssl'])) {
1192
                                  ['attribs']['ssl'])) {
1193
                                unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
1193
                                unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
1194
                            }
1194
                            }
1195
                        } else {
1195
                        } else {
1196
                            $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
1196
                            $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
1197
                        }
1197
                        }
1198
                        return true;
1198
                        return true;
1199
                    }
1199
                    }
1200
                }
1200
                }
1201
                return false;
1201
                return false;
1202
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1202
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1203
                if (!$ssl) {
1203
                if (!$ssl) {
1204
                    if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
1204
                    if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
1205
                        unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
1205
                        unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
1206
                    }
1206
                    }
1207
                } else {
1207
                } else {
1208
                    $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
1208
                    $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
1209
                }
1209
                }
1210
                $this->_isValid = false;
1210
                $this->_isValid = false;
1211
                return true;
1211
                return true;
1212
            }
1212
            }
1213
        }
1213
        }
1214
        if ($ssl) {
1214
        if ($ssl) {
1215
            $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
1215
            $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
1216
        } else {
1216
        } else {
1217
            if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
1217
            if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
1218
                unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
1218
                unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
1219
            }
1219
            }
1220
        }
1220
        }
1221
        $this->_isValid = false;
1221
        $this->_isValid = false;
1222
        return true;
1222
        return true;
1223
    }
1223
    }
1224
1224
1225
    /**
1225
    /**
1226
     * Set the socket number (port) that is used to connect to this channel
1226
     * Set the socket number (port) that is used to connect to this channel
1227
     * @param integer
1227
     * @param integer
1228
     * @param string|false name of the mirror server, or false for the primary
1228
     * @param string|false name of the mirror server, or false for the primary
1229
     */
1229
     */
1230
    function setPath($protocol, $path, $mirror = false)
1230
    function setPath($protocol, $path, $mirror = false)
1231
    {
1231
    {
1232
        if (!in_array($protocol, array('xmlrpc', 'soap'))) {
1232
        if (!in_array($protocol, array('xmlrpc', 'soap'))) {
1233
            return false;
1233
            return false;
1234
        }
1234
        }
1235
        if ($mirror) {
1235
        if ($mirror) {
1236
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1236
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1237
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1237
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1238
                    array('mirror' => $mirror));
1238
                    array('mirror' => $mirror));
1239
                return false;
1239
                return false;
1240
            }
1240
            }
1241
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1241
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1242
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1242
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1243
                    if ($mirror == $mir['attribs']['host']) {
1243
                    if ($mirror == $mir['attribs']['host']) {
1244
                        $this->_channelInfo['servers']['mirror'][$i][$protocol]['attribs']['path'] =
1244
                        $this->_channelInfo['servers']['mirror'][$i][$protocol]['attribs']['path'] =
1245
                            $path;
1245
                            $path;
1246
                        return true;
1246
                        return true;
1247
                    }
1247
                    }
1248
                }
1248
                }
1249
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1249
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1250
                    array('mirror' => $mirror));
1250
                    array('mirror' => $mirror));
1251
                return false;
1251
                return false;
1252
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1252
            } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1253
                $this->_channelInfo['servers']['mirror'][$protocol]['attribs']['path'] = $path;
1253
                $this->_channelInfo['servers']['mirror'][$protocol]['attribs']['path'] = $path;
1254
                $this->_isValid = false;
1254
                $this->_isValid = false;
1255
                return true;
1255
                return true;
1256
            }
1256
            }
1257
        }
1257
        }
1258
        $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'] = $path;
1258
        $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'] = $path;
1259
        $this->_isValid = false;
1259
        $this->_isValid = false;
1260
        return true;
1260
        return true;
1261
    }
1261
    }
1262
1262
1263
    /**
1263
    /**
1264
     * @param string
1264
     * @param string
1265
     * @return string|false
1265
     * @return string|false
1266
     * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
1266
     * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
1267
     * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
1267
     * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
1268
     */
1268
     */
1269
    function setServer($server, $mirror = false)
1269
    function setServer($server, $mirror = false)
1270
    {
1270
    {
1271
        if (empty($server)) {
1271
        if (empty($server)) {
1272
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
1272
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
1273
            return false;
1273
            return false;
1274
        } elseif (!$this->validChannelServer($server)) {
1274
        } elseif (!$this->validChannelServer($server)) {
1275
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
1275
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
1276
                array('tag' => 'name', 'name' => $server));
1276
                array('tag' => 'name', 'name' => $server));
1277
            return false;
1277
            return false;
1278
        }
1278
        }
1279
        if ($mirror) {
1279
        if ($mirror) {
1280
            $found = false;
1280
            $found = false;
1281
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1281
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1282
                if ($mirror == $mir['attribs']['host']) {
1282
                if ($mirror == $mir['attribs']['host']) {
1283
                    $found = true;
1283
                    $found = true;
1284
                    break;
1284
                    break;
1285
                }
1285
                }
1286
            }
1286
            }
1287
            if (!$found) {
1287
            if (!$found) {
1288
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1288
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1289
                    array('mirror' => $mirror));
1289
                    array('mirror' => $mirror));
1290
                return false;
1290
                return false;
1291
            }
1291
            }
1292
            $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
1292
            $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
1293
            return true;
1293
            return true;
1294
        }
1294
        }
1295
        $this->_channelInfo['name'] = $server;
1295
        $this->_channelInfo['name'] = $server;
1296
        return true;
1296
        return true;
1297
    }
1297
    }
1298
1298
1299
    /**
1299
    /**
1300
     * @param string
1300
     * @param string
1301
     * @return boolean success
1301
     * @return boolean success
1302
     * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
1302
     * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
1303
     * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
1303
     * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
1304
     */
1304
     */
1305
    function setSummary($summary)
1305
    function setSummary($summary)
1306
    {
1306
    {
1307
        if (empty($summary)) {
1307
        if (empty($summary)) {
1308
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
1308
            $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
1309
            return false;
1309
            return false;
1310
        } elseif (strpos(trim($summary), "\n") !== false) {
1310
        } elseif (strpos(trim($summary), "\n") !== false) {
1311
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
1311
            $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
1312
                array('summary' => $summary));
1312
                array('summary' => $summary));
1313
        }
1313
        }
1314
        $this->_channelInfo['summary'] = $summary;
1314
        $this->_channelInfo['summary'] = $summary;
1315
        return true;
1315
        return true;
1316
    }
1316
    }
1317
1317
1318
    /**
1318
    /**
1319
     * @param string
1319
     * @param string
1320
     * @param boolean determines whether the alias is in channel.xml or local
1320
     * @param boolean determines whether the alias is in channel.xml or local
1321
     * @return boolean success
1321
     * @return boolean success
1322
     */
1322
     */
1323
    function setAlias($alias, $local = false)
1323
    function setAlias($alias, $local = false)
1324
    {
1324
    {
1325
        if (!$this->validChannelServer($alias)) {
1325
        if (!$this->validChannelServer($alias)) {
1326
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
1326
            $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
1327
                array('tag' => 'suggestedalias', 'name' => $alias));
1327
                array('tag' => 'suggestedalias', 'name' => $alias));
1328
            return false;
1328
            return false;
1329
        }
1329
        }
1330
        if ($local) {
1330
        if ($local) {
1331
            $this->_channelInfo['localalias'] = $alias;
1331
            $this->_channelInfo['localalias'] = $alias;
1332
        } else {
1332
        } else {
1333
            $this->_channelInfo['suggestedalias'] = $alias;
1333
            $this->_channelInfo['suggestedalias'] = $alias;
1334
        }
1334
        }
1335
        return true;
1335
        return true;
1336
    }
1336
    }
1337
1337
1338
    /**
1338
    /**
1339
     * @return string
1339
     * @return string
1340
     */
1340
     */
1341
    function getAlias()
1341
    function getAlias()
1342
    {
1342
    {
1343
        if (isset($this->_channelInfo['localalias'])) {
1343
        if (isset($this->_channelInfo['localalias'])) {
1344
            return $this->_channelInfo['localalias'];
1344
            return $this->_channelInfo['localalias'];
1345
        }
1345
        }
1346
        if (isset($this->_channelInfo['suggestedalias'])) {
1346
        if (isset($this->_channelInfo['suggestedalias'])) {
1347
            return $this->_channelInfo['suggestedalias'];
1347
            return $this->_channelInfo['suggestedalias'];
1348
        }
1348
        }
1349
        if (isset($this->_channelInfo['name'])) {
1349
        if (isset($this->_channelInfo['name'])) {
1350
            return $this->_channelInfo['name'];
1350
            return $this->_channelInfo['name'];
1351
        }
1351
        }
1352
        return '';
1352
        return '';
1353
    }
1353
    }
1354
1354
1355
    /**
1355
    /**
1356
     * Set the package validation object if it differs from PEAR's default
1356
     * Set the package validation object if it differs from PEAR's default
1357
     * The class must be includeable via changing _ in the classname to path separator,
1357
     * The class must be includeable via changing _ in the classname to path separator,
1358
     * but no checking of this is made.
1358
     * but no checking of this is made.
1359
     * @param string|false pass in false to reset to the default packagename regex
1359
     * @param string|false pass in false to reset to the default packagename regex
1360
     * @return boolean success
1360
     * @return boolean success
1361
     */
1361
     */
1362
    function setValidationPackage($validateclass, $version)
1362
    function setValidationPackage($validateclass, $version)
1363
    {
1363
    {
1364
        if (empty($validateclass)) {
1364
        if (empty($validateclass)) {
1365
            unset($this->_channelInfo['validatepackage']);
1365
            unset($this->_channelInfo['validatepackage']);
1366
        }
1366
        }
1367
        $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
1367
        $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
1368
        $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
1368
        $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
1369
    }
1369
    }
1370
1370
1371
    /**
1371
    /**
1372
     * Add a protocol to the provides section
1372
     * Add a protocol to the provides section
1373
     * @param string protocol type
1373
     * @param string protocol type
1374
     * @param string protocol version
1374
     * @param string protocol version
1375
     * @param string protocol name, if any
1375
     * @param string protocol name, if any
1376
     * @param string mirror name, if this is a mirror's protocol
1376
     * @param string mirror name, if this is a mirror's protocol
1377
     * @return bool
1377
     * @return bool
1378
     */
1378
     */
1379
    function addFunction($type, $version, $name = '', $mirror = false)
1379
    function addFunction($type, $version, $name = '', $mirror = false)
1380
    {
1380
    {
1381
        if ($mirror) {
1381
        if ($mirror) {
1382
            return $this->addMirrorFunction($mirror, $type, $version, $name);
1382
            return $this->addMirrorFunction($mirror, $type, $version, $name);
1383
        }
1383
        }
1384
        $set = array('attribs' => array('version' => $version), '_content' => $name);
1384
        $set = array('attribs' => array('version' => $version), '_content' => $name);
1385
        if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
1385
        if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
1386
            if (!isset($this->_channelInfo['servers'])) {
1386
            if (!isset($this->_channelInfo['servers'])) {
1387
                $this->_channelInfo['servers'] = array('primary' =>
1387
                $this->_channelInfo['servers'] = array('primary' =>
1388
                    array($type => array()));
1388
                    array($type => array()));
1389
            } elseif (!isset($this->_channelInfo['servers']['primary'])) {
1389
            } elseif (!isset($this->_channelInfo['servers']['primary'])) {
1390
                $this->_channelInfo['servers']['primary'] = array($type => array());
1390
                $this->_channelInfo['servers']['primary'] = array($type => array());
1391
            }
1391
            }
1392
            $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
1392
            $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
1393
            $this->_isValid = false;
1393
            $this->_isValid = false;
1394
            return true;
1394
            return true;
1395
        } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
1395
        } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
1396
            $this->_channelInfo['servers']['primary'][$type]['function'] = array(
1396
            $this->_channelInfo['servers']['primary'][$type]['function'] = array(
1397
                $this->_channelInfo['servers']['primary'][$type]['function']);
1397
                $this->_channelInfo['servers']['primary'][$type]['function']);
1398
        }
1398
        }
1399
        $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
1399
        $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
1400
        return true;
1400
        return true;
1401
    }
1401
    }
1402
    /**
1402
    /**
1403
     * Add a protocol to a mirror's provides section
1403
     * Add a protocol to a mirror's provides section
1404
     * @param string mirror name (server)
1404
     * @param string mirror name (server)
1405
     * @param string protocol type
1405
     * @param string protocol type
1406
     * @param string protocol version
1406
     * @param string protocol version
1407
     * @param string protocol name, if any
1407
     * @param string protocol name, if any
1408
     */
1408
     */
1409
    function addMirrorFunction($mirror, $type, $version, $name = '')
1409
    function addMirrorFunction($mirror, $type, $version, $name = '')
1410
    {
1410
    {
1411
        if (!isset($this->_channelInfo['servers']['mirror'])) {
1411
        if (!isset($this->_channelInfo['servers']['mirror'])) {
1412
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1412
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1413
                array('mirror' => $mirror));
1413
                array('mirror' => $mirror));
1414
            return false;
1414
            return false;
1415
        }
1415
        }
1416
        $setmirror = false;
1416
        $setmirror = false;
1417
        if (isset($this->_channelInfo['servers']['mirror'][0])) {
1417
        if (isset($this->_channelInfo['servers']['mirror'][0])) {
1418
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1418
            foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1419
                if ($mirror == $mir['attribs']['host']) {
1419
                if ($mirror == $mir['attribs']['host']) {
1420
                    $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
1420
                    $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
1421
                    break;
1421
                    break;
1422
                }
1422
                }
1423
            }
1423
            }
1424
        } else {
1424
        } else {
1425
            if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1425
            if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1426
                $setmirror = &$this->_channelInfo['servers']['mirror'];
1426
                $setmirror = &$this->_channelInfo['servers']['mirror'];
1427
            }
1427
            }
1428
        }
1428
        }
1429
        if (!$setmirror) {
1429
        if (!$setmirror) {
1430
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1430
            $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1431
                array('mirror' => $mirror));
1431
                array('mirror' => $mirror));
1432
            return false;
1432
            return false;
1433
        }
1433
        }
1434
        $set = array('attribs' => array('version' => $version), '_content' => $name);
1434
        $set = array('attribs' => array('version' => $version), '_content' => $name);
1435
        if (!isset($setmirror[$type]['function'])) {
1435
        if (!isset($setmirror[$type]['function'])) {
1436
            $setmirror[$type]['function'] = $set;
1436
            $setmirror[$type]['function'] = $set;
1437
            $this->_isValid = false;
1437
            $this->_isValid = false;
1438
            return true;
1438
            return true;
1439
        } elseif (!isset($setmirror[$type]['function'][0])) {
1439
        } elseif (!isset($setmirror[$type]['function'][0])) {
1440
            $setmirror[$type]['function'] = array($setmirror[$type]['function']);
1440
            $setmirror[$type]['function'] = array($setmirror[$type]['function']);
1441
        }
1441
        }
1442
        $setmirror[$type]['function'][] = $set;
1442
        $setmirror[$type]['function'][] = $set;
1443
        $this->_isValid = false;
1443
        $this->_isValid = false;
1444
        return true;
1444
        return true;
1445
    }
1445
    }
1446
1446
1447
    /**
1447
    /**
1448
     * @param string Resource Type this url links to
1448
     * @param string Resource Type this url links to
1449
     * @param string URL
1449
     * @param string URL
1450
     * @param string|false mirror name, if this is not a primary server REST base URL
1450
     * @param string|false mirror name, if this is not a primary server REST base URL
1451
     */
1451
     */
1452
    function setBaseURL($resourceType, $url, $mirror = false)
1452
    function setBaseURL($resourceType, $url, $mirror = false)
1453
    {
1453
    {
1454
        if ($mirror) {
1454
        if ($mirror) {
1455
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1455
            if (!isset($this->_channelInfo['servers']['mirror'])) {
1456
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1456
                $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
1457
                    array('mirror' => $mirror));
1457
                    array('mirror' => $mirror));
1458
                return false;
1458
                return false;
1459
            }
1459
            }
1460
            $setmirror = false;
1460
            $setmirror = false;
1461
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1461
            if (isset($this->_channelInfo['servers']['mirror'][0])) {
1462
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1462
                foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
1463
                    if ($mirror == $mir['attribs']['host']) {
1463
                    if ($mirror == $mir['attribs']['host']) {
1464
                        $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
1464
                        $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
1465
                        break;
1465
                        break;
1466
                    }
1466
                    }
1467
                }
1467
                }
1468
            } else {
1468
            } else {
1469
                if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1469
                if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
1470
                    $setmirror = &$this->_channelInfo['servers']['mirror'];
1470
                    $setmirror = &$this->_channelInfo['servers']['mirror'];
1471
                }
1471
                }
1472
            }
1472
            }
1473
        } else {
1473
        } else {
1474
            $setmirror = &$this->_channelInfo['servers']['primary'];
1474
            $setmirror = &$this->_channelInfo['servers']['primary'];
1475
        }
1475
        }
1476
        $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
1476
        $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
1477
        if (!isset($setmirror['rest'])) {
1477
        if (!isset($setmirror['rest'])) {
1478
            $setmirror['rest'] = array();
1478
            $setmirror['rest'] = array();
1479
        }
1479
        }
1480
        if (!isset($setmirror['rest']['baseurl'])) {
1480
        if (!isset($setmirror['rest']['baseurl'])) {
1481
            $setmirror['rest']['baseurl'] = $set;
1481
            $setmirror['rest']['baseurl'] = $set;
1482
            $this->_isValid = false;
1482
            $this->_isValid = false;
1483
            return true;
1483
            return true;
1484
        } elseif (!isset($setmirror['rest']['baseurl'][0])) {
1484
        } elseif (!isset($setmirror['rest']['baseurl'][0])) {
1485
            $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
1485
            $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
1486
        }
1486
        }
1487
        foreach ($setmirror['rest']['baseurl'] as $i => $url) {
1487
        foreach ($setmirror['rest']['baseurl'] as $i => $url) {
1488
            if ($url['attribs']['type'] == $resourceType) {
1488
            if ($url['attribs']['type'] == $resourceType) {
1489
                $this->_isValid = false;
1489
                $this->_isValid = false;
1490
                $setmirror['rest']['baseurl'][$i] = $set;
1490
                $setmirror['rest']['baseurl'][$i] = $set;
1491
                return true;
1491
                return true;
1492
            }
1492
            }
1493
        }
1493
        }
1494
        $setmirror['rest']['baseurl'][] = $set;
1494
        $setmirror['rest']['baseurl'][] = $set;
1495
        $this->_isValid = false;
1495
        $this->_isValid = false;
1496
        return true;
1496
        return true;
1497
    }
1497
    }
1498
1498
1499
    /**
1499
    /**
1500
     * @param string mirror server
1500
     * @param string mirror server
1501
     * @param int mirror http port
1501
     * @param int mirror http port
1502
     * @return boolean
1502
     * @return boolean
1503
     */
1503
     */
1504
    function addMirror($server, $port = null)
1504
    function addMirror($server, $port = null)
1505
    {
1505
    {
1506
        if ($this->_channelInfo['name'] == '__uri') {
1506
        if ($this->_channelInfo['name'] == '__uri') {
1507
            return false; // the __uri channel cannot have mirrors by definition
1507
            return false; // the __uri channel cannot have mirrors by definition
1508
        }
1508
        }
1509
        $set = array('attribs' => array('host' => $server));
1509
        $set = array('attribs' => array('host' => $server));
1510
        if (is_numeric($port)) {
1510
        if (is_numeric($port)) {
1511
            $set['attribs']['port'] = $port;
1511
            $set['attribs']['port'] = $port;
1512
        }
1512
        }
1513
        if (!isset($this->_channelInfo['servers']['mirror'])) {
1513
        if (!isset($this->_channelInfo['servers']['mirror'])) {
1514
            $this->_channelInfo['servers']['mirror'] = $set;
1514
            $this->_channelInfo['servers']['mirror'] = $set;
1515
            return true;
1515
            return true;
1516
        } else {
1516
        } else {
1517
            if (!isset($this->_channelInfo['servers']['mirror'][0])) {
1517
            if (!isset($this->_channelInfo['servers']['mirror'][0])) {
1518
                $this->_channelInfo['servers']['mirror'] =
1518
                $this->_channelInfo['servers']['mirror'] =
1519
                    array($this->_channelInfo['servers']['mirror']);
1519
                    array($this->_channelInfo['servers']['mirror']);
1520
            }
1520
            }
1521
        }
1521
        }
1522
        $this->_channelInfo['servers']['mirror'][] = $set;
1522
        $this->_channelInfo['servers']['mirror'][] = $set;
1523
        return true;
1523
        return true;
1524
    }
1524
    }
1525
1525
1526
    /**
1526
    /**
1527
     * Retrieve the name of the validation package for this channel
1527
     * Retrieve the name of the validation package for this channel
1528
     * @return string|false
1528
     * @return string|false
1529
     */
1529
     */
1530
    function getValidationPackage()
1530
    function getValidationPackage()
1531
    {
1531
    {
1532
        if (!$this->_isValid && !$this->validate()) {
1532
        if (!$this->_isValid && !$this->validate()) {
1533
            return false;
1533
            return false;
1534
        }
1534
        }
1535
        if (!isset($this->_channelInfo['validatepackage'])) {
1535
        if (!isset($this->_channelInfo['validatepackage'])) {
1536
            return array('attribs' => array('version' => 'default'),
1536
            return array('attribs' => array('version' => 'default'),
1537
                '_content' => 'PEAR_Validate');
1537
                '_content' => 'PEAR_Validate');
1538
        }
1538
        }
1539
        return $this->_channelInfo['validatepackage'];
1539
        return $this->_channelInfo['validatepackage'];
1540
    }
1540
    }
1541
1541
1542
    /**
1542
    /**
1543
     * Retrieve the object that can be used for custom validation
1543
     * Retrieve the object that can be used for custom validation
1544
     * @param string|false the name of the package to validate.  If the package is
1544
     * @param string|false the name of the package to validate.  If the package is
1545
     *                     the channel validation package, PEAR_Validate is returned
1545
     *                     the channel validation package, PEAR_Validate is returned
1546
     * @return PEAR_Validate|false false is returned if the validation package
1546
     * @return PEAR_Validate|false false is returned if the validation package
1547
     *         cannot be located
1547
     *         cannot be located
1548
     */
1548
     */
1549
    function &getValidationObject($package = false)
1549
    function &getValidationObject($package = false)
1550
    {
1550
    {
1551
        if (!class_exists('PEAR_Validate')) {
1551
        if (!class_exists('PEAR_Validate')) {
1552
            require_once 'PEAR/Validate.php';
1552
            require_once 'PEAR/Validate.php';
1553
        }
1553
        }
1554
        if (!$this->_isValid) {
1554
        if (!$this->_isValid) {
1555
            if (!$this->validate()) {
1555
            if (!$this->validate()) {
1556
                $a = false;
1556
                $a = false;
1557
                return $a;
1557
                return $a;
1558
            }
1558
            }
1559
        }
1559
        }
1560
        if (isset($this->_channelInfo['validatepackage'])) {
1560
        if (isset($this->_channelInfo['validatepackage'])) {
1561
            if ($package == $this->_channelInfo['validatepackage']) {
1561
            if ($package == $this->_channelInfo['validatepackage']) {
1562
                // channel validation packages are always validated by PEAR_Validate
1562
                // channel validation packages are always validated by PEAR_Validate
1563
                $val = &new PEAR_Validate;
1563
                $val = &new PEAR_Validate;
1564
                return $val;
1564
                return $val;
1565
            }
1565
            }
1566
            if (!class_exists(str_replace('.', '_',
1566
            if (!class_exists(str_replace('.', '_',
1567
                  $this->_channelInfo['validatepackage']['_content']))) {
1567
                  $this->_channelInfo['validatepackage']['_content']))) {
1568
                if ($this->isIncludeable(str_replace('_', '/',
1568
                if ($this->isIncludeable(str_replace('_', '/',
1569
                      $this->_channelInfo['validatepackage']['_content']) . '.php')) {
1569
                      $this->_channelInfo['validatepackage']['_content']) . '.php')) {
1570
                    include_once str_replace('_', '/',
1570
                    include_once str_replace('_', '/',
1571
                        $this->_channelInfo['validatepackage']['_content']) . '.php';
1571
                        $this->_channelInfo['validatepackage']['_content']) . '.php';
1572
                    $vclass = str_replace('.', '_',
1572
                    $vclass = str_replace('.', '_',
1573
                        $this->_channelInfo['validatepackage']['_content']);
1573
                        $this->_channelInfo['validatepackage']['_content']);
1574
                    $val = &new $vclass;
1574
                    $val = &new $vclass;
1575
                } else {
1575
                } else {
1576
                    $a = false;
1576
                    $a = false;
1577
                    return $a;
1577
                    return $a;
1578
                }
1578
                }
1579
            } else {
1579
            } else {
1580
                $vclass = str_replace('.', '_',
1580
                $vclass = str_replace('.', '_',
1581
                    $this->_channelInfo['validatepackage']['_content']);
1581
                    $this->_channelInfo['validatepackage']['_content']);
1582
                $val = &new $vclass;
1582
                $val = &new $vclass;
1583
            }
1583
            }
1584
        } else {
1584
        } else {
1585
            $val = &new PEAR_Validate;
1585
            $val = &new PEAR_Validate;
1586
        }
1586
        }
1587
        return $val;
1587
        return $val;
1588
    }
1588
    }
1589
1589
1590
    function isIncludeable($path)
1590
    function isIncludeable($path)
1591
    {
1591
    {
1592
        $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
1592
        $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
1593
        foreach ($possibilities as $dir) {
1593
        foreach ($possibilities as $dir) {
1594
            if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
1594
            if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
1595
                  && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
1595
                  && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
1596
                return true;
1596
                return true;
1597
            }
1597
            }
1598
        }
1598
        }
1599
        return false;
1599
        return false;
1600
    }
1600
    }
1601
1601
1602
    /**
1602
    /**
1603
     * This function is used by the channel updater and retrieves a value set by
1603
     * This function is used by the channel updater and retrieves a value set by
1604
     * the registry, or the current time if it has not been set
1604
     * the registry, or the current time if it has not been set
1605
     * @return string
1605
     * @return string
1606
     */
1606
     */
1607
    function lastModified()
1607
    function lastModified()
1608
    {
1608
    {
1609
        if (isset($this->_channelInfo['_lastmodified'])) {
1609
        if (isset($this->_channelInfo['_lastmodified'])) {
1610
            return $this->_channelInfo['_lastmodified'];
1610
            return $this->_channelInfo['_lastmodified'];
1611
        }
1611
        }
1612
        return time();
1612
        return time();
1613
    }
1613
    }
1614
}
1614
}
1615
?>
1615
?>
1616
 
1616