PageRenderTime 47ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/SyracavaPHP/syracava/ext/pear/PEAR/Registry.php

http://syracava.googlecode.com/
PHP | 2038 lines | 1415 code | 139 blank | 484 comment | 357 complexity | 332704f5861dcf290ab8b721573e59d6 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1

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

  1. <?php
  2. /**
  3. * PEAR_Registry
  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: Registry.php 125 2009-08-21 01:35:18Z takuji.mezawa $
  21. * @link http://pear.php.net/package/PEAR
  22. * @since File available since Release 0.1
  23. */
  24. /**
  25. * for PEAR_Error
  26. */
  27. require_once 'PEAR.php';
  28. require_once 'PEAR/DependencyDB.php';
  29. define('PEAR_REGISTRY_ERROR_LOCK', -2);
  30. define('PEAR_REGISTRY_ERROR_FORMAT', -3);
  31. define('PEAR_REGISTRY_ERROR_FILE', -4);
  32. define('PEAR_REGISTRY_ERROR_CONFLICT', -5);
  33. define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
  34. /**
  35. * Administration class used to maintain the installed package database.
  36. * @category pear
  37. * @package PEAR
  38. * @author Stig Bakken <ssb@php.net>
  39. * @author Tomas V. V. Cox <cox@idecnet.com>
  40. * @author Greg Beaver <cellog@php.net>
  41. * @copyright 1997-2008 The PHP Group
  42. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  43. * @version Release: 1.7.2
  44. * @link http://pear.php.net/package/PEAR
  45. * @since Class available since Release 1.4.0a1
  46. */
  47. class PEAR_Registry extends PEAR
  48. {
  49. // {{{ properties
  50. /**
  51. * File containing all channel information.
  52. * @var string
  53. */
  54. var $channels = '';
  55. /** Directory where registry files are stored.
  56. * @var string
  57. */
  58. var $statedir = '';
  59. /** File where the file map is stored
  60. * @var string
  61. */
  62. var $filemap = '';
  63. /** Directory where registry files for channels are stored.
  64. * @var string
  65. */
  66. var $channelsdir = '';
  67. /** Name of file used for locking the registry
  68. * @var string
  69. */
  70. var $lockfile = '';
  71. /** File descriptor used during locking
  72. * @var resource
  73. */
  74. var $lock_fp = null;
  75. /** Mode used during locking
  76. * @var int
  77. */
  78. var $lock_mode = 0; // XXX UNUSED
  79. /** Cache of package information. Structure:
  80. * array(
  81. * 'package' => array('id' => ... ),
  82. * ... )
  83. * @var array
  84. */
  85. var $pkginfo_cache = array();
  86. /** Cache of file map. Structure:
  87. * array( '/path/to/file' => 'package', ... )
  88. * @var array
  89. */
  90. var $filemap_cache = array();
  91. /**
  92. * @var false|PEAR_ChannelFile
  93. */
  94. var $_pearChannel;
  95. /**
  96. * @var false|PEAR_ChannelFile
  97. */
  98. var $_peclChannel;
  99. /**
  100. * @var PEAR_DependencyDB
  101. */
  102. var $_dependencyDB;
  103. /**
  104. * @var PEAR_Config
  105. */
  106. var $_config;
  107. // }}}
  108. // {{{ constructor
  109. /**
  110. * PEAR_Registry constructor.
  111. *
  112. * @param string (optional) PEAR install directory (for .php files)
  113. * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
  114. * default values are not desired. Only used the very first time a PEAR
  115. * repository is initialized
  116. * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
  117. * default values are not desired. Only used the very first time a PEAR
  118. * repository is initialized
  119. *
  120. * @access public
  121. */
  122. function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
  123. $pecl_channel = false)
  124. {
  125. parent::PEAR();
  126. $this->setInstallDir($pear_install_dir);
  127. $this->_pearChannel = $pear_channel;
  128. $this->_peclChannel = $pecl_channel;
  129. $this->_config = false;
  130. }
  131. function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR)
  132. {
  133. $ds = DIRECTORY_SEPARATOR;
  134. $this->install_dir = $pear_install_dir;
  135. $this->channelsdir = $pear_install_dir.$ds.'.channels';
  136. $this->statedir = $pear_install_dir.$ds.'.registry';
  137. $this->filemap = $pear_install_dir.$ds.'.filemap';
  138. $this->lockfile = $pear_install_dir.$ds.'.lock';
  139. }
  140. function hasWriteAccess()
  141. {
  142. if (!file_exists($this->install_dir)) {
  143. $dir = $this->install_dir;
  144. while ($dir && $dir != '.') {
  145. $olddir = $dir;
  146. $dir = dirname($dir); // cd ..
  147. if ($dir != '.' && file_exists($dir)) {
  148. if (is_writeable($dir)) {
  149. return true;
  150. } else {
  151. return false;
  152. }
  153. }
  154. if ($dir == $olddir) { // this can happen in safe mode
  155. return @is_writable($dir);
  156. }
  157. }
  158. return false;
  159. }
  160. return is_writeable($this->install_dir);
  161. }
  162. function setConfig(&$config, $resetInstallDir = true)
  163. {
  164. $this->_config = &$config;
  165. if ($resetInstallDir) {
  166. $this->setInstallDir($config->get('php_dir'));
  167. }
  168. }
  169. function _initializeChannelDirs()
  170. {
  171. static $running = false;
  172. if (!$running) {
  173. $running = true;
  174. $ds = DIRECTORY_SEPARATOR;
  175. if (!is_dir($this->channelsdir) ||
  176. !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
  177. !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
  178. !file_exists($this->channelsdir . $ds . '__uri.reg')) {
  179. if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
  180. $pear_channel = $this->_pearChannel;
  181. if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
  182. if (!class_exists('PEAR_ChannelFile')) {
  183. require_once 'PEAR/ChannelFile.php';
  184. }
  185. $pear_channel = new PEAR_ChannelFile;
  186. $pear_channel->setName('pear.php.net');
  187. $pear_channel->setAlias('pear');
  188. $pear_channel->setServer('pear.php.net');
  189. $pear_channel->setSummary('PHP Extension and Application Repository');
  190. $pear_channel->setDefaultPEARProtocols();
  191. $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
  192. $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
  193. } else {
  194. $pear_channel->setName('pear.php.net');
  195. $pear_channel->setAlias('pear');
  196. }
  197. $pear_channel->validate();
  198. $this->_addChannel($pear_channel);
  199. }
  200. if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
  201. $pecl_channel = $this->_peclChannel;
  202. if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
  203. if (!class_exists('PEAR_ChannelFile')) {
  204. require_once 'PEAR/ChannelFile.php';
  205. }
  206. $pecl_channel = new PEAR_ChannelFile;
  207. $pecl_channel->setName('pecl.php.net');
  208. $pecl_channel->setAlias('pecl');
  209. $pecl_channel->setServer('pecl.php.net');
  210. $pecl_channel->setSummary('PHP Extension Community Library');
  211. $pecl_channel->setDefaultPEARProtocols();
  212. $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
  213. $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
  214. $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
  215. } else {
  216. $pecl_channel->setName('pecl.php.net');
  217. $pecl_channel->setAlias('pecl');
  218. }
  219. $pecl_channel->validate();
  220. $this->_addChannel($pecl_channel);
  221. }
  222. if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
  223. if (!class_exists('PEAR_ChannelFile')) {
  224. require_once 'PEAR/ChannelFile.php';
  225. }
  226. $private = new PEAR_ChannelFile;
  227. $private->setName('__uri');
  228. $private->addFunction('xmlrpc', '1.0', '****');
  229. $private->setSummary('Pseudo-channel for static packages');
  230. $this->_addChannel($private);
  231. }
  232. $this->_rebuildFileMap();
  233. }
  234. $running = false;
  235. }
  236. }
  237. function _initializeDirs()
  238. {
  239. $ds = DIRECTORY_SEPARATOR;
  240. // XXX Compatibility code should be removed in the future
  241. // rename all registry files if any to lowercase
  242. if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
  243. $handle = opendir($this->statedir)) {
  244. $dest = $this->statedir . $ds;
  245. while (false !== ($file = readdir($handle))) {
  246. if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
  247. rename($dest . $file, $dest . strtolower($file));
  248. }
  249. }
  250. closedir($handle);
  251. }
  252. $this->_initializeChannelDirs();
  253. if (!file_exists($this->filemap)) {
  254. $this->_rebuildFileMap();
  255. }
  256. $this->_initializeDepDB();
  257. }
  258. function _initializeDepDB()
  259. {
  260. if (!isset($this->_dependencyDB)) {
  261. static $initializing = false;
  262. if (!$initializing) {
  263. $initializing = true;
  264. if (!$this->_config) { // never used?
  265. if (OS_WINDOWS) {
  266. $file = 'pear.ini';
  267. } else {
  268. $file = '.pearrc';
  269. }
  270. $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
  271. $file);
  272. $this->_config->setRegistry($this);
  273. $this->_config->set('php_dir', $this->install_dir);
  274. }
  275. $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
  276. if (PEAR::isError($this->_dependencyDB)) {
  277. // attempt to recover by removing the dep db
  278. if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
  279. DIRECTORY_SEPARATOR . '.depdb')) {
  280. @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
  281. DIRECTORY_SEPARATOR . '.depdb');
  282. }
  283. $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
  284. if (PEAR::isError($this->_dependencyDB)) {
  285. echo $this->_dependencyDB->getMessage();
  286. echo 'Unrecoverable error';
  287. exit(1);
  288. }
  289. }
  290. $initializing = false;
  291. }
  292. }
  293. }
  294. // }}}
  295. // {{{ destructor
  296. /**
  297. * PEAR_Registry destructor. Makes sure no locks are forgotten.
  298. *
  299. * @access private
  300. */
  301. function _PEAR_Registry()
  302. {
  303. parent::_PEAR();
  304. if (is_resource($this->lock_fp)) {
  305. $this->_unlock();
  306. }
  307. }
  308. // }}}
  309. // {{{ _assertStateDir()
  310. /**
  311. * Make sure the directory where we keep registry files exists.
  312. *
  313. * @return bool TRUE if directory exists, FALSE if it could not be
  314. * created
  315. *
  316. * @access private
  317. */
  318. function _assertStateDir($channel = false)
  319. {
  320. if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
  321. return $this->_assertChannelStateDir($channel);
  322. }
  323. static $init = false;
  324. if (!file_exists($this->statedir)) {
  325. if (!$this->hasWriteAccess()) {
  326. return false;
  327. }
  328. require_once 'System.php';
  329. if (!System::mkdir(array('-p', $this->statedir))) {
  330. return $this->raiseError("could not create directory '{$this->statedir}'");
  331. }
  332. $init = true;
  333. } elseif (!is_dir($this->statedir)) {
  334. return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
  335. 'it already exists and is not a directory');
  336. }
  337. $ds = DIRECTORY_SEPARATOR;
  338. if (!file_exists($this->channelsdir)) {
  339. if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
  340. !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
  341. !file_exists($this->channelsdir . $ds . '__uri.reg')) {
  342. $init = true;
  343. }
  344. } elseif (!is_dir($this->channelsdir)) {
  345. return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
  346. 'it already exists and is not a directory');
  347. }
  348. if ($init) {
  349. static $running = false;
  350. if (!$running) {
  351. $running = true;
  352. $this->_initializeDirs();
  353. $running = false;
  354. $init = false;
  355. }
  356. } else {
  357. $this->_initializeDepDB();
  358. }
  359. return true;
  360. }
  361. // }}}
  362. // {{{ _assertChannelStateDir()
  363. /**
  364. * Make sure the directory where we keep registry files exists for a non-standard channel.
  365. *
  366. * @param string channel name
  367. * @return bool TRUE if directory exists, FALSE if it could not be
  368. * created
  369. *
  370. * @access private
  371. */
  372. function _assertChannelStateDir($channel)
  373. {
  374. $ds = DIRECTORY_SEPARATOR;
  375. if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
  376. if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
  377. $this->_initializeChannelDirs();
  378. }
  379. return $this->_assertStateDir($channel);
  380. }
  381. $channelDir = $this->_channelDirectoryName($channel);
  382. if (!is_dir($this->channelsdir) ||
  383. !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
  384. $this->_initializeChannelDirs();
  385. }
  386. if (!file_exists($channelDir)) {
  387. if (!$this->hasWriteAccess()) {
  388. return false;
  389. }
  390. require_once 'System.php';
  391. if (!System::mkdir(array('-p', $channelDir))) {
  392. return $this->raiseError("could not create directory '" . $channelDir .
  393. "'");
  394. }
  395. } elseif (!is_dir($channelDir)) {
  396. return $this->raiseError("could not create directory '" . $channelDir .
  397. "', already exists and is not a directory");
  398. }
  399. return true;
  400. }
  401. // }}}
  402. // {{{ _assertChannelDir()
  403. /**
  404. * Make sure the directory where we keep registry files for channels exists
  405. *
  406. * @return bool TRUE if directory exists, FALSE if it could not be
  407. * created
  408. *
  409. * @access private
  410. */
  411. function _assertChannelDir()
  412. {
  413. if (!file_exists($this->channelsdir)) {
  414. if (!$this->hasWriteAccess()) {
  415. return false;
  416. }
  417. require_once 'System.php';
  418. if (!System::mkdir(array('-p', $this->channelsdir))) {
  419. return $this->raiseError("could not create directory '{$this->channelsdir}'");
  420. }
  421. } elseif (!is_dir($this->channelsdir)) {
  422. return $this->raiseError("could not create directory '{$this->channelsdir}" .
  423. "', it already exists and is not a directory");
  424. }
  425. if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
  426. if (!$this->hasWriteAccess()) {
  427. return false;
  428. }
  429. require_once 'System.php';
  430. if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
  431. return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
  432. }
  433. } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
  434. return $this->raiseError("could not create directory '{$this->channelsdir}" .
  435. "/.alias', it already exists and is not a directory");
  436. }
  437. return true;
  438. }
  439. // }}}
  440. // {{{ _packageFileName()
  441. /**
  442. * Get the name of the file where data for a given package is stored.
  443. *
  444. * @param string channel name, or false if this is a PEAR package
  445. * @param string package name
  446. *
  447. * @return string registry file name
  448. *
  449. * @access public
  450. */
  451. function _packageFileName($package, $channel = false)
  452. {
  453. if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
  454. return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
  455. strtolower($package) . '.reg';
  456. }
  457. return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
  458. }
  459. // }}}
  460. // {{{ _channelFileName()
  461. /**
  462. * Get the name of the file where data for a given channel is stored.
  463. * @param string channel name
  464. * @return string registry file name
  465. */
  466. function _channelFileName($channel, $noaliases = false)
  467. {
  468. if (!$noaliases) {
  469. if (file_exists($this->_getChannelAliasFileName($channel))) {
  470. $channel = implode('', file($this->_getChannelAliasFileName($channel)));
  471. }
  472. }
  473. return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
  474. strtolower($channel)) . '.reg';
  475. }
  476. // }}}
  477. // {{{ getChannelAliasFileName()
  478. /**
  479. * @param string
  480. * @return string
  481. */
  482. function _getChannelAliasFileName($alias)
  483. {
  484. return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
  485. DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
  486. }
  487. // }}}
  488. // {{{ _getChannelFromAlias()
  489. /**
  490. * Get the name of a channel from its alias
  491. */
  492. function _getChannelFromAlias($channel)
  493. {
  494. if (!$this->_channelExists($channel)) {
  495. if ($channel == 'pear.php.net') {
  496. return 'pear.php.net';
  497. }
  498. if ($channel == 'pecl.php.net') {
  499. return 'pecl.php.net';
  500. }
  501. if ($channel == '__uri') {
  502. return '__uri';
  503. }
  504. return false;
  505. }
  506. $channel = strtolower($channel);
  507. if (file_exists($this->_getChannelAliasFileName($channel))) {
  508. // translate an alias to an actual channel
  509. return implode('', file($this->_getChannelAliasFileName($channel)));
  510. } else {
  511. return $channel;
  512. }
  513. }
  514. // }}}
  515. // {{{ _getChannelFromAlias()
  516. /**
  517. * Get the alias of a channel from its alias or its name
  518. */
  519. function _getAlias($channel)
  520. {
  521. if (!$this->_channelExists($channel)) {
  522. if ($channel == 'pear.php.net') {
  523. return 'pear';
  524. }
  525. if ($channel == 'pecl.php.net') {
  526. return 'pecl';
  527. }
  528. return false;
  529. }
  530. $channel = $this->_getChannel($channel);
  531. if (PEAR::isError($channel)) {
  532. return $channel;
  533. }
  534. return $channel->getAlias();
  535. }
  536. // }}}
  537. // {{{ _channelDirectoryName()
  538. /**
  539. * Get the name of the file where data for a given package is stored.
  540. *
  541. * @param string channel name, or false if this is a PEAR package
  542. * @param string package name
  543. *
  544. * @return string registry file name
  545. *
  546. * @access public
  547. */
  548. function _channelDirectoryName($channel)
  549. {
  550. if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
  551. return $this->statedir;
  552. } else {
  553. $ch = $this->_getChannelFromAlias($channel);
  554. if (!$ch) {
  555. $ch = $channel;
  556. }
  557. return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
  558. str_replace('/', '_', $ch));
  559. }
  560. }
  561. // }}}
  562. // {{{ _openPackageFile()
  563. function _openPackageFile($package, $mode, $channel = false)
  564. {
  565. if (!$this->_assertStateDir($channel)) {
  566. return null;
  567. }
  568. if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
  569. return null;
  570. }
  571. $file = $this->_packageFileName($package, $channel);
  572. if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
  573. return null;
  574. }
  575. $fp = @fopen($file, $mode);
  576. if (!$fp) {
  577. return null;
  578. }
  579. return $fp;
  580. }
  581. // }}}
  582. // {{{ _closePackageFile()
  583. function _closePackageFile($fp)
  584. {
  585. fclose($fp);
  586. }
  587. // }}}
  588. // {{{ _openChannelFile()
  589. function _openChannelFile($channel, $mode)
  590. {
  591. if (!$this->_assertChannelDir()) {
  592. return null;
  593. }
  594. if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
  595. return null;
  596. }
  597. $file = $this->_channelFileName($channel);
  598. if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
  599. return null;
  600. }
  601. $fp = @fopen($file, $mode);
  602. if (!$fp) {
  603. return null;
  604. }
  605. return $fp;
  606. }
  607. // }}}
  608. // {{{ _closePackageFile()
  609. function _closeChannelFile($fp)
  610. {
  611. fclose($fp);
  612. }
  613. // }}}
  614. // {{{ _rebuildFileMap()
  615. function _rebuildFileMap()
  616. {
  617. if (!class_exists('PEAR_Installer_Role')) {
  618. require_once 'PEAR/Installer/Role.php';
  619. }
  620. $channels = $this->_listAllPackages();
  621. $files = array();
  622. foreach ($channels as $channel => $packages) {
  623. foreach ($packages as $package) {
  624. $version = $this->_packageInfo($package, 'version', $channel);
  625. $filelist = $this->_packageInfo($package, 'filelist', $channel);
  626. if (!is_array($filelist)) {
  627. continue;
  628. }
  629. foreach ($filelist as $name => $attrs) {
  630. if (isset($attrs['attribs'])) {
  631. $attrs = $attrs['attribs'];
  632. }
  633. // it is possible for conflicting packages in different channels to
  634. // conflict with data files/doc files
  635. if ($name == 'dirtree') {
  636. continue;
  637. }
  638. if (isset($attrs['role']) && !in_array($attrs['role'],
  639. PEAR_Installer_Role::getInstallableRoles())) {
  640. // these are not installed
  641. continue;
  642. }
  643. if (isset($attrs['role']) && !in_array($attrs['role'],
  644. PEAR_Installer_Role::getBaseinstallRoles())) {
  645. $attrs['baseinstalldir'] = $package;
  646. }
  647. if (isset($attrs['baseinstalldir'])) {
  648. $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
  649. } else {
  650. $file = $name;
  651. }
  652. $file = preg_replace(',^/+,', '', $file);
  653. if ($channel != 'pear.php.net') {
  654. if (!isset($files[$attrs['role']])) {
  655. $files[$attrs['role']] = array();
  656. }
  657. $files[$attrs['role']][$file] = array(strtolower($channel),
  658. strtolower($package));
  659. } else {
  660. if (!isset($files[$attrs['role']])) {
  661. $files[$attrs['role']] = array();
  662. }
  663. $files[$attrs['role']][$file] = strtolower($package);
  664. }
  665. }
  666. }
  667. }
  668. $this->_assertStateDir();
  669. if (!$this->hasWriteAccess()) {
  670. return false;
  671. }
  672. $fp = @fopen($this->filemap, 'wb');
  673. if (!$fp) {
  674. return false;
  675. }
  676. $this->filemap_cache = $files;
  677. fwrite($fp, serialize($files));
  678. fclose($fp);
  679. return true;
  680. }
  681. // }}}
  682. // {{{ _readFileMap()
  683. function _readFileMap()
  684. {
  685. if (!file_exists($this->filemap)) {
  686. return array();
  687. }
  688. $fp = @fopen($this->filemap, 'r');
  689. if (!$fp) {
  690. return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
  691. }
  692. clearstatcache();
  693. $rt = get_magic_quotes_runtime();
  694. set_magic_quotes_runtime(0);
  695. $fsize = filesize($this->filemap);
  696. fclose($fp);
  697. $data = file_get_contents($this->filemap);
  698. set_magic_quotes_runtime($rt);
  699. $tmp = unserialize($data);
  700. if (!$tmp && $fsize > 7) {
  701. return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
  702. }
  703. $this->filemap_cache = $tmp;
  704. return true;
  705. }
  706. // }}}
  707. // {{{ _lock()
  708. /**
  709. * Lock the registry.
  710. *
  711. * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
  712. * See flock manual for more information.
  713. *
  714. * @return bool TRUE on success, FALSE if locking failed, or a
  715. * PEAR error if some other error occurs (such as the
  716. * lock file not being writable).
  717. *
  718. * @access private
  719. */
  720. function _lock($mode = LOCK_EX)
  721. {
  722. if (!eregi('Windows 9', php_uname())) {
  723. if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
  724. // XXX does not check type of lock (LOCK_SH/LOCK_EX)
  725. return true;
  726. }
  727. if (!$this->_assertStateDir()) {
  728. if ($mode == LOCK_EX) {
  729. return $this->raiseError('Registry directory is not writeable by the current user');
  730. } else {
  731. return true;
  732. }
  733. }
  734. $open_mode = 'w';
  735. // XXX People reported problems with LOCK_SH and 'w'
  736. if ($mode === LOCK_SH || $mode === LOCK_UN) {
  737. if (!file_exists($this->lockfile)) {
  738. touch($this->lockfile);
  739. }
  740. $open_mode = 'r';
  741. }
  742. if (!is_resource($this->lock_fp)) {
  743. $this->lock_fp = @fopen($this->lockfile, $open_mode);
  744. }
  745. if (!is_resource($this->lock_fp)) {
  746. $this->lock_fp = null;
  747. return $this->raiseError("could not create lock file" .
  748. (isset($php_errormsg) ? ": " . $php_errormsg : ""));
  749. }
  750. if (!(int)flock($this->lock_fp, $mode)) {
  751. switch ($mode) {
  752. case LOCK_SH: $str = 'shared'; break;
  753. case LOCK_EX: $str = 'exclusive'; break;
  754. case LOCK_UN: $str = 'unlock'; break;
  755. default: $str = 'unknown'; break;
  756. }
  757. //is resource at this point, close it on error.
  758. fclose($this->lock_fp);
  759. $this->lock_fp = null;
  760. return $this->raiseError("could not acquire $str lock ($this->lockfile)",
  761. PEAR_REGISTRY_ERROR_LOCK);
  762. }
  763. }
  764. return true;
  765. }
  766. // }}}
  767. // {{{ _unlock()
  768. function _unlock()
  769. {
  770. $ret = $this->_lock(LOCK_UN);
  771. if (is_resource($this->lock_fp)) {
  772. fclose($this->lock_fp);
  773. }
  774. $this->lock_fp = null;
  775. return $ret;
  776. }
  777. // }}}
  778. // {{{ _packageExists()
  779. function _packageExists($package, $channel = false)
  780. {
  781. return file_exists($this->_packageFileName($package, $channel));
  782. }
  783. // }}}
  784. // {{{ _channelExists()
  785. /**
  786. * Determine whether a channel exists in the registry
  787. * @param string Channel name
  788. * @param bool if true, then aliases will be ignored
  789. * @return boolean
  790. */
  791. function _channelExists($channel, $noaliases = false)
  792. {
  793. $a = file_exists($this->_channelFileName($channel, $noaliases));
  794. if (!$a && $channel == 'pear.php.net') {
  795. return true;
  796. }
  797. if (!$a && $channel == 'pecl.php.net') {
  798. return true;
  799. }
  800. return $a;
  801. }
  802. // }}}
  803. // {{{ _addChannel()
  804. /**
  805. * @param PEAR_ChannelFile Channel object
  806. * @param donotuse
  807. * @param string Last-Modified HTTP tag from remote request
  808. * @return boolean|PEAR_Error True on creation, false if it already exists
  809. */
  810. function _addChannel($channel, $update = false, $lastmodified = false)
  811. {
  812. if (!is_a($channel, 'PEAR_ChannelFile')) {
  813. return false;
  814. }
  815. if (!$channel->validate()) {
  816. return false;
  817. }
  818. if (file_exists($this->_channelFileName($channel->getName()))) {
  819. if (!$update) {
  820. return false;
  821. }
  822. $checker = $this->_getChannel($channel->getName());
  823. if (PEAR::isError($checker)) {
  824. return $checker;
  825. }
  826. if ($channel->getAlias() != $checker->getAlias()) {
  827. if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
  828. @unlink($this->_getChannelAliasFileName($checker->getAlias()));
  829. }
  830. }
  831. } else {
  832. if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) {
  833. return false;
  834. }
  835. }
  836. $ret = $this->_assertChannelDir();
  837. if (PEAR::isError($ret)) {
  838. return $ret;
  839. }
  840. $ret = $this->_assertChannelStateDir($channel->getName());
  841. if (PEAR::isError($ret)) {
  842. return $ret;
  843. }
  844. if ($channel->getAlias() != $channel->getName()) {
  845. if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
  846. $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
  847. $channel->setAlias($channel->getName());
  848. }
  849. if (!$this->hasWriteAccess()) {
  850. return false;
  851. }
  852. $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
  853. if (!$fp) {
  854. return false;
  855. }
  856. fwrite($fp, $channel->getName());
  857. fclose($fp);
  858. }
  859. if (!$this->hasWriteAccess()) {
  860. return false;
  861. }
  862. $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
  863. if (!$fp) {
  864. return false;
  865. }
  866. $info = $channel->toArray();
  867. if ($lastmodified) {
  868. $info['_lastmodified'] = $lastmodified;
  869. } else {
  870. $info['_lastmodified'] = date('r');
  871. }
  872. fwrite($fp, serialize($info));
  873. fclose($fp);
  874. return true;
  875. }
  876. // }}}
  877. // {{{ _deleteChannel()
  878. /**
  879. * Deletion fails if there are any packages installed from the channel
  880. * @param string|PEAR_ChannelFile channel name
  881. * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
  882. */
  883. function _deleteChannel($channel)
  884. {
  885. if (!is_string($channel)) {
  886. if (is_a($channel, 'PEAR_ChannelFile')) {
  887. if (!$channel->validate()) {
  888. return false;
  889. }
  890. $channel = $channel->getName();
  891. } else {
  892. return false;
  893. }
  894. }
  895. if ($this->_getChannelFromAlias($channel) == '__uri') {
  896. return false;
  897. }
  898. if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
  899. return false;
  900. }
  901. if (!$this->_channelExists($channel)) {
  902. return false;
  903. }
  904. if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
  905. return false;
  906. }
  907. $channel = $this->_getChannelFromAlias($channel);
  908. if ($channel == 'pear.php.net') {
  909. return false;
  910. }
  911. $test = $this->_listChannelPackages($channel);
  912. if (count($test)) {
  913. return false;
  914. }
  915. $test = @rmdir($this->_channelDirectoryName($channel));
  916. if (!$test) {
  917. return false;
  918. }
  919. $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
  920. if (file_exists($file)) {
  921. $test = @unlink($file);
  922. if (!$test) {
  923. return false;
  924. }
  925. }
  926. $file = $this->_channelFileName($channel);
  927. $ret = true;
  928. if (file_exists($file)) {
  929. $ret = @unlink($file);
  930. }
  931. return $ret;
  932. }
  933. // }}}
  934. // {{{ _isChannelAlias()
  935. /**
  936. * Determine whether a channel exists in the registry
  937. * @param string Channel Alias
  938. * @return boolean
  939. */
  940. function _isChannelAlias($alias)
  941. {
  942. return file_exists($this->_getChannelAliasFileName($alias));
  943. }
  944. // }}}
  945. // {{{ _packageInfo()
  946. /**
  947. * @param string|null
  948. * @param string|null
  949. * @param string|null
  950. * @return array|null
  951. * @access private
  952. */
  953. function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
  954. {
  955. if ($package === null) {
  956. if ($channel === null) {
  957. $channels = $this->_listChannels();
  958. $ret = array();
  959. foreach ($channels as $channel) {
  960. $channel = strtolower($channel);
  961. $ret[$channel] = array();
  962. $packages = $this->_listPackages($channel);
  963. foreach ($packages as $package) {
  964. $ret[$channel][] = $this->_packageInfo($package, null, $channel);
  965. }
  966. }
  967. return $ret;
  968. }
  969. $ps = $this->_listPackages($channel);
  970. if (!count($ps)) {
  971. return array();
  972. }
  973. return array_map(array(&$this, '_packageInfo'),
  974. $ps, array_fill(0, count($ps), null),
  975. array_fill(0, count($ps), $channel));
  976. }
  977. $fp = $this->_openPackageFile($package, 'r', $channel);
  978. if ($fp === null) {
  979. return null;
  980. }
  981. $rt = get_magic_quotes_runtime();
  982. set_magic_quotes_runtime(0);
  983. clearstatcache();
  984. $this->_closePackageFile($fp);
  985. $data = file_get_contents($this->_packageFileName($package, $channel));
  986. set_magic_quotes_runtime($rt);
  987. $data = unserialize($data);
  988. if ($key === null) {
  989. return $data;
  990. }
  991. // compatibility for package.xml version 2.0
  992. if (isset($data['old'][$key])) {
  993. return $data['old'][$key];
  994. }
  995. if (isset($data[$key])) {
  996. return $data[$key];
  997. }
  998. return null;
  999. }
  1000. // }}}
  1001. // {{{ _channelInfo()
  1002. /**
  1003. * @param string Channel name
  1004. * @param bool whether to strictly retrieve info of channels, not just aliases
  1005. * @return array|null
  1006. */
  1007. function _channelInfo($channel, $noaliases = false)
  1008. {
  1009. if (!$this->_channelExists($channel, $noaliases)) {
  1010. return null;
  1011. }
  1012. $fp = $this->_openChannelFile($channel, 'r');
  1013. if ($fp === null) {
  1014. return null;
  1015. }
  1016. $rt = get_magic_quotes_runtime();
  1017. set_magic_quotes_runtime(0);
  1018. clearstatcache();
  1019. $this->_closeChannelFile($fp);
  1020. $data = file_get_contents($this->_channelFileName($channel));
  1021. set_magic_quotes_runtime($rt);
  1022. $data = unserialize($data);
  1023. return $data;
  1024. }
  1025. // }}}
  1026. // {{{ _listChannels()
  1027. function _listChannels()
  1028. {
  1029. $channellist = array();
  1030. if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
  1031. return array('pear.php.net', 'pecl.php.net', '__uri');
  1032. }
  1033. $dp = opendir($this->channelsdir);
  1034. while ($ent = readdir($dp)) {
  1035. if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
  1036. continue;
  1037. }
  1038. if ($ent == '__uri.reg') {
  1039. $channellist[] = '__uri';
  1040. continue;
  1041. }
  1042. $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
  1043. }
  1044. closedir($dp);
  1045. if (!in_array('pear.php.net', $channellist)) {
  1046. $channellist[] = 'pear.php.net';
  1047. }
  1048. if (!in_array('pecl.php.net', $channellist)) {
  1049. $channellist[] = 'pecl.php.net';
  1050. }
  1051. if (!in_array('__uri', $channellist)) {
  1052. $channellist[] = '__uri';
  1053. }
  1054. natsort($channellist);
  1055. return $channellist;
  1056. }
  1057. // }}}
  1058. // {{{ _listPackages()
  1059. function _listPackages($channel = false)
  1060. {
  1061. if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
  1062. return $this->_listChannelPackages($channel);
  1063. }
  1064. if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
  1065. return array();
  1066. }
  1067. $pkglist = array();
  1068. $dp = opendir($this->statedir);
  1069. if (!$dp) {
  1070. return $pkglist;
  1071. }
  1072. while ($ent = readdir($dp)) {
  1073. if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
  1074. continue;
  1075. }
  1076. $pkglist[] = substr($ent, 0, -4);
  1077. }
  1078. closedir($dp);
  1079. return $pkglist;
  1080. }
  1081. // }}}
  1082. // {{{ _listChannelPackages()
  1083. function _listChannelPackages($channel)
  1084. {
  1085. $pkglist = array();
  1086. if (!file_exists($this->_channelDirectoryName($channel)) ||
  1087. !is_dir($this->_channelDirectoryName($channel))) {
  1088. return array();
  1089. }
  1090. $dp = opendir($this->_channelDirectoryName($channel));
  1091. if (!$dp) {
  1092. return $pkglist;
  1093. }
  1094. while ($ent = readdir($dp)) {
  1095. if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
  1096. continue;
  1097. }
  1098. $pkglist[] = substr($ent, 0, -4);
  1099. }
  1100. closedir($dp);
  1101. return $pkglist;
  1102. }
  1103. // }}}
  1104. function _listAllPackages()
  1105. {
  1106. $ret = array();
  1107. foreach ($this->_listChannels() as $channel) {
  1108. $ret[$channel] = $this->_listPackages($channel);
  1109. }
  1110. return $ret;
  1111. }
  1112. /**
  1113. * Add an installed package to the registry
  1114. * @param string package name
  1115. * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
  1116. * @return bool success of saving
  1117. * @access private
  1118. */
  1119. function _addPackage($package, $info)
  1120. {
  1121. if ($this->_packageExists($package)) {
  1122. return false;
  1123. }
  1124. $fp = $this->_openPackageFile($package, 'wb');
  1125. if ($fp === null) {
  1126. return false;
  1127. }
  1128. $info['_lastmodified'] = time();
  1129. fwrite($fp, serialize($info));
  1130. $this->_closePackageFile($fp);
  1131. if (isset($info['filelist'])) {
  1132. $this->_rebuildFileMap();
  1133. }
  1134. return true;
  1135. }
  1136. /**
  1137. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  1138. * @return bool
  1139. * @access private
  1140. */
  1141. function _addPackage2($info)
  1142. {
  1143. if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
  1144. return false;
  1145. }
  1146. if (!$info->validate()) {
  1147. if (class_exists('PEAR_Common')) {
  1148. $ui = PEAR_Frontend::singleton();
  1149. if ($ui) {
  1150. foreach ($info->getValidationWarnings() as $err) {
  1151. $ui->log($err['message'], true);
  1152. }
  1153. }
  1154. }
  1155. return false;
  1156. }
  1157. $channel = $info->getChannel();
  1158. $package = $info->getPackage();
  1159. $save = $info;
  1160. if ($this->_packageExists($package, $channel)) {
  1161. return false;
  1162. }
  1163. if (!$this->_channelExists($channel, true)) {
  1164. return false;
  1165. }
  1166. $info = $info->toArray(true);
  1167. if (!$info) {
  1168. return false;
  1169. }
  1170. $fp = $this->_openPackageFile($package, 'wb', $channel);
  1171. if ($fp === null) {
  1172. return false;
  1173. }
  1174. $info['_lastmodified'] = time();
  1175. fwrite($fp, serialize($info));
  1176. $this->_closePackageFile($fp);
  1177. $this->_rebuildFileMap();
  1178. return true;
  1179. }
  1180. /**
  1181. * @param string Package name
  1182. * @param array parsed package.xml 1.0
  1183. * @param bool this parameter is only here for BC. Don't use it.
  1184. * @access private
  1185. */
  1186. function _updatePackage($package, $info, $merge = true)
  1187. {
  1188. $oldinfo = $this->_packageInfo($package);
  1189. if (empty($oldinfo)) {
  1190. return false;
  1191. }
  1192. $fp = $this->_openPackageFile($package, 'w');
  1193. if ($fp === null) {
  1194. return false;
  1195. }
  1196. if (is_object($info)) {
  1197. $info = $info->toArray();
  1198. }
  1199. $info['_lastmodified'] = time();
  1200. $newinfo = $info;
  1201. if ($merge) {
  1202. $info = array_merge($oldinfo, $info);
  1203. } else {
  1204. $diff = $info;
  1205. }
  1206. fwrite($fp, serialize($info));
  1207. $this->_closePackageFile($fp);
  1208. if (isset($newinfo['filelist'])) {
  1209. $this->_rebuildFileMap();
  1210. }
  1211. return true;
  1212. }
  1213. /**
  1214. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  1215. * @return bool
  1216. * @access private
  1217. */
  1218. function _updatePackage2($info)
  1219. {
  1220. if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
  1221. return false;
  1222. }
  1223. $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
  1224. if ($fp === null) {
  1225. return false;
  1226. }
  1227. $save = $info;
  1228. $info = $save->getArray(true);
  1229. $info['_lastmodified'] = time();
  1230. fwrite($fp, serialize($info));
  1231. $this->_closePackageFile($fp);
  1232. $this->_rebuildFileMap();
  1233. return true;
  1234. }
  1235. /**
  1236. * @param string Package name
  1237. * @param string Channel name
  1238. * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
  1239. * @access private
  1240. */
  1241. function &_getPackage($package, $channel = 'pear.php.net')
  1242. {
  1243. $info = $this->_packageInfo($package, null, $channel);
  1244. if ($info === null) {
  1245. return $info;
  1246. }
  1247. $a = $this->_config;
  1248. if (!$a) {
  1249. $this->_config = &new PEAR_Config;
  1250. $this->_config->set('php_dir', $this->statedir);
  1251. }
  1252. if (!class_exists('PEAR_PackageFile')) {
  1253. require_once 'PEAR/PackageFile.php';
  1254. }
  1255. $pkg = &new PEAR_PackageFile($this->_config);
  1256. $pf = &$pkg->fromArray($info);
  1257. return $pf;
  1258. }
  1259. /**
  1260. * @param string channel name
  1261. * @param bool whether to strictly retrieve channel names
  1262. * @return PEAR_ChannelFile|PEAR_Error
  1263. * @access private
  1264. */
  1265. function &_getChannel($channel, $noaliases = false)
  1266. {
  1267. $ch = false;
  1268. if ($this->_channelExists($channel, $noaliases)) {
  1269. $chinfo = $this->_channelInfo($channel, $noaliases);
  1270. if ($chinfo) {
  1271. if (!class_exists('PEAR_ChannelFile')) {
  1272. require_once 'PEAR/ChannelFile.php';
  1273. }
  1274. $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
  1275. }
  1276. }
  1277. if ($ch) {
  1278. if ($ch->validate()) {
  1279. return $ch;
  1280. }
  1281. foreach ($ch->getErrors(true) as $err) {
  1282. $message = $err['message'] . "\n";
  1283. }
  1284. $ch = PEAR::raiseError($message);
  1285. return $ch;
  1286. }
  1287. if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
  1288. // the registry is not properly set up, so use defaults
  1289. if (!class_exists('PEAR_ChannelFile')) {
  1290. require_once 'PEAR/ChannelFile.php';
  1291. }
  1292. $pear_channel = new PEAR_ChannelFile;
  1293. $pear_channel->setName('pear.php.net');
  1294. $pear_channel->setAlias('pear');
  1295. $pear_channel->setSummary('PHP Extension and Application Repository');
  1296. $pear_channel->setDefaultPEARProtocols();
  1297. $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
  1298. $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
  1299. return $pear_channel;
  1300. }
  1301. if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
  1302. // the registry is not properly set up, so use defaults
  1303. if (!class_exists('PEAR_ChannelFile')) {
  1304. require_once 'PEAR/ChannelFile.php';
  1305. }
  1306. $pear_channel = new PEAR_ChannelFile;
  1307. $pear_channel->setName('pecl.php.net');
  1308. $pear_channel->setAlias('pecl');
  1309. $pear_channel->setSummary('PHP Extension Community Library');
  1310. $pear_channel->setDefaultPEARProtocols();
  1311. $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
  1312. $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
  1313. $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
  1314. return $pear_channel;
  1315. }
  1316. if ($this->_getChannelFromAlias($channel) == '__uri') {
  1317. // the registry is not properly set up, so use defaults
  1318. if (!class_exists('PEAR_ChannelFile')) {
  1319. require_once 'PEAR/ChannelFile.php';
  1320. }
  1321. $private = new PEAR_ChannelFile;
  1322. $private->setName('__uri');
  1323. $private->addFunction('xmlrpc', '1.0', '****');
  1324. $private->setSummary('Pseudo-channel for static packages');
  1325. return $private;
  1326. }
  1327. return $ch;
  1328. }
  1329. // {{{ packageExists()
  1330. /**
  1331. * @param string Package name
  1332. * @param string Channel name
  1333. * @return bool
  1334. */
  1335. function packageExists($package, $channel = 'pear.php.net')
  1336. {
  1337. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1338. return $e;
  1339. }
  1340. $ret = $this->_packageExists($package, $channel);
  1341. $this->_unlock();
  1342. return $ret;
  1343. }
  1344. // }}}
  1345. // {{{ channelExists()
  1346. /**
  1347. * @param string channel name
  1348. * @param bool if true, then aliases will be ignored
  1349. * @return bool
  1350. */
  1351. function channelExists($channel, $noaliases = false)
  1352. {
  1353. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1354. return $e;
  1355. }
  1356. $ret = $this->_channelExists($channel, $noaliases);
  1357. $this->_unlock();
  1358. return $ret;
  1359. }
  1360. // }}}
  1361. // {{{ isAlias()
  1362. /**
  1363. * Determines whether the parameter is an alias of a channel
  1364. * @param string
  1365. * @return bool
  1366. */
  1367. function isAlias($alias)
  1368. {
  1369. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1370. return $e;
  1371. }
  1372. $ret = $this->_isChannelAlias($alias);
  1373. $this->_unlock();
  1374. return $ret;
  1375. }
  1376. // }}}
  1377. // {{{ packageInfo()
  1378. /**
  1379. * @param string|null
  1380. * @param string|null
  1381. * @param string
  1382. * @return array|null
  1383. */
  1384. function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
  1385. {
  1386. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1387. return $e;
  1388. }
  1389. $ret = $this->_packageInfo($package, $key, $channel);
  1390. $this->_unlock();
  1391. return $ret;
  1392. }
  1393. // }}}
  1394. // {{{ channelInfo()
  1395. /**
  1396. * Retrieve a raw array of channel data.
  1397. *
  1398. * Do not use this, instead use {@link getChannel()} for normal
  1399. * operations. Array structure is undefined in this method
  1400. * @param string channel name
  1401. * @param bool whether to strictly retrieve information only on non-aliases
  1402. * @return array|null|PEAR_Error
  1403. */
  1404. function channelInfo($channel = null, $noaliases = false)
  1405. {
  1406. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1407. return $e;
  1408. }
  1409. $ret = $this->_channelInfo($channel, $noaliases);
  1410. $this->_unlock();
  1411. return $ret;
  1412. }
  1413. // }}}
  1414. /**
  1415. * @param string
  1416. */
  1417. function channelName($channel)
  1418. {
  1419. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1420. return $e;
  1421. }
  1422. $ret = $this->_getChannelFromAlias($channel);
  1423. $this->_unlock();
  1424. return $ret;
  1425. }
  1426. /**
  1427. * @param string
  1428. */
  1429. function channelAlias($channel)
  1430. {
  1431. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1432. return $e;
  1433. }
  1434. $ret = $this->_getAlias($channel);
  1435. $this->_unlock();
  1436. return $ret;
  1437. }
  1438. // {{{ listPackages()
  1439. function listPackages($channel = false)
  1440. {
  1441. if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
  1442. return $e;
  1443. }
  1444. $ret = $this

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