PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/script/lib/PEAR/PackageFile/v1.php

https://bitbucket.org/renaatdemuynck/chamilo
PHP | 1705 lines | 1238 code | 145 blank | 322 comment | 168 complexity | ec0c248c5146f02ed30c4f521d38de9f MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0

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

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