Subversion Repositories Applications.gtt

Rev

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

Rev Author Line No. Line
94 jpm 1
<?php
2
/**
3
 * package.xml parsing class, package.xml version 1.0
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * that is available through the world-wide-web at the following URI:
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * the PHP License and are unable to obtain it through the web, please
11
 * send a note to license@php.net so we can mail you a copy immediately.
12
 *
13
 * @category   pear
14
 * @package    PEAR
15
 * @author     Greg Beaver <cellog@php.net>
16
 * @copyright  1997-2006 The PHP Group
17
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
18
 * @version    CVS: $Id: v1.php,v 1.22 2006/03/27 05:25:48 cellog Exp $
19
 * @link       http://pear.php.net/package/PEAR
20
 * @since      File available since Release 1.4.0a1
21
 */
22
/**
23
 * package.xml abstraction class
24
 */
25
require_once 'PEAR/PackageFile/v1.php';
26
/**
27
 * Parser for package.xml version 1.0
28
 * @category   pear
29
 * @package    PEAR
30
 * @author     Greg Beaver <cellog@php.net>
31
 * @copyright  1997-2006 The PHP Group
32
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
33
 * @version    Release: @PEAR-VER@
34
 * @link       http://pear.php.net/package/PEAR
35
 * @since      Class available since Release 1.4.0a1
36
 */
37
class PEAR_PackageFile_Parser_v1
38
{
39
    var $_registry;
40
    var $_config;
41
    var $_logger;
42
    /**
43
     * BC hack to allow PEAR_Common::infoFromString() to sort of
44
     * work with the version 2.0 format - there's no filelist though
45
     * @param PEAR_PackageFile_v2
46
     */
47
    function fromV2($packagefile)
48
    {
49
        $info = $packagefile->getArray(true);
50
        $ret = new PEAR_PackageFile_v1;
51
        $ret->fromArray($info['old']);
52
    }
53
 
54
    function setConfig(&$c)
55
    {
56
        $this->_config = &$c;
57
        $this->_registry = &$c->getRegistry();
58
    }
59
 
60
    function setLogger(&$l)
61
    {
62
        $this->_logger = &$l;
63
    }
64
 
65
    /**
66
     * @param string contents of package.xml file, version 1.0
67
     * @return bool success of parsing
68
     */
69
    function parse($data, $file, $archive = false)
70
    {
71
        if (!extension_loaded('xml')) {
72
            return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
73
        }
74
        $xp = xml_parser_create();
75
        if (!$xp) {
76
            return PEAR::raiseError('Cannot create xml parser for parsing package.xml');
77
        }
78
        xml_set_object($xp, $this);
79
        xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
80
        xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
81
        xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
82
 
83
        $this->element_stack = array();
84
        $this->_packageInfo = array('provides' => array());
85
        $this->current_element = false;
86
        unset($this->dir_install);
87
        $this->_packageInfo['filelist'] = array();
88
        $this->filelist =& $this->_packageInfo['filelist'];
89
        $this->dir_names = array();
90
        $this->in_changelog = false;
91
        $this->d_i = 0;
92
        $this->cdata = '';
93
        $this->_isValid = true;
94
 
95
        if (!xml_parse($xp, $data, 1)) {
96
            $code = xml_get_error_code($xp);
97
            $line = xml_get_current_line_number($xp);
98
            xml_parser_free($xp);
99
            return PEAR::raiseError(sprintf("XML error: %s at line %d",
100
                           $str = xml_error_string($code), $line), 2);
101
        }
102
 
103
        xml_parser_free($xp);
104
 
105
        $pf = new PEAR_PackageFile_v1;
106
        $pf->setConfig($this->_config);
107
        if (isset($this->_logger)) {
108
            $pf->setLogger($this->_logger);
109
        }
110
        $pf->setPackagefile($file, $archive);
111
        $pf->fromArray($this->_packageInfo);
112
        return $pf;
113
    }
114
    // {{{ _unIndent()
115
 
116
    /**
117
     * Unindent given string
118
     *
119
     * @param string $str The string that has to be unindented.
120
     * @return string
121
     * @access private
122
     */
123
    function _unIndent($str)
124
    {
125
        // remove leading newlines
126
        $str = preg_replace('/^[\r\n]+/', '', $str);
127
        // find whitespace at the beginning of the first line
128
        $indent_len = strspn($str, " \t");
129
        $indent = substr($str, 0, $indent_len);
130
        $data = '';
131
        // remove the same amount of whitespace from following lines
132
        foreach (explode("\n", $str) as $line) {
133
            if (substr($line, 0, $indent_len) == $indent) {
134
                $data .= substr($line, $indent_len) . "\n";
135
            }
136
        }
137
        return $data;
138
    }
139
 
140
    // Support for package DTD v1.0:
141
    // {{{ _element_start_1_0()
142
 
143
    /**
144
     * XML parser callback for ending elements.  Used for version 1.0
145
     * packages.
146
     *
147
     * @param resource  $xp    XML parser resource
148
     * @param string    $name  name of ending element
149
     *
150
     * @return void
151
     *
152
     * @access private
153
     */
154
    function _element_start_1_0($xp, $name, $attribs)
155
    {
156
        array_push($this->element_stack, $name);
157
        $this->current_element = $name;
158
        $spos = sizeof($this->element_stack) - 2;
159
        $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
160
        $this->current_attributes = $attribs;
161
        $this->cdata = '';
162
        switch ($name) {
163
            case 'dir':
164
                if ($this->in_changelog) {
165
                    break;
166
                }
167
                if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
168
                    $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
169
                        $attribs['name']);
170
                    if (strrpos($attribs['name'], '/') == strlen($attribs['name']) - 1) {
171
                        $attribs['name'] = substr($attribs['name'], 0,
172
                            strlen($attribs['name']) - 1);
173
                    }
174
                    if (strpos($attribs['name'], '/') === 0) {
175
                        $attribs['name'] = substr($attribs['name'], 1);
176
                    }
177
                    $this->dir_names[] = $attribs['name'];
178
                }
179
                if (isset($attribs['baseinstalldir'])) {
180
                    $this->dir_install = $attribs['baseinstalldir'];
181
                }
182
                if (isset($attribs['role'])) {
183
                    $this->dir_role = $attribs['role'];
184
                }
185
                break;
186
            case 'file':
187
                if ($this->in_changelog) {
188
                    break;
189
                }
190
                if (isset($attribs['name'])) {
191
                    $path = '';
192
                    if (count($this->dir_names)) {
193
                        foreach ($this->dir_names as $dir) {
194
                            $path .= $dir . '/';
195
                        }
196
                    }
197
                    $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
198
                        $attribs['name']);
199
                    unset($attribs['name']);
200
                    $this->current_path = $path;
201
                    $this->filelist[$path] = $attribs;
202
                    // Set the baseinstalldir only if the file don't have this attrib
203
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
204
                        isset($this->dir_install))
205
                    {
206
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
207
                    }
208
                    // Set the Role
209
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
210
                        $this->filelist[$path]['role'] = $this->dir_role;
211
                    }
212
                }
213
                break;
214
            case 'replace':
215
                if (!$this->in_changelog) {
216
                    $this->filelist[$this->current_path]['replacements'][] = $attribs;
217
                }
218
                break;
219
            case 'maintainers':
220
                $this->_packageInfo['maintainers'] = array();
221
                $this->m_i = 0; // maintainers array index
222
                break;
223
            case 'maintainer':
224
                // compatibility check
225
                if (!isset($this->_packageInfo['maintainers'])) {
226
                    $this->_packageInfo['maintainers'] = array();
227
                    $this->m_i = 0;
228
                }
229
                $this->_packageInfo['maintainers'][$this->m_i] = array();
230
                $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
231
                break;
232
            case 'changelog':
233
                $this->_packageInfo['changelog'] = array();
234
                $this->c_i = 0; // changelog array index
235
                $this->in_changelog = true;
236
                break;
237
            case 'release':
238
                if ($this->in_changelog) {
239
                    $this->_packageInfo['changelog'][$this->c_i] = array();
240
                    $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
241
                } else {
242
                    $this->current_release = &$this->_packageInfo;
243
                }
244
                break;
245
            case 'deps':
246
                if (!$this->in_changelog) {
247
                    $this->_packageInfo['release_deps'] = array();
248
                }
249
                break;
250
            case 'dep':
251
                // dependencies array index
252
                if (!$this->in_changelog) {
253
                    $this->d_i++;
254
                    isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
255
                    $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
256
                }
257
                break;
258
            case 'configureoptions':
259
                if (!$this->in_changelog) {
260
                    $this->_packageInfo['configure_options'] = array();
261
                }
262
                break;
263
            case 'configureoption':
264
                if (!$this->in_changelog) {
265
                    $this->_packageInfo['configure_options'][] = $attribs;
266
                }
267
                break;
268
            case 'provides':
269
                if (empty($attribs['type']) || empty($attribs['name'])) {
270
                    break;
271
                }
272
                $attribs['explicit'] = true;
273
                $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
274
                break;
275
            case 'package' :
276
                if (isset($attribs['version'])) {
277
                    $this->_packageInfo['xsdversion'] = trim($attribs['version']);
278
                } else {
279
                    $this->_packageInfo['xsdversion'] = '1.0';
280
                }
281
                if (isset($attribs['packagerversion'])) {
282
                    $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
283
                }
284
                break;
285
        }
286
    }
287
 
288
    // }}}
289
    // {{{ _element_end_1_0()
290
 
291
    /**
292
     * XML parser callback for ending elements.  Used for version 1.0
293
     * packages.
294
     *
295
     * @param resource  $xp    XML parser resource
296
     * @param string    $name  name of ending element
297
     *
298
     * @return void
299
     *
300
     * @access private
301
     */
302
    function _element_end_1_0($xp, $name)
303
    {
304
        $data = trim($this->cdata);
305
        switch ($name) {
306
            case 'name':
307
                switch ($this->prev_element) {
308
                    case 'package':
309
                        $this->_packageInfo['package'] = $data;
310
                        break;
311
                    case 'maintainer':
312
                        $this->current_maintainer['name'] = $data;
313
                        break;
314
                }
315
                break;
316
            case 'extends' :
317
                $this->_packageInfo['extends'] = $data;
318
                break;
319
            case 'summary':
320
                $this->_packageInfo['summary'] = $data;
321
                break;
322
            case 'description':
323
                $data = $this->_unIndent($this->cdata);
324
                $this->_packageInfo['description'] = $data;
325
                break;
326
            case 'user':
327
                $this->current_maintainer['handle'] = $data;
328
                break;
329
            case 'email':
330
                $this->current_maintainer['email'] = $data;
331
                break;
332
            case 'role':
333
                $this->current_maintainer['role'] = $data;
334
                break;
335
            case 'version':
336
                //$data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data);
337
                if ($this->in_changelog) {
338
                    $this->current_release['version'] = $data;
339
                } else {
340
                    $this->_packageInfo['version'] = $data;
341
                }
342
                break;
343
            case 'date':
344
                if ($this->in_changelog) {
345
                    $this->current_release['release_date'] = $data;
346
                } else {
347
                    $this->_packageInfo['release_date'] = $data;
348
                }
349
                break;
350
            case 'notes':
351
                // try to "de-indent" release notes in case someone
352
                // has been over-indenting their xml ;-)
353
                $data = $this->_unIndent($this->cdata);
354
                if ($this->in_changelog) {
355
                    $this->current_release['release_notes'] = $data;
356
                } else {
357
                    $this->_packageInfo['release_notes'] = $data;
358
                }
359
                break;
360
            case 'warnings':
361
                if ($this->in_changelog) {
362
                    $this->current_release['release_warnings'] = $data;
363
                } else {
364
                    $this->_packageInfo['release_warnings'] = $data;
365
                }
366
                break;
367
            case 'state':
368
                if ($this->in_changelog) {
369
                    $this->current_release['release_state'] = $data;
370
                } else {
371
                    $this->_packageInfo['release_state'] = $data;
372
                }
373
                break;
374
            case 'license':
375
                if ($this->in_changelog) {
376
                    $this->current_release['release_license'] = $data;
377
                } else {
378
                    $this->_packageInfo['release_license'] = $data;
379
                }
380
                break;
381
            case 'dep':
382
                if ($data && !$this->in_changelog) {
383
                    $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
384
                }
385
                break;
386
            case 'dir':
387
                if ($this->in_changelog) {
388
                    break;
389
                }
390
                array_pop($this->dir_names);
391
                break;
392
            case 'file':
393
                if ($this->in_changelog) {
394
                    break;
395
                }
396
                if ($data) {
397
                    $path = '';
398
                    if (count($this->dir_names)) {
399
                        foreach ($this->dir_names as $dir) {
400
                            $path .= $dir . '/';
401
                        }
402
                    }
403
                    $path .= $data;
404
                    $this->filelist[$path] = $this->current_attributes;
405
                    // Set the baseinstalldir only if the file don't have this attrib
406
                    if (!isset($this->filelist[$path]['baseinstalldir']) &&
407
                        isset($this->dir_install))
408
                    {
409
                        $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
410
                    }
411
                    // Set the Role
412
                    if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
413
                        $this->filelist[$path]['role'] = $this->dir_role;
414
                    }
415
                }
416
                break;
417
            case 'maintainer':
418
                if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
419
                    $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
420
                }
421
                $this->m_i++;
422
                break;
423
            case 'release':
424
                if ($this->in_changelog) {
425
                    $this->c_i++;
426
                }
427
                break;
428
            case 'changelog':
429
                $this->in_changelog = false;
430
                break;
431
        }
432
        array_pop($this->element_stack);
433
        $spos = sizeof($this->element_stack) - 1;
434
        $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
435
        $this->cdata = '';
436
    }
437
 
438
    // }}}
439
    // {{{ _pkginfo_cdata_1_0()
440
 
441
    /**
442
     * XML parser callback for character data.  Used for version 1.0
443
     * packages.
444
     *
445
     * @param resource  $xp    XML parser resource
446
     * @param string    $name  character data
447
     *
448
     * @return void
449
     *
450
     * @access private
451
     */
452
    function _pkginfo_cdata_1_0($xp, $data)
453
    {
454
        if (isset($this->cdata)) {
455
            $this->cdata .= $data;
456
        }
457
    }
458
 
459
    // }}}
460
}
461
?>