PageRenderTime 54ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/downloader/pearlib/php/PEAR/PackageFile/v1.php

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

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