PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/common/libraries/plugin/pear/PEAR/PackageFile/v1.php

https://bitbucket.org/ywarnier/chamilo-dev
PHP | 1711 lines | 1238 code | 145 blank | 328 comment | 168 complexity | 9a9f734550205bb2ceec799283f1a40d MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT

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

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