PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/app/siteinvoice/lib/PEAR/PEAR/Common.php

https://github.com/lux/sitellite
PHP | 1117 lines | 559 code | 92 blank | 466 comment | 92 complexity | a76ed6cb121a935e3338b416385d1834 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. /**
  3. * PEAR_Common, the base class for the PEAR Installer
  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 Stig Bakken <ssb@php.net>
  16. * @author Tomas V. V. Cox <cox@idecnet.com>
  17. * @author Greg Beaver <cellog@php.net>
  18. * @copyright 1997-2005 The PHP Group
  19. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  20. * @version CVS: $Id: Common.php,v 1.1 2005/07/02 21:12:30 lux Exp $
  21. * @link http://pear.php.net/package/PEAR
  22. * @since File available since Release 0.1.0
  23. * @deprecated File deprecated since Release 1.4.0a1
  24. */
  25. /**
  26. * Include error handling
  27. */
  28. require_once 'PEAR.php';
  29. // {{{ constants and globals
  30. /**
  31. * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
  32. */
  33. define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
  34. define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
  35. define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/');
  36. // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
  37. define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
  38. define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i');
  39. // XXX far from perfect :-)
  40. define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
  41. ')(-([.0-9a-zA-Z]+))?');
  42. define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
  43. '$/');
  44. define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9_\.]+');
  45. define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '$/');
  46. // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
  47. define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(\/[a-zA-Z0-9-]+)*');
  48. define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '$/i');
  49. define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
  50. . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
  51. define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '$/i');
  52. define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
  53. . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
  54. define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '$/');
  55. /**
  56. * List of temporary files and directories registered by
  57. * PEAR_Common::addTempFile().
  58. * @var array
  59. */
  60. $GLOBALS['_PEAR_Common_tempfiles'] = array();
  61. /**
  62. * Valid maintainer roles
  63. * @var array
  64. */
  65. $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
  66. /**
  67. * Valid release states
  68. * @var array
  69. */
  70. $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
  71. /**
  72. * Valid dependency types
  73. * @var array
  74. */
  75. $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
  76. /**
  77. * Valid dependency relations
  78. * @var array
  79. */
  80. $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
  81. /**
  82. * Valid file roles
  83. * @var array
  84. */
  85. $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
  86. /**
  87. * Valid replacement types
  88. * @var array
  89. */
  90. $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
  91. /**
  92. * Valid "provide" types
  93. * @var array
  94. */
  95. $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
  96. /**
  97. * Valid "provide" types
  98. * @var array
  99. */
  100. $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');
  101. // }}}
  102. /**
  103. * Class providing common functionality for PEAR administration classes.
  104. * @category pear
  105. * @package PEAR
  106. * @author Stig Bakken <ssb@php.net>
  107. * @author Tomas V. V. Cox <cox@idecnet.com>
  108. * @author Greg Beaver <cellog@php.net>
  109. * @copyright 1997-2005 The PHP Group
  110. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  111. * @version Release: 1.4.0a12
  112. * @link http://pear.php.net/package/PEAR
  113. * @since Class available since Release 1.4.0a1
  114. * @deprecated This class will disappear, and its components will be spread
  115. * into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
  116. */
  117. class PEAR_Common extends PEAR
  118. {
  119. // {{{ properties
  120. /** stack of elements, gives some sort of XML context */
  121. var $element_stack = array();
  122. /** name of currently parsed XML element */
  123. var $current_element;
  124. /** array of attributes of the currently parsed XML element */
  125. var $current_attributes = array();
  126. /** assoc with information about a package */
  127. var $pkginfo = array();
  128. /**
  129. * User Interface object (PEAR_Frontend_* class). If null,
  130. * the log() method uses print.
  131. * @var object
  132. */
  133. var $ui = null;
  134. /**
  135. * Configuration object (PEAR_Config).
  136. * @var object
  137. */
  138. var $config = null;
  139. var $current_path = null;
  140. /**
  141. * PEAR_SourceAnalyzer instance
  142. * @var object
  143. */
  144. var $source_analyzer = null;
  145. /**
  146. * Flag variable used to mark a valid package file
  147. * @var boolean
  148. * @access private
  149. */
  150. var $_validPackageFile;
  151. // }}}
  152. // {{{ constructor
  153. /**
  154. * PEAR_Common constructor
  155. *
  156. * @access public
  157. */
  158. function PEAR_Common()
  159. {
  160. parent::PEAR();
  161. $this->config = &PEAR_Config::singleton();
  162. $this->debug = $this->config->get('verbose');
  163. }
  164. // }}}
  165. // {{{ destructor
  166. /**
  167. * PEAR_Common destructor
  168. *
  169. * @access private
  170. */
  171. function _PEAR_Common()
  172. {
  173. // doesn't work due to bug #14744
  174. //$tempfiles = $this->_tempfiles;
  175. $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
  176. while ($file = array_shift($tempfiles)) {
  177. if (@is_dir($file)) {
  178. if (!class_exists('System')) {
  179. require_once 'System.php';
  180. }
  181. System::rm(array('-rf', $file));
  182. } elseif (file_exists($file)) {
  183. unlink($file);
  184. }
  185. }
  186. }
  187. // }}}
  188. // {{{ addTempFile()
  189. /**
  190. * Register a temporary file or directory. When the destructor is
  191. * executed, all registered temporary files and directories are
  192. * removed.
  193. *
  194. * @param string $file name of file or directory
  195. *
  196. * @return void
  197. *
  198. * @access public
  199. */
  200. function addTempFile($file)
  201. {
  202. if (!class_exists('PEAR_Frontend')) {
  203. require_once 'PEAR/Frontend.php';
  204. }
  205. PEAR_Frontend::addTempFile($file);
  206. }
  207. // }}}
  208. // {{{ mkDirHier()
  209. /**
  210. * Wrapper to System::mkDir(), creates a directory as well as
  211. * any necessary parent directories.
  212. *
  213. * @param string $dir directory name
  214. *
  215. * @return bool TRUE on success, or a PEAR error
  216. *
  217. * @access public
  218. */
  219. function mkDirHier($dir)
  220. {
  221. $this->log(2, "+ create dir $dir");
  222. if (!class_exists('System')) {
  223. require_once 'System.php';
  224. }
  225. return System::mkDir(array('-p', $dir));
  226. }
  227. // }}}
  228. // {{{ log()
  229. /**
  230. * Logging method.
  231. *
  232. * @param int $level log level (0 is quiet, higher is noisier)
  233. * @param string $msg message to write to the log
  234. *
  235. * @return void
  236. *
  237. * @access public
  238. * @static
  239. */
  240. function log($level, $msg, $append_crlf = true)
  241. {
  242. if ($this->debug >= $level) {
  243. if (!class_exists('PEAR_Frontend')) {
  244. require_once 'PEAR/Frontend.php';
  245. }
  246. $ui = &PEAR_Frontend::singleton();
  247. if (is_a($ui, 'PEAR_Frontend')) {
  248. $ui->log($msg, $append_crlf);
  249. } else {
  250. print "$msg\n";
  251. }
  252. }
  253. }
  254. // }}}
  255. // {{{ mkTempDir()
  256. /**
  257. * Create and register a temporary directory.
  258. *
  259. * @param string $tmpdir (optional) Directory to use as tmpdir.
  260. * Will use system defaults (for example
  261. * /tmp or c:\windows\temp) if not specified
  262. *
  263. * @return string name of created directory
  264. *
  265. * @access public
  266. */
  267. function mkTempDir($tmpdir = '')
  268. {
  269. if ($tmpdir) {
  270. $topt = array('-t', $tmpdir);
  271. } else {
  272. $topt = array();
  273. }
  274. $topt = array_merge($topt, array('-d', 'pear'));
  275. if (!class_exists('System')) {
  276. require_once 'System.php';
  277. }
  278. if (!$tmpdir = System::mktemp($topt)) {
  279. return false;
  280. }
  281. $this->addTempFile($tmpdir);
  282. return $tmpdir;
  283. }
  284. // }}}
  285. // {{{ setFrontendObject()
  286. /**
  287. * Set object that represents the frontend to be used.
  288. *
  289. * @param object Reference of the frontend object
  290. * @return void
  291. * @access public
  292. */
  293. function setFrontendObject(&$ui)
  294. {
  295. $this->ui = &$ui;
  296. }
  297. // }}}
  298. // {{{ infoFromTgzFile()
  299. /**
  300. * Returns information about a package file. Expects the name of
  301. * a gzipped tar file as input.
  302. *
  303. * @param string $file name of .tgz file
  304. *
  305. * @return array array with package information
  306. *
  307. * @access public
  308. * @deprecated use PEAR_PackageFile->fromTgzFile() instead
  309. *
  310. */
  311. function infoFromTgzFile($file)
  312. {
  313. $packagefile = &new PEAR_PackageFile($this->config);
  314. $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
  315. if (PEAR::isError($pf)) {
  316. $errs = $pf->getUserinfo();
  317. if (is_array($errs)) {
  318. foreach ($errs as $error) {
  319. $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
  320. }
  321. }
  322. return $pf;
  323. }
  324. return $this->_postProcessValidPackagexml($pf);
  325. }
  326. // }}}
  327. // {{{ infoFromDescriptionFile()
  328. /**
  329. * Returns information about a package file. Expects the name of
  330. * a package xml file as input.
  331. *
  332. * @param string $descfile name of package xml file
  333. *
  334. * @return array array with package information
  335. *
  336. * @access public
  337. * @deprecated use PEAR_PackageFile->fromPackageFile() instead
  338. *
  339. */
  340. function infoFromDescriptionFile($descfile)
  341. {
  342. $packagefile = &new PEAR_PackageFile($this->config);
  343. $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
  344. if (PEAR::isError($pf)) {
  345. $errs = $pf->getUserinfo();
  346. if (is_array($errs)) {
  347. foreach ($errs as $error) {
  348. $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
  349. }
  350. }
  351. return $pf;
  352. }
  353. return $this->_postProcessValidPackagexml($pf);
  354. }
  355. // }}}
  356. // {{{ infoFromString()
  357. /**
  358. * Returns information about a package file. Expects the contents
  359. * of a package xml file as input.
  360. *
  361. * @param string $data contents of package.xml file
  362. *
  363. * @return array array with package information
  364. *
  365. * @access public
  366. * @deprecated use PEAR_PackageFile->fromXmlstring() instead
  367. *
  368. */
  369. function infoFromString($data)
  370. {
  371. $packagefile = &new PEAR_PackageFile($this->config);
  372. $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
  373. if (PEAR::isError($pf)) {
  374. $errs = $pf->getUserinfo();
  375. if (is_array($errs)) {
  376. foreach ($errs as $error) {
  377. $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
  378. }
  379. }
  380. return $pf;
  381. }
  382. return $this->_postProcessValidPackagexml($pf);
  383. }
  384. // }}}
  385. /**
  386. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  387. * @return array
  388. */
  389. function _postProcessValidPackagexml(&$pf)
  390. {
  391. if (is_a($pf, 'PEAR_PackageFile_v2')) {
  392. // sort of make this into a package.xml 1.0-style array
  393. // changelog is not converted to old format.
  394. $arr = $pf->toArray(true);
  395. $arr = array_merge($arr, $arr['old']);
  396. unset($arr['old']);
  397. unset($arr['xsdversion']);
  398. unset($arr['contents']);
  399. unset($arr['compatible']);
  400. unset($arr['channel']);
  401. unset($arr['uri']);
  402. unset($arr['dependencies']);
  403. unset($arr['phprelease']);
  404. unset($arr['extsrcrelease']);
  405. unset($arr['extbinrelease']);
  406. unset($arr['bundle']);
  407. unset($arr['lead']);
  408. unset($arr['developer']);
  409. unset($arr['helper']);
  410. unset($arr['contributor']);
  411. $arr['filelist'] = $pf->getFilelist();
  412. $this->pkginfo = $arr;
  413. return $arr;
  414. } else {
  415. $this->pkginfo = $pf->toArray();
  416. return $this->pkginfo;
  417. }
  418. }
  419. // {{{ infoFromAny()
  420. /**
  421. * Returns package information from different sources
  422. *
  423. * This method is able to extract information about a package
  424. * from a .tgz archive or from a XML package definition file.
  425. *
  426. * @access public
  427. * @param string Filename of the source ('package.xml', '<package>.tgz')
  428. * @return string
  429. * @deprecated use PEAR_PackageFile->fromAnyFile() instead
  430. */
  431. function infoFromAny($info)
  432. {
  433. if (is_string($info) && file_exists($info)) {
  434. $packagefile = &new PEAR_PackageFile($this->config);
  435. $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
  436. if (PEAR::isError($pf)) {
  437. $errs = $pf->getUserinfo();
  438. if (is_array($errs)) {
  439. foreach ($errs as $error) {
  440. $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
  441. }
  442. }
  443. return $pf;
  444. }
  445. return $this->_postProcessValidPackagexml($pf);
  446. }
  447. return $info;
  448. }
  449. // }}}
  450. // {{{ xmlFromInfo()
  451. /**
  452. * Return an XML document based on the package info (as returned
  453. * by the PEAR_Common::infoFrom* methods).
  454. *
  455. * @param array $pkginfo package info
  456. *
  457. * @return string XML data
  458. *
  459. * @access public
  460. * @deprecated use a PEAR_PackageFile_v* object's generator instead
  461. */
  462. function xmlFromInfo($pkginfo)
  463. {
  464. $config = &PEAR_Config::singleton();
  465. $packagefile = &new PEAR_PackageFile($config);
  466. $pf = &$packagefile->fromArray($pkginfo);
  467. $gen = &$pf->getDefaultGenerator();
  468. return $gen->toXml(PEAR_VALIDATE_PACKAGING);
  469. }
  470. // }}}
  471. // {{{ validatePackageInfo()
  472. /**
  473. * Validate XML package definition file.
  474. *
  475. * @param string $info Filename of the package archive or of the
  476. * package definition file
  477. * @param array $errors Array that will contain the errors
  478. * @param array $warnings Array that will contain the warnings
  479. * @param string $dir_prefix (optional) directory where source files
  480. * may be found, or empty if they are not available
  481. * @access public
  482. * @return boolean
  483. * @deprecated use the validation of PEAR_PackageFile objects
  484. */
  485. function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
  486. {
  487. $config = &PEAR_Config::singleton();
  488. $packagefile = &new PEAR_PackageFile($config);
  489. PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
  490. $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
  491. PEAR::staticPopErrorHandling();
  492. if (PEAR::isError($pf)) {
  493. $errs = $pf->getUserinfo();
  494. if (is_array($errs)) {
  495. foreach ($errs as $error) {
  496. if ($error['level'] == 'error') {
  497. $errors[] = $error['message'];
  498. } else {
  499. $warnings[] = $error['message'];
  500. }
  501. }
  502. }
  503. return false;
  504. }
  505. return true;
  506. }
  507. // }}}
  508. // {{{ buildProvidesArray()
  509. /**
  510. * Build a "provides" array from data returned by
  511. * analyzeSourceCode(). The format of the built array is like
  512. * this:
  513. *
  514. * array(
  515. * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
  516. * ...
  517. * )
  518. *
  519. *
  520. * @param array $srcinfo array with information about a source file
  521. * as returned by the analyzeSourceCode() method.
  522. *
  523. * @return void
  524. *
  525. * @access public
  526. *
  527. */
  528. function buildProvidesArray($srcinfo)
  529. {
  530. $file = basename($srcinfo['source_file']);
  531. $pn = '';
  532. if (isset($this->_packageName)) {
  533. $pn = $this->_packageName;
  534. }
  535. $pnl = strlen($pn);
  536. foreach ($srcinfo['declared_classes'] as $class) {
  537. $key = "class;$class";
  538. if (isset($this->pkginfo['provides'][$key])) {
  539. continue;
  540. }
  541. $this->pkginfo['provides'][$key] =
  542. array('file'=> $file, 'type' => 'class', 'name' => $class);
  543. if (isset($srcinfo['inheritance'][$class])) {
  544. $this->pkginfo['provides'][$key]['extends'] =
  545. $srcinfo['inheritance'][$class];
  546. }
  547. }
  548. foreach ($srcinfo['declared_methods'] as $class => $methods) {
  549. foreach ($methods as $method) {
  550. $function = "$class::$method";
  551. $key = "function;$function";
  552. if ($method{0} == '_' || !strcasecmp($method, $class) ||
  553. isset($this->pkginfo['provides'][$key])) {
  554. continue;
  555. }
  556. $this->pkginfo['provides'][$key] =
  557. array('file'=> $file, 'type' => 'function', 'name' => $function);
  558. }
  559. }
  560. foreach ($srcinfo['declared_functions'] as $function) {
  561. $key = "function;$function";
  562. if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
  563. continue;
  564. }
  565. if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
  566. $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
  567. }
  568. $this->pkginfo['provides'][$key] =
  569. array('file'=> $file, 'type' => 'function', 'name' => $function);
  570. }
  571. }
  572. // }}}
  573. // {{{ analyzeSourceCode()
  574. /**
  575. * Analyze the source code of the given PHP file
  576. *
  577. * @param string Filename of the PHP file
  578. * @return mixed
  579. * @access public
  580. */
  581. function analyzeSourceCode($file)
  582. {
  583. if (!function_exists("token_get_all")) {
  584. return false;
  585. }
  586. if (!defined('T_DOC_COMMENT')) {
  587. define('T_DOC_COMMENT', T_COMMENT);
  588. }
  589. if (!defined('T_INTERFACE')) {
  590. define('T_INTERFACE', -1);
  591. }
  592. if (!defined('T_IMPLEMENTS')) {
  593. define('T_IMPLEMENTS', -1);
  594. }
  595. if (!$fp = @fopen($file, "r")) {
  596. return false;
  597. }
  598. $contents = fread($fp, filesize($file));
  599. $tokens = token_get_all($contents);
  600. /*
  601. for ($i = 0; $i < sizeof($tokens); $i++) {
  602. @list($token, $data) = $tokens[$i];
  603. if (is_string($token)) {
  604. var_dump($token);
  605. } else {
  606. print token_name($token) . ' ';
  607. var_dump(rtrim($data));
  608. }
  609. }
  610. */
  611. $look_for = 0;
  612. $paren_level = 0;
  613. $bracket_level = 0;
  614. $brace_level = 0;
  615. $lastphpdoc = '';
  616. $current_class = '';
  617. $current_interface = '';
  618. $current_class_level = -1;
  619. $current_function = '';
  620. $current_function_level = -1;
  621. $declared_classes = array();
  622. $declared_interfaces = array();
  623. $declared_functions = array();
  624. $declared_methods = array();
  625. $used_classes = array();
  626. $used_functions = array();
  627. $extends = array();
  628. $implements = array();
  629. $nodeps = array();
  630. $inquote = false;
  631. $interface = false;
  632. for ($i = 0; $i < sizeof($tokens); $i++) {
  633. if (is_array($tokens[$i])) {
  634. list($token, $data) = $tokens[$i];
  635. } else {
  636. $token = $tokens[$i];
  637. $data = '';
  638. }
  639. if ($inquote) {
  640. if ($token != '"') {
  641. continue;
  642. } else {
  643. $inquote = false;
  644. }
  645. }
  646. switch ($token) {
  647. case T_WHITESPACE:
  648. continue;
  649. case ';':
  650. if ($interface) {
  651. $current_function = '';
  652. $current_function_level = -1;
  653. }
  654. break;
  655. case '"':
  656. $inquote = true;
  657. break;
  658. case T_CURLY_OPEN:
  659. case T_DOLLAR_OPEN_CURLY_BRACES:
  660. case '{': $brace_level++; continue 2;
  661. case '}':
  662. $brace_level--;
  663. if ($current_class_level == $brace_level) {
  664. $current_class = '';
  665. $current_class_level = -1;
  666. }
  667. if ($current_function_level == $brace_level) {
  668. $current_function = '';
  669. $current_function_level = -1;
  670. }
  671. continue 2;
  672. case '[': $bracket_level++; continue 2;
  673. case ']': $bracket_level--; continue 2;
  674. case '(': $paren_level++; continue 2;
  675. case ')': $paren_level--; continue 2;
  676. case T_INTERFACE:
  677. $interface = true;
  678. case T_CLASS:
  679. if (($current_class_level != -1) || ($current_function_level != -1)) {
  680. PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
  681. PEAR_COMMON_ERROR_INVALIDPHP);
  682. return false;
  683. }
  684. case T_FUNCTION:
  685. case T_NEW:
  686. case T_EXTENDS:
  687. case T_IMPLEMENTS:
  688. $look_for = $token;
  689. continue 2;
  690. case T_STRING:
  691. if (version_compare(zend_version(), '2.0', '<')) {
  692. if (in_array(strtolower($data),
  693. array('public', 'private', 'protected', 'abstract',
  694. 'interface', 'implements', 'clone', 'throw')
  695. )) {
  696. PEAR::raiseError('Error: PHP5 packages must be packaged by php 5 PEAR');
  697. return false;
  698. }
  699. }
  700. if ($look_for == T_CLASS) {
  701. $current_class = $data;
  702. $current_class_level = $brace_level;
  703. $declared_classes[] = $current_class;
  704. } elseif ($look_for == T_INTERFACE) {
  705. $current_interface = $data;
  706. $current_class_level = $brace_level;
  707. $declared_interfaces[] = $current_interface;
  708. } elseif ($look_for == T_IMPLEMENTS) {
  709. $implements[$current_class] = $data;
  710. } elseif ($look_for == T_EXTENDS) {
  711. $extends[$current_class] = $data;
  712. } elseif ($look_for == T_FUNCTION) {
  713. if ($current_class) {
  714. $current_function = "$current_class::$data";
  715. $declared_methods[$current_class][] = $data;
  716. } elseif ($current_interface) {
  717. $current_function = "$current_interface::$data";
  718. $declared_methods[$current_interface][] = $data;
  719. } else {
  720. $current_function = $data;
  721. $declared_functions[] = $current_function;
  722. }
  723. $current_function_level = $brace_level;
  724. $m = array();
  725. } elseif ($look_for == T_NEW) {
  726. $used_classes[$data] = true;
  727. }
  728. $look_for = 0;
  729. continue 2;
  730. case T_VARIABLE:
  731. $look_for = 0;
  732. continue 2;
  733. case T_DOC_COMMENT:
  734. case T_COMMENT:
  735. if (preg_match('!^/\*\*\s!', $data)) {
  736. $lastphpdoc = $data;
  737. if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
  738. $nodeps = array_merge($nodeps, $m[1]);
  739. }
  740. }
  741. continue 2;
  742. case T_DOUBLE_COLON:
  743. if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
  744. PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
  745. PEAR_COMMON_ERROR_INVALIDPHP);
  746. return false;
  747. }
  748. $class = $tokens[$i - 1][1];
  749. if (strtolower($class) != 'parent') {
  750. $used_classes[$class] = true;
  751. }
  752. continue 2;
  753. }
  754. }
  755. return array(
  756. "source_file" => $file,
  757. "declared_classes" => $declared_classes,
  758. "declared_interfaces" => $declared_interfaces,
  759. "declared_methods" => $declared_methods,
  760. "declared_functions" => $declared_functions,
  761. "used_classes" => array_diff(array_keys($used_classes), $nodeps),
  762. "inheritance" => $extends,
  763. "implements" => $implements,
  764. );
  765. }
  766. // }}}
  767. // {{{ betterStates()
  768. /**
  769. * Return an array containing all of the states that are more stable than
  770. * or equal to the passed in state
  771. *
  772. * @param string Release state
  773. * @param boolean Determines whether to include $state in the list
  774. * @return false|array False if $state is not a valid release state
  775. */
  776. function betterStates($state, $include = false)
  777. {
  778. static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
  779. $i = array_search($state, $states);
  780. if ($i === false) {
  781. return false;
  782. }
  783. if ($include) {
  784. $i--;
  785. }
  786. return array_slice($states, $i + 1);
  787. }
  788. // }}}
  789. // {{{ detectDependencies()
  790. function detectDependencies($any, $status_callback = null)
  791. {
  792. if (!function_exists("token_get_all")) {
  793. return false;
  794. }
  795. if (PEAR::isError($info = $this->infoFromAny($any))) {
  796. return $this->raiseError($info);
  797. }
  798. if (!is_array($info)) {
  799. return false;
  800. }
  801. $deps = array();
  802. $used_c = $decl_c = $decl_f = $decl_m = array();
  803. foreach ($info['filelist'] as $file => $fa) {
  804. $tmp = $this->analyzeSourceCode($file);
  805. $used_c = @array_merge($used_c, $tmp['used_classes']);
  806. $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
  807. $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
  808. $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
  809. $inheri = @array_merge($inheri, $tmp['inheritance']);
  810. }
  811. $used_c = array_unique($used_c);
  812. $decl_c = array_unique($decl_c);
  813. $undecl_c = array_diff($used_c, $decl_c);
  814. return array('used_classes' => $used_c,
  815. 'declared_classes' => $decl_c,
  816. 'declared_methods' => $decl_m,
  817. 'declared_functions' => $decl_f,
  818. 'undeclared_classes' => $undecl_c,
  819. 'inheritance' => $inheri,
  820. );
  821. }
  822. // }}}
  823. // {{{ getUserRoles()
  824. /**
  825. * Get the valid roles for a PEAR package maintainer
  826. *
  827. * @return array
  828. * @static
  829. */
  830. function getUserRoles()
  831. {
  832. return $GLOBALS['_PEAR_Common_maintainer_roles'];
  833. }
  834. // }}}
  835. // {{{ getReleaseStates()
  836. /**
  837. * Get the valid package release states of packages
  838. *
  839. * @return array
  840. * @static
  841. */
  842. function getReleaseStates()
  843. {
  844. return $GLOBALS['_PEAR_Common_release_states'];
  845. }
  846. // }}}
  847. // {{{ getDependencyTypes()
  848. /**
  849. * Get the implemented dependency types (php, ext, pkg etc.)
  850. *
  851. * @return array
  852. * @static
  853. */
  854. function getDependencyTypes()
  855. {
  856. return $GLOBALS['_PEAR_Common_dependency_types'];
  857. }
  858. // }}}
  859. // {{{ getDependencyRelations()
  860. /**
  861. * Get the implemented dependency relations (has, lt, ge etc.)
  862. *
  863. * @return array
  864. * @static
  865. */
  866. function getDependencyRelations()
  867. {
  868. return $GLOBALS['_PEAR_Common_dependency_relations'];
  869. }
  870. // }}}
  871. // {{{ getFileRoles()
  872. /**
  873. * Get the implemented file roles
  874. *
  875. * @return array
  876. * @static
  877. */
  878. function getFileRoles()
  879. {
  880. return $GLOBALS['_PEAR_Common_file_roles'];
  881. }
  882. // }}}
  883. // {{{ getReplacementTypes()
  884. /**
  885. * Get the implemented file replacement types in
  886. *
  887. * @return array
  888. * @static
  889. */
  890. function getReplacementTypes()
  891. {
  892. return $GLOBALS['_PEAR_Common_replacement_types'];
  893. }
  894. // }}}
  895. // {{{ getProvideTypes()
  896. /**
  897. * Get the implemented file replacement types in
  898. *
  899. * @return array
  900. * @static
  901. */
  902. function getProvideTypes()
  903. {
  904. return $GLOBALS['_PEAR_Common_provide_types'];
  905. }
  906. // }}}
  907. // {{{ getScriptPhases()
  908. /**
  909. * Get the implemented file replacement types in
  910. *
  911. * @return array
  912. * @static
  913. */
  914. function getScriptPhases()
  915. {
  916. return $GLOBALS['_PEAR_Common_script_phases'];
  917. }
  918. // }}}
  919. // {{{ validPackageName()
  920. /**
  921. * Test whether a string contains a valid package name.
  922. *
  923. * @param string $name the package name to test
  924. *
  925. * @return bool
  926. *
  927. * @access public
  928. */
  929. function validPackageName($name)
  930. {
  931. return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
  932. }
  933. // }}}
  934. // {{{ validPackageVersion()
  935. /**
  936. * Test whether a string contains a valid package version.
  937. *
  938. * @param string $ver the package version to test
  939. *
  940. * @return bool
  941. *
  942. * @access public
  943. */
  944. function validPackageVersion($ver)
  945. {
  946. return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
  947. }
  948. // }}}
  949. // {{{ downloadHttp()
  950. /**
  951. * Download a file through HTTP. Considers suggested file name in
  952. * Content-disposition: header and can run a callback function for
  953. * different events. The callback will be called with two
  954. * parameters: the callback type, and parameters. The implemented
  955. * callback types are:
  956. *
  957. * 'setup' called at the very beginning, parameter is a UI object
  958. * that should be used for all output
  959. * 'message' the parameter is a string with an informational message
  960. * 'saveas' may be used to save with a different file name, the
  961. * parameter is the filename that is about to be used.
  962. * If a 'saveas' callback returns a non-empty string,
  963. * that file name will be used as the filename instead.
  964. * Note that $save_dir will not be affected by this, only
  965. * the basename of the file.
  966. * 'start' download is starting, parameter is number of bytes
  967. * that are expected, or -1 if unknown
  968. * 'bytesread' parameter is the number of bytes read so far
  969. * 'done' download is complete, parameter is the total number
  970. * of bytes read
  971. * 'connfailed' if the TCP connection fails, this callback is called
  972. * with array(host,port,errno,errmsg)
  973. * 'writefailed' if writing to disk fails, this callback is called
  974. * with array(destfile,errmsg)
  975. *
  976. * If an HTTP proxy has been configured (http_proxy PEAR_Config
  977. * setting), the proxy will be used.
  978. *
  979. * @param string $url the URL to download
  980. * @param object $ui PEAR_Frontend_* instance
  981. * @param object $config PEAR_Config instance
  982. * @param string $save_dir (optional) directory to save file in
  983. * @param mixed $callback (optional) function/method to call for status
  984. * updates
  985. *
  986. * @return string Returns the full path of the downloaded file or a PEAR
  987. * error on failure. If the error is caused by
  988. * socket-related errors, the error object will
  989. * have the fsockopen error code available through
  990. * getCode().
  991. *
  992. * @access public
  993. * @deprecated in favor of PEAR_Downloader::downloadHttp()
  994. */
  995. function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
  996. {
  997. if (!class_exists('PEAR_Downloader')) {
  998. require_once 'PEAR/Downloader.php';
  999. }
  1000. return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
  1001. }
  1002. // }}}
  1003. /**
  1004. * @param string $path relative or absolute include path
  1005. * @return boolean
  1006. * @static
  1007. */
  1008. function isIncludeable($path)
  1009. {
  1010. if (file_exists($path) && is_readable($path)) {
  1011. return true;
  1012. }
  1013. $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
  1014. foreach ($ipath as $include) {
  1015. $test = realpath($include . DIRECTORY_SEPARATOR . $path);
  1016. if (file_exists($test) && is_readable($test)) {
  1017. return true;
  1018. }
  1019. }
  1020. return false;
  1021. }
  1022. }
  1023. require_once 'PEAR/Config.php';
  1024. require_once 'PEAR/PackageFile.php';
  1025. ?>