Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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