Subversion Repositories Applications.gtt

Rev

Rev 94 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 94 Rev 187
1
<?php
1
<?php
2
//
2
/**
3
// +----------------------------------------------------------------------+
-
 
4
// | PHP Version 5                                                        |
-
 
5
// +----------------------------------------------------------------------+
-
 
6
// | Copyright (c) 1997-2004 The PHP Group                                |
-
 
7
// +----------------------------------------------------------------------+
-
 
8
// | This source file is subject to version 3.0 of the PHP license,       |
3
 * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
-
 
4
 *
9
// | that is bundled with this package in the file LICENSE, and is        |
5
 * PHP versions 4 and 5
-
 
6
 *
10
// | available through the world-wide-web at the following url:           |
7
 * @category   pear
11
// | http://www.php.net/license/3_0.txt.                                  |
8
 * @package    PEAR
12
// | If you did not receive a copy of the PHP license and are unable to   |
9
 * @author     Greg Beaver <cellog@php.net>
13
// | obtain it through the world-wide-web, please send a note to          |
10
 * @copyright  1997-2009 The Authors
14
// | license@php.net so we can mail you a copy immediately.               |
11
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
15
// +----------------------------------------------------------------------+
-
 
16
// | Author: Greg Beaver <cellog@php.net>                                 |
12
 * @link       http://pear.php.net/package/PEAR
17
// |                                                                      |
13
 * @since      File available since Release 1.4.0a8
18
// +----------------------------------------------------------------------+
-
 
19
//
14
 */
20
// $Id: Validator.php,v 1.97 2007/02/10 05:56:18 cellog Exp $
-
 
21
/**
15
/**
22
 * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
16
 * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
23
 * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
17
 * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
-
 
18
 * @category   pear
-
 
19
 * @package    PEAR
24
 * @author Greg Beaver <cellog@php.net>
20
 * @author     Greg Beaver <cellog@php.net>
-
 
21
 * @copyright  1997-2009 The Authors
-
 
22
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
-
 
23
 * @version    Release: 1.10.1
-
 
24
 * @link       http://pear.php.net/package/PEAR
-
 
25
 * @since      Class available since Release 1.4.0a8
25
 * @access private
26
 * @access private
26
 */
27
 */
27
class PEAR_PackageFile_v2_Validator
28
class PEAR_PackageFile_v2_Validator
28
{
29
{
29
    /**
30
    /**
30
     * @var array
31
     * @var array
31
     */
32
     */
32
    var $_packageInfo;
33
    var $_packageInfo;
33
    /**
34
    /**
34
     * @var PEAR_PackageFile_v2
35
     * @var PEAR_PackageFile_v2
35
     */
36
     */
36
    var $_pf;
37
    var $_pf;
37
    /**
38
    /**
38
     * @var PEAR_ErrorStack
39
     * @var PEAR_ErrorStack
39
     */
40
     */
40
    var $_stack;
41
    var $_stack;
41
    /**
42
    /**
42
     * @var int
43
     * @var int
43
     */
44
     */
44
    var $_isValid = 0;
45
    var $_isValid = 0;
45
    /**
46
    /**
46
     * @var int
47
     * @var int
47
     */
48
     */
48
    var $_filesValid = 0;
49
    var $_filesValid = 0;
49
    /**
50
    /**
50
     * @var int
51
     * @var int
51
     */
52
     */
52
    var $_curState = 0;
53
    var $_curState = 0;
53
    /**
54
    /**
54
     * @param PEAR_PackageFile_v2
55
     * @param PEAR_PackageFile_v2
55
     * @param int
56
     * @param int
56
     */
57
     */
57
    function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
58
    function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
58
    {
59
    {
59
        $this->_pf = &$pf;
60
        $this->_pf = &$pf;
60
        $this->_curState = $state;
61
        $this->_curState = $state;
61
        $this->_packageInfo = $this->_pf->getArray();
62
        $this->_packageInfo = $this->_pf->getArray();
62
        $this->_isValid = $this->_pf->_isValid;
63
        $this->_isValid = $this->_pf->_isValid;
63
        $this->_filesValid = $this->_pf->_filesValid;
64
        $this->_filesValid = $this->_pf->_filesValid;
64
        $this->_stack = &$pf->_stack;
65
        $this->_stack = &$pf->_stack;
65
        $this->_stack->getErrors(true);
66
        $this->_stack->getErrors(true);
66
        if (($this->_isValid & $state) == $state) {
67
        if (($this->_isValid & $state) == $state) {
67
            return true;
68
            return true;
68
        }
69
        }
69
        if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
70
        if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
70
            return false;
71
            return false;
71
        }
72
        }
72
        if (!isset($this->_packageInfo['attribs']['version']) ||
73
        if (!isset($this->_packageInfo['attribs']['version']) ||
73
              ($this->_packageInfo['attribs']['version'] != '2.0' &&
74
              ($this->_packageInfo['attribs']['version'] != '2.0' &&
74
               $this->_packageInfo['attribs']['version'] != '2.1')) {
75
               $this->_packageInfo['attribs']['version'] != '2.1')
-
 
76
        ) {
75
            $this->_noPackageVersion();
77
            $this->_noPackageVersion();
76
        }
78
        }
77
        $structure =
79
        $structure =
78
        array(
80
        array(
79
            'name',
81
            'name',
80
            'channel|uri',
82
            'channel|uri',
81
            '*extends', // can't be multiple, but this works fine
83
            '*extends', // can't be multiple, but this works fine
82
            'summary',
84
            'summary',
83
            'description',
85
            'description',
84
            '+lead', // these all need content checks
86
            '+lead', // these all need content checks
85
            '*developer',
87
            '*developer',
86
            '*contributor',
88
            '*contributor',
87
            '*helper',
89
            '*helper',
88
            'date',
90
            'date',
89
            '*time',
91
            '*time',
90
            'version',
92
            'version',
91
            'stability',
93
            'stability',
92
            'license->?uri->?filesource',
94
            'license->?uri->?filesource',
93
            'notes',
95
            'notes',
94
            'contents', //special validation needed
96
            'contents', //special validation needed
95
            '*compatible',
97
            '*compatible',
96
            'dependencies', //special validation needed
98
            'dependencies', //special validation needed
97
            '*usesrole',
99
            '*usesrole',
98
            '*usestask', // reserve these for 1.4.0a1 to implement
100
            '*usestask', // reserve these for 1.4.0a1 to implement
99
                         // this will allow a package.xml to gracefully say it
101
                         // this will allow a package.xml to gracefully say it
100
                         // needs a certain package installed in order to implement a role or task
102
                         // needs a certain package installed in order to implement a role or task
101
            '*providesextension',
103
            '*providesextension',
102
            '*srcpackage|*srcuri',
104
            '*srcpackage|*srcuri',
103
            '+phprelease|+extsrcrelease|+extbinrelease|' .
105
            '+phprelease|+extsrcrelease|+extbinrelease|' .
104
                '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
106
                '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
105
            '*changelog',
107
            '*changelog',
106
        );
108
        );
107
        $test = $this->_packageInfo;
109
        $test = $this->_packageInfo;
108
        if (isset($test['dependencies']) &&
110
        if (isset($test['dependencies']) &&
109
              isset($test['dependencies']['required']) &&
111
              isset($test['dependencies']['required']) &&
110
              isset($test['dependencies']['required']['pearinstaller']) &&
112
              isset($test['dependencies']['required']['pearinstaller']) &&
111
              isset($test['dependencies']['required']['pearinstaller']['min']) &&
113
              isset($test['dependencies']['required']['pearinstaller']['min']) &&
-
 
114
              '1.10.1' != '@package' . '_version@' &&
112
              version_compare('1.5.1',
115
              version_compare('1.10.1',
113
                $test['dependencies']['required']['pearinstaller']['min'], '<')) {
116
                $test['dependencies']['required']['pearinstaller']['min'], '<')
-
 
117
        ) {
114
            $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
118
            $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
115
            return false;
119
            return false;
116
        }
120
        }
117
        // ignore post-installation array fields
121
        // ignore post-installation array fields
118
        if (array_key_exists('filelist', $test)) {
122
        if (array_key_exists('filelist', $test)) {
119
            unset($test['filelist']);
123
            unset($test['filelist']);
120
        }
124
        }
121
        if (array_key_exists('_lastmodified', $test)) {
125
        if (array_key_exists('_lastmodified', $test)) {
122
            unset($test['_lastmodified']);
126
            unset($test['_lastmodified']);
123
        }
127
        }
124
        if (array_key_exists('#binarypackage', $test)) {
128
        if (array_key_exists('#binarypackage', $test)) {
125
            unset($test['#binarypackage']);
129
            unset($test['#binarypackage']);
126
        }
130
        }
127
        if (array_key_exists('old', $test)) {
131
        if (array_key_exists('old', $test)) {
128
            unset($test['old']);
132
            unset($test['old']);
129
        }
133
        }
130
        if (array_key_exists('_lastversion', $test)) {
134
        if (array_key_exists('_lastversion', $test)) {
131
            unset($test['_lastversion']);
135
            unset($test['_lastversion']);
132
        }
136
        }
133
        if (!$this->_stupidSchemaValidate($structure,
137
        if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
134
                                          $test, '<package>')) {
-
 
135
            return false;
138
            return false;
136
        }
139
        }
137
        if (empty($this->_packageInfo['name'])) {
140
        if (empty($this->_packageInfo['name'])) {
138
            $this->_tagCannotBeEmpty('name');
141
            $this->_tagCannotBeEmpty('name');
139
        }
142
        }
140
        if (isset($this->_packageInfo['uri'])) {
143
        $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
141
            $test = 'uri';
-
 
142
        } else {
-
 
143
            $test = 'channel';
-
 
144
        }
-
 
145
        if (empty($this->_packageInfo[$test])) {
144
        if (empty($this->_packageInfo[$test])) {
146
            $this->_tagCannotBeEmpty($test);
145
            $this->_tagCannotBeEmpty($test);
147
        }
146
        }
148
        if (is_array($this->_packageInfo['license']) &&
147
        if (is_array($this->_packageInfo['license']) &&
149
              (!isset($this->_packageInfo['license']['_content']) ||
148
              (!isset($this->_packageInfo['license']['_content']) ||
150
              empty($this->_packageInfo['license']['_content']))) {
149
              empty($this->_packageInfo['license']['_content']))) {
151
            $this->_tagCannotBeEmpty('license');
150
            $this->_tagCannotBeEmpty('license');
152
        } elseif (empty($this->_packageInfo['license'])) {
151
        } elseif (empty($this->_packageInfo['license'])) {
153
            $this->_tagCannotBeEmpty('license');
152
            $this->_tagCannotBeEmpty('license');
154
        }
153
        }
155
        if (empty($this->_packageInfo['summary'])) {
154
        if (empty($this->_packageInfo['summary'])) {
156
            $this->_tagCannotBeEmpty('summary');
155
            $this->_tagCannotBeEmpty('summary');
157
        }
156
        }
158
        if (empty($this->_packageInfo['description'])) {
157
        if (empty($this->_packageInfo['description'])) {
159
            $this->_tagCannotBeEmpty('description');
158
            $this->_tagCannotBeEmpty('description');
160
        }
159
        }
161
        if (empty($this->_packageInfo['date'])) {
160
        if (empty($this->_packageInfo['date'])) {
162
            $this->_tagCannotBeEmpty('date');
161
            $this->_tagCannotBeEmpty('date');
163
        }
162
        }
164
        if (empty($this->_packageInfo['notes'])) {
163
        if (empty($this->_packageInfo['notes'])) {
165
            $this->_tagCannotBeEmpty('notes');
164
            $this->_tagCannotBeEmpty('notes');
166
        }
165
        }
167
        if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
166
        if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
168
            $this->_tagCannotBeEmpty('time');
167
            $this->_tagCannotBeEmpty('time');
169
        }
168
        }
170
        if (isset($this->_packageInfo['dependencies'])) {
169
        if (isset($this->_packageInfo['dependencies'])) {
171
            $this->_validateDependencies();
170
            $this->_validateDependencies();
172
        }
171
        }
173
        if (isset($this->_packageInfo['compatible'])) {
172
        if (isset($this->_packageInfo['compatible'])) {
174
            $this->_validateCompatible();
173
            $this->_validateCompatible();
175
        }
174
        }
176
        if (!isset($this->_packageInfo['bundle'])) {
175
        if (!isset($this->_packageInfo['bundle'])) {
177
            if (empty($this->_packageInfo['contents'])) {
176
            if (empty($this->_packageInfo['contents'])) {
178
                $this->_tagCannotBeEmpty('contents');
177
                $this->_tagCannotBeEmpty('contents');
179
            }
178
            }
180
            if (!isset($this->_packageInfo['contents']['dir'])) {
179
            if (!isset($this->_packageInfo['contents']['dir'])) {
181
                $this->_filelistMustContainDir('contents');
180
                $this->_filelistMustContainDir('contents');
182
                return false;
181
                return false;
183
            }
182
            }
184
            if (isset($this->_packageInfo['contents']['file'])) {
183
            if (isset($this->_packageInfo['contents']['file'])) {
185
                $this->_filelistCannotContainFile('contents');
184
                $this->_filelistCannotContainFile('contents');
186
                return false;
185
                return false;
187
            }
186
            }
188
        }
187
        }
189
        $this->_validateMaintainers();
188
        $this->_validateMaintainers();
190
        $this->_validateStabilityVersion();
189
        $this->_validateStabilityVersion();
191
        $fail = false;
190
        $fail = false;
192
        if (array_key_exists('usesrole', $this->_packageInfo)) {
191
        if (array_key_exists('usesrole', $this->_packageInfo)) {
193
            $roles = $this->_packageInfo['usesrole'];
192
            $roles = $this->_packageInfo['usesrole'];
194
            if (!is_array($roles) || !isset($roles[0])) {
193
            if (!is_array($roles) || !isset($roles[0])) {
195
                $roles = array($roles);
194
                $roles = array($roles);
196
            }
195
            }
197
            foreach ($roles as $role) {
196
            foreach ($roles as $role) {
198
                if (!isset($role['role'])) {
197
                if (!isset($role['role'])) {
199
                    $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
198
                    $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
200
                    $fail = true;
199
                    $fail = true;
201
                } else {
200
                } else {
202
                    if (!isset($role['channel'])) {
201
                    if (!isset($role['channel'])) {
203
                        if (!isset($role['uri'])) {
202
                        if (!isset($role['uri'])) {
204
                            $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
203
                            $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
205
                            $fail = true;
204
                            $fail = true;
206
                        }
205
                        }
207
                    } elseif (!isset($role['package'])) {
206
                    } elseif (!isset($role['package'])) {
208
                        $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
207
                        $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
209
                        $fail = true;
208
                        $fail = true;
210
                    }
209
                    }
211
                }
210
                }
212
            }
211
            }
213
        }
212
        }
214
        if (array_key_exists('usestask', $this->_packageInfo)) {
213
        if (array_key_exists('usestask', $this->_packageInfo)) {
215
            $roles = $this->_packageInfo['usestask'];
214
            $roles = $this->_packageInfo['usestask'];
216
            if (!is_array($roles) || !isset($roles[0])) {
215
            if (!is_array($roles) || !isset($roles[0])) {
217
                $roles = array($roles);
216
                $roles = array($roles);
218
            }
217
            }
219
            foreach ($roles as $role) {
218
            foreach ($roles as $role) {
220
                if (!isset($role['task'])) {
219
                if (!isset($role['task'])) {
221
                    $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
220
                    $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
222
                    $fail = true;
221
                    $fail = true;
223
                } else {
222
                } else {
224
                    if (!isset($role['channel'])) {
223
                    if (!isset($role['channel'])) {
225
                        if (!isset($role['uri'])) {
224
                        if (!isset($role['uri'])) {
226
                            $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
225
                            $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
227
                            $fail = true;
226
                            $fail = true;
228
                        }
227
                        }
229
                    } elseif (!isset($role['package'])) {
228
                    } elseif (!isset($role['package'])) {
230
                        $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
229
                        $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
231
                        $fail = true;
230
                        $fail = true;
232
                    }
231
                    }
233
                }
232
                }
234
            }
233
            }
235
        }
234
        }
-
 
235
 
236
        if ($fail) {
236
        if ($fail) {
237
            return false;
237
            return false;
238
        }
238
        }
-
 
239
 
239
        $list = $this->_packageInfo['contents'];
240
        $list = $this->_packageInfo['contents'];
240
        if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
241
        if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
241
            $this->_multipleToplevelDirNotAllowed();
242
            $this->_multipleToplevelDirNotAllowed();
242
            return $this->_isValid = 0;
243
            return $this->_isValid = 0;
243
        }
244
        }
-
 
245
 
244
        $this->_validateFilelist();
246
        $this->_validateFilelist();
245
        $this->_validateRelease();
247
        $this->_validateRelease();
246
        if (!$this->_stack->hasErrors()) {
248
        if (!$this->_stack->hasErrors()) {
247
            $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
249
            $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
248
            if (PEAR::isError($chan)) {
250
            if (PEAR::isError($chan)) {
249
                $this->_unknownChannel($this->_pf->getChannel());
251
                $this->_unknownChannel($this->_pf->getChannel());
250
            } else {
252
            } else {
251
                $valpack = $chan->getValidationPackage();
253
                $valpack = $chan->getValidationPackage();
252
                // for channel validator packages, always use the default PEAR validator.
254
                // for channel validator packages, always use the default PEAR validator.
253
                // otherwise, they can't be installed or packaged
255
                // otherwise, they can't be installed or packaged
254
                $validator = $chan->getValidationObject($this->_pf->getPackage());
256
                $validator = $chan->getValidationObject($this->_pf->getPackage());
255
                if (!$validator) {
257
                if (!$validator) {
256
                    $this->_stack->push(__FUNCTION__, 'error',
258
                    $this->_stack->push(__FUNCTION__, 'error',
257
                        array_merge(
-
 
258
                            array('channel' => $chan->getName(),
259
                        array('channel' => $chan->getName(),
259
                                  'package' => $this->_pf->getPackage()),
260
                              'package' => $this->_pf->getPackage(),
260
                              $valpack
261
                              'name'    => $valpack['_content'],
261
                            ),
262
                              'version' => $valpack['attribs']['version']),
262
                        'package "%channel%/%package%" cannot be properly validated without ' .
263
                        'package "%channel%/%package%" cannot be properly validated without ' .
263
                        'validation package "%channel%/%name%-%version%"');
264
                        'validation package "%channel%/%name%-%version%"');
264
                    return $this->_isValid = 0;
265
                    return $this->_isValid = 0;
265
                }
266
                }
266
                $validator->setPackageFile($this->_pf);
267
                $validator->setPackageFile($this->_pf);
267
                $validator->validate($state);
268
                $validator->validate($state);
268
                $failures = $validator->getFailures();
269
                $failures = $validator->getFailures();
269
                foreach ($failures['errors'] as $error) {
270
                foreach ($failures['errors'] as $error) {
270
                    $this->_stack->push(__FUNCTION__, 'error', $error,
271
                    $this->_stack->push(__FUNCTION__, 'error', $error,
271
                        'Channel validator error: field "%field%" - %reason%');
272
                        'Channel validator error: field "%field%" - %reason%');
272
                }
273
                }
273
                foreach ($failures['warnings'] as $warning) {
274
                foreach ($failures['warnings'] as $warning) {
274
                    $this->_stack->push(__FUNCTION__, 'warning', $warning,
275
                    $this->_stack->push(__FUNCTION__, 'warning', $warning,
275
                        'Channel validator warning: field "%field%" - %reason%');
276
                        'Channel validator warning: field "%field%" - %reason%');
276
                }
277
                }
277
            }
278
            }
278
        }
279
        }
-
 
280
 
279
        $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
281
        $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
280
        if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
282
        if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
281
            if ($this->_pf->getPackageType() == 'bundle') {
283
            if ($this->_pf->getPackageType() == 'bundle') {
282
                if ($this->_analyzeBundledPackages()) {
284
                if ($this->_analyzeBundledPackages()) {
283
                    $this->_filesValid = $this->_pf->_filesValid = true;
285
                    $this->_filesValid = $this->_pf->_filesValid = true;
284
                } else {
286
                } else {
285
                    $this->_pf->_isValid = $this->_isValid = 0;
287
                    $this->_pf->_isValid = $this->_isValid = 0;
286
                }
288
                }
287
            } else {
289
            } else {
288
                if (!$this->_analyzePhpFiles()) {
290
                if (!$this->_analyzePhpFiles()) {
289
                    $this->_pf->_isValid = $this->_isValid = 0;
291
                    $this->_pf->_isValid = $this->_isValid = 0;
290
                } else {
292
                } else {
291
                    $this->_filesValid = $this->_pf->_filesValid = true;
293
                    $this->_filesValid = $this->_pf->_filesValid = true;
292
                }
294
                }
293
            }
295
            }
294
        }
296
        }
-
 
297
 
295
        if ($this->_isValid) {
298
        if ($this->_isValid) {
296
            return $this->_pf->_isValid = $this->_isValid = $state;
299
            return $this->_pf->_isValid = $this->_isValid = $state;
297
        }
300
        }
-
 
301
 
298
        return $this->_pf->_isValid = $this->_isValid = 0;
302
        return $this->_pf->_isValid = $this->_isValid = 0;
299
    }
303
    }
300
 
304
 
301
    function _stupidSchemaValidate($structure, $xml, $root)
305
    function _stupidSchemaValidate($structure, $xml, $root)
302
    {
306
    {
303
        if (!is_array($xml)) {
307
        if (!is_array($xml)) {
304
            $xml = array();
308
            $xml = array();
305
        }
309
        }
306
        $keys = array_keys($xml);
310
        $keys = array_keys($xml);
307
        reset($keys);
311
        reset($keys);
308
        $key = current($keys);
312
        $key = current($keys);
309
        while ($key == 'attribs' || $key == '_contents') {
313
        while ($key == 'attribs' || $key == '_contents') {
310
            $key = next($keys);
314
            $key = next($keys);
311
        }
315
        }
312
        $unfoundtags = $optionaltags = array();
316
        $unfoundtags = $optionaltags = array();
313
        $ret = true;
317
        $ret = true;
314
        $mismatch = false;
318
        $mismatch = false;
315
        foreach ($structure as $struc) {
319
        foreach ($structure as $struc) {
316
            if ($key) {
320
            if ($key) {
317
                $tag = $xml[$key];
321
                $tag = $xml[$key];
318
            }
322
            }
319
            $test = $this->_processStructure($struc);
323
            $test = $this->_processStructure($struc);
320
            if (isset($test['choices'])) {
324
            if (isset($test['choices'])) {
321
                $loose = true;
325
                $loose = true;
322
                foreach ($test['choices'] as $choice) {
326
                foreach ($test['choices'] as $choice) {
323
                    if ($key == $choice['tag']) {
327
                    if ($key == $choice['tag']) {
324
                        $key = next($keys);
328
                        $key = next($keys);
325
                        while ($key == 'attribs' || $key == '_contents') {
329
                        while ($key == 'attribs' || $key == '_contents') {
326
                            $key = next($keys);
330
                            $key = next($keys);
327
                        }
331
                        }
328
                        $unfoundtags = $optionaltags = array();
332
                        $unfoundtags = $optionaltags = array();
329
                        $mismatch = false;
333
                        $mismatch = false;
330
                        if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
334
                        if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
331
                            $unfoundtags[] = $choice['tag'];
335
                            $unfoundtags[] = $choice['tag'];
332
                            $optionaltags[] = $choice['tag'];
336
                            $optionaltags[] = $choice['tag'];
333
                            if ($key) {
337
                            if ($key) {
334
                                $mismatch = true;
338
                                $mismatch = true;
335
                            }
339
                            }
336
                        }
340
                        }
337
                        $ret &= $this->_processAttribs($choice, $tag, $root);
341
                        $ret &= $this->_processAttribs($choice, $tag, $root);
338
                        continue 2;
342
                        continue 2;
339
                    } else {
343
                    } else {
340
                        $unfoundtags[] = $choice['tag'];
344
                        $unfoundtags[] = $choice['tag'];
341
                        $mismatch = true;
345
                        $mismatch = true;
342
                    }
346
                    }
343
                    if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
347
                    if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
344
                        $loose = false;
348
                        $loose = false;
345
                    } else {
349
                    } else {
346
                        $optionaltags[] = $choice['tag'];
350
                        $optionaltags[] = $choice['tag'];
347
                    }
351
                    }
348
                }
352
                }
349
                if (!$loose) {
353
                if (!$loose) {
350
                    $this->_invalidTagOrder($unfoundtags, $key, $root);
354
                    $this->_invalidTagOrder($unfoundtags, $key, $root);
351
                    return false;
355
                    return false;
352
                }
356
                }
353
            } else {
357
            } else {
354
                if ($key != $test['tag']) {
358
                if ($key != $test['tag']) {
355
                    if (isset($test['multiple']) && $test['multiple'] != '*') {
359
                    if (isset($test['multiple']) && $test['multiple'] != '*') {
356
                        $unfoundtags[] = $test['tag'];
360
                        $unfoundtags[] = $test['tag'];
357
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
361
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
358
                        return false;
362
                        return false;
359
                    } else {
363
                    } else {
360
                        if ($key) {
364
                        if ($key) {
361
                            $mismatch = true;
365
                            $mismatch = true;
362
                        }
366
                        }
363
                        $unfoundtags[] = $test['tag'];
367
                        $unfoundtags[] = $test['tag'];
364
                        $optionaltags[] = $test['tag'];
368
                        $optionaltags[] = $test['tag'];
365
                    }
369
                    }
366
                    if (!isset($test['multiple'])) {
370
                    if (!isset($test['multiple'])) {
367
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
371
                        $this->_invalidTagOrder($unfoundtags, $key, $root);
368
                        return false;
372
                        return false;
369
                    }
373
                    }
370
                    continue;
374
                    continue;
371
                } else {
375
                } else {
372
                    $unfoundtags = $optionaltags = array();
376
                    $unfoundtags = $optionaltags = array();
373
                    $mismatch = false;
377
                    $mismatch = false;
374
                }
378
                }
375
                $key = next($keys);
379
                $key = next($keys);
376
                while ($key == 'attribs' || $key == '_contents') {
380
                while ($key == 'attribs' || $key == '_contents') {
377
                    $key = next($keys);
381
                    $key = next($keys);
378
                }
382
                }
379
                if ($key && $key != $test['tag'] && isset($test['multiple'])) {
383
                if ($key && $key != $test['tag'] && isset($test['multiple'])) {
380
                    $unfoundtags[] = $test['tag'];
384
                    $unfoundtags[] = $test['tag'];
381
                    $optionaltags[] = $test['tag'];
385
                    $optionaltags[] = $test['tag'];
382
                    $mismatch = true;
386
                    $mismatch = true;
383
                }
387
                }
384
                $ret &= $this->_processAttribs($test, $tag, $root);
388
                $ret &= $this->_processAttribs($test, $tag, $root);
385
                continue;
389
                continue;
386
            }
390
            }
387
        }
391
        }
388
        if (!$mismatch && count($optionaltags)) {
392
        if (!$mismatch && count($optionaltags)) {
389
            // don't error out on any optional tags
393
            // don't error out on any optional tags
390
            $unfoundtags = array_diff($unfoundtags, $optionaltags);
394
            $unfoundtags = array_diff($unfoundtags, $optionaltags);
391
        }
395
        }
392
        if (count($unfoundtags)) {
396
        if (count($unfoundtags)) {
393
            $this->_invalidTagOrder($unfoundtags, $key, $root);
397
            $this->_invalidTagOrder($unfoundtags, $key, $root);
394
        } elseif ($key) {
398
        } elseif ($key) {
395
            // unknown tags
399
            // unknown tags
396
            $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
400
            $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
397
            while ($key = next($keys)) {
401
            while ($key = next($keys)) {
398
                $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
402
                $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
399
            }
403
            }
400
        }
404
        }
401
        return $ret;
405
        return $ret;
402
    }
406
    }
403
 
407
 
404
    function _processAttribs($choice, $tag, $context)
408
    function _processAttribs($choice, $tag, $context)
405
    {
409
    {
406
        if (isset($choice['attribs'])) {
410
        if (isset($choice['attribs'])) {
407
            if (!is_array($tag)) {
411
            if (!is_array($tag)) {
408
                $tag = array($tag);
412
                $tag = array($tag);
409
            }
413
            }
410
            $tags = $tag;
414
            $tags = $tag;
411
            if (!isset($tags[0])) {
415
            if (!isset($tags[0])) {
412
                $tags = array($tags);
416
                $tags = array($tags);
413
            }
417
            }
414
            $ret = true;
418
            $ret = true;
415
            foreach ($tags as $i => $tag) {
419
            foreach ($tags as $i => $tag) {
416
                if (!is_array($tag) || !isset($tag['attribs'])) {
420
                if (!is_array($tag) || !isset($tag['attribs'])) {
417
                    foreach ($choice['attribs'] as $attrib) {
421
                    foreach ($choice['attribs'] as $attrib) {
418
                        if ($attrib{0} != '?') {
422
                        if ($attrib{0} != '?') {
419
                            $ret &= $this->_tagHasNoAttribs($choice['tag'],
423
                            $ret &= $this->_tagHasNoAttribs($choice['tag'],
420
                                $context);
424
                                $context);
421
                            continue 2;
425
                            continue 2;
422
                        }
426
                        }
423
                    }
427
                    }
424
                }
428
                }
425
                foreach ($choice['attribs'] as $attrib) {
429
                foreach ($choice['attribs'] as $attrib) {
426
                    if ($attrib{0} != '?') {
430
                    if ($attrib{0} != '?') {
427
                        if (!isset($tag['attribs'][$attrib])) {
431
                        if (!isset($tag['attribs'][$attrib])) {
428
                            $ret &= $this->_tagMissingAttribute($choice['tag'],
432
                            $ret &= $this->_tagMissingAttribute($choice['tag'],
429
                                $attrib, $context);
433
                                $attrib, $context);
430
                        }
434
                        }
431
                    }
435
                    }
432
                }
436
                }
433
            }
437
            }
434
            return $ret;
438
            return $ret;
435
        }
439
        }
436
        return true;
440
        return true;
437
    }
441
    }
438
 
442
 
439
    function _processStructure($key)
443
    function _processStructure($key)
440
    {
444
    {
441
        $ret = array();
445
        $ret = array();
442
        if (count($pieces = explode('|', $key)) > 1) {
446
        if (count($pieces = explode('|', $key)) > 1) {
443
            $ret['choices'] = array();
447
            $ret['choices'] = array();
444
            foreach ($pieces as $piece) {
448
            foreach ($pieces as $piece) {
445
                $ret['choices'][] = $this->_processStructure($piece);
449
                $ret['choices'][] = $this->_processStructure($piece);
446
            }
450
            }
447
            return $ret;
451
            return $ret;
448
        }
452
        }
449
        $multi = $key{0};
453
        $multi = $key{0};
450
        if ($multi == '+' || $multi == '*') {
454
        if ($multi == '+' || $multi == '*') {
451
            $ret['multiple'] = $key{0};
455
            $ret['multiple'] = $key{0};
452
            $key = substr($key, 1);
456
            $key = substr($key, 1);
453
        }
457
        }
454
        if (count($attrs = explode('->', $key)) > 1) {
458
        if (count($attrs = explode('->', $key)) > 1) {
455
            $ret['tag'] = array_shift($attrs);
459
            $ret['tag'] = array_shift($attrs);
456
            $ret['attribs'] = $attrs;
460
            $ret['attribs'] = $attrs;
457
        } else {
461
        } else {
458
            $ret['tag'] = $key;
462
            $ret['tag'] = $key;
459
        }
463
        }
460
        return $ret;
464
        return $ret;
461
    }
465
    }
462
 
466
 
463
    function _validateStabilityVersion()
467
    function _validateStabilityVersion()
464
    {
468
    {
465
        $structure = array('release', 'api');
469
        $structure = array('release', 'api');
466
        $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
470
        $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
467
        $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
471
        $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
468
        if ($a) {
472
        if ($a) {
469
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
473
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
470
                  $this->_packageInfo['version']['release'])) {
474
                  $this->_packageInfo['version']['release'])) {
471
                $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
475
                $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
472
            }
476
            }
473
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
477
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
474
                  $this->_packageInfo['version']['api'])) {
478
                  $this->_packageInfo['version']['api'])) {
475
                $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
479
                $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
476
            }
480
            }
477
            if (!in_array($this->_packageInfo['stability']['release'],
481
            if (!in_array($this->_packageInfo['stability']['release'],
478
                  array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
482
                  array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
479
                $this->_invalidState('release', $this->_packageinfo['stability']['release']);
483
                $this->_invalidState('release', $this->_packageInfo['stability']['release']);
480
            }
484
            }
481
            if (!in_array($this->_packageInfo['stability']['api'],
485
            if (!in_array($this->_packageInfo['stability']['api'],
482
                  array('devel', 'alpha', 'beta', 'stable'))) {
486
                  array('devel', 'alpha', 'beta', 'stable'))) {
483
                $this->_invalidState('api', $this->_packageinfo['stability']['api']);
487
                $this->_invalidState('api', $this->_packageInfo['stability']['api']);
484
            }
488
            }
485
        }
489
        }
486
    }
490
    }
487
 
491
 
488
    function _validateMaintainers()
492
    function _validateMaintainers()
489
    {
493
    {
490
        $structure =
494
        $structure =
491
            array(
495
            array(
492
                'name',
496
                'name',
493
                'user',
497
                'user',
494
                'email',
498
                'email',
495
                'active',
499
                'active',
496
            );
500
            );
497
        foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
501
        foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
498
            if (!isset($this->_packageInfo[$type])) {
502
            if (!isset($this->_packageInfo[$type])) {
499
                continue;
503
                continue;
500
            }
504
            }
501
            if (isset($this->_packageInfo[$type][0])) {
505
            if (isset($this->_packageInfo[$type][0])) {
502
                foreach ($this->_packageInfo[$type] as $lead) {
506
                foreach ($this->_packageInfo[$type] as $lead) {
503
                    $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
507
                    $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
504
                }
508
                }
505
            } else {
509
            } else {
506
                $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
510
                $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
507
                    '<' . $type . '>');
511
                    '<' . $type . '>');
508
            }
512
            }
509
        }
513
        }
510
    }
514
    }
511
 
515
 
512
    function _validatePhpDep($dep, $installcondition = false)
516
    function _validatePhpDep($dep, $installcondition = false)
513
    {
517
    {
514
        $structure = array(
518
        $structure = array(
515
            'min',
519
            'min',
516
            '*max',
520
            '*max',
517
            '*exclude',
521
            '*exclude',
518
        );
522
        );
519
        $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
523
        $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
520
        $this->_stupidSchemaValidate($structure, $dep, $type);
524
        $this->_stupidSchemaValidate($structure, $dep, $type);
521
        if (isset($dep['min'])) {
525
        if (isset($dep['min'])) {
522
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
526
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
523
                  $dep['min'])) {
527
                  $dep['min'])) {
524
                $this->_invalidVersion($type . '<min>', $dep['min']);
528
                $this->_invalidVersion($type . '<min>', $dep['min']);
525
            }
529
            }
526
        }
530
        }
527
        if (isset($dep['max'])) {
531
        if (isset($dep['max'])) {
528
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
532
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
529
                  $dep['max'])) {
533
                  $dep['max'])) {
530
                $this->_invalidVersion($type . '<max>', $dep['max']);
534
                $this->_invalidVersion($type . '<max>', $dep['max']);
531
            }
535
            }
532
        }
536
        }
533
        if (isset($dep['exclude'])) {
537
        if (isset($dep['exclude'])) {
534
            if (!is_array($dep['exclude'])) {
538
            if (!is_array($dep['exclude'])) {
535
                $dep['exclude'] = array($dep['exclude']);
539
                $dep['exclude'] = array($dep['exclude']);
536
            }
540
            }
537
            foreach ($dep['exclude'] as $exclude) {
541
            foreach ($dep['exclude'] as $exclude) {
538
                if (!preg_match(
542
                if (!preg_match(
539
                     '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
543
                     '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
540
                     $exclude)) {
544
                     $exclude)) {
541
                    $this->_invalidVersion($type . '<exclude>', $exclude);
545
                    $this->_invalidVersion($type . '<exclude>', $exclude);
542
                }
546
                }
543
            }
547
            }
544
        }
548
        }
545
    }
549
    }
546
 
550
 
547
    function _validatePearinstallerDep($dep)
551
    function _validatePearinstallerDep($dep)
548
    {
552
    {
549
        $structure = array(
553
        $structure = array(
550
            'min',
554
            'min',
551
            '*max',
555
            '*max',
552
            '*recommended',
556
            '*recommended',
553
            '*exclude',
557
            '*exclude',
554
        );
558
        );
555
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
559
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
556
        if (isset($dep['min'])) {
560
        if (isset($dep['min'])) {
557
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
561
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
558
                  $dep['min'])) {
562
                  $dep['min'])) {
559
                $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
563
                $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
560
                    $dep['min']);
564
                    $dep['min']);
561
            }
565
            }
562
        }
566
        }
563
        if (isset($dep['max'])) {
567
        if (isset($dep['max'])) {
564
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
568
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
565
                  $dep['max'])) {
569
                  $dep['max'])) {
566
                $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
570
                $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
567
                    $dep['max']);
571
                    $dep['max']);
568
            }
572
            }
569
        }
573
        }
570
        if (isset($dep['recommended'])) {
574
        if (isset($dep['recommended'])) {
571
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
575
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
572
                  $dep['recommended'])) {
576
                  $dep['recommended'])) {
573
                $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
577
                $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
574
                    $dep['recommended']);
578
                    $dep['recommended']);
575
            }
579
            }
576
        }
580
        }
577
        if (isset($dep['exclude'])) {
581
        if (isset($dep['exclude'])) {
578
            if (!is_array($dep['exclude'])) {
582
            if (!is_array($dep['exclude'])) {
579
                $dep['exclude'] = array($dep['exclude']);
583
                $dep['exclude'] = array($dep['exclude']);
580
            }
584
            }
581
            foreach ($dep['exclude'] as $exclude) {
585
            foreach ($dep['exclude'] as $exclude) {
582
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
586
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
583
                      $exclude)) {
587
                      $exclude)) {
584
                    $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
588
                    $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
585
                        $exclude);
589
                        $exclude);
586
                }
590
                }
587
            }
591
            }
588
        }
592
        }
589
    }
593
    }
590
 
594
 
591
    function _validatePackageDep($dep, $group, $type = '<package>')
595
    function _validatePackageDep($dep, $group, $type = '<package>')
592
    {
596
    {
593
        if (isset($dep['uri'])) {
597
        if (isset($dep['uri'])) {
594
            if (isset($dep['conflicts'])) {
598
            if (isset($dep['conflicts'])) {
595
                $structure = array(
599
                $structure = array(
596
                    'name',
600
                    'name',
597
                    'uri',
601
                    'uri',
598
                    'conflicts',
602
                    'conflicts',
599
                    '*providesextension',
603
                    '*providesextension',
600
                );
604
                );
601
            } else {
605
            } else {
602
                $structure = array(
606
                $structure = array(
603
                    'name',
607
                    'name',
604
                    'uri',
608
                    'uri',
605
                    '*providesextension',
609
                    '*providesextension',
606
                );
610
                );
607
            }
611
            }
608
        } else {
612
        } else {
609
            if (isset($dep['conflicts'])) {
613
            if (isset($dep['conflicts'])) {
610
                $structure = array(
614
                $structure = array(
611
                    'name',
615
                    'name',
612
                    'channel',
616
                    'channel',
613
                    '*min',
617
                    '*min',
614
                    '*max',
618
                    '*max',
615
                    '*exclude',
619
                    '*exclude',
616
                    'conflicts',
620
                    'conflicts',
617
                    '*providesextension',
621
                    '*providesextension',
618
                );
622
                );
619
            } else {
623
            } else {
620
                $structure = array(
624
                $structure = array(
621
                    'name',
625
                    'name',
622
                    'channel',
626
                    'channel',
623
                    '*min',
627
                    '*min',
624
                    '*max',
628
                    '*max',
625
                    '*recommended',
629
                    '*recommended',
626
                    '*exclude',
630
                    '*exclude',
627
                    '*nodefault',
631
                    '*nodefault',
628
                    '*providesextension',
632
                    '*providesextension',
629
                );
633
                );
630
            }
634
            }
631
        }
635
        }
632
        if (isset($dep['name'])) {
636
        if (isset($dep['name'])) {
633
            $type .= '<name>' . $dep['name'] . '</name>';
637
            $type .= '<name>' . $dep['name'] . '</name>';
634
        }
638
        }
635
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
639
        $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
636
        if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
640
        if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
637
              isset($dep['recommended']) || isset($dep['exclude']))) {
641
              isset($dep['recommended']) || isset($dep['exclude']))) {
638
            $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
642
            $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
639
        }
643
        }
640
        if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
644
        if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
641
            $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
645
            $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
642
        }
646
        }
643
        if (isset($dep['min'])) {
647
        if (isset($dep['min'])) {
644
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
648
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
645
                  $dep['min'])) {
649
                  $dep['min'])) {
646
                $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
650
                $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
647
            }
651
            }
648
        }
652
        }
649
        if (isset($dep['max'])) {
653
        if (isset($dep['max'])) {
650
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
654
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
651
                  $dep['max'])) {
655
                  $dep['max'])) {
652
                $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
656
                $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
653
            }
657
            }
654
        }
658
        }
655
        if (isset($dep['recommended'])) {
659
        if (isset($dep['recommended'])) {
656
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
660
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
657
                  $dep['recommended'])) {
661
                  $dep['recommended'])) {
658
                $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
662
                $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
659
                    $dep['recommended']);
663
                    $dep['recommended']);
660
            }
664
            }
661
        }
665
        }
662
        if (isset($dep['exclude'])) {
666
        if (isset($dep['exclude'])) {
663
            if (!is_array($dep['exclude'])) {
667
            if (!is_array($dep['exclude'])) {
664
                $dep['exclude'] = array($dep['exclude']);
668
                $dep['exclude'] = array($dep['exclude']);
665
            }
669
            }
666
            foreach ($dep['exclude'] as $exclude) {
670
            foreach ($dep['exclude'] as $exclude) {
667
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
671
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
668
                      $exclude)) {
672
                      $exclude)) {
669
                    $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
673
                    $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
670
                        $exclude);
674
                        $exclude);
671
                }
675
                }
672
            }
676
            }
673
        }
677
        }
674
    }
678
    }
675
 
679
 
676
    function _validateSubpackageDep($dep, $group)
680
    function _validateSubpackageDep($dep, $group)
677
    {
681
    {
678
        $this->_validatePackageDep($dep, $group, '<subpackage>');
682
        $this->_validatePackageDep($dep, $group, '<subpackage>');
679
        if (isset($dep['providesextension'])) {
683
        if (isset($dep['providesextension'])) {
680
            $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
684
            $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
681
        }
685
        }
682
        if (isset($dep['conflicts'])) {
686
        if (isset($dep['conflicts'])) {
683
            $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
687
            $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
684
        }
688
        }
685
    }
689
    }
686
 
690
 
687
    function _validateExtensionDep($dep, $group = false, $installcondition = false)
691
    function _validateExtensionDep($dep, $group = false, $installcondition = false)
688
    {
692
    {
689
        if (isset($dep['conflicts'])) {
693
        if (isset($dep['conflicts'])) {
690
            $structure = array(
694
            $structure = array(
691
                'name',
695
                'name',
692
                '*min',
696
                '*min',
693
                '*max',
697
                '*max',
694
                '*exclude',
698
                '*exclude',
695
                'conflicts',
699
                'conflicts',
696
            );
700
            );
697
        } else {
701
        } else {
698
            $structure = array(
702
            $structure = array(
699
                'name',
703
                'name',
700
                '*min',
704
                '*min',
701
                '*max',
705
                '*max',
702
                '*recommended',
706
                '*recommended',
703
                '*exclude',
707
                '*exclude',
704
            );
708
            );
705
        }
709
        }
706
        if ($installcondition) {
710
        if ($installcondition) {
707
            $type = '<installcondition><extension>';
711
            $type = '<installcondition><extension>';
708
        } else {
712
        } else {
709
            $type = '<dependencies>' . $group . '<extension>';
713
            $type = '<dependencies>' . $group . '<extension>';
710
        }
714
        }
711
        if (isset($dep['name'])) {
715
        if (isset($dep['name'])) {
712
            $type .= '<name>' . $dep['name'] . '</name>';
716
            $type .= '<name>' . $dep['name'] . '</name>';
713
        }
717
        }
714
        $this->_stupidSchemaValidate($structure, $dep, $type);
718
        $this->_stupidSchemaValidate($structure, $dep, $type);
715
        if (isset($dep['min'])) {
719
        if (isset($dep['min'])) {
716
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
720
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
717
                  $dep['min'])) {
721
                  $dep['min'])) {
718
                $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
722
                $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
719
            }
723
            }
720
        }
724
        }
721
        if (isset($dep['max'])) {
725
        if (isset($dep['max'])) {
722
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
726
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
723
                  $dep['max'])) {
727
                  $dep['max'])) {
724
                $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
728
                $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
725
            }
729
            }
726
        }
730
        }
727
        if (isset($dep['recommended'])) {
731
        if (isset($dep['recommended'])) {
728
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
732
            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
729
                  $dep['recommended'])) {
733
                  $dep['recommended'])) {
730
                $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
734
                $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
731
            }
735
            }
732
        }
736
        }
733
        if (isset($dep['exclude'])) {
737
        if (isset($dep['exclude'])) {
734
            if (!is_array($dep['exclude'])) {
738
            if (!is_array($dep['exclude'])) {
735
                $dep['exclude'] = array($dep['exclude']);
739
                $dep['exclude'] = array($dep['exclude']);
736
            }
740
            }
737
            foreach ($dep['exclude'] as $exclude) {
741
            foreach ($dep['exclude'] as $exclude) {
738
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
742
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
739
                      $exclude)) {
743
                      $exclude)) {
740
                    $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
744
                    $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
741
                }
745
                }
742
            }
746
            }
743
        }
747
        }
744
    }
748
    }
745
 
749
 
746
    function _validateOsDep($dep, $installcondition = false)
750
    function _validateOsDep($dep, $installcondition = false)
747
    {
751
    {
748
        $structure = array(
752
        $structure = array(
749
            'name',
753
            'name',
750
            '*conflicts',
754
            '*conflicts',
751
        );
755
        );
752
        $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
756
        $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
753
        if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
757
        if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
754
            if ($dep['name'] == '*') {
758
            if ($dep['name'] == '*') {
755
                if (array_key_exists('conflicts', $dep)) {
759
                if (array_key_exists('conflicts', $dep)) {
756
                    $this->_cannotConflictWithAllOs($type);
760
                    $this->_cannotConflictWithAllOs($type);
757
                }
761
                }
758
            }
762
            }
759
        }
763
        }
760
    }
764
    }
761
 
765
 
762
    function _validateArchDep($dep, $installcondition = false)
766
    function _validateArchDep($dep, $installcondition = false)
763
    {
767
    {
764
        $structure = array(
768
        $structure = array(
765
            'pattern',
769
            'pattern',
766
            '*conflicts',
770
            '*conflicts',
767
        );
771
        );
768
        $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
772
        $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
769
        $this->_stupidSchemaValidate($structure, $dep, $type);
773
        $this->_stupidSchemaValidate($structure, $dep, $type);
770
    }
774
    }
771
 
775
 
772
    function _validateInstallConditions($cond, $release)
776
    function _validateInstallConditions($cond, $release)
773
    {
777
    {
774
        $structure = array(
778
        $structure = array(
775
            '*php',
779
            '*php',
776
            '*extension',
780
            '*extension',
777
            '*os',
781
            '*os',
778
            '*arch',
782
            '*arch',
779
        );
783
        );
780
        if (!$this->_stupidSchemaValidate($structure,
784
        if (!$this->_stupidSchemaValidate($structure,
781
              $cond, $release)) {
785
              $cond, $release)) {
782
            return false;
786
            return false;
783
        }
787
        }
784
        foreach (array('php', 'extension', 'os', 'arch') as $type) {
788
        foreach (array('php', 'extension', 'os', 'arch') as $type) {
785
            if (isset($cond[$type])) {
789
            if (isset($cond[$type])) {
786
                $iter = $cond[$type];
790
                $iter = $cond[$type];
787
                if (!is_array($iter) || !isset($iter[0])) {
791
                if (!is_array($iter) || !isset($iter[0])) {
788
                    $iter = array($iter);
792
                    $iter = array($iter);
789
                }
793
                }
790
                foreach ($iter as $package) {
794
                foreach ($iter as $package) {
791
                    if ($type == 'extension') {
795
                    if ($type == 'extension') {
792
                        $this->{"_validate{$type}Dep"}($package, false, true);
796
                        $this->{"_validate{$type}Dep"}($package, false, true);
793
                    } else {
797
                    } else {
794
                        $this->{"_validate{$type}Dep"}($package, true);
798
                        $this->{"_validate{$type}Dep"}($package, true);
795
                    }
799
                    }
796
                }
800
                }
797
            }
801
            }
798
        }
802
        }
799
    }
803
    }
800
 
804
 
801
    function _validateDependencies()
805
    function _validateDependencies()
802
    {
806
    {
803
        $structure = array(
807
        $structure = array(
804
            'required',
808
            'required',
805
            '*optional',
809
            '*optional',
806
            '*group->name->hint'
810
            '*group->name->hint'
807
        );
811
        );
808
        if (!$this->_stupidSchemaValidate($structure,
812
        if (!$this->_stupidSchemaValidate($structure,
809
              $this->_packageInfo['dependencies'], '<dependencies>')) {
813
              $this->_packageInfo['dependencies'], '<dependencies>')) {
810
            return false;
814
            return false;
811
        }
815
        }
812
        foreach (array('required', 'optional') as $simpledep) {
816
        foreach (array('required', 'optional') as $simpledep) {
813
            if (isset($this->_packageInfo['dependencies'][$simpledep])) {
817
            if (isset($this->_packageInfo['dependencies'][$simpledep])) {
814
                if ($simpledep == 'optional') {
818
                if ($simpledep == 'optional') {
815
                    $structure = array(
819
                    $structure = array(
816
                        '*package',
820
                        '*package',
817
                        '*subpackage',
821
                        '*subpackage',
818
                        '*extension',
822
                        '*extension',
819
                    );
823
                    );
820
                } else {
824
                } else {
821
                    $structure = array(
825
                    $structure = array(
822
                        'php',
826
                        'php',
823
                        'pearinstaller',
827
                        'pearinstaller',
824
                        '*package',
828
                        '*package',
825
                        '*subpackage',
829
                        '*subpackage',
826
                        '*extension',
830
                        '*extension',
827
                        '*os',
831
                        '*os',
828
                        '*arch',
832
                        '*arch',
829
                    );
833
                    );
830
                }
834
                }
831
                if ($this->_stupidSchemaValidate($structure,
835
                if ($this->_stupidSchemaValidate($structure,
832
                      $this->_packageInfo['dependencies'][$simpledep],
836
                      $this->_packageInfo['dependencies'][$simpledep],
833
                      "<dependencies><$simpledep>")) {
837
                      "<dependencies><$simpledep>")) {
834
                    foreach (array('package', 'subpackage', 'extension') as $type) {
838
                    foreach (array('package', 'subpackage', 'extension') as $type) {
835
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
839
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
836
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
840
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
837
                            if (!isset($iter[0])) {
841
                            if (!isset($iter[0])) {
838
                                $iter = array($iter);
842
                                $iter = array($iter);
839
                            }
843
                            }
840
                            foreach ($iter as $package) {
844
                            foreach ($iter as $package) {
841
                                if ($type != 'extension') {
845
                                if ($type != 'extension') {
842
                                    if (isset($package['uri'])) {
846
                                    if (isset($package['uri'])) {
843
                                        if (isset($package['channel'])) {
847
                                        if (isset($package['channel'])) {
844
                                            $this->_UrlOrChannel($type,
848
                                            $this->_UrlOrChannel($type,
845
                                                $package['name']);
849
                                                $package['name']);
846
                                        }
850
                                        }
847
                                    } else {
851
                                    } else {
848
                                        if (!isset($package['channel'])) {
852
                                        if (!isset($package['channel'])) {
849
                                            $this->_NoChannel($type, $package['name']);
853
                                            $this->_NoChannel($type, $package['name']);
850
                                        }
854
                                        }
851
                                    }
855
                                    }
852
                                }
856
                                }
853
                                $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
857
                                $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
854
                            }
858
                            }
855
                        }
859
                        }
856
                    }
860
                    }
857
                    if ($simpledep == 'optional') {
861
                    if ($simpledep == 'optional') {
858
                        continue;
862
                        continue;
859
                    }
863
                    }
860
                    foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
864
                    foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
861
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
865
                        if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
862
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
866
                            $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
863
                            if (!isset($iter[0])) {
867
                            if (!isset($iter[0])) {
864
                                $iter = array($iter);
868
                                $iter = array($iter);
865
                            }
869
                            }
866
                            foreach ($iter as $package) {
870
                            foreach ($iter as $package) {
867
                                $this->{"_validate{$type}Dep"}($package);
871
                                $this->{"_validate{$type}Dep"}($package);
868
                            }
872
                            }
869
                        }
873
                        }
870
                    }
874
                    }
871
                }
875
                }
872
            }
876
            }
873
        }
877
        }
874
        if (isset($this->_packageInfo['dependencies']['group'])) {
878
        if (isset($this->_packageInfo['dependencies']['group'])) {
875
            $groups = $this->_packageInfo['dependencies']['group'];
879
            $groups = $this->_packageInfo['dependencies']['group'];
876
            if (!isset($groups[0])) {
880
            if (!isset($groups[0])) {
877
                $groups = array($groups);
881
                $groups = array($groups);
878
            }
882
            }
879
            $structure = array(
883
            $structure = array(
880
                '*package',
884
                '*package',
881
                '*subpackage',
885
                '*subpackage',
882
                '*extension',
886
                '*extension',
883
            );
887
            );
884
            foreach ($groups as $group) {
888
            foreach ($groups as $group) {
885
                if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
889
                if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
886
                    if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
890
                    if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
887
                        $this->_invalidDepGroupName($group['attribs']['name']);
891
                        $this->_invalidDepGroupName($group['attribs']['name']);
888
                    }
892
                    }
889
                    foreach (array('package', 'subpackage', 'extension') as $type) {
893
                    foreach (array('package', 'subpackage', 'extension') as $type) {
890
                        if (isset($group[$type])) {
894
                        if (isset($group[$type])) {
891
                            $iter = $group[$type];
895
                            $iter = $group[$type];
892
                            if (!isset($iter[0])) {
896
                            if (!isset($iter[0])) {
893
                                $iter = array($iter);
897
                                $iter = array($iter);
894
                            }
898
                            }
895
                            foreach ($iter as $package) {
899
                            foreach ($iter as $package) {
896
                                if ($type != 'extension') {
900
                                if ($type != 'extension') {
897
                                    if (isset($package['uri'])) {
901
                                    if (isset($package['uri'])) {
898
                                        if (isset($package['channel'])) {
902
                                        if (isset($package['channel'])) {
899
                                            $this->_UrlOrChannelGroup($type,
903
                                            $this->_UrlOrChannelGroup($type,
900
                                                $package['name'],
904
                                                $package['name'],
901
                                                $group['name']);
905
                                                $group['name']);
902
                                        }
906
                                        }
903
                                    } else {
907
                                    } else {
904
                                        if (!isset($package['channel'])) {
908
                                        if (!isset($package['channel'])) {
905
                                            $this->_NoChannelGroup($type,
909
                                            $this->_NoChannelGroup($type,
906
                                                $package['name'],
910
                                                $package['name'],
907
                                                $group['name']);
911
                                                $group['name']);
908
                                        }
912
                                        }
909
                                    }
913
                                    }
910
                                }
914
                                }
911
                                $this->{"_validate{$type}Dep"}($package, '<group name="' .
915
                                $this->{"_validate{$type}Dep"}($package, '<group name="' .
912
                                    $group['attribs']['name'] . '">');
916
                                    $group['attribs']['name'] . '">');
913
                            }
917
                            }
914
                        }
918
                        }
915
                    }
919
                    }
916
                }
920
                }
917
            }
921
            }
918
        }
922
        }
919
    }
923
    }
920
 
924
 
921
    function _validateCompatible()
925
    function _validateCompatible()
922
    {
926
    {
923
        $compat = $this->_packageInfo['compatible'];
927
        $compat = $this->_packageInfo['compatible'];
924
        if (!isset($compat[0])) {
928
        if (!isset($compat[0])) {
925
            $compat = array($compat);
929
            $compat = array($compat);
926
        }
930
        }
927
        $required = array('name', 'channel', 'min', 'max', '*exclude');
931
        $required = array('name', 'channel', 'min', 'max', '*exclude');
928
        foreach ($compat as $package) {
932
        foreach ($compat as $package) {
929
            $type = '<compatible>';
933
            $type = '<compatible>';
930
            if (is_array($package) && array_key_exists('name', $package)) {
934
            if (is_array($package) && array_key_exists('name', $package)) {
931
                $type .= '<name>' . $package['name'] . '</name>';
935
                $type .= '<name>' . $package['name'] . '</name>';
932
            }
936
            }
933
            $this->_stupidSchemaValidate($required, $package, $type);
937
            $this->_stupidSchemaValidate($required, $package, $type);
934
            if (is_array($package) && array_key_exists('min', $package)) {
938
            if (is_array($package) && array_key_exists('min', $package)) {
935
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
939
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
936
                      $package['min'])) {
940
                      $package['min'])) {
937
                    $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
941
                    $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
938
                }
942
                }
939
            }
943
            }
940
            if (is_array($package) && array_key_exists('max', $package)) {
944
            if (is_array($package) && array_key_exists('max', $package)) {
941
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
945
                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
942
                      $package['max'])) {
946
                      $package['max'])) {
943
                    $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
947
                    $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
944
                }
948
                }
945
            }
949
            }
946
            if (is_array($package) && array_key_exists('exclude', $package)) {
950
            if (is_array($package) && array_key_exists('exclude', $package)) {
947
                if (!is_array($package['exclude'])) {
951
                if (!is_array($package['exclude'])) {
948
                    $package['exclude'] = array($package['exclude']);
952
                    $package['exclude'] = array($package['exclude']);
949
                }
953
                }
950
                foreach ($package['exclude'] as $exclude) {
954
                foreach ($package['exclude'] as $exclude) {
951
                    if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
955
                    if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
952
                          $exclude)) {
956
                          $exclude)) {
953
                        $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
957
                        $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
954
                    }
958
                    }
955
                }
959
                }
956
            }
960
            }
957
        }
961
        }
958
    }
962
    }
959
 
963
 
960
    function _validateBundle($list)
964
    function _validateBundle($list)
961
    {
965
    {
962
        if (!is_array($list) || !isset($list['bundledpackage'])) {
966
        if (!is_array($list) || !isset($list['bundledpackage'])) {
963
            return $this->_NoBundledPackages();
967
            return $this->_NoBundledPackages();
964
        }
968
        }
965
        if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
969
        if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
966
            return $this->_AtLeast2BundledPackages();
970
            return $this->_AtLeast2BundledPackages();
967
        }
971
        }
968
        foreach ($list['bundledpackage'] as $package) {
972
        foreach ($list['bundledpackage'] as $package) {
969
            if (!is_string($package)) {
973
            if (!is_string($package)) {
970
                $this->_bundledPackagesMustBeFilename();
974
                $this->_bundledPackagesMustBeFilename();
971
            }
975
            }
972
        }
976
        }
973
    }
977
    }
974
 
978
 
975
    function _validateFilelist($list = false, $allowignore = false, $dirs = '')
979
    function _validateFilelist($list = false, $allowignore = false, $dirs = '')
976
    {
980
    {
977
        $iscontents = false;
981
        $iscontents = false;
978
        if (!$list) {
982
        if (!$list) {
979
            $iscontents = true;
983
            $iscontents = true;
980
            $list = $this->_packageInfo['contents'];
984
            $list = $this->_packageInfo['contents'];
981
            if (isset($this->_packageInfo['bundle'])) {
985
            if (isset($this->_packageInfo['bundle'])) {
982
                return $this->_validateBundle($list);
986
                return $this->_validateBundle($list);
983
            }
987
            }
984
        }
988
        }
985
        if ($allowignore) {
989
        if ($allowignore) {
986
            $struc = array(
990
            $struc = array(
987
                '*install->name->as',
991
                '*install->name->as',
988
                '*ignore->name'
992
                '*ignore->name'
989
            );
993
            );
990
        } else {
994
        } else {
991
            $struc = array(
995
            $struc = array(
992
                '*dir->name->?baseinstalldir',
996
                '*dir->name->?baseinstalldir',
993
                '*file->name->role->?baseinstalldir->?md5sum'
997
                '*file->name->role->?baseinstalldir->?md5sum'
994
            );
998
            );
995
            if (isset($list['dir']) && isset($list['file'])) {
999
            if (isset($list['dir']) && isset($list['file'])) {
996
                // stave off validation errors without requiring a set order.
1000
                // stave off validation errors without requiring a set order.
997
                $_old = $list;
1001
                $_old = $list;
998
                if (isset($list['attribs'])) {
1002
                if (isset($list['attribs'])) {
999
                    $list = array('attribs' => $_old['attribs']);
1003
                    $list = array('attribs' => $_old['attribs']);
1000
                }
1004
                }
1001
                $list['dir'] = $_old['dir'];
1005
                $list['dir'] = $_old['dir'];
1002
                $list['file'] = $_old['file'];
1006
                $list['file'] = $_old['file'];
1003
            }
1007
            }
1004
        }
1008
        }
1005
        if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
1009
        if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
1006
            $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
1010
            $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
1007
            $dirname = $iscontents ? '<contents>' : $unknown;
1011
            $dirname = $iscontents ? '<contents>' : $unknown;
1008
        } else {
1012
        } else {
1009
            $dirname = '<dir name="' . $list['attribs']['name'] . '">';
1013
            $dirname = '<dir name="' . $list['attribs']['name'] . '">';
-
 
1014
            if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
-
 
1015
                          str_replace('\\', '/', $list['attribs']['name']))) {
-
 
1016
                // file contains .. parent directory or . cur directory
-
 
1017
                $this->_invalidDirName($list['attribs']['name']);
-
 
1018
            }
1010
        }
1019
        }
1011
        $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
1020
        $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
1012
        if ($allowignore && $res) {
1021
        if ($allowignore && $res) {
1013
            $ignored_or_installed = array();
1022
            $ignored_or_installed = array();
1014
            $this->_pf->getFilelist();
1023
            $this->_pf->getFilelist();
1015
            $fcontents = $this->_pf->getContents();
1024
            $fcontents = $this->_pf->getContents();
1016
            $filelist = array();
1025
            $filelist = array();
1017
            if (!isset($fcontents['dir']['file'][0])) {
1026
            if (!isset($fcontents['dir']['file'][0])) {
1018
                $fcontents['dir']['file'] = array($fcontents['dir']['file']);
1027
                $fcontents['dir']['file'] = array($fcontents['dir']['file']);
1019
            }
1028
            }
1020
            foreach ($fcontents['dir']['file'] as $file) {
1029
            foreach ($fcontents['dir']['file'] as $file) {
1021
                $filelist[$file['attribs']['name']] = true;
1030
                $filelist[$file['attribs']['name']] = true;
1022
            }
1031
            }
1023
            if (isset($list['install'])) {
1032
            if (isset($list['install'])) {
1024
                if (!isset($list['install'][0])) {
1033
                if (!isset($list['install'][0])) {
1025
                    $list['install'] = array($list['install']);
1034
                    $list['install'] = array($list['install']);
1026
                }
1035
                }
1027
                foreach ($list['install'] as $file) {
1036
                foreach ($list['install'] as $file) {
1028
                    if (!isset($filelist[$file['attribs']['name']])) {
1037
                    if (!isset($filelist[$file['attribs']['name']])) {
1029
                        $this->_notInContents($file['attribs']['name'], 'install');
1038
                        $this->_notInContents($file['attribs']['name'], 'install');
1030
                        continue;
1039
                        continue;
1031
                    }
1040
                    }
1032
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1041
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1033
                        $this->_multipleInstallAs($file['attribs']['name']);
1042
                        $this->_multipleInstallAs($file['attribs']['name']);
1034
                    }
1043
                    }
1035
                    if (!isset($ignored_or_installed[$file['attribs']['name']])) {
1044
                    if (!isset($ignored_or_installed[$file['attribs']['name']])) {
1036
                        $ignored_or_installed[$file['attribs']['name']] = array();
1045
                        $ignored_or_installed[$file['attribs']['name']] = array();
1037
                    }
1046
                    }
1038
                    $ignored_or_installed[$file['attribs']['name']][] = 1;
1047
                    $ignored_or_installed[$file['attribs']['name']][] = 1;
-
 
1048
                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
-
 
1049
                                  str_replace('\\', '/', $file['attribs']['as']))) {
-
 
1050
                        // file contains .. parent directory or . cur directory references
-
 
1051
                        $this->_invalidFileInstallAs($file['attribs']['name'],
-
 
1052
                            $file['attribs']['as']);
-
 
1053
                    }
1039
                }
1054
                }
1040
            }
1055
            }
1041
            if (isset($list['ignore'])) {
1056
            if (isset($list['ignore'])) {
1042
                if (!isset($list['ignore'][0])) {
1057
                if (!isset($list['ignore'][0])) {
1043
                    $list['ignore'] = array($list['ignore']);
1058
                    $list['ignore'] = array($list['ignore']);
1044
                }
1059
                }
1045
                foreach ($list['ignore'] as $file) {
1060
                foreach ($list['ignore'] as $file) {
1046
                    if (!isset($filelist[$file['attribs']['name']])) {
1061
                    if (!isset($filelist[$file['attribs']['name']])) {
1047
                        $this->_notInContents($file['attribs']['name'], 'ignore');
1062
                        $this->_notInContents($file['attribs']['name'], 'ignore');
1048
                        continue;
1063
                        continue;
1049
                    }
1064
                    }
1050
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1065
                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1051
                        $this->_ignoreAndInstallAs($file['attribs']['name']);
1066
                        $this->_ignoreAndInstallAs($file['attribs']['name']);
1052
                    }
1067
                    }
1053
                }
1068
                }
1054
            }
1069
            }
1055
        }
1070
        }
1056
        if (!$allowignore && isset($list['file'])) {
1071
        if (!$allowignore && isset($list['file'])) {
-
 
1072
            if (is_string($list['file'])) {
-
 
1073
                $this->_oldStyleFileNotAllowed();
-
 
1074
                return false;
-
 
1075
            }
1057
            if (!isset($list['file'][0])) {
1076
            if (!isset($list['file'][0])) {
1058
                // single file
1077
                // single file
1059
                $list['file'] = array($list['file']);
1078
                $list['file'] = array($list['file']);
1060
            }
1079
            }
1061
            foreach ($list['file'] as $i => $file)
1080
            foreach ($list['file'] as $i => $file)
1062
            {
1081
            {
1063
                if (isset($file['attribs']) && isset($file['attribs']['name']) &&
1082
                if (isset($file['attribs']) && isset($file['attribs']['name'])) {
1064
                      $file['attribs']['name']{0} == '.' &&
1083
                    if ($file['attribs']['name']{0} == '.' &&
1065
                        $file['attribs']['name']{1} == '/') {
1084
                          $file['attribs']['name']{1} == '/') {
1066
                    // name is something like "./doc/whatever.txt"
1085
                        // name is something like "./doc/whatever.txt"
-
 
1086
                        $this->_invalidFileName($file['attribs']['name'], $dirname);
-
 
1087
                    }
-
 
1088
                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
-
 
1089
                                  str_replace('\\', '/', $file['attribs']['name']))) {
-
 
1090
                        // file contains .. parent directory or . cur directory
1067
                    $this->_invalidFileName($file['attribs']['name']);
1091
                        $this->_invalidFileName($file['attribs']['name'], $dirname);
-
 
1092
                    }
1068
                }
1093
                }
1069
                if (isset($file['attribs']) && isset($file['attribs']['role'])) {
1094
                if (isset($file['attribs']) && isset($file['attribs']['role'])) {
1070
                    if (!$this->_validateRole($file['attribs']['role'])) {
1095
                    if (!$this->_validateRole($file['attribs']['role'])) {
1071
                        if (isset($this->_packageInfo['usesrole'])) {
1096
                        if (isset($this->_packageInfo['usesrole'])) {
1072
                            $roles = $this->_packageInfo['usesrole'];
1097
                            $roles = $this->_packageInfo['usesrole'];
1073
                            if (!isset($roles[0])) {
1098
                            if (!isset($roles[0])) {
1074
                                $roles = array($roles);
1099
                                $roles = array($roles);
1075
                            }
1100
                            }
1076
                            foreach ($roles as $role) {
1101
                            foreach ($roles as $role) {
1077
                                if ($role['role'] = $file['attribs']['role']) {
1102
                                if ($role['role'] = $file['attribs']['role']) {
1078
                                    $msg = 'This package contains role "%role%" and requires ' .
1103
                                    $msg = 'This package contains role "%role%" and requires ' .
1079
                                        'package "%package%" to be used';
1104
                                        'package "%package%" to be used';
1080
                                    if (isset($role['uri'])) {
1105
                                    if (isset($role['uri'])) {
1081
                                        $params = array('role' => $role['role'],
1106
                                        $params = array('role' => $role['role'],
1082
                                            'package' => $role['uri']);
1107
                                            'package' => $role['uri']);
1083
                                    } else {
1108
                                    } else {
1084
                                        $params = array('role' => $role['role'],
1109
                                        $params = array('role' => $role['role'],
1085
                                            'package' => $this->_pf->_registry->
1110
                                            'package' => $this->_pf->_registry->
1086
                                            parsedPackageNameToString(array('package' =>
1111
                                            parsedPackageNameToString(array('package' =>
1087
                                                $role['package'], 'channel' => $role['channel']),
1112
                                                $role['package'], 'channel' => $role['channel']),
1088
                                                true));
1113
                                                true));
1089
                                    }
1114
                                    }
1090
                                    $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
1115
                                    $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
1091
                                }
1116
                                }
1092
                            }
1117
                            }
1093
                        }
1118
                        }
1094
                        $this->_invalidFileRole($file['attribs']['name'],
1119
                        $this->_invalidFileRole($file['attribs']['name'],
1095
                            $dirname, $file['attribs']['role']);
1120
                            $dirname, $file['attribs']['role']);
1096
                    }
1121
                    }
1097
                }
1122
                }
1098
                if (!isset($file['attribs'])) {
1123
                if (!isset($file['attribs'])) {
1099
                    continue;
1124
                    continue;
1100
                }
1125
                }
1101
                $save = $file['attribs'];
1126
                $save = $file['attribs'];
1102
                if ($dirs) {
1127
                if ($dirs) {
1103
                    $save['name'] = $dirs . '/' . $save['name'];
1128
                    $save['name'] = $dirs . '/' . $save['name'];
1104
                }
1129
                }
1105
                unset($file['attribs']);
1130
                unset($file['attribs']);
1106
                if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
1131
                if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
1107
                    foreach ($file as $task => $value) {
1132
                    foreach ($file as $task => $value) {
1108
                        if ($tagClass = $this->_pf->getTask($task)) {
1133
                        if ($tagClass = $this->_pf->getTask($task)) {
1109
                            if (!is_array($value) || !isset($value[0])) {
1134
                            if (!is_array($value) || !isset($value[0])) {
1110
                                $value = array($value);
1135
                                $value = array($value);
1111
                            }
1136
                            }
1112
                            foreach ($value as $v) {
1137
                            foreach ($value as $v) {
1113
                                $ret = call_user_func(array($tagClass, 'validateXml'),
1138
                                $ret = call_user_func(array($tagClass, 'validateXml'),
1114
                                    $this->_pf, $v, $this->_pf->_config, $save);
1139
                                    $this->_pf, $v, $this->_pf->_config, $save);
1115
                                if (is_array($ret)) {
1140
                                if (is_array($ret)) {
1116
                                    $this->_invalidTask($task, $ret, isset($save['name']) ?
1141
                                    $this->_invalidTask($task, $ret, isset($save['name']) ?
1117
                                        $save['name'] : '');
1142
                                        $save['name'] : '');
1118
                                }
1143
                                }
1119
                            }
1144
                            }
1120
                        } else {
1145
                        } else {
1121
                            if (isset($this->_packageInfo['usestask'])) {
1146
                            if (isset($this->_packageInfo['usestask'])) {
1122
                                $roles = $this->_packageInfo['usestask'];
1147
                                $roles = $this->_packageInfo['usestask'];
1123
                                if (!isset($roles[0])) {
1148
                                if (!isset($roles[0])) {
1124
                                    $roles = array($roles);
1149
                                    $roles = array($roles);
1125
                                }
1150
                                }
1126
                                foreach ($roles as $role) {
1151
                                foreach ($roles as $role) {
1127
                                    if ($role['task'] = $task) {
1152
                                    if ($role['task'] = $task) {
1128
                                        $msg = 'This package contains task "%task%" and requires ' .
1153
                                        $msg = 'This package contains task "%task%" and requires ' .
1129
                                            'package "%package%" to be used';
1154
                                            'package "%package%" to be used';
1130
                                        if (isset($role['uri'])) {
1155
                                        if (isset($role['uri'])) {
1131
                                            $params = array('task' => $role['task'],
1156
                                            $params = array('task' => $role['task'],
1132
                                                'package' => $role['uri']);
1157
                                                'package' => $role['uri']);
1133
                                        } else {
1158
                                        } else {
1134
                                            $params = array('task' => $role['task'],
1159
                                            $params = array('task' => $role['task'],
1135
                                                'package' => $this->_pf->_registry->
1160
                                                'package' => $this->_pf->_registry->
1136
                                                parsedPackageNameToString(array('package' =>
1161
                                                parsedPackageNameToString(array('package' =>
1137
                                                    $role['package'], 'channel' => $role['channel']),
1162
                                                    $role['package'], 'channel' => $role['channel']),
1138
                                                    true));
1163
                                                    true));
1139
                                        }
1164
                                        }
1140
                                        $this->_stack->push('_mustInstallTask', 'error',
1165
                                        $this->_stack->push('_mustInstallTask', 'error',
1141
                                            $params, $msg);
1166
                                            $params, $msg);
1142
                                    }
1167
                                    }
1143
                                }
1168
                                }
1144
                            }
1169
                            }
1145
                            $this->_unknownTask($task, $save['name']);
1170
                            $this->_unknownTask($task, $save['name']);
1146
                        }
1171
                        }
1147
                    }
1172
                    }
1148
                }
1173
                }
1149
            }
1174
            }
1150
        }
1175
        }
1151
        if (isset($list['ignore'])) {
1176
        if (isset($list['ignore'])) {
1152
            if (!$allowignore) {
1177
            if (!$allowignore) {
1153
                $this->_ignoreNotAllowed('ignore');
1178
                $this->_ignoreNotAllowed('ignore');
1154
            }
1179
            }
1155
        }
1180
        }
1156
        if (isset($list['install'])) {
1181
        if (isset($list['install'])) {
1157
            if (!$allowignore) {
1182
            if (!$allowignore) {
1158
                $this->_ignoreNotAllowed('install');
1183
                $this->_ignoreNotAllowed('install');
1159
            }
1184
            }
1160
        }
1185
        }
1161
        if (isset($list['file'])) {
1186
        if (isset($list['file'])) {
1162
            if ($allowignore) {
1187
            if ($allowignore) {
1163
                $this->_fileNotAllowed('file');
1188
                $this->_fileNotAllowed('file');
1164
            }
1189
            }
1165
        }
1190
        }
1166
        if (isset($list['dir'])) {
1191
        if (isset($list['dir'])) {
1167
            if ($allowignore) {
1192
            if ($allowignore) {
1168
                $this->_fileNotAllowed('dir');
1193
                $this->_fileNotAllowed('dir');
1169
            } else {
1194
            } else {
1170
                if (!isset($list['dir'][0])) {
1195
                if (!isset($list['dir'][0])) {
1171
                    $list['dir'] = array($list['dir']);
1196
                    $list['dir'] = array($list['dir']);
1172
                }
1197
                }
1173
                foreach ($list['dir'] as $dir) {
1198
                foreach ($list['dir'] as $dir) {
1174
                    if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
1199
                    if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
1175
                        if ($dir['attribs']['name'] == '/' ||
1200
                        if ($dir['attribs']['name'] == '/' ||
1176
                              !isset($this->_packageInfo['contents']['dir']['dir'])) {
1201
                              !isset($this->_packageInfo['contents']['dir']['dir'])) {
1177
                            // always use nothing if the filelist has already been flattened
1202
                            // always use nothing if the filelist has already been flattened
1178
                            $newdirs = '';
1203
                            $newdirs = '';
1179
                        } elseif ($dirs == '') {
1204
                        } elseif ($dirs == '') {
1180
                            $newdirs = $dir['attribs']['name'];
1205
                            $newdirs = $dir['attribs']['name'];
1181
                        } else {
1206
                        } else {
1182
                            $newdirs = $dirs . '/' . $dir['attribs']['name'];
1207
                            $newdirs = $dirs . '/' . $dir['attribs']['name'];
1183
                        }
1208
                        }
1184
                    } else {
1209
                    } else {
1185
                        $newdirs = $dirs;
1210
                        $newdirs = $dirs;
1186
                    }
1211
                    }
1187
                    $this->_validateFilelist($dir, $allowignore, $newdirs);
1212
                    $this->_validateFilelist($dir, $allowignore, $newdirs);
1188
                }
1213
                }
1189
            }
1214
            }
1190
        }
1215
        }
1191
    }
1216
    }
1192
 
1217
 
1193
    function _validateRelease()
1218
    function _validateRelease()
1194
    {
1219
    {
1195
        if (isset($this->_packageInfo['phprelease'])) {
1220
        if (isset($this->_packageInfo['phprelease'])) {
1196
            $release = 'phprelease';
1221
            $release = 'phprelease';
1197
            if (isset($this->_packageInfo['providesextension'])) {
1222
            if (isset($this->_packageInfo['providesextension'])) {
1198
                $this->_cannotProvideExtension($release);
1223
                $this->_cannotProvideExtension($release);
1199
            }
1224
            }
1200
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1225
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1201
                $this->_cannotHaveSrcpackage($release);
1226
                $this->_cannotHaveSrcpackage($release);
1202
            }
1227
            }
1203
            $releases = $this->_packageInfo['phprelease'];
1228
            $releases = $this->_packageInfo['phprelease'];
1204
            if (!is_array($releases)) {
1229
            if (!is_array($releases)) {
1205
                return true;
1230
                return true;
1206
            }
1231
            }
1207
            if (!isset($releases[0])) {
1232
            if (!isset($releases[0])) {
1208
                $releases = array($releases);
1233
                $releases = array($releases);
1209
            }
1234
            }
1210
            foreach ($releases as $rel) {
1235
            foreach ($releases as $rel) {
1211
                $this->_stupidSchemaValidate(array(
1236
                $this->_stupidSchemaValidate(array(
1212
                    '*installconditions',
1237
                    '*installconditions',
1213
                    '*filelist',
1238
                    '*filelist',
1214
                ), $rel, '<phprelease>');
1239
                ), $rel, '<phprelease>');
1215
            }
1240
            }
1216
        }
1241
        }
1217
        foreach (array('', 'zend') as $prefix) {
1242
        foreach (array('', 'zend') as $prefix) {
1218
            $releasetype = $prefix . 'extsrcrelease';
1243
            $releasetype = $prefix . 'extsrcrelease';
1219
            if (isset($this->_packageInfo[$releasetype])) {
1244
            if (isset($this->_packageInfo[$releasetype])) {
1220
                $release = $releasetype;
1245
                $release = $releasetype;
1221
                if (!isset($this->_packageInfo['providesextension'])) {
1246
                if (!isset($this->_packageInfo['providesextension'])) {
1222
                    $this->_mustProvideExtension($release);
1247
                    $this->_mustProvideExtension($release);
1223
                }
1248
                }
1224
                if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1249
                if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1225
                    $this->_cannotHaveSrcpackage($release);
1250
                    $this->_cannotHaveSrcpackage($release);
1226
                }
1251
                }
1227
                $releases = $this->_packageInfo[$releasetype];
1252
                $releases = $this->_packageInfo[$releasetype];
1228
                if (!is_array($releases)) {
1253
                if (!is_array($releases)) {
1229
                    return true;
1254
                    return true;
1230
                }
1255
                }
1231
                if (!isset($releases[0])) {
1256
                if (!isset($releases[0])) {
1232
                    $releases = array($releases);
1257
                    $releases = array($releases);
1233
                }
1258
                }
1234
                foreach ($releases as $rel) {
1259
                foreach ($releases as $rel) {
1235
                    $this->_stupidSchemaValidate(array(
1260
                    $this->_stupidSchemaValidate(array(
1236
                        '*installconditions',
1261
                        '*installconditions',
1237
                        '*configureoption->name->prompt->?default',
1262
                        '*configureoption->name->prompt->?default',
1238
                        '*binarypackage',
1263
                        '*binarypackage',
1239
                        '*filelist',
1264
                        '*filelist',
1240
                    ), $rel, '<' . $releasetype . '>');
1265
                    ), $rel, '<' . $releasetype . '>');
1241
                    if (isset($rel['binarypackage'])) {
1266
                    if (isset($rel['binarypackage'])) {
1242
                        if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
1267
                        if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
1243
                            $rel['binarypackage'] = array($rel['binarypackage']);
1268
                            $rel['binarypackage'] = array($rel['binarypackage']);
1244
                        }
1269
                        }
1245
                        foreach ($rel['binarypackage'] as $bin) {
1270
                        foreach ($rel['binarypackage'] as $bin) {
1246
                            if (!is_string($bin)) {
1271
                            if (!is_string($bin)) {
1247
                                $this->_binaryPackageMustBePackagename();
1272
                                $this->_binaryPackageMustBePackagename();
1248
                            }
1273
                            }
1249
                        }
1274
                        }
1250
                    }
1275
                    }
1251
                }
1276
                }
1252
            }
1277
            }
1253
            $releasetype = 'extbinrelease';
1278
            $releasetype = 'extbinrelease';
1254
            if (isset($this->_packageInfo[$releasetype])) {
1279
            if (isset($this->_packageInfo[$releasetype])) {
1255
                $release = $releasetype;
1280
                $release = $releasetype;
1256
                if (!isset($this->_packageInfo['providesextension'])) {
1281
                if (!isset($this->_packageInfo['providesextension'])) {
1257
                    $this->_mustProvideExtension($release);
1282
                    $this->_mustProvideExtension($release);
1258
                }
1283
                }
1259
                if (isset($this->_packageInfo['channel']) &&
1284
                if (isset($this->_packageInfo['channel']) &&
1260
                      !isset($this->_packageInfo['srcpackage'])) {
1285
                      !isset($this->_packageInfo['srcpackage'])) {
1261
                    $this->_mustSrcPackage($release);
1286
                    $this->_mustSrcPackage($release);
1262
                }
1287
                }
1263
                if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
1288
                if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
1264
                    $this->_mustSrcuri($release);
1289
                    $this->_mustSrcuri($release);
1265
                }
1290
                }
1266
                $releases = $this->_packageInfo[$releasetype];
1291
                $releases = $this->_packageInfo[$releasetype];
1267
                if (!is_array($releases)) {
1292
                if (!is_array($releases)) {
1268
                    return true;
1293
                    return true;
1269
                }
1294
                }
1270
                if (!isset($releases[0])) {
1295
                if (!isset($releases[0])) {
1271
                    $releases = array($releases);
1296
                    $releases = array($releases);
1272
                }
1297
                }
1273
                foreach ($releases as $rel) {
1298
                foreach ($releases as $rel) {
1274
                    $this->_stupidSchemaValidate(array(
1299
                    $this->_stupidSchemaValidate(array(
1275
                        '*installconditions',
1300
                        '*installconditions',
1276
                        '*filelist',
1301
                        '*filelist',
1277
                    ), $rel, '<' . $releasetype . '>');
1302
                    ), $rel, '<' . $releasetype . '>');
1278
                }
1303
                }
1279
            }
1304
            }
1280
        }
1305
        }
1281
        if (isset($this->_packageInfo['bundle'])) {
1306
        if (isset($this->_packageInfo['bundle'])) {
1282
            $release = 'bundle';
1307
            $release = 'bundle';
1283
            if (isset($this->_packageInfo['providesextension'])) {
1308
            if (isset($this->_packageInfo['providesextension'])) {
1284
                $this->_cannotProvideExtension($release);
1309
                $this->_cannotProvideExtension($release);
1285
            }
1310
            }
1286
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1311
            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1287
                $this->_cannotHaveSrcpackage($release);
1312
                $this->_cannotHaveSrcpackage($release);
1288
            }
1313
            }
1289
            $releases = $this->_packageInfo['bundle'];
1314
            $releases = $this->_packageInfo['bundle'];
1290
            if (!is_array($releases) || !isset($releases[0])) {
1315
            if (!is_array($releases) || !isset($releases[0])) {
1291
                $releases = array($releases);
1316
                $releases = array($releases);
1292
            }
1317
            }
1293
            foreach ($releases as $rel) {
1318
            foreach ($releases as $rel) {
1294
                $this->_stupidSchemaValidate(array(
1319
                $this->_stupidSchemaValidate(array(
1295
                    '*installconditions',
1320
                    '*installconditions',
1296
                    '*filelist',
1321
                    '*filelist',
1297
                ), $rel, '<bundle>');
1322
                ), $rel, '<bundle>');
1298
            }
1323
            }
1299
        }
1324
        }
1300
        foreach ($releases as $rel) {
1325
        foreach ($releases as $rel) {
1301
            if (is_array($rel) && array_key_exists('installconditions', $rel)) {
1326
            if (is_array($rel) && array_key_exists('installconditions', $rel)) {
1302
                $this->_validateInstallConditions($rel['installconditions'],
1327
                $this->_validateInstallConditions($rel['installconditions'],
1303
                    "<$release><installconditions>");
1328
                    "<$release><installconditions>");
1304
            }
1329
            }
1305
            if (is_array($rel) && array_key_exists('filelist', $rel)) {
1330
            if (is_array($rel) && array_key_exists('filelist', $rel)) {
1306
                if ($rel['filelist']) {
1331
                if ($rel['filelist']) {
1307
                    
1332
 
1308
                    $this->_validateFilelist($rel['filelist'], true);
1333
                    $this->_validateFilelist($rel['filelist'], true);
1309
                }
1334
                }
1310
            }
1335
            }
1311
        }
1336
        }
1312
    }
1337
    }
1313
 
1338
 
1314
    /**
1339
    /**
1315
     * This is here to allow role extension through plugins
1340
     * This is here to allow role extension through plugins
1316
     * @param string
1341
     * @param string
1317
     */
1342
     */
1318
    function _validateRole($role)
1343
    function _validateRole($role)
1319
    {
1344
    {
1320
        return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
1345
        return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
1321
    }
1346
    }
1322
 
1347
 
1323
    function _pearVersionTooLow($version)
1348
    function _pearVersionTooLow($version)
1324
    {
1349
    {
1325
        $this->_stack->push(__FUNCTION__, 'error',
1350
        $this->_stack->push(__FUNCTION__, 'error',
1326
            array('version' => $version),
1351
            array('version' => $version),
1327
            'This package.xml requires PEAR version %version% to parse properly, we are ' .
1352
            'This package.xml requires PEAR version %version% to parse properly, we are ' .
1328
            'version 1.5.1');
1353
            'version 1.10.1');
1329
    }
1354
    }
1330
 
1355
 
1331
    function _invalidTagOrder($oktags, $actual, $root)
1356
    function _invalidTagOrder($oktags, $actual, $root)
1332
    {
1357
    {
1333
        $this->_stack->push(__FUNCTION__, 'error',
1358
        $this->_stack->push(__FUNCTION__, 'error',
1334
            array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
1359
            array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
1335
            'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
1360
            'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
1336
    }
1361
    }
1337
 
1362
 
1338
    function _ignoreNotAllowed($type)
1363
    function _ignoreNotAllowed($type)
1339
    {
1364
    {
1340
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1365
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1341
            '<%type%> is not allowed inside global <contents>, only inside ' .
1366
            '<%type%> is not allowed inside global <contents>, only inside ' .
1342
            '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
1367
            '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
1343
    }
1368
    }
1344
 
1369
 
1345
    function _fileNotAllowed($type)
1370
    function _fileNotAllowed($type)
1346
    {
1371
    {
1347
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1372
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1348
            '<%type%> is not allowed inside release <filelist>, only inside ' .
1373
            '<%type%> is not allowed inside release <filelist>, only inside ' .
1349
            '<contents>, use <ignore> and <install> only');
1374
            '<contents>, use <ignore> and <install> only');
1350
    }
1375
    }
-
 
1376
 
-
 
1377
    function _oldStyleFileNotAllowed()
-
 
1378
    {
-
 
1379
        $this->_stack->push(__FUNCTION__, 'error', array(),
-
 
1380
            'Old-style <file>name</file> is not allowed.  Use' .
-
 
1381
            '<file name="name" role="role"/>');
-
 
1382
    }
1351
 
1383
 
1352
    function _tagMissingAttribute($tag, $attr, $context)
1384
    function _tagMissingAttribute($tag, $attr, $context)
1353
    {
1385
    {
1354
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1386
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1355
            'attribute' => $attr, 'context' => $context),
1387
            'attribute' => $attr, 'context' => $context),
1356
            'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
1388
            'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
1357
    }
1389
    }
1358
 
1390
 
1359
    function _tagHasNoAttribs($tag, $context)
1391
    function _tagHasNoAttribs($tag, $context)
1360
    {
1392
    {
1361
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1393
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1362
            'context' => $context),
1394
            'context' => $context),
1363
            'tag <%tag%> has no attributes in context "%context%"');
1395
            'tag <%tag%> has no attributes in context "%context%"');
1364
    }
1396
    }
1365
 
1397
 
1366
    function _invalidInternalStructure()
1398
    function _invalidInternalStructure()
1367
    {
1399
    {
1368
        $this->_stack->push(__FUNCTION__, 'exception', array(),
1400
        $this->_stack->push(__FUNCTION__, 'exception', array(),
1369
            'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
1401
            'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
1370
    }
1402
    }
1371
 
1403
 
1372
    function _invalidFileRole($file, $dir, $role)
1404
    function _invalidFileRole($file, $dir, $role)
1373
    {
1405
    {
1374
        $this->_stack->push(__FUNCTION__, 'error', array(
1406
        $this->_stack->push(__FUNCTION__, 'error', array(
1375
            'file' => $file, 'dir' => $dir, 'role' => $role,
1407
            'file' => $file, 'dir' => $dir, 'role' => $role,
1376
            'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
1408
            'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
1377
            'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
1409
            'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
1378
    }
1410
    }
1379
 
1411
 
1380
    function _invalidFileName($file, $dir)
1412
    function _invalidFileName($file, $dir)
1381
    {
1413
    {
1382
        $this->_stack->push(__FUNCTION__, 'error', array(
1414
        $this->_stack->push(__FUNCTION__, 'error', array(
1383
            'file' => $file),
1415
            'file' => $file),
-
 
1416
            'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
-
 
1417
    }
-
 
1418
 
-
 
1419
    function _invalidFileInstallAs($file, $as)
-
 
1420
    {
-
 
1421
        $this->_stack->push(__FUNCTION__, 'error', array(
-
 
1422
            'file' => $file, 'as' => $as),
-
 
1423
            'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
-
 
1424
    }
-
 
1425
 
-
 
1426
    function _invalidDirName($dir)
-
 
1427
    {
-
 
1428
        $this->_stack->push(__FUNCTION__, 'error', array(
-
 
1429
            'dir' => $file),
1384
            'File "%file%" cannot begin with "."');
1430
            'Directory "%dir%" cannot begin with "./" or contain ".."');
1385
    }
1431
    }
1386
 
1432
 
1387
    function _filelistCannotContainFile($filelist)
1433
    function _filelistCannotContainFile($filelist)
1388
    {
1434
    {
1389
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1435
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1390
            '<%tag%> can only contain <dir>, contains <file>.  Use ' .
1436
            '<%tag%> can only contain <dir>, contains <file>.  Use ' .
1391
            '<dir name="/"> as the first dir element');
1437
            '<dir name="/"> as the first dir element');
1392
    }
1438
    }
1393
 
1439
 
1394
    function _filelistMustContainDir($filelist)
1440
    function _filelistMustContainDir($filelist)
1395
    {
1441
    {
1396
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1442
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1397
            '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
1443
            '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
1398
            'first dir element');
1444
            'first dir element');
1399
    }
1445
    }
1400
 
1446
 
1401
    function _tagCannotBeEmpty($tag)
1447
    function _tagCannotBeEmpty($tag)
1402
    {
1448
    {
1403
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1449
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1404
            '<%tag%> cannot be empty (<%tag%/>)');
1450
            '<%tag%> cannot be empty (<%tag%/>)');
1405
    }
1451
    }
1406
 
1452
 
1407
    function _UrlOrChannel($type, $name)
1453
    function _UrlOrChannel($type, $name)
1408
    {
1454
    {
1409
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1455
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1410
            'name' => $name),
1456
            'name' => $name),
1411
            'Required dependency <%type%> "%name%" can have either url OR ' .
1457
            'Required dependency <%type%> "%name%" can have either url OR ' .
1412
            'channel attributes, and not both');
1458
            'channel attributes, and not both');
1413
    }
1459
    }
1414
 
1460
 
1415
    function _NoChannel($type, $name)
1461
    function _NoChannel($type, $name)
1416
    {
1462
    {
1417
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1463
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1418
            'name' => $name),
1464
            'name' => $name),
1419
            'Required dependency <%type%> "%name%" must have either url OR ' .
1465
            'Required dependency <%type%> "%name%" must have either url OR ' .
1420
            'channel attributes');
1466
            'channel attributes');
1421
    }
1467
    }
1422
 
1468
 
1423
    function _UrlOrChannelGroup($type, $name, $group)
1469
    function _UrlOrChannelGroup($type, $name, $group)
1424
    {
1470
    {
1425
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1471
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1426
            'name' => $name, 'group' => $group),
1472
            'name' => $name, 'group' => $group),
1427
            'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
1473
            'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
1428
            'channel attributes, and not both');
1474
            'channel attributes, and not both');
1429
    }
1475
    }
1430
 
1476
 
1431
    function _NoChannelGroup($type, $name, $group)
1477
    function _NoChannelGroup($type, $name, $group)
1432
    {
1478
    {
1433
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1479
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1434
            'name' => $name, 'group' => $group),
1480
            'name' => $name, 'group' => $group),
1435
            'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
1481
            'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
1436
            'channel attributes');
1482
            'channel attributes');
1437
    }
1483
    }
1438
 
1484
 
1439
    function _unknownChannel($channel)
1485
    function _unknownChannel($channel)
1440
    {
1486
    {
1441
        $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
1487
        $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
1442
            'Unknown channel "%channel%"');
1488
            'Unknown channel "%channel%"');
1443
    }
1489
    }
1444
 
1490
 
1445
    function _noPackageVersion()
1491
    function _noPackageVersion()
1446
    {
1492
    {
1447
        $this->_stack->push(__FUNCTION__, 'error', array(),
1493
        $this->_stack->push(__FUNCTION__, 'error', array(),
1448
            'package.xml <package> tag has no version attribute, or version is not 2.0');
1494
            'package.xml <package> tag has no version attribute, or version is not 2.0');
1449
    }
1495
    }
1450
 
1496
 
1451
    function _NoBundledPackages()
1497
    function _NoBundledPackages()
1452
    {
1498
    {
1453
        $this->_stack->push(__FUNCTION__, 'error', array(),
1499
        $this->_stack->push(__FUNCTION__, 'error', array(),
1454
            'No <bundledpackage> tag was found in <contents>, required for bundle packages');
1500
            'No <bundledpackage> tag was found in <contents>, required for bundle packages');
1455
    }
1501
    }
1456
 
1502
 
1457
    function _AtLeast2BundledPackages()
1503
    function _AtLeast2BundledPackages()
1458
    {
1504
    {
1459
        $this->_stack->push(__FUNCTION__, 'error', array(),
1505
        $this->_stack->push(__FUNCTION__, 'error', array(),
1460
            'At least 2 packages must be bundled in a bundle package');
1506
            'At least 2 packages must be bundled in a bundle package');
1461
    }
1507
    }
1462
 
1508
 
1463
    function _ChannelOrUri($name)
1509
    function _ChannelOrUri($name)
1464
    {
1510
    {
1465
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1511
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1466
            'Bundled package "%name%" can have either a uri or a channel, not both');
1512
            'Bundled package "%name%" can have either a uri or a channel, not both');
1467
    }
1513
    }
1468
 
1514
 
1469
    function _noChildTag($child, $tag)
1515
    function _noChildTag($child, $tag)
1470
    {
1516
    {
1471
        $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
1517
        $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
1472
            'Tag <%tag%> is missing child tag <%child%>');
1518
            'Tag <%tag%> is missing child tag <%child%>');
1473
    }
1519
    }
1474
 
1520
 
1475
    function _invalidVersion($type, $value)
1521
    function _invalidVersion($type, $value)
1476
    {
1522
    {
1477
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
1523
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
1478
            'Version type <%type%> is not a valid version (%value%)');
1524
            'Version type <%type%> is not a valid version (%value%)');
1479
    }
1525
    }
1480
 
1526
 
1481
    function _invalidState($type, $value)
1527
    function _invalidState($type, $value)
1482
    {
1528
    {
1483
        $states = array('stable', 'beta', 'alpha', 'devel');
1529
        $states = array('stable', 'beta', 'alpha', 'devel');
1484
        if ($type != 'api') {
1530
        if ($type != 'api') {
1485
            $states[] = 'snapshot';
1531
            $states[] = 'snapshot';
1486
        }
1532
        }
1487
        if (strtolower($value) == 'rc') {
1533
        if (strtolower($value) == 'rc') {
1488
            $this->_stack->push(__FUNCTION__, 'error',
1534
            $this->_stack->push(__FUNCTION__, 'error',
1489
                array('version' => $this->_packageInfo['version']['release']),
1535
                array('version' => $this->_packageInfo['version']['release']),
1490
                'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
1536
                'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
1491
        }
1537
        }
1492
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
1538
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
1493
            'types' => $states),
1539
            'types' => $states),
1494
            'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
1540
            'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
1495
            '%types%');
1541
            '%types%');
1496
    }
1542
    }
1497
 
1543
 
1498
    function _invalidTask($task, $ret, $file)
1544
    function _invalidTask($task, $ret, $file)
1499
    {
1545
    {
1500
        switch ($ret[0]) {
1546
        switch ($ret[0]) {
1501
            case PEAR_TASK_ERROR_MISSING_ATTRIB :
1547
            case PEAR_TASK_ERROR_MISSING_ATTRIB :
1502
                $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
1548
                $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
1503
                $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
1549
                $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
1504
            break;
1550
            break;
1505
            case PEAR_TASK_ERROR_NOATTRIBS :
1551
            case PEAR_TASK_ERROR_NOATTRIBS :
1506
                $info = array('task' => $task, 'file' => $file);
1552
                $info = array('task' => $task, 'file' => $file);
1507
                $msg = 'task <%task%> has no attributes in file %file%';
1553
                $msg = 'task <%task%> has no attributes in file %file%';
1508
            break;
1554
            break;
1509
            case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
1555
            case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
1510
                $info = array('attrib' => $ret[1], 'values' => $ret[3],
1556
                $info = array('attrib' => $ret[1], 'values' => $ret[3],
1511
                    'was' => $ret[2], 'task' => $task, 'file' => $file);
1557
                    'was' => $ret[2], 'task' => $task, 'file' => $file);
1512
                $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
1558
                $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
1513
                    'in file %file%, expecting one of "%values%"';
1559
                    'in file %file%, expecting one of "%values%"';
1514
            break;
1560
            break;
1515
            case PEAR_TASK_ERROR_INVALID :
1561
            case PEAR_TASK_ERROR_INVALID :
1516
                $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
1562
                $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
1517
                $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
1563
                $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
1518
            break;
1564
            break;
1519
        }
1565
        }
1520
        $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
1566
        $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
1521
    }
1567
    }
1522
 
1568
 
1523
    function _unknownTask($task, $file)
1569
    function _unknownTask($task, $file)
1524
    {
1570
    {
1525
        $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
1571
        $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
1526
            'Unknown task "%task%" passed in file <file name="%file%">');
1572
            'Unknown task "%task%" passed in file <file name="%file%">');
1527
    }
1573
    }
1528
 
1574
 
1529
    function _subpackageCannotProvideExtension($name)
1575
    function _subpackageCannotProvideExtension($name)
1530
    {
1576
    {
1531
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1577
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1532
            'Subpackage dependency "%name%" cannot use <providesextension>, ' .
1578
            'Subpackage dependency "%name%" cannot use <providesextension>, ' .
1533
            'only package dependencies can use this tag');
1579
            'only package dependencies can use this tag');
1534
    }
1580
    }
1535
 
1581
 
1536
    function _subpackagesCannotConflict($name)
1582
    function _subpackagesCannotConflict($name)
1537
    {
1583
    {
1538
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1584
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1539
            'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
1585
            'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
1540
            'only package dependencies can use this tag');
1586
            'only package dependencies can use this tag');
1541
    }
1587
    }
1542
 
1588
 
1543
    function _cannotProvideExtension($release)
1589
    function _cannotProvideExtension($release)
1544
    {
1590
    {
1545
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1591
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1546
            '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
1592
            '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
1547
    }
1593
    }
1548
 
1594
 
1549
    function _mustProvideExtension($release)
1595
    function _mustProvideExtension($release)
1550
    {
1596
    {
1551
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1597
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1552
            '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
1598
            '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
1553
    }
1599
    }
1554
 
1600
 
1555
    function _cannotHaveSrcpackage($release)
1601
    function _cannotHaveSrcpackage($release)
1556
    {
1602
    {
1557
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1603
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1558
            '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
1604
            '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
1559
    }
1605
    }
1560
 
1606
 
1561
    function _mustSrcPackage($release)
1607
    function _mustSrcPackage($release)
1562
    {
1608
    {
1563
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1609
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1564
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
1610
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
1565
    }
1611
    }
1566
 
1612
 
1567
    function _mustSrcuri($release)
1613
    function _mustSrcuri($release)
1568
    {
1614
    {
1569
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1615
        $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1570
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
1616
            '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
1571
    }
1617
    }
1572
 
1618
 
1573
    function _uriDepsCannotHaveVersioning($type)
1619
    function _uriDepsCannotHaveVersioning($type)
1574
    {
1620
    {
1575
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1621
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1576
            '%type%: dependencies with a <uri> tag cannot have any versioning information');
1622
            '%type%: dependencies with a <uri> tag cannot have any versioning information');
1577
    }
1623
    }
1578
 
1624
 
1579
    function _conflictingDepsCannotHaveVersioning($type)
1625
    function _conflictingDepsCannotHaveVersioning($type)
1580
    {
1626
    {
1581
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1627
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1582
            '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
1628
            '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
1583
            'exclude specific versions of a dependency');
1629
            'exclude specific versions of a dependency');
1584
    }
1630
    }
1585
 
1631
 
1586
    function _DepchannelCannotBeUri($type)
1632
    function _DepchannelCannotBeUri($type)
1587
    {
1633
    {
1588
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1634
        $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1589
            '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
1635
            '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
1590
            'dependencies only');
1636
            'dependencies only');
1591
    }
1637
    }
1592
 
1638
 
1593
    function _bundledPackagesMustBeFilename()
1639
    function _bundledPackagesMustBeFilename()
1594
    {
1640
    {
1595
        $this->_stack->push(__FUNCTION__, 'error', array(),
1641
        $this->_stack->push(__FUNCTION__, 'error', array(),
1596
            '<bundledpackage> tags must contain only the filename of a package release ' .
1642
            '<bundledpackage> tags must contain only the filename of a package release ' .
1597
            'in the bundle');
1643
            'in the bundle');
1598
    }
1644
    }
1599
 
1645
 
1600
    function _binaryPackageMustBePackagename()
1646
    function _binaryPackageMustBePackagename()
1601
    {
1647
    {
1602
        $this->_stack->push(__FUNCTION__, 'error', array(),
1648
        $this->_stack->push(__FUNCTION__, 'error', array(),
1603
            '<binarypackage> tags must contain the name of a package that is ' .
1649
            '<binarypackage> tags must contain the name of a package that is ' .
1604
            'a compiled version of this extsrc/zendextsrc package');
1650
            'a compiled version of this extsrc/zendextsrc package');
1605
    }
1651
    }
1606
 
1652
 
1607
    function _fileNotFound($file)
1653
    function _fileNotFound($file)
1608
    {
1654
    {
1609
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1655
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1610
            'File "%file%" in package.xml does not exist');
1656
            'File "%file%" in package.xml does not exist');
1611
    }
1657
    }
1612
 
1658
 
1613
    function _notInContents($file, $tag)
1659
    function _notInContents($file, $tag)
1614
    {
1660
    {
1615
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
1661
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
1616
            '<%tag% name="%file%"> is invalid, file is not in <contents>');
1662
            '<%tag% name="%file%"> is invalid, file is not in <contents>');
1617
    }
1663
    }
1618
 
1664
 
1619
    function _cannotValidateNoPathSet()
1665
    function _cannotValidateNoPathSet()
1620
    {
1666
    {
1621
        $this->_stack->push(__FUNCTION__, 'error', array(),
1667
        $this->_stack->push(__FUNCTION__, 'error', array(),
1622
            'Cannot validate files, no path to package file is set (use setPackageFile())');
1668
            'Cannot validate files, no path to package file is set (use setPackageFile())');
1623
    }
1669
    }
1624
 
1670
 
1625
    function _usesroletaskMustHaveChannelOrUri($role, $tag)
1671
    function _usesroletaskMustHaveChannelOrUri($role, $tag)
1626
    {
1672
    {
1627
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1673
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1628
            '<%tag%> must contain either <uri>, or <channel> and <package>');
1674
            '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
1629
    }
1675
    }
1630
 
1676
 
1631
    function _usesroletaskMustHavePackage($role, $tag)
1677
    function _usesroletaskMustHavePackage($role, $tag)
1632
    {
1678
    {
1633
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1679
        $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1634
            '<%tag%> must contain <package>');
1680
            '<%tag%> for role "%role%" must contain <package>');
1635
    }
1681
    }
1636
 
1682
 
1637
    function _usesroletaskMustHaveRoleTask($tag, $type)
1683
    function _usesroletaskMustHaveRoleTask($tag, $type)
1638
    {
1684
    {
1639
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
1685
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
1640
            '<%tag%> must contain <%type%> defining the %type% to be used');
1686
            '<%tag%> must contain <%type%> defining the %type% to be used');
1641
    }
1687
    }
1642
 
1688
 
1643
    function _cannotConflictWithAllOs($type)
1689
    function _cannotConflictWithAllOs($type)
1644
    {
1690
    {
1645
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1691
        $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1646
            '%tag% cannot conflict with all OSes');
1692
            '%tag% cannot conflict with all OSes');
1647
    }
1693
    }
1648
 
1694
 
1649
    function _invalidDepGroupName($name)
1695
    function _invalidDepGroupName($name)
1650
    {
1696
    {
1651
        $this->_stack->push(__FUNCTION__, 'error', array('group' => $name),
1697
        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1652
            'Invalid dependency group name "%name%"');
1698
            'Invalid dependency group name "%name%"');
1653
    }
1699
    }
1654
 
1700
 
1655
    function _multipleToplevelDirNotAllowed()
1701
    function _multipleToplevelDirNotAllowed()
1656
    {
1702
    {
1657
        $this->_stack->push(__FUNCTION__, 'error', array(),
1703
        $this->_stack->push(__FUNCTION__, 'error', array(),
1658
            'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
1704
            'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
1659
                'in a <dir name="/">');
1705
                'in a <dir name="/">');
1660
    }
1706
    }
1661
 
1707
 
1662
    function _multipleInstallAs($file)
1708
    function _multipleInstallAs($file)
1663
    {
1709
    {
1664
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1710
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1665
            'Only one <install> tag is allowed for file "%file%"');
1711
            'Only one <install> tag is allowed for file "%file%"');
1666
    }
1712
    }
1667
 
1713
 
1668
    function _ignoreAndInstallAs($file)
1714
    function _ignoreAndInstallAs($file)
1669
    {
1715
    {
1670
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1716
        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1671
            'Cannot have both <ignore> and <install> tags for file "%file%"');
1717
            'Cannot have both <ignore> and <install> tags for file "%file%"');
1672
    }
1718
    }
1673
 
1719
 
1674
    function _analyzeBundledPackages()
1720
    function _analyzeBundledPackages()
1675
    {
1721
    {
1676
        if (!$this->_isValid) {
1722
        if (!$this->_isValid) {
1677
            return false;
1723
            return false;
1678
        }
1724
        }
1679
        if (!$this->_pf->getPackageType() == 'bundle') {
1725
        if (!$this->_pf->getPackageType() == 'bundle') {
1680
            return false;
1726
            return false;
1681
        }
1727
        }
1682
        if (!isset($this->_pf->_packageFile)) {
1728
        if (!isset($this->_pf->_packageFile)) {
1683
            return false;
1729
            return false;
1684
        }
1730
        }
1685
        $dir_prefix = dirname($this->_pf->_packageFile);
1731
        $dir_prefix = dirname($this->_pf->_packageFile);
-
 
1732
        $common = new PEAR_Common;
1686
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1733
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1687
            array('PEAR_Common', 'log');
1734
            array($common, 'log');
1688
        $info = $this->_pf->getContents();
1735
        $info = $this->_pf->getContents();
1689
        $info = $info['bundledpackage'];
1736
        $info = $info['bundledpackage'];
1690
        if (!is_array($info)) {
1737
        if (!is_array($info)) {
1691
            $info = array($info);
1738
            $info = array($info);
1692
        }
1739
        }
1693
        $pkg = &new PEAR_PackageFile($this->_pf->_config);
1740
        $pkg = new PEAR_PackageFile($this->_pf->_config);
1694
        foreach ($info as $package) {
1741
        foreach ($info as $package) {
1695
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
1742
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
1696
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
1743
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
1697
                $this->_isValid = 0;
1744
                $this->_isValid = 0;
1698
                continue;
1745
                continue;
1699
            }
1746
            }
1700
            call_user_func_array($log, array(1, "Analyzing bundled package $package"));
1747
            call_user_func_array($log, array(1, "Analyzing bundled package $package"));
1701
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1748
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1702
            $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
1749
            $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
1703
                PEAR_VALIDATE_NORMAL);
1750
                PEAR_VALIDATE_NORMAL);
1704
            PEAR::popErrorHandling();
1751
            PEAR::popErrorHandling();
1705
            if (PEAR::isError($ret)) {
1752
            if (PEAR::isError($ret)) {
1706
                call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
1753
                call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
1707
                    'package'));
1754
                    'package'));
1708
                $inf = $ret->getUserInfo();
1755
                $inf = $ret->getUserInfo();
1709
                if (is_array($inf)) {
1756
                if (is_array($inf)) {
1710
                    foreach ($inf as $err) {
1757
                    foreach ($inf as $err) {
1711
                        call_user_func_array($log, array(1, $err['message']));
1758
                        call_user_func_array($log, array(1, $err['message']));
1712
                    }
1759
                    }
1713
                }
1760
                }
1714
                return false;
1761
                return false;
1715
            }
1762
            }
1716
        }
1763
        }
1717
        return true;
1764
        return true;
1718
    }
1765
    }
1719
 
1766
 
1720
    function _analyzePhpFiles()
1767
    function _analyzePhpFiles()
1721
    {
1768
    {
1722
        if (!$this->_isValid) {
1769
        if (!$this->_isValid) {
1723
            return false;
1770
            return false;
1724
        }
1771
        }
1725
        if (!isset($this->_pf->_packageFile)) {
1772
        if (!isset($this->_pf->_packageFile)) {
1726
            $this->_cannotValidateNoPathSet();
1773
            $this->_cannotValidateNoPathSet();
1727
            return false;
1774
            return false;
1728
        }
1775
        }
1729
        $dir_prefix = dirname($this->_pf->_packageFile);
1776
        $dir_prefix = dirname($this->_pf->_packageFile);
1730
        $common = new PEAR_Common;
1777
        $common = new PEAR_Common;
1731
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1778
        $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1732
            array(&$common, 'log');
1779
            array(&$common, 'log');
1733
        $info = $this->_pf->getContents();
1780
        $info = $this->_pf->getContents();
1734
        if (!$info || !isset($info['dir']['file'])) {
1781
        if (!$info || !isset($info['dir']['file'])) {
1735
            $this->_tagCannotBeEmpty('contents><dir');
1782
            $this->_tagCannotBeEmpty('contents><dir');
1736
            return false;
1783
            return false;
1737
        }
1784
        }
1738
        $info = $info['dir']['file'];
1785
        $info = $info['dir']['file'];
1739
        if (isset($info['attribs'])) {
1786
        if (isset($info['attribs'])) {
1740
            $info = array($info);
1787
            $info = array($info);
1741
        }
1788
        }
1742
        $provides = array();
1789
        $provides = array();
1743
        foreach ($info as $fa) {
1790
        foreach ($info as $fa) {
1744
            $fa = $fa['attribs'];
1791
            $fa = $fa['attribs'];
1745
            $file = $fa['name'];
1792
            $file = $fa['name'];
1746
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
1793
            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
1747
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
1794
                $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
1748
                $this->_isValid = 0;
1795
                $this->_isValid = 0;
1749
                continue;
1796
                continue;
1750
            }
1797
            }
1751
            if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
1798
            if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
1752
                call_user_func_array($log, array(1, "Analyzing $file"));
1799
                call_user_func_array($log, array(1, "Analyzing $file"));
1753
                $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
1800
                $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
1754
                if ($srcinfo) {
1801
                if ($srcinfo) {
1755
                    $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
1802
                    $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
1756
                }
1803
                }
1757
            }
1804
            }
1758
        }
1805
        }
1759
        $this->_packageName = $pn = $this->_pf->getPackage();
1806
        $this->_packageName = $pn = $this->_pf->getPackage();
1760
        $pnl = strlen($pn);
1807
        $pnl = strlen($pn);
1761
        foreach ($provides as $key => $what) {
1808
        foreach ($provides as $key => $what) {
1762
            if (isset($what['explicit']) || !$what) {
1809
            if (isset($what['explicit']) || !$what) {
1763
                // skip conformance checks if the provides entry is
1810
                // skip conformance checks if the provides entry is
1764
                // specified in the package.xml file
1811
                // specified in the package.xml file
1765
                continue;
1812
                continue;
1766
            }
1813
            }
1767
            extract($what);
1814
            extract($what);
1768
            if ($type == 'class') {
1815
            if ($type == 'class') {
1769
                if (!strncasecmp($name, $pn, $pnl)) {
1816
                if (!strncasecmp($name, $pn, $pnl)) {
1770
                    continue;
1817
                    continue;
1771
                }
1818
                }
1772
                $this->_stack->push(__FUNCTION__, 'warning',
1819
                $this->_stack->push(__FUNCTION__, 'warning',
1773
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1820
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1774
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1821
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1775
            } elseif ($type == 'function') {
1822
            } elseif ($type == 'function') {
1776
                if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
1823
                if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
1777
                    continue;
1824
                    continue;
1778
                }
1825
                }
1779
                $this->_stack->push(__FUNCTION__, 'warning',
1826
                $this->_stack->push(__FUNCTION__, 'warning',
1780
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1827
                    array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1781
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1828
                    'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1782
            }
1829
            }
1783
        }
1830
        }
1784
        return $this->_isValid;
1831
        return $this->_isValid;
1785
    }
1832
    }
1786
 
1833
 
1787
    /**
1834
    /**
1788
     * Analyze the source code of the given PHP file
1835
     * Analyze the source code of the given PHP file
1789
     *
1836
     *
1790
     * @param  string Filename of the PHP file
1837
     * @param  string Filename of the PHP file
1791
     * @param  boolean whether to analyze $file as the file contents
1838
     * @param  boolean whether to analyze $file as the file contents
1792
     * @return mixed
1839
     * @return mixed
1793
     */
1840
     */
1794
    function analyzeSourceCode($file, $string = false)
1841
    function analyzeSourceCode($file, $string = false)
1795
    {
1842
    {
1796
        if (!function_exists("token_get_all")) {
1843
        if (!function_exists("token_get_all")) {
1797
            $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1844
            $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1798
                'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
1845
                'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
1799
            return false;
1846
            return false;
1800
        }
1847
        }
-
 
1848
 
1801
        if (!defined('T_DOC_COMMENT')) {
1849
        if (!defined('T_DOC_COMMENT')) {
1802
            define('T_DOC_COMMENT', T_COMMENT);
1850
            define('T_DOC_COMMENT', T_COMMENT);
1803
        }
1851
        }
-
 
1852
 
1804
        if (!defined('T_INTERFACE')) {
1853
        if (!defined('T_INTERFACE')) {
1805
            define('T_INTERFACE', -1);
1854
            define('T_INTERFACE', -1);
1806
        }
1855
        }
-
 
1856
 
1807
        if (!defined('T_IMPLEMENTS')) {
1857
        if (!defined('T_IMPLEMENTS')) {
1808
            define('T_IMPLEMENTS', -1);
1858
            define('T_IMPLEMENTS', -1);
1809
        }
1859
        }
-
 
1860
 
1810
        if ($string) {
1861
        if ($string) {
1811
            $contents = $file;
1862
            $contents = $file;
1812
        } else {
1863
        } else {
1813
            if (!$fp = @fopen($file, "r")) {
1864
            if (!$fp = @fopen($file, "r")) {
1814
                return false;
1865
                return false;
1815
            }
1866
            }
1816
            fclose($fp);
1867
            fclose($fp);
1817
            $contents = file_get_contents($file);
1868
            $contents = file_get_contents($file);
1818
        }
1869
        }
-
 
1870
 
-
 
1871
        // Silence this function so we can catch PHP Warnings and show our own custom message
1819
        $tokens = token_get_all($contents);
1872
        $tokens = @token_get_all($contents);
-
 
1873
        if (isset($php_errormsg)) {
-
 
1874
            if (isset($this->_stack)) {
-
 
1875
                $pn = $this->_pf->getPackage();
-
 
1876
                $this->_stack->push(__FUNCTION__, 'warning',
-
 
1877
                        array('file' => $file, 'package' => $pn),
-
 
1878
                        'in %file%: Could not process file for unknown reasons,' .
-
 
1879
                        ' possibly a PHP parse error in %file% from %package%');
-
 
1880
            }
-
 
1881
        }
1820
/*
1882
/*
1821
        for ($i = 0; $i < sizeof($tokens); $i++) {
1883
        for ($i = 0; $i < sizeof($tokens); $i++) {
1822
            @list($token, $data) = $tokens[$i];
1884
            @list($token, $data) = $tokens[$i];
1823
            if (is_string($token)) {
1885
            if (is_string($token)) {
1824
                var_dump($token);
1886
                var_dump($token);
1825
            } else {
1887
            } else {
1826
                print token_name($token) . ' ';
1888
                print token_name($token) . ' ';
1827
                var_dump(rtrim($data));
1889
                var_dump(rtrim($data));
1828
            }
1890
            }
1829
        }
1891
        }
1830
*/
1892
*/
1831
        $look_for = 0;
1893
        $look_for = 0;
1832
        $paren_level = 0;
1894
        $paren_level = 0;
1833
        $bracket_level = 0;
1895
        $bracket_level = 0;
1834
        $brace_level = 0;
1896
        $brace_level = 0;
1835
        $lastphpdoc = '';
1897
        $lastphpdoc = '';
1836
        $current_class = '';
1898
        $current_class = '';
1837
        $current_interface = '';
1899
        $current_interface = '';
1838
        $current_class_level = -1;
1900
        $current_class_level = -1;
1839
        $current_function = '';
1901
        $current_function = '';
1840
        $current_function_level = -1;
1902
        $current_function_level = -1;
1841
        $declared_classes = array();
1903
        $declared_classes = array();
1842
        $declared_interfaces = array();
1904
        $declared_interfaces = array();
1843
        $declared_functions = array();
1905
        $declared_functions = array();
1844
        $declared_methods = array();
1906
        $declared_methods = array();
1845
        $used_classes = array();
1907
        $used_classes = array();
1846
        $used_functions = array();
1908
        $used_functions = array();
1847
        $extends = array();
1909
        $extends = array();
1848
        $implements = array();
1910
        $implements = array();
1849
        $nodeps = array();
1911
        $nodeps = array();
1850
        $inquote = false;
1912
        $inquote = false;
1851
        $interface = false;
1913
        $interface = false;
1852
        for ($i = 0; $i < sizeof($tokens); $i++) {
1914
        for ($i = 0; $i < sizeof($tokens); $i++) {
1853
            if (is_array($tokens[$i])) {
1915
            if (is_array($tokens[$i])) {
1854
                list($token, $data) = $tokens[$i];
1916
                list($token, $data) = $tokens[$i];
1855
            } else {
1917
            } else {
1856
                $token = $tokens[$i];
1918
                $token = $tokens[$i];
1857
                $data = '';
1919
                $data = '';
1858
            }
1920
            }
-
 
1921
 
1859
            if ($inquote) {
1922
            if ($inquote) {
1860
                if ($token != '"' && $token != T_END_HEREDOC) {
1923
                if ($token != '"' && $token != T_END_HEREDOC) {
1861
                    continue;
1924
                    continue;
1862
                } else {
1925
                } else {
1863
                    $inquote = false;
1926
                    $inquote = false;
1864
                    continue;
1927
                    continue;
1865
                }
1928
                }
1866
            }
1929
            }
-
 
1930
 
1867
            switch ($token) {
1931
            switch ($token) {
1868
                case T_WHITESPACE :
1932
                case T_WHITESPACE :
1869
                    continue;
1933
                    continue;
1870
                case ';':
1934
                case ';':
1871
                    if ($interface) {
1935
                    if ($interface) {
1872
                        $current_function = '';
1936
                        $current_function = '';
1873
                        $current_function_level = -1;
1937
                        $current_function_level = -1;
1874
                    }
1938
                    }
1875
                    break;
1939
                    break;
1876
                case '"':
1940
                case '"':
1877
                case T_START_HEREDOC:
1941
                case T_START_HEREDOC:
1878
                    $inquote = true;
1942
                    $inquote = true;
1879
                    break;
1943
                    break;
1880
                case T_CURLY_OPEN:
1944
                case T_CURLY_OPEN:
1881
                case T_DOLLAR_OPEN_CURLY_BRACES:
1945
                case T_DOLLAR_OPEN_CURLY_BRACES:
1882
                case '{': $brace_level++; continue 2;
1946
                case '{': $brace_level++; continue 2;
1883
                case '}':
1947
                case '}':
1884
                    $brace_level--;
1948
                    $brace_level--;
1885
                    if ($current_class_level == $brace_level) {
1949
                    if ($current_class_level == $brace_level) {
1886
                        $current_class = '';
1950
                        $current_class = '';
1887
                        $current_class_level = -1;
1951
                        $current_class_level = -1;
1888
                    }
1952
                    }
1889
                    if ($current_function_level == $brace_level) {
1953
                    if ($current_function_level == $brace_level) {
1890
                        $current_function = '';
1954
                        $current_function = '';
1891
                        $current_function_level = -1;
1955
                        $current_function_level = -1;
1892
                    }
1956
                    }
1893
                    continue 2;
1957
                    continue 2;
1894
                case '[': $bracket_level++; continue 2;
1958
                case '[': $bracket_level++; continue 2;
1895
                case ']': $bracket_level--; continue 2;
1959
                case ']': $bracket_level--; continue 2;
1896
                case '(': $paren_level++;   continue 2;
1960
                case '(': $paren_level++;   continue 2;
1897
                case ')': $paren_level--;   continue 2;
1961
                case ')': $paren_level--;   continue 2;
1898
                case T_INTERFACE:
1962
                case T_INTERFACE:
1899
                    $interface = true;
1963
                    $interface = true;
1900
                case T_CLASS:
1964
                case T_CLASS:
1901
                    if (($current_class_level != -1) || ($current_function_level != -1)) {
1965
                    if (($current_class_level != -1) || ($current_function_level != -1)) {
-
 
1966
                        if (isset($this->_stack)) {
1902
                        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1967
                            $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1903
                        'Parser error: invalid PHP found in file "%file%"');
1968
                            'Parser error: invalid PHP found in file "%file%"');
-
 
1969
                        } else {
-
 
1970
                            PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
-
 
1971
                                PEAR_COMMON_ERROR_INVALIDPHP);
-
 
1972
                        }
-
 
1973
 
1904
                        return false;
1974
                        return false;
1905
                    }
1975
                    }
1906
                case T_FUNCTION:
1976
                case T_FUNCTION:
1907
                case T_NEW:
1977
                case T_NEW:
1908
                case T_EXTENDS:
1978
                case T_EXTENDS:
1909
                case T_IMPLEMENTS:
1979
                case T_IMPLEMENTS:
1910
                    $look_for = $token;
1980
                    $look_for = $token;
1911
                    continue 2;
1981
                    continue 2;
1912
                case T_STRING:
1982
                case T_STRING:
1913
                    if (version_compare(zend_version(), '2.0', '<')) {
-
 
1914
                        if (in_array(strtolower($data),
-
 
1915
                            array('public', 'private', 'protected', 'abstract',
-
 
1916
                                  'interface', 'implements', 'throw') 
-
 
1917
                                 )) {
-
 
1918
                            $this->_stack->push(__FUNCTION__, 'warning', array(
-
 
1919
                                'file' => $file),
-
 
1920
                                'Error, PHP5 token encountered in %file%,' .
-
 
1921
                                ' analysis should be in PHP5');
-
 
1922
                        }
-
 
1923
                    }
-
 
1924
                    if ($look_for == T_CLASS) {
1983
                    if ($look_for == T_CLASS) {
1925
                        $current_class = $data;
1984
                        $current_class = $data;
1926
                        $current_class_level = $brace_level;
1985
                        $current_class_level = $brace_level;
1927
                        $declared_classes[] = $current_class;
1986
                        $declared_classes[] = $current_class;
1928
                    } elseif ($look_for == T_INTERFACE) {
1987
                    } elseif ($look_for == T_INTERFACE) {
1929
                        $current_interface = $data;
1988
                        $current_interface = $data;
1930
                        $current_class_level = $brace_level;
1989
                        $current_class_level = $brace_level;
1931
                        $declared_interfaces[] = $current_interface;
1990
                        $declared_interfaces[] = $current_interface;
1932
                    } elseif ($look_for == T_IMPLEMENTS) {
1991
                    } elseif ($look_for == T_IMPLEMENTS) {
1933
                        $implements[$current_class] = $data;
1992
                        $implements[$current_class] = $data;
1934
                    } elseif ($look_for == T_EXTENDS) {
1993
                    } elseif ($look_for == T_EXTENDS) {
1935
                        $extends[$current_class] = $data;
1994
                        $extends[$current_class] = $data;
1936
                    } elseif ($look_for == T_FUNCTION) {
1995
                    } elseif ($look_for == T_FUNCTION) {
1937
                        if ($current_class) {
1996
                        if ($current_class) {
1938
                            $current_function = "$current_class::$data";
1997
                            $current_function = "$current_class::$data";
1939
                            $declared_methods[$current_class][] = $data;
1998
                            $declared_methods[$current_class][] = $data;
1940
                        } elseif ($current_interface) {
1999
                        } elseif ($current_interface) {
1941
                            $current_function = "$current_interface::$data";
2000
                            $current_function = "$current_interface::$data";
1942
                            $declared_methods[$current_interface][] = $data;
2001
                            $declared_methods[$current_interface][] = $data;
1943
                        } else {
2002
                        } else {
1944
                            $current_function = $data;
2003
                            $current_function = $data;
1945
                            $declared_functions[] = $current_function;
2004
                            $declared_functions[] = $current_function;
1946
                        }
2005
                        }
-
 
2006
 
1947
                        $current_function_level = $brace_level;
2007
                        $current_function_level = $brace_level;
1948
                        $m = array();
2008
                        $m = array();
1949
                    } elseif ($look_for == T_NEW) {
2009
                    } elseif ($look_for == T_NEW) {
1950
                        $used_classes[$data] = true;
2010
                        $used_classes[$data] = true;
1951
                    }
2011
                    }
-
 
2012
 
1952
                    $look_for = 0;
2013
                    $look_for = 0;
1953
                    continue 2;
2014
                    continue 2;
1954
                case T_VARIABLE:
2015
                case T_VARIABLE:
1955
                    $look_for = 0;
2016
                    $look_for = 0;
1956
                    continue 2;
2017
                    continue 2;
1957
                case T_DOC_COMMENT:
2018
                case T_DOC_COMMENT:
1958
                case T_COMMENT:
2019
                case T_COMMENT:
1959
                    if (preg_match('!^/\*\*\s!', $data)) {
2020
                    if (preg_match('!^/\*\*\s!', $data)) {
1960
                        $lastphpdoc = $data;
2021
                        $lastphpdoc = $data;
1961
                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
2022
                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
1962
                            $nodeps = array_merge($nodeps, $m[1]);
2023
                            $nodeps = array_merge($nodeps, $m[1]);
1963
                        }
2024
                        }
1964
                    }
2025
                    }
1965
                    continue 2;
2026
                    continue 2;
1966
                case T_DOUBLE_COLON:
2027
                case T_DOUBLE_COLON:
-
 
2028
                    $token = $tokens[$i - 1][0];
1967
                    if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
2029
                    if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) {
-
 
2030
                        if (isset($this->_stack)) {
1968
                        $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
2031
                            $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
1969
                            'Parser error: invalid PHP found in file "%file%"');
2032
                                'Parser error: invalid PHP found in file "%file%"');
-
 
2033
                        } else {
-
 
2034
                            PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
-
 
2035
                                PEAR_COMMON_ERROR_INVALIDPHP);
-
 
2036
                        }
-
 
2037
 
1970
                        return false;
2038
                        return false;
1971
                    }
2039
                    }
-
 
2040
 
1972
                    $class = $tokens[$i - 1][1];
2041
                    $class = $tokens[$i - 1][1];
1973
                    if (strtolower($class) != 'parent') {
2042
                    if (strtolower($class) != 'parent') {
1974
                        $used_classes[$class] = true;
2043
                        $used_classes[$class] = true;
1975
                    }
2044
                    }
-
 
2045
 
1976
                    continue 2;
2046
                    continue 2;
1977
            }
2047
            }
1978
        }
2048
        }
-
 
2049
 
1979
        return array(
2050
        return array(
1980
            "source_file" => $file,
2051
            "source_file" => $file,
1981
            "declared_classes" => $declared_classes,
2052
            "declared_classes" => $declared_classes,
1982
            "declared_interfaces" => $declared_interfaces,
2053
            "declared_interfaces" => $declared_interfaces,
1983
            "declared_methods" => $declared_methods,
2054
            "declared_methods" => $declared_methods,
1984
            "declared_functions" => $declared_functions,
2055
            "declared_functions" => $declared_functions,
1985
            "used_classes" => array_diff(array_keys($used_classes), $nodeps),
2056
            "used_classes" => array_diff(array_keys($used_classes), $nodeps),
1986
            "inheritance" => $extends,
2057
            "inheritance" => $extends,
1987
            "implements" => $implements,
2058
            "implements" => $implements,
1988
            );
2059
        );
1989
    }
2060
    }
1990
 
2061
 
1991
    /**
2062
    /**
1992
     * Build a "provides" array from data returned by
2063
     * Build a "provides" array from data returned by
1993
     * analyzeSourceCode().  The format of the built array is like
2064
     * analyzeSourceCode().  The format of the built array is like
1994
     * this:
2065
     * this:
1995
     *
2066
     *
1996
     *  array(
2067
     *  array(
1997
     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
2068
     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
1998
     *    ...
2069
     *    ...
1999
     *  )
2070
     *  )
2000
     *
2071
     *
2001
     *
2072
     *
2002
     * @param array $srcinfo array with information about a source file
2073
     * @param array $srcinfo array with information about a source file
2003
     * as returned by the analyzeSourceCode() method.
2074
     * as returned by the analyzeSourceCode() method.
2004
     *
2075
     *
2005
     * @return void
2076
     * @return void
2006
     *
2077
     *
2007
     * @access private
2078
     * @access private
2008
     *
2079
     *
2009
     */
2080
     */
2010
    function _buildProvidesArray($srcinfo)
2081
    function _buildProvidesArray($srcinfo)
2011
    {
2082
    {
2012
        if (!$this->_isValid) {
2083
        if (!$this->_isValid) {
2013
            return array();
2084
            return array();
2014
        }
2085
        }
-
 
2086
 
2015
        $providesret = array();
2087
        $providesret = array();
2016
        $file = basename($srcinfo['source_file']);
2088
        $file        = basename($srcinfo['source_file']);
2017
        $pn = $this->_pf->getPackage();
2089
        $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
2018
        $pnl = strlen($pn);
2090
        $pnl         = strlen($pn);
2019
        foreach ($srcinfo['declared_classes'] as $class) {
2091
        foreach ($srcinfo['declared_classes'] as $class) {
2020
            $key = "class;$class";
2092
            $key = "class;$class";
2021
            if (isset($providesret[$key])) {
2093
            if (isset($providesret[$key])) {
2022
                continue;
2094
                continue;
2023
            }
2095
            }
-
 
2096
 
2024
            $providesret[$key] =
2097
            $providesret[$key] =
2025
                array('file'=> $file, 'type' => 'class', 'name' => $class);
2098
                array('file'=> $file, 'type' => 'class', 'name' => $class);
2026
            if (isset($srcinfo['inheritance'][$class])) {
2099
            if (isset($srcinfo['inheritance'][$class])) {
2027
                $providesret[$key]['extends'] =
2100
                $providesret[$key]['extends'] =
2028
                    $srcinfo['inheritance'][$class];
2101
                    $srcinfo['inheritance'][$class];
2029
            }
2102
            }
2030
        }
2103
        }
-
 
2104
 
2031
        foreach ($srcinfo['declared_methods'] as $class => $methods) {
2105
        foreach ($srcinfo['declared_methods'] as $class => $methods) {
2032
            foreach ($methods as $method) {
2106
            foreach ($methods as $method) {
2033
                $function = "$class::$method";
2107
                $function = "$class::$method";
2034
                $key = "function;$function";
2108
                $key = "function;$function";
2035
                if ($method{0} == '_' || !strcasecmp($method, $class) ||
2109
                if ($method{0} == '_' || !strcasecmp($method, $class) ||
2036
                    isset($providesret[$key])) {
2110
                    isset($providesret[$key])) {
2037
                    continue;
2111
                    continue;
2038
                }
2112
                }
-
 
2113
 
2039
                $providesret[$key] =
2114
                $providesret[$key] =
2040
                    array('file'=> $file, 'type' => 'function', 'name' => $function);
2115
                    array('file'=> $file, 'type' => 'function', 'name' => $function);
2041
            }
2116
            }
2042
        }
2117
        }
2043
 
2118
 
2044
        foreach ($srcinfo['declared_functions'] as $function) {
2119
        foreach ($srcinfo['declared_functions'] as $function) {
2045
            $key = "function;$function";
2120
            $key = "function;$function";
2046
            if ($function{0} == '_' || isset($providesret[$key])) {
2121
            if ($function{0} == '_' || isset($providesret[$key])) {
2047
                continue;
2122
                continue;
2048
            }
2123
            }
-
 
2124
 
2049
            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
2125
            if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
2050
                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
2126
                $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
2051
            }
2127
            }
-
 
2128
 
2052
            $providesret[$key] =
2129
            $providesret[$key] =
2053
                array('file'=> $file, 'type' => 'function', 'name' => $function);
2130
                array('file'=> $file, 'type' => 'function', 'name' => $function);
2054
        }
2131
        }
-
 
2132
 
2055
        return $providesret;
2133
        return $providesret;
2056
    }
2134
    }
2057
}
2135
}
2058
?>
-
 
2059
2136