PageRenderTime 224ms CodeModel.GetById 176ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

/pimcore/lib/PEAR/PackageFile/v1.php

https://github.com/benawv/bogor-city-guide
PHP | 1612 lines | 1145 code | 145 blank | 322 comment | 171 complexity | efd089af85e376ac3b81c8ca5d6a4d55 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * PEAR_PackageFile_v1, 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,v 1.75 2009/02/24 23:39:16 dufuz Exp $
  13 * @link       http://pear.php.net/package/PEAR
  14 * @since      File available since Release 1.4.0a1
  15 */
  16/**
  17 * For error handling
  18 */
  19require_once 'PEAR/ErrorStack.php';
  20
  21/**
  22 * Error code if parsing is attempted with no xml extension
  23 */
  24define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
  25
  26/**
  27 * Error code if creating the xml parser resource fails
  28 */
  29define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
  30
  31/**
  32 * Error code used for all sax xml parsing errors
  33 */
  34define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
  35
  36/**
  37 * Error code used when there is no name
  38 */
  39define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
  40
  41/**
  42 * Error code when a package name is not valid
  43 */
  44define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
  45
  46/**
  47 * Error code used when no summary is parsed
  48 */
  49define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
  50
  51/**
  52 * Error code for summaries that are more than 1 line
  53 */
  54define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
  55
  56/**
  57 * Error code used when no description is present
  58 */
  59define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
  60
  61/**
  62 * Error code used when no license is present
  63 */
  64define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
  65
  66/**
  67 * Error code used when a <version> version number is not present
  68 */
  69define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
  70
  71/**
  72 * Error code used when a <version> version number is invalid
  73 */
  74define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
  75
  76/**
  77 * Error code when release state is missing
  78 */
  79define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
  80
  81/**
  82 * Error code when release state is invalid
  83 */
  84define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
  85
  86/**
  87 * Error code when release state is missing
  88 */
  89define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
  90
  91/**
  92 * Error code when release state is invalid
  93 */
  94define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
  95
  96/**
  97 * Error code when no release notes are found
  98 */
  99define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
 100
 101/**
 102 * Error code when no maintainers are found
 103 */
 104define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
 105
 106/**
 107 * Error code when a maintainer has no handle
 108 */
 109define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
 110
 111/**
 112 * Error code when a maintainer has no handle
 113 */
 114define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
 115
 116/**
 117 * Error code when a maintainer has no name
 118 */
 119define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
 120
 121/**
 122 * Error code when a maintainer has no email
 123 */
 124define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
 125
 126/**
 127 * Error code when a maintainer has no handle
 128 */
 129define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
 130
 131/**
 132 * Error code when a dependency is not a PHP dependency, but has no name
 133 */
 134define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
 135
 136/**
 137 * Error code when a dependency has no type (pkg, php, etc.)
 138 */
 139define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
 140
 141/**
 142 * Error code when a dependency has no relation (lt, ge, has, etc.)
 143 */
 144define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
 145
 146/**
 147 * Error code when a dependency is not a 'has' relation, but has no version
 148 */
 149define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
 150
 151/**
 152 * Error code when a dependency has an invalid relation
 153 */
 154define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
 155
 156/**
 157 * Error code when a dependency has an invalid type
 158 */
 159define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
 160
 161/**
 162 * Error code when a dependency has an invalid optional option
 163 */
 164define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
 165
 166/**
 167 * Error code when a dependency is a pkg dependency, and has an invalid package name
 168 */
 169define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
 170
 171/**
 172 * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
 173 */
 174define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
 175
 176/**
 177 * Error code when rel="has" and version attribute is present.
 178 */
 179define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
 180
 181/**
 182 * Error code when type="php" and dependency name is present
 183 */
 184define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
 185
 186/**
 187 * Error code when a configure option has no name
 188 */
 189define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
 190
 191/**
 192 * Error code when a configure option has no name
 193 */
 194define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
 195
 196/**
 197 * Error code when a file in the filelist has an invalid role
 198 */
 199define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
 200
 201/**
 202 * Error code when a file in the filelist has no role
 203 */
 204define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
 205
 206/**
 207 * Error code when analyzing a php source file that has parse errors
 208 */
 209define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
 210
 211/**
 212 * Error code when analyzing a php source file reveals a source element
 213 * without a package name prefix
 214 */
 215define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
 216
 217/**
 218 * Error code when an unknown channel is specified
 219 */
 220define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
 221
 222/**
 223 * Error code when no files are found in the filelist
 224 */
 225define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
 226
 227/**
 228 * Error code when a file is not valid php according to _analyzeSourceCode()
 229 */
 230define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
 231
 232/**
 233 * Error code when the channel validator returns an error or warning
 234 */
 235define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
 236
 237/**
 238 * Error code when a php5 package is packaged in php4 (analysis doesn't work)
 239 */
 240define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
 241
 242/**
 243 * Error code when a file is listed in package.xml but does not exist
 244 */
 245define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
 246
 247/**
 248 * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
 249 */
 250define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
 251
 252/**
 253 * Error code when a package.xml contains non-ISO-8859-1 characters
 254 */
 255define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
 256
 257/**
 258 * Error code when a dependency is not a 'has' relation, but has no version
 259 */
 260define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
 261
 262/**
 263 * Error code when a package has no lead developer
 264 */
 265define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
 266
 267/**
 268 * Error code when a filename begins with "."
 269 */
 270define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
 271/**
 272 * package.xml encapsulator
 273 * @category   pear
 274 * @package    PEAR
 275 * @author     Greg Beaver <cellog@php.net>
 276 * @copyright  1997-2009 The Authors
 277 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 278 * @version    Release: 1.8.1
 279 * @link       http://pear.php.net/package/PEAR
 280 * @since      Class available since Release 1.4.0a1
 281 */
 282class PEAR_PackageFile_v1
 283{
 284    /**
 285     * @access private
 286     * @var PEAR_ErrorStack
 287     * @access private
 288     */
 289    var $_stack;
 290
 291    /**
 292     * A registry object, used to access the package name validation regex for non-standard channels
 293     * @var PEAR_Registry
 294     * @access private
 295     */
 296    var $_registry;
 297
 298    /**
 299     * An object that contains a log method that matches PEAR_Common::log's signature
 300     * @var object
 301     * @access private
 302     */
 303    var $_logger;
 304
 305    /**
 306     * Parsed package information
 307     * @var array
 308     * @access private
 309     */
 310    var $_packageInfo;
 311
 312    /**
 313     * path to package.xml
 314     * @var string
 315     * @access private
 316     */
 317    var $_packageFile;
 318
 319    /**
 320     * path to package .tgz or false if this is a local/extracted package.xml
 321     * @var string
 322     * @access private
 323     */
 324    var $_archiveFile;
 325
 326    /**
 327     * @var int
 328     * @access private
 329     */
 330    var $_isValid = 0;
 331
 332    /**
 333     * Determines whether this packagefile was initialized only with partial package info
 334     *
 335     * If this package file was constructed via parsing REST, it will only contain
 336     *
 337     * - package name
 338     * - channel name
 339     * - dependencies 
 340     * @var boolean
 341     * @access private
 342     */
 343    var $_incomplete = true;
 344
 345    /**
 346     * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
 347     * @param string Name of Error Stack class to use.
 348     */
 349    function PEAR_PackageFile_v1()
 350    {
 351        $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
 352        $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
 353        $this->_isValid = 0;
 354    }
 355
 356    function installBinary($installer)
 357    {
 358        return false;
 359    }
 360
 361    function isExtension($name)
 362    {
 363        return false;
 364    }
 365
 366    function setConfig(&$config)
 367    {
 368        $this->_config = &$config;
 369        $this->_registry = &$config->getRegistry();
 370    }
 371
 372    function setRequestedGroup()
 373    {
 374        // placeholder
 375    }
 376
 377    /**
 378     * For saving in the registry.
 379     *
 380     * Set the last version that was installed
 381     * @param string
 382     */
 383    function setLastInstalledVersion($version)
 384    {
 385        $this->_packageInfo['_lastversion'] = $version;
 386    }
 387
 388    /**
 389     * @return string|false
 390     */
 391    function getLastInstalledVersion()
 392    {
 393        if (isset($this->_packageInfo['_lastversion'])) {
 394            return $this->_packageInfo['_lastversion'];
 395        }
 396        return false;
 397    }
 398
 399    function getInstalledBinary()
 400    {
 401        return false;
 402    }
 403
 404    function listPostinstallScripts()
 405    {
 406        return false;
 407    }
 408
 409    function initPostinstallScripts()
 410    {
 411        return false;
 412    }
 413
 414    function setLogger(&$logger)
 415    {
 416        if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
 417            return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
 418        }
 419        $this->_logger = &$logger;
 420    }
 421
 422    function setPackagefile($file, $archive = false)
 423    {
 424        $this->_packageFile = $file;
 425        $this->_archiveFile = $archive ? $archive : $file;
 426    }
 427
 428    function getPackageFile()
 429    {
 430        return isset($this->_packageFile) ? $this->_packageFile : false;
 431    }
 432
 433    function getPackageType()
 434    {
 435        return 'php';
 436    }
 437
 438    function getArchiveFile()
 439    {
 440        return $this->_archiveFile;
 441    }
 442
 443    function packageInfo($field)
 444    {
 445        if (!is_string($field) || empty($field) ||
 446            !isset($this->_packageInfo[$field])) {
 447            return false;
 448        }
 449        return $this->_packageInfo[$field];
 450    }
 451
 452    function setDirtree($path)
 453    {
 454        if (!isset($this->_packageInfo['dirtree'])) {
 455            $this->_packageInfo['dirtree'] = array();
 456        }
 457        $this->_packageInfo['dirtree'][$path] = true;
 458    }
 459
 460    function getDirtree()
 461    {
 462        if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
 463            return $this->_packageInfo['dirtree'];
 464        }
 465        return false;
 466    }
 467
 468    function resetDirtree()
 469    {
 470        unset($this->_packageInfo['dirtree']);
 471    }
 472
 473    function fromArray($pinfo)
 474    {
 475        $this->_incomplete = false;
 476        $this->_packageInfo = $pinfo;
 477    }
 478
 479    function isIncomplete()
 480    {
 481        return $this->_incomplete;
 482    }
 483
 484    function getChannel()
 485    {
 486        return 'pear.php.net';
 487    }
 488
 489    function getUri()
 490    {
 491        return false;
 492    }
 493
 494    function getTime()
 495    {
 496        return false;
 497    }
 498
 499    function getExtends()
 500    {
 501        if (isset($this->_packageInfo['extends'])) {
 502            return $this->_packageInfo['extends'];
 503        }
 504        return false;
 505    }
 506
 507    /**
 508     * @return array
 509     */
 510    function toArray()
 511    {
 512        if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
 513            return false;
 514        }
 515        return $this->getArray();
 516    }
 517
 518    function getArray()
 519    {
 520        return $this->_packageInfo;
 521    }
 522
 523    function getName()
 524    {
 525        return $this->getPackage();
 526    }
 527
 528    function getPackage()
 529    {
 530        if (isset($this->_packageInfo['package'])) {
 531            return $this->_packageInfo['package'];
 532        }
 533        return false;
 534    }
 535
 536    /**
 537     * WARNING - don't use this unless you know what you are doing
 538     */
 539    function setRawPackage($package)
 540    {
 541        $this->_packageInfo['package'] = $package;
 542    }
 543
 544    function setPackage($package)
 545    {
 546        $this->_packageInfo['package'] = $package;
 547        $this->_isValid = false;
 548    }
 549
 550    function getVersion()
 551    {
 552        if (isset($this->_packageInfo['version'])) {
 553            return $this->_packageInfo['version'];
 554        }
 555        return false;
 556    }
 557
 558    function setVersion($version)
 559    {
 560        $this->_packageInfo['version'] = $version;
 561        $this->_isValid = false;
 562    }
 563
 564    function clearMaintainers()
 565    {
 566        unset($this->_packageInfo['maintainers']);
 567    }
 568
 569    function getMaintainers()
 570    {
 571        if (isset($this->_packageInfo['maintainers'])) {
 572            return $this->_packageInfo['maintainers'];
 573        }
 574        return false;
 575    }
 576
 577    /**
 578     * Adds a new maintainer - no checking of duplicates is performed, use
 579     * updatemaintainer for that purpose.
 580     */
 581    function addMaintainer($role, $handle, $name, $email)
 582    {
 583        $this->_packageInfo['maintainers'][] =
 584            array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
 585        $this->_isValid = false;
 586    }
 587
 588    function updateMaintainer($role, $handle, $name, $email)
 589    {
 590        $found = false;
 591        if (!isset($this->_packageInfo['maintainers']) ||
 592              !is_array($this->_packageInfo['maintainers'])) {
 593            return $this->addMaintainer($role, $handle, $name, $email);
 594        }
 595        foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
 596            if ($maintainer['handle'] == $handle) {
 597                $found = $i;
 598                break;
 599            }
 600        }
 601        if ($found !== false) {
 602            unset($this->_packageInfo['maintainers'][$found]);
 603            $this->_packageInfo['maintainers'] =
 604                array_values($this->_packageInfo['maintainers']);
 605        }
 606        $this->addMaintainer($role, $handle, $name, $email);
 607    }
 608
 609    function deleteMaintainer($handle)
 610    {
 611        $found = false;
 612        foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
 613            if ($maintainer['handle'] == $handle) {
 614                $found = $i;
 615                break;
 616            }
 617        }
 618        if ($found !== false) {
 619            unset($this->_packageInfo['maintainers'][$found]);
 620            $this->_packageInfo['maintainers'] =
 621                array_values($this->_packageInfo['maintainers']);
 622            return true;
 623        }
 624        return false;
 625    }
 626
 627    function getState()
 628    {
 629        if (isset($this->_packageInfo['release_state'])) {
 630            return $this->_packageInfo['release_state'];
 631        }
 632        return false;
 633    }
 634
 635    function setRawState($state)
 636    {
 637        $this->_packageInfo['release_state'] = $state;
 638    }
 639
 640    function setState($state)
 641    {
 642        $this->_packageInfo['release_state'] = $state;
 643        $this->_isValid = false;
 644    }
 645
 646    function getDate()
 647    {
 648        if (isset($this->_packageInfo['release_date'])) {
 649            return $this->_packageInfo['release_date'];
 650        }
 651        return false;
 652    }
 653
 654    function setDate($date)
 655    {
 656        $this->_packageInfo['release_date'] = $date;
 657        $this->_isValid = false;
 658    }
 659
 660    function getLicense()
 661    {
 662        if (isset($this->_packageInfo['release_license'])) {
 663            return $this->_packageInfo['release_license'];
 664        }
 665        return false;
 666    }
 667
 668    function setLicense($date)
 669    {
 670        $this->_packageInfo['release_license'] = $date;
 671        $this->_isValid = false;
 672    }
 673
 674    function getSummary()
 675    {
 676        if (isset($this->_packageInfo['summary'])) {
 677            return $this->_packageInfo['summary'];
 678        }
 679        return false;
 680    }
 681
 682    function setSummary($summary)
 683    {
 684        $this->_packageInfo['summary'] = $summary;
 685        $this->_isValid = false;
 686    }
 687
 688    function getDescription()
 689    {
 690        if (isset($this->_packageInfo['description'])) {
 691            return $this->_packageInfo['description'];
 692        }
 693        return false;
 694    }
 695
 696    function setDescription($desc)
 697    {
 698        $this->_packageInfo['description'] = $desc;
 699        $this->_isValid = false;
 700    }
 701
 702    function getNotes()
 703    {
 704        if (isset($this->_packageInfo['release_notes'])) {
 705            return $this->_packageInfo['release_notes'];
 706        }
 707        return false;
 708    }
 709
 710    function setNotes($notes)
 711    {
 712        $this->_packageInfo['release_notes'] = $notes;
 713        $this->_isValid = false;
 714    }
 715
 716    function getDeps()
 717    {
 718        if (isset($this->_packageInfo['release_deps'])) {
 719            return $this->_packageInfo['release_deps'];
 720        }
 721        return false;
 722    }
 723
 724    /**
 725     * Reset dependencies prior to adding new ones
 726     */
 727    function clearDeps()
 728    {
 729        unset($this->_packageInfo['release_deps']);
 730    }
 731
 732    function addPhpDep($version, $rel)
 733    {
 734        $this->_isValid = false;
 735        $this->_packageInfo['release_deps'][] =
 736            array('type' => 'php',
 737                  'rel' => $rel,
 738                  'version' => $version);
 739    }
 740
 741    function addPackageDep($name, $version, $rel, $optional = 'no')
 742    {
 743        $this->_isValid = false;
 744        $dep =
 745            array('type' => 'pkg',
 746                  'name' => $name,
 747                  'rel' => $rel,
 748                  'optional' => $optional);
 749        if ($rel != 'has' && $rel != 'not') {
 750            $dep['version'] = $version;
 751        }
 752        $this->_packageInfo['release_deps'][] = $dep;
 753    }
 754
 755    function addExtensionDep($name, $version, $rel, $optional = 'no')
 756    {
 757        $this->_isValid = false;
 758        $this->_packageInfo['release_deps'][] =
 759            array('type' => 'ext',
 760                  'name' => $name,
 761                  'rel' => $rel,
 762                  'version' => $version,
 763                  'optional' => $optional);
 764    }
 765
 766    /**
 767     * WARNING - do not use this function directly unless you know what you're doing
 768     */
 769    function setDeps($deps)
 770    {
 771        $this->_packageInfo['release_deps'] = $deps;
 772    }
 773
 774    function hasDeps()
 775    {
 776        return isset($this->_packageInfo['release_deps']) &&
 777            count($this->_packageInfo['release_deps']);
 778    }
 779
 780    function getDependencyGroup($group)
 781    {
 782        return false;
 783    }
 784
 785    function isCompatible($pf)
 786    {
 787        return false;
 788    }
 789
 790    function isSubpackageOf($p)
 791    {
 792        return $p->isSubpackage($this);
 793    }
 794
 795    function isSubpackage($p)
 796    {
 797        return false;
 798    }
 799
 800    function dependsOn($package, $channel)
 801    {
 802        if (strtolower($channel) != 'pear.php.net') {
 803            return false;
 804        }
 805        if (!($deps = $this->getDeps())) {
 806            return false;
 807        }
 808        foreach ($deps as $dep) {
 809            if ($dep['type'] != 'pkg') {
 810                continue;
 811            }
 812            if (strtolower($dep['name']) == strtolower($package)) {
 813                return true;
 814            }
 815        }
 816        return false;
 817    }
 818
 819    function getConfigureOptions()
 820    {
 821        if (isset($this->_packageInfo['configure_options'])) {
 822            return $this->_packageInfo['configure_options'];
 823        }
 824        return false;
 825    }
 826
 827    function hasConfigureOptions()
 828    {
 829        return isset($this->_packageInfo['configure_options']) &&
 830            count($this->_packageInfo['configure_options']);
 831    }
 832
 833    function addConfigureOption($name, $prompt, $default = false)
 834    {
 835        $o = array('name' => $name, 'prompt' => $prompt);
 836        if ($default !== false) {
 837            $o['default'] = $default;
 838        }
 839        if (!isset($this->_packageInfo['configure_options'])) {
 840            $this->_packageInfo['configure_options'] = array();
 841        }
 842        $this->_packageInfo['configure_options'][] = $o;
 843    }
 844
 845    function clearConfigureOptions()
 846    {
 847        unset($this->_packageInfo['configure_options']);
 848    }
 849
 850    function getProvides()
 851    {
 852        if (isset($this->_packageInfo['provides'])) {
 853            return $this->_packageInfo['provides'];
 854        }
 855        return false;
 856    }
 857
 858    function getProvidesExtension()
 859    {
 860        return false;
 861    }
 862
 863    function addFile($dir, $file, $attrs)
 864    {
 865        $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
 866        if ($dir == '/' || $dir == '') {
 867            $dir = '';
 868        } else {
 869            $dir .= '/';
 870        }
 871        $file = $dir . $file;
 872        $file = preg_replace('![\\/]+!', '/', $file);
 873        $this->_packageInfo['filelist'][$file] = $attrs;
 874    }
 875
 876    function getInstallationFilelist()
 877    {
 878        return $this->getFilelist();
 879    }
 880
 881    function getFilelist()
 882    {
 883        if (isset($this->_packageInfo['filelist'])) {
 884            return $this->_packageInfo['filelist'];
 885        }
 886        return false;
 887    }
 888
 889    function setFileAttribute($file, $attr, $value)
 890    {
 891        $this->_packageInfo['filelist'][$file][$attr] = $value;
 892    }
 893
 894    function resetFilelist()
 895    {
 896        $this->_packageInfo['filelist'] = array();
 897    }
 898
 899    function setInstalledAs($file, $path)
 900    {
 901        if ($path) {
 902            return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
 903        }
 904        unset($this->_packageInfo['filelist'][$file]['installed_as']);
 905    }
 906
 907    function installedFile($file, $atts)
 908    {
 909        if (isset($this->_packageInfo['filelist'][$file])) {
 910            $this->_packageInfo['filelist'][$file] =
 911                array_merge($this->_packageInfo['filelist'][$file], $atts);
 912        } else {
 913            $this->_packageInfo['filelist'][$file] = $atts;
 914        }
 915    }
 916
 917    function getChangelog()
 918    {
 919        if (isset($this->_packageInfo['changelog'])) {
 920            return $this->_packageInfo['changelog'];
 921        }
 922        return false;
 923    }
 924
 925    function getPackagexmlVersion()
 926    {
 927        return '1.0';
 928    }
 929
 930    /**
 931     * Wrapper to {@link PEAR_ErrorStack::getErrors()}
 932     * @param boolean determines whether to purge the error stack after retrieving
 933     * @return array
 934     */
 935    function getValidationWarnings($purge = true)
 936    {
 937        return $this->_stack->getErrors($purge);
 938    }
 939
 940    // }}}
 941    /**
 942     * Validation error.  Also marks the object contents as invalid
 943     * @param error code
 944     * @param array error information
 945     * @access private
 946     */
 947    function _validateError($code, $params = array())
 948    {
 949        $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
 950        $this->_isValid = false;
 951    }
 952
 953    /**
 954     * Validation warning.  Does not mark the object contents invalid.
 955     * @param error code
 956     * @param array error information
 957     * @access private
 958     */
 959    function _validateWarning($code, $params = array())
 960    {
 961        $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
 962    }
 963
 964    /**
 965     * @param integer error code
 966     * @access protected
 967     */
 968    function _getErrorMessage()
 969    {
 970        return array(
 971                PEAR_PACKAGEFILE_ERROR_NO_NAME =>
 972                    'Missing Package Name',
 973                PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
 974                    'No summary found',
 975                PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
 976                    'Summary should be on one line',
 977                PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
 978                    'Missing description',
 979                PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
 980                    'Missing license',
 981                PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
 982                    'No release version found',
 983                PEAR_PACKAGEFILE_ERROR_NO_STATE =>
 984                    'No release state found',
 985                PEAR_PACKAGEFILE_ERROR_NO_DATE =>
 986                    'No release date found',
 987                PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
 988                    'No release notes found',
 989                PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
 990                    'Package must have at least one lead maintainer',
 991                PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
 992                    'No maintainers found, at least one must be defined',
 993                PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
 994                    'Maintainer %index% has no handle (user ID at channel server)',
 995                PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
 996                    'Maintainer %index% has no role',
 997                PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
 998                    'Maintainer %index% has no name',
 999                PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
1000                    'Maintainer %index% has no email',
1001                PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
1002                    'Dependency %index% is not a php dependency, and has no name',
1003                PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
1004                    'Dependency %index% has no relation (rel)',
1005                PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
1006                    'Dependency %index% has no type',
1007                PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
1008                    'PHP Dependency %index% has a name attribute of "%name%" which will be' .
1009                        ' ignored!',
1010                PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
1011                    'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
1012                        'and has no version',
1013                PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
1014                    'Dependency %index% is a type="php" dependency, ' .
1015                        'and has no version',
1016                PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
1017                    'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
1018                PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
1019                    'Dependency %index% has invalid optional value "%opt%", should be yes or no',
1020                PEAR_PACKAGEFILE_PHP_NO_NOT =>
1021                    'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
1022                        ' to exclude specific versions',
1023                PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
1024                    'Configure Option %index% has no name',
1025                PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
1026                    'Configure Option %index% has no prompt',
1027                PEAR_PACKAGEFILE_ERROR_NO_FILES =>
1028                    'No files in <filelist> section of package.xml',
1029                PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
1030                    'File "%file%" has no role, expecting one of "%roles%"',
1031                PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
1032                    'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
1033                PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
1034                    'File "%file%" cannot start with ".", cannot package or install',
1035                PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
1036                    'Parser error: invalid PHP found in file "%file%"',
1037                PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
1038                    'in %file%: %type% "%name%" not prefixed with package name "%package%"',
1039                PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
1040                    'Parser error: invalid PHP file "%file%"',
1041                PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
1042                    'Channel validator error: field "%field%" - %reason%',
1043                PEAR_PACKAGEFILE_ERROR_PHP5 =>
1044                    'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
1045                PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
1046                    'File "%file%" in package.xml does not exist',
1047                PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
1048                    'Package.xml contains non-ISO-8859-1 characters, and may not validate',
1049            );
1050    }
1051
1052    /**
1053     * Validate XML package definition file.
1054     *
1055     * @access public
1056     * @return boolean
1057     */
1058    function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
1059    {
1060        if (($this->_isValid & $state) == $state) {
1061            return true;
1062        }
1063        $this->_isValid = true;
1064        $info = $this->_packageInfo;
1065        if (empty($info['package'])) {
1066            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
1067            $this->_packageName = $pn = 'unknown';
1068        } else {
1069            $this->_packageName = $pn = $info['package'];
1070        }
1071
1072        if (empty($info['summary'])) {
1073            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
1074        } elseif (strpos(trim($info['summary']), "\n") !== false) {
1075            $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
1076                array('summary' => $info['summary']));
1077        }
1078        if (empty($info['description'])) {
1079            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
1080        }
1081        if (empty($info['release_license'])) {
1082            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
1083        }
1084        if (empty($info['version'])) {
1085            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
1086        }
1087        if (empty($info['release_state'])) {
1088            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
1089        }
1090        if (empty($info['release_date'])) {
1091            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
1092        }
1093        if (empty($info['release_notes'])) {
1094            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
1095        }
1096        if (empty($info['maintainers'])) {
1097            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
1098        } else {
1099            $haslead = false;
1100            $i = 1;
1101            foreach ($info['maintainers'] as $m) {
1102                if (empty($m['handle'])) {
1103                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
1104                        array('index' => $i));
1105                }
1106                if (empty($m['role'])) {
1107                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
1108                        array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
1109                } elseif ($m['role'] == 'lead') {
1110                    $haslead = true;
1111                }
1112                if (empty($m['name'])) {
1113                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
1114                        array('index' => $i));
1115                }
1116                if (empty($m['email'])) {
1117                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
1118                        array('index' => $i));
1119                }
1120                $i++;
1121            }
1122            if (!$haslead) {
1123                $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
1124            }
1125        }
1126        if (!empty($info['release_deps'])) {
1127            $i = 1;
1128            foreach ($info['release_deps'] as $d) {
1129                if (!isset($d['type']) || empty($d['type'])) {
1130                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
1131                        array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
1132                    continue;
1133                }
1134                if (!isset($d['rel']) || empty($d['rel'])) {
1135                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
1136                        array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
1137                    continue;
1138                }
1139                if (!empty($d['optional'])) {
1140                    if (!in_array($d['optional'], array('yes', 'no'))) {
1141                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
1142                            array('index' => $i, 'opt' => $d['optional']));
1143                    }
1144                }
1145                if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
1146                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
1147                        array('index' => $i));
1148                } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
1149                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
1150                        array('index' => $i, 'rel' => $d['rel']));
1151                }
1152                if ($d['type'] == 'php' && !empty($d['name'])) {
1153                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
1154                        array('index' => $i, 'name' => $d['name']));
1155                } elseif ($d['type'] != 'php' && empty($d['name'])) {
1156                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
1157                        array('index' => $i));
1158                }
1159                if ($d['type'] == 'php' && empty($d['version'])) {
1160                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
1161                        array('index' => $i));
1162                }
1163                if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
1164                    $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
1165                        array('index' => $i));
1166                }
1167                $i++;
1168            }
1169        }
1170        if (!empty($info['configure_options'])) {
1171            $i = 1;
1172            foreach ($info['configure_options'] as $c) {
1173                if (empty($c['name'])) {
1174                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
1175                        array('index' => $i));
1176                }
1177                if (empty($c['prompt'])) {
1178                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
1179                        array('index' => $i));
1180                }
1181                $i++;
1182            }
1183        }
1184        if (empty($info['filelist'])) {
1185            $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
1186            $errors[] = 'no files';
1187        } else {
1188            foreach ($info['filelist'] as $file => $fa) {
1189                if (empty($fa['role'])) {
1190                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
1191                        array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
1192                    continue;
1193                } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
1194                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
1195                        array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
1196                }
1197                if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
1198                    // file contains .. parent directory or . cur directory references
1199                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
1200                        array('file' => $file));
1201                }
1202                if (isset($fa['install-as']) &&
1203                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
1204                                 str_replace('\\', '/', $fa['install-as']))) {
1205                    // install-as contains .. parent directory or . cur directory references
1206                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
1207                        array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
1208                }
1209                if (isset($fa['baseinstalldir']) &&
1210                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
1211                                 str_replace('\\', '/', $fa['baseinstalldir']))) {
1212                    // install-as contains .. parent directory or . cur directory references
1213                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
1214                        array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
1215                }
1216            }
1217        }
1218        if (isset($this->_registry) && $this->_isValid) {
1219            $chan = $this->_registry->getChannel('pear.php.net');
1220            if (PEAR::isError($chan)) {
1221                $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
1222                return $this->_isValid = 0;
1223            }
1224            $validator = $chan->getValidationObject();
1225            $validator->setPackageFile($this);
1226            $validator->validate($state);
1227            $failures = $validator->getFailures();
1228            foreach ($failures['errors'] as $error) {
1229                $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
1230            }
1231            foreach ($failures['warnings'] as $warning) {
1232                $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
1233            }
1234        }
1235        if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
1236            if ($this->_analyzePhpFiles()) {
1237                $this->_isValid = true;
1238            }
1239        }
1240        if ($this->_isValid) {
1241            return $this->_isValid = $state;
1242        }
1243        return $this->_isValid = 0;
1244    }
1245
1246    function _analyzePhpFiles()
1247    {
1248        if (!$this->_isValid) {
1249            return false;
1250        }
1251        if (!isset($this->_packageFile)) {
1252            return false;
1253        }
1254        $dir_prefix = dirname($this->_packageFile);
1255        $common = new PEAR_Common;
1256        $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
1257            array($common, 'log');
1258        $info = $this->getFilelist();
1259        foreach ($info as $file => $fa) {
1260            if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
1261                $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
1262                    array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
1263                continue;
1264            }
1265            if ($fa['role'] == 'php' && $dir_prefix) {
1266                call_user_func_array($log, array(1, "Analyzing $file"));
1267                $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
1268                if ($srcinfo) {
1269                    $this->_buildProvidesArray($srcinfo);
1270                }
1271            }
1272        }
1273        $this->_packageName = $pn = $this->getPackage();
1274        $pnl = strlen($pn);
1275        if (isset($this->_packageInfo['provides'])) {
1276            foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
1277                if (isset($what['explicit'])) {
1278                    // skip conformance checks if the provides entry is
1279                    // specified in the package.xml file
1280                    continue;
1281                }
1282                extract($what);
1283                if ($type == 'class') {
1284                    if (!strncasecmp($name, $pn, $pnl)) {
1285                        continue;
1286                    }
1287                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
1288                        array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
1289                } elseif ($type == 'function') {
1290                    if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
1291                        continue;
1292                    }
1293                    $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
1294                        array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
1295                }
1296            }
1297        }
1298        return $this->_isValid;
1299    }
1300
1301    /**
1302     * Get the default xml generator object
1303     *
1304     * @return PEAR_PackageFile_Generator_v1
1305     */
1306    function &getDefaultGenerator()
1307    {
1308        if (!class_exists('PEAR_PackageFile_Generator_v1')) {
1309            require_once 'PEAR/PackageFile/Generator/v1.php';
1310        }
1311        $a = &new PEAR_PackageFile_Generator_v1($this);
1312        return $a;
1313    }
1314
1315    /**
1316     * Get the contents of a file listed within the package.xml
1317     * @param string
1318     * @return string
1319     */
1320    function getFileContents($file)
1321    {
1322        if ($this->_archiveFile == $this->_packageFile) { // unpacked
1323            $dir = dirname($this->_packageFile);
1324            $file = $dir . DIRECTORY_SEPARATOR . $file;
1325            $file = str_replace(array('/', '\\'),
1326                array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
1327            if (file_exists($file) && is_readable($file)) {
1328                return implode('', file($file));
1329            }
1330        } else { // tgz
1331            if (!class_exists('Archive_Tar')) {
1332                require_once 'Archive/Tar.php';
1333            }
1334            $tar = &new Archive_Tar($this->_archiveFile);
1335            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
1336            if ($file != 'package.xml' && $file != 'package2.xml') {
1337                $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
1338            }
1339            $file = $tar->extractInString($file);
1340            $tar->popErrorHandling();
1341            if (PEAR::isError($file)) {
1342                return PEAR::raiseError("Cannot locate file '$file' in archive");
1343            }
1344            return $file;
1345        }
1346    }
1347
1348    // {{{ analyzeSourceCode()
1349    /**
1350     * Analyze the source code of the given PHP file
1351     *
1352     * @param  string Filename of the PHP file
1353     * @return mixed
1354     * @access private
1355     */
1356    function _analyzeSourceCode($file)
1357    {
1358        if (!function_exists("token_get_all")) {
1359            return false;
1360        }
1361        if (!defined('T_DOC_COMMENT')) {
1362            define('T_DOC_COMMENT', T_COMMENT);
1363        }
1364        if (!defined('T_INTERFACE')) {
1365            define('T_INTERFACE', -1);
1366        }
1367        if (!defined('T_IMPLEMENTS')) {
1368            define('T_IMPLEMENTS', -1);
1369        }
1370        if (!$fp = @fopen($file, "r")) {
1371            return false;
1372        }
1373        fclose($fp);
1374        $contents = file_get_contents($file);
1375        $tokens = token_get_all($contents);
1376/*
1377        for ($i = 0; $i < sizeof($tokens); $i++) {
1378            @list($token, $data) = $tokens[$i];
1379            if (is_string($token)) {
1380                var_dump($token);
1381            } else {
1382                print token_name($token) . ' ';
1383                var_dump(rtrim($data));
1384            }
1385        }
1386*/
1387        $look_for = 0;
1388        $paren_level = 0;
1389        $bracket_level = 0;
1390        $brace_level = 0;
1391        $lastphpdoc = '';
1392        $current_class = '';
1393        $current_interface = '';
1394        $current_class_level = -1;
1395        $current_function = '';
1396        $current_function_level = -1;
1397        $declared_classes = array();
1398        $declared_interfaces = array();
1399        $declared_functions = array();
1400        $declared_methods = array();
1401        $used_classes = array();
1402        $used_functions = array();
1403        $extends = array();
1404        $implements = array();
1405        $nodeps = array();
1406        $inquote = false;
1407        $interface = false;
1408        for ($i = 0; $i < sizeof($tokens); $i++) {
1409            if (is_array($tokens[$i])) {
1410                list($token, $data) = $tokens[$i];
1411            } else {
1412                $token = $tokens[$i];
1413                $data = '';
1414            }
1415            if ($inquote) {
1416                if ($token != '"' && $token != T_END_HEREDOC) {
1417                    continue;
1418                } else {
1419                    $inquote = false;
1420                    continue;
1421                }
1422            }
1423            switch ($token) {
1424                case T_WHITESPACE :
1425                    continue;
1426                case ';':
1427                    if ($interface) {
1428                        $current_function = '';
1429                        $current_function_level = -1;
1430                    }
1431                    break;
1432                case '"':
1433                case T_START_HEREDOC:
1434                    $inquote = true;
1435                    break;
1436                case T_CURLY_OPEN:
1437                case T_DOLLAR_OPEN_CURLY_BRACES:
1438                case '{': $brace_level++; continue 2;
1439                case '}':
1440                    $brace_level--;
1441                    if ($current_class_level == $brace_level) {
1442                        $current_class = '';
1443                        $current_class_level = -1;
1444                    }
1445                    if ($current_function_level == $brace_level) {
1446                        $current_function = '';
1447                        $current_function_level = -1;
1448                    }
1449                    continue 2;
1450                case '[': $bracket_level++; continue 2;
1451                case ']': $bracket_level--; continue 2;
1452                case '(': $paren_level++;   continue 2;
1453                case ')': $paren_level--;   continue 2;
1454                case T_INTERFACE:
1455                    $interface = true;
1456                case T_CLASS:
1457                    if (($current_class_level != -1) || ($current_function_level != -1)) {
1458                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
1459                            array('file' => $file));
1460                        return false;
1461                    }
1462                case T_FUNCTION:
1463                case T_NEW:
1464                case T_EXTENDS:
1465                case T_IMPLEMENTS:
1466                    $look_for = $token;
1467                    continue 2;
1468                case T_STRING:
1469                    if (version_compare(zend_version(), '2.0', '<')) {
1470                        if (in_array(strtolower($data),
1471                            array('public', 'private', 'protected', 'abstract',
1472                                  'interface', 'implements', 'throw') 
1473                                 )) {
1474                            $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
1475                                array($file));
1476                        }
1477                    }
1478                    if ($look_for == T_CLASS) {
1479                        $current_class = $data;
1480                        $current_class_level = $brace_level;
1481                        $declared_classes[] = $current_class;
1482                    } elseif ($look_for == T_INTERFACE) {
1483                        $current_interface = $data;
1484                        $current_class_level = $brace_level;
1485                        $declared_interfaces[] = $current_interface;
1486                    } elseif ($look_for == T_IMPLEMENTS) {
1487                        $implements[$current_class] = $data;
1488                    } elseif ($look_for == T_EXTENDS) {
1489                        $extends[$current_class] = $data;
1490                    } elseif ($look_for == T_FUNCTION) {
1491                        if ($current_class) {
1492                            $current_function = "$current_class::$data";
1493                            $declared_methods[$current_class][] = $data;
1494                        } elseif ($current_interface) {
1495                            $current_function = "$current_interface::$data";
1496                            $declared_methods[$current_interface][] = $data;
1497                        } else {
1498                            $current_function = $data;
1499                            $declared_functions[] = $current_function;
1500                        }
1501                        $current_function_level = $brace_level;
1502                        $m = array();
1503                    } elseif ($look_for == T_NEW) {
1504                        $used_classes[$data] = true;
1505                    }
1506                    $look_for = 0;
1507                    continue 2;
1508                case T_VARIABLE:
1509                    $look_for = 0;
1510                    continue 2;
1511                case T_DOC_COMMENT:
1512                case T_COMMENT:
1513                    if (preg_match('!^/\*\*\s!', $data)) {
1514                        $lastphpdoc = $data;
1515                        if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
1516                            $nodeps = array_merge($nodeps, $m[1]);
1517                        }
1518                    }
1519                    continue 2;
1520                case T_DOUBLE_COLON:
1521                    if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
1522                        $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
1523                            array('file' => $file));
1524                        return false;
1525                    }
1526                    $class = $tokens[$i - 1][1];
1527                    if (strtolower($class) != 'parent') {
1528                        $used_classes[$class] = true;
1529                    }
1530                    continue 2;
1531            }
1532        }
1533        return array(
1534            "source_file" => $file,
1535            "declared_classes" => $declared_classes,
1536            "declared_interfaces" => $declared_interfaces,
1537            "declared_methods" => $declared_methods,
1538            "declared_functions" => $declared_functions,
1539            "used_classes" => array_diff(array_keys($used_classes), $nodeps),
1540            "inheritance" => $extends,
1541            "implements" => $implements,
1542            );
1543    }
1544
1545    /**
1546     * Build a "provides" array from data returned by
1547     * analyzeSourceCode().  The format of the built array is like
1548     * this:
1549     *
1550     *  array(
1551     *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
1552     *    ...
1553     *  )
1554     *
1555     *
1556     * @param array $srcinfo array with information about a source file
1557     * as returned by the analyzeSourceCode() method.
1558     *
1559     * @return void
1560     *
1561     * @access private
1562     *
1563     */
1564    function _buildProvidesArray($srcinfo)
1565    {
1566        if (!$this->_isValid) {
1567            return false;
1568        }
1569        $file = basename($srcinfo['source_file']);
1570        $pn = $this->getPackage();
1571        $pnl = strlen($pn);
1572        foreach ($srcinfo['declared_classes'] as $class) {
1573            $key = "class;$class";
1574            if (isset($this->_packageInfo['provides'][$key])) {
1575                continue;
1576            }
1577            $this->_packageInfo['provides'][$key] =
1578                array('file'=> $file, 'type' => 'class', 'name' => $class);
1579            if (isset($srcinfo['inheritance'][$class])) {
1580                $this->_packageInfo['provides'][$key]['extends'] =
1581                    $srcinfo['inheritance'][$class];
1582        

Large files files are truncated, but you can click here to view the full file