PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/plugin/pear/PEAR/Common.php

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